diff --git a/Documentation/git.txt b/Documentation/git.txt index abace9eac2..d63c65e67d 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -867,15 +867,16 @@ for full details. end user, to be recorded in the body of the reflog. `GIT_REF_PARANOIA`:: - If set to `1`, include broken or badly named refs when iterating - over lists of refs. In a normal, non-corrupted repository, this - does nothing. However, enabling it may help git to detect and - abort some operations in the presence of broken refs. Git sets - this variable automatically when performing destructive - operations like linkgit:git-prune[1]. You should not need to set - it yourself unless you want to be paranoid about making sure - an operation has touched every ref (e.g., because you are - cloning a repository to make a backup). + If set to `0`, ignore broken or badly named refs when iterating + over lists of refs. Normally Git will try to include any such + refs, which may cause some operations to fail. This is usually + preferable, as potentially destructive operations (e.g., + linkgit:git-prune[1]) are better off aborting rather than + ignoring broken refs (and thus considering the history they + point to as not worth saving). The default value is `1` (i.e., + be paranoid about detecting and aborting all operations). You + should not normally need to set this to `0`, but it may be + useful when trying to salvage data from a corrupted repository. `GIT_ALLOW_PROTOCOL`:: If set to a colon-separated list of protocols, behave as if diff --git a/builtin/branch.c b/builtin/branch.c index 03c7b7253a..0b7ed82654 100644 --- a/builtin/branch.c +++ b/builtin/branch.c @@ -427,7 +427,7 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin memset(&array, 0, sizeof(array)); - filter_refs(&array, filter, filter->kind | FILTER_REFS_INCLUDE_BROKEN); + filter_refs(&array, filter, filter->kind); if (filter->verbose) maxwidth = calc_maxwidth(&array, strlen(remote_prefix)); diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c index 89cb6307d4..642b4b888f 100644 --- a/builtin/for-each-ref.c +++ b/builtin/for-each-ref.c @@ -77,7 +77,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix) filter.name_patterns = argv; filter.match_as_path = 1; - filter_refs(&array, &filter, FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN); + filter_refs(&array, &filter, FILTER_REFS_ALL); ref_array_sort(sorting, &array); if (!maxcount || array.nr < maxcount) diff --git a/builtin/prune.c b/builtin/prune.c index 02c6ab7cba..485c9a3c56 100644 --- a/builtin/prune.c +++ b/builtin/prune.c @@ -143,7 +143,6 @@ int cmd_prune(int argc, const char **argv, const char *prefix) expire = TIME_MAX; save_commit_buffer = 0; read_replace_refs = 0; - ref_paranoia = 1; repo_init_revisions(the_repository, &revs, prefix); argc = parse_options(argc, argv, prefix, options, prune_usage, 0); diff --git a/builtin/repack.c b/builtin/repack.c index c1a209013b..cb9f4bfed3 100644 --- a/builtin/repack.c +++ b/builtin/repack.c @@ -586,15 +586,12 @@ int cmd_repack(int argc, const char **argv, const char *prefix) strvec_pushf(&cmd.args, "--unpack-unreachable=%s", unpack_unreachable); - strvec_push(&cmd.env_array, "GIT_REF_PARANOIA=1"); } else if (pack_everything & LOOSEN_UNREACHABLE) { strvec_push(&cmd.args, "--unpack-unreachable"); } else if (keep_unreachable) { strvec_push(&cmd.args, "--keep-unreachable"); strvec_push(&cmd.args, "--pack-loose-unreachable"); - } else { - strvec_push(&cmd.env_array, "GIT_REF_PARANOIA=1"); } } } else if (geometry) { diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index 22c4e1a4ff..8480a59f57 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -863,8 +863,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) continue; } if (!strcmp(arg, "--bisect")) { - for_each_fullref_in("refs/bisect/bad", show_reference, NULL, 0); - for_each_fullref_in("refs/bisect/good", anti_reference, NULL, 0); + for_each_fullref_in("refs/bisect/bad", show_reference, NULL); + for_each_fullref_in("refs/bisect/good", anti_reference, NULL); continue; } if (opt_with_value(arg, "--branches", &arg)) { diff --git a/cache.h b/cache.h index 3e5658c6dd..1e2e6ee8cb 100644 --- a/cache.h +++ b/cache.h @@ -994,14 +994,6 @@ extern const char *core_fsmonitor; extern int core_apply_sparse_checkout; extern int core_sparse_checkout_cone; -/* - * Include broken refs in all ref iterations, which will - * generally choke dangerous operations rather than letting - * them silently proceed without taking the broken ref into - * account. - */ -extern int ref_paranoia; - /* * Returns the boolean value of $GIT_OPTIONAL_LOCKS (or the default value). */ diff --git a/environment.c b/environment.c index 43bb1b35ff..9da7f3c1a1 100644 --- a/environment.c +++ b/environment.c @@ -31,7 +31,6 @@ int prefer_symlink_refs; int is_bare_repository_cfg = -1; /* unspecified */ int warn_ambiguous_refs = 1; int warn_on_object_refname_ambiguity = 1; -int ref_paranoia = -1; int repository_format_precious_objects; int repository_format_worktree_config; const char *git_commit_encoding; diff --git a/ls-refs.c b/ls-refs.c index 73eb7da528..54078323dc 100644 --- a/ls-refs.c +++ b/ls-refs.c @@ -189,7 +189,7 @@ int ls_refs(struct repository *r, struct packet_reader *request) if (!data.prefixes.nr) strvec_push(&data.prefixes, ""); for_each_fullref_in_prefixes(get_git_namespace(), data.prefixes.v, - send_ref, &data, 0); + send_ref, &data); packet_fflush(stdout); strvec_clear(&data.prefixes); strbuf_release(&data.buf); diff --git a/ref-filter.c b/ref-filter.c index 93ce2a6ef2..e15f0c4bac 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -2100,8 +2100,7 @@ static int filter_pattern_match(struct ref_filter *filter, const char *refname) */ static int for_each_fullref_in_pattern(struct ref_filter *filter, each_ref_fn cb, - void *cb_data, - int broken) + void *cb_data) { if (!filter->match_as_path) { /* @@ -2109,7 +2108,7 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter, * prefixes like "refs/heads/" etc. are stripped off, * so we have to look at everything: */ - return for_each_fullref_in("", cb, cb_data, broken); + return for_each_fullref_in("", cb, cb_data); } if (filter->ignore_case) { @@ -2118,16 +2117,16 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter, * so just return everything and let the caller * sort it out. */ - return for_each_fullref_in("", cb, cb_data, broken); + return for_each_fullref_in("", cb, cb_data); } if (!filter->name_patterns[0]) { /* no patterns; we have to look at everything */ - return for_each_fullref_in("", cb, cb_data, broken); + return for_each_fullref_in("", cb, cb_data); } return for_each_fullref_in_prefixes(NULL, filter->name_patterns, - cb, cb_data, broken); + cb, cb_data); } /* @@ -2405,13 +2404,10 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int { struct ref_filter_cbdata ref_cbdata; int ret = 0; - unsigned int broken = 0; ref_cbdata.array = array; ref_cbdata.filter = filter; - if (type & FILTER_REFS_INCLUDE_BROKEN) - broken = 1; filter->kind = type & FILTER_REFS_KIND_MASK; init_contains_cache(&ref_cbdata.contains_cache); @@ -2428,13 +2424,13 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int * of filter_ref_kind(). */ if (filter->kind == FILTER_REFS_BRANCHES) - ret = for_each_fullref_in("refs/heads/", ref_filter_handler, &ref_cbdata, broken); + ret = for_each_fullref_in("refs/heads/", ref_filter_handler, &ref_cbdata); else if (filter->kind == FILTER_REFS_REMOTES) - ret = for_each_fullref_in("refs/remotes/", ref_filter_handler, &ref_cbdata, broken); + ret = for_each_fullref_in("refs/remotes/", ref_filter_handler, &ref_cbdata); else if (filter->kind == FILTER_REFS_TAGS) - ret = for_each_fullref_in("refs/tags/", ref_filter_handler, &ref_cbdata, broken); + ret = for_each_fullref_in("refs/tags/", ref_filter_handler, &ref_cbdata); else if (filter->kind & FILTER_REFS_ALL) - ret = for_each_fullref_in_pattern(filter, ref_filter_handler, &ref_cbdata, broken); + ret = for_each_fullref_in_pattern(filter, ref_filter_handler, &ref_cbdata); if (!ret && (filter->kind & FILTER_REFS_DETACHED_HEAD)) head_ref(ref_filter_handler, &ref_cbdata); } diff --git a/ref-filter.h b/ref-filter.h index c15dee8d6b..b636f4389d 100644 --- a/ref-filter.h +++ b/ref-filter.h @@ -13,7 +13,6 @@ #define QUOTE_PYTHON 4 #define QUOTE_TCL 8 -#define FILTER_REFS_INCLUDE_BROKEN 0x0001 #define FILTER_REFS_TAGS 0x0002 #define FILTER_REFS_BRANCHES 0x0004 #define FILTER_REFS_REMOTES 0x0008 diff --git a/refs.c b/refs.c index 9339e99fae..2166f37399 100644 --- a/refs.c +++ b/refs.c @@ -1409,14 +1409,21 @@ int head_ref(each_ref_fn fn, void *cb_data) struct ref_iterator *refs_ref_iterator_begin( struct ref_store *refs, - const char *prefix, int trim, int flags) + const char *prefix, int trim, + enum do_for_each_ref_flags flags) { struct ref_iterator *iter; - if (ref_paranoia < 0) - ref_paranoia = git_env_bool("GIT_REF_PARANOIA", 0); - if (ref_paranoia) - flags |= DO_FOR_EACH_INCLUDE_BROKEN; + if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) { + static int ref_paranoia = -1; + + if (ref_paranoia < 0) + ref_paranoia = git_env_bool("GIT_REF_PARANOIA", 1); + if (ref_paranoia) { + flags |= DO_FOR_EACH_INCLUDE_BROKEN; + flags |= DO_FOR_EACH_OMIT_DANGLING_SYMREFS; + } + } iter = refs->be->iterator_begin(refs, prefix, flags); @@ -1475,7 +1482,8 @@ static int do_for_each_ref_helper(struct repository *r, } static int do_for_each_ref(struct ref_store *refs, const char *prefix, - each_ref_fn fn, int trim, int flags, void *cb_data) + each_ref_fn fn, int trim, + enum do_for_each_ref_flags flags, void *cb_data) { struct ref_iterator *iter; struct do_for_each_ref_help hp = { fn, cb_data }; @@ -1510,25 +1518,16 @@ int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data) return refs_for_each_ref_in(get_main_ref_store(the_repository), prefix, fn, cb_data); } -int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, unsigned int broken) +int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data) { - unsigned int flag = 0; - - if (broken) - flag = DO_FOR_EACH_INCLUDE_BROKEN; return do_for_each_ref(get_main_ref_store(the_repository), - prefix, fn, 0, flag, cb_data); + prefix, fn, 0, 0, cb_data); } int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix, - each_ref_fn fn, void *cb_data, - unsigned int broken) + each_ref_fn fn, void *cb_data) { - unsigned int flag = 0; - - if (broken) - flag = DO_FOR_EACH_INCLUDE_BROKEN; - return do_for_each_ref(refs, prefix, fn, 0, flag, cb_data); + return do_for_each_ref(refs, prefix, fn, 0, 0, cb_data); } int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data) @@ -1620,8 +1619,7 @@ static void find_longest_prefixes(struct string_list *out, int for_each_fullref_in_prefixes(const char *namespace, const char **patterns, - each_ref_fn fn, void *cb_data, - unsigned int broken) + each_ref_fn fn, void *cb_data) { struct string_list prefixes = STRING_LIST_INIT_DUP; struct string_list_item *prefix; @@ -1636,7 +1634,7 @@ int for_each_fullref_in_prefixes(const char *namespace, for_each_string_list_item(prefix, &prefixes) { strbuf_addstr(&buf, prefix->string); - ret = for_each_fullref_in(buf.buf, fn, cb_data, broken); + ret = for_each_fullref_in(buf.buf, fn, cb_data); if (ret) break; strbuf_setlen(&buf, namespace_len); diff --git a/refs.h b/refs.h index 654310d3e2..d5099d4984 100644 --- a/refs.h +++ b/refs.h @@ -342,10 +342,8 @@ int for_each_ref(each_ref_fn fn, void *cb_data); int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data); int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix, - each_ref_fn fn, void *cb_data, - unsigned int broken); -int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, - unsigned int broken); + each_ref_fn fn, void *cb_data); +int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data); /** * iterate all refs in "patterns" by partitioning patterns into disjoint sets @@ -354,8 +352,7 @@ int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, * callers should be prepared to ignore references that they did not ask for. */ int for_each_fullref_in_prefixes(const char *namespace, const char **patterns, - each_ref_fn fn, void *cb_data, - unsigned int broken); + each_ref_fn fn, void *cb_data); /** * iterate refs from the respective area. */ diff --git a/refs/files-backend.c b/refs/files-backend.c index 8d627adf99..6a6ead0b99 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -744,6 +744,11 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator) ref_type(iter->iter0->refname) != REF_TYPE_PER_WORKTREE) continue; + if ((iter->flags & DO_FOR_EACH_OMIT_DANGLING_SYMREFS) && + (iter->iter0->flags & REF_ISSYMREF) && + (iter->iter0->flags & REF_ISBROKEN)) + continue; + if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) && !ref_resolves_to_object(iter->iter0->refname, iter->iter0->oid, diff --git a/refs/refs-internal.h b/refs/refs-internal.h index ddd6d7f8eb..72746407fc 100644 --- a/refs/refs-internal.h +++ b/refs/refs-internal.h @@ -245,8 +245,36 @@ int refs_rename_ref_available(struct ref_store *refs, /* We allow "recursive" symbolic refs. Only within reason, though */ #define SYMREF_MAXDEPTH 5 -/* Include broken references in a do_for_each_ref*() iteration: */ -#define DO_FOR_EACH_INCLUDE_BROKEN 0x01 +/* + * These flags are passed to refs_ref_iterator_begin() (and do_for_each_ref(), + * which feeds it). + */ +enum do_for_each_ref_flags { + /* + * Include broken references in a do_for_each_ref*() iteration, which + * would normally be omitted. This includes both refs that point to + * missing objects (a true repository corruption), ones with illegal + * names (which we prefer not to expose to callers), as well as + * dangling symbolic refs (i.e., those that point to a non-existent + * ref; this is not a corruption, but as they have no valid oid, we + * omit them from normal iteration results). + */ + DO_FOR_EACH_INCLUDE_BROKEN = (1 << 0), + + /* + * Only include per-worktree refs in a do_for_each_ref*() iteration. + * Normally this will be used with a files ref_store, since that's + * where all reference backends will presumably store their + * per-worktree refs. + */ + DO_FOR_EACH_PER_WORKTREE_ONLY = (1 << 1), + + /* + * Omit dangling symrefs from output; this only has an effect with + * INCLUDE_BROKEN, since they are otherwise not included at all. + */ + DO_FOR_EACH_OMIT_DANGLING_SYMREFS = (1 << 2), +}; /* * Reference iterators @@ -349,16 +377,12 @@ int is_empty_ref_iterator(struct ref_iterator *ref_iterator); * Return an iterator that goes over each reference in `refs` for * which the refname begins with prefix. If trim is non-zero, then * trim that many characters off the beginning of each refname. - * The output is ordered by refname. The following flags are supported: - * - * DO_FOR_EACH_INCLUDE_BROKEN: include broken references in - * the iteration. - * - * DO_FOR_EACH_PER_WORKTREE_ONLY: only produce REF_TYPE_PER_WORKTREE refs. + * The output is ordered by refname. */ struct ref_iterator *refs_ref_iterator_begin( struct ref_store *refs, - const char *prefix, int trim, int flags); + const char *prefix, int trim, + enum do_for_each_ref_flags flags); /* * A callback function used to instruct merge_ref_iterator how to @@ -446,10 +470,8 @@ void base_ref_iterator_free(struct ref_iterator *iter); /* * backend-specific implementation of ref_iterator_advance. For symrefs, the * function should set REF_ISSYMREF, and it should also dereference the symref - * to provide the OID referent. If DO_FOR_EACH_INCLUDE_BROKEN is set, symrefs - * with non-existent referents and refs pointing to non-existent object names - * should also be returned. If DO_FOR_EACH_PER_WORKTREE_ONLY, only - * REF_TYPE_PER_WORKTREE refs should be returned. + * to provide the OID referent. It should respect do_for_each_ref_flags + * that were passed to refs_ref_iterator_begin(). */ typedef int ref_iterator_advance_fn(struct ref_iterator *ref_iterator); @@ -498,14 +520,6 @@ int do_for_each_repo_ref_iterator(struct repository *r, struct ref_iterator *iter, each_repo_ref_fn fn, void *cb_data); -/* - * Only include per-worktree refs in a do_for_each_ref*() iteration. - * Normally this will be used with a files ref_store, since that's - * where all reference backends will presumably store their - * per-worktree refs. - */ -#define DO_FOR_EACH_PER_WORKTREE_ONLY 0x02 - struct ref_store; /* refs backends */ diff --git a/revision.c b/revision.c index 7e7c41fedd..3ad217f2ff 100644 --- a/revision.c +++ b/revision.c @@ -2548,7 +2548,7 @@ static int for_each_bisect_ref(struct ref_store *refs, each_ref_fn fn, struct strbuf bisect_refs = STRBUF_INIT; int status; strbuf_addf(&bisect_refs, "refs/bisect/%s", term); - status = refs_for_each_fullref_in(refs, bisect_refs.buf, fn, cb_data, 0); + status = refs_for_each_fullref_in(refs, bisect_refs.buf, fn, cb_data); strbuf_release(&bisect_refs); return status; } diff --git a/t/t1430-bad-ref-name.sh b/t/t1430-bad-ref-name.sh index b1839e0877..fa3aeb80f2 100755 --- a/t/t1430-bad-ref-name.sh +++ b/t/t1430-bad-ref-name.sh @@ -170,7 +170,7 @@ test_expect_success 'for-each-ref emits warnings for broken names' ' ! grep -e "badname" output && ! grep -e "broken\.\.\.symref" output && test_i18ngrep "ignoring ref with broken name refs/heads/broken\.\.\.ref" error && - test_i18ngrep "ignoring broken ref refs/heads/badname" error && + test_i18ngrep ! "ignoring broken ref refs/heads/badname" error && test_i18ngrep "ignoring ref with broken name refs/heads/broken\.\.\.symref" error ' diff --git a/t/t5312-prune-corruption.sh b/t/t5312-prune-corruption.sh index 11423b3cb2..ea889c088a 100755 --- a/t/t5312-prune-corruption.sh +++ b/t/t5312-prune-corruption.sh @@ -7,6 +7,9 @@ if we see, for example, a ref with a bogus name, it is OK either to bail out or to proceed using it as a reachable tip, but it is _not_ OK to proceed as if it did not exist. Otherwise we might silently delete objects that cannot be recovered. + +Note that we do assert command failure in these cases, because that is +what currently happens. If that changes, these tests should be revisited. ' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME @@ -18,39 +21,58 @@ test_expect_success 'disable reflogs' ' git reflog expire --expire=all --all ' +create_bogus_ref () { + test_when_finished 'rm -f .git/refs/heads/bogus..name' && + echo $bogus >.git/refs/heads/bogus..name +} + test_expect_success 'create history reachable only from a bogus-named ref' ' test_tick && git commit --allow-empty -m main && base=$(git rev-parse HEAD) && test_tick && git commit --allow-empty -m bogus && bogus=$(git rev-parse HEAD) && git cat-file commit $bogus >saved && - echo $bogus >.git/refs/heads/bogus..name && git reset --hard HEAD^ ' test_expect_success 'pruning does not drop bogus object' ' test_when_finished "git hash-object -w -t commit saved" && - test_might_fail git prune --expire=now && - verbose git cat-file -e $bogus + create_bogus_ref && + test_must_fail git prune --expire=now && + git cat-file -e $bogus ' test_expect_success 'put bogus object into pack' ' git tag reachable $bogus && git repack -ad && git tag -d reachable && - verbose git cat-file -e $bogus + git cat-file -e $bogus ' +test_expect_success 'non-destructive repack bails on bogus ref' ' + create_bogus_ref && + test_must_fail git repack -adk +' + +test_expect_success 'GIT_REF_PARANOIA=0 overrides safety' ' + create_bogus_ref && + GIT_REF_PARANOIA=0 git repack -adk +' + + test_expect_success 'destructive repack keeps packed object' ' - test_might_fail git repack -Ad --unpack-unreachable=now && - verbose git cat-file -e $bogus && - test_might_fail git repack -ad && - verbose git cat-file -e $bogus + create_bogus_ref && + test_must_fail git repack -Ad --unpack-unreachable=now && + git cat-file -e $bogus && + test_must_fail git repack -ad && + git cat-file -e $bogus ' -# subsequent tests will have different corruptions -test_expect_success 'clean up bogus ref' ' - rm .git/refs/heads/bogus..name +test_expect_success 'destructive repack not confused by dangling symref' ' + test_when_finished "git symbolic-ref -d refs/heads/dangling" && + git symbolic-ref refs/heads/dangling refs/heads/does-not-exist && + git repack -ad && + test_must_fail git cat-file -e $bogus ' # We create two new objects here, "one" and "two". Our @@ -77,8 +99,8 @@ test_expect_success 'create history with missing tip commit' ' test_expect_success 'pruning with a corrupted tip does not drop history' ' test_when_finished "git hash-object -w -t commit saved" && - test_might_fail git prune --expire=now && - verbose git cat-file -e $recoverable + test_must_fail git prune --expire=now && + git cat-file -e $recoverable ' test_expect_success 'pack-refs does not silently delete broken loose ref' ' diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 4db8edd9c8..8212ca56dc 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -662,10 +662,10 @@ test_expect_success 'push does not update local refs on failure' ' test_expect_success 'allow deleting an invalid remote ref' ' - mk_test testrepo heads/main && + mk_test testrepo heads/branch && rm -f testrepo/.git/objects/??/* && - git push testrepo :refs/heads/main && - (cd testrepo && test_must_fail git rev-parse --verify refs/heads/main) + git push testrepo :refs/heads/branch && + (cd testrepo && test_must_fail git rev-parse --verify refs/heads/branch) ' @@ -706,25 +706,26 @@ test_expect_success 'pushing valid refs triggers post-receive and post-update ho ' test_expect_success 'deleting dangling ref triggers hooks with correct args' ' - mk_test_with_hooks testrepo heads/main && + mk_test_with_hooks testrepo heads/branch && + orig=$(git -C testrepo rev-parse refs/heads/branch) && rm -f testrepo/.git/objects/??/* && - git push testrepo :refs/heads/main && + git push testrepo :refs/heads/branch && ( cd testrepo/.git && cat >pre-receive.expect <<-EOF && - $ZERO_OID $ZERO_OID refs/heads/main + $orig $ZERO_OID refs/heads/branch EOF cat >update.expect <<-EOF && - refs/heads/main $ZERO_OID $ZERO_OID + refs/heads/branch $orig $ZERO_OID EOF cat >post-receive.expect <<-EOF && - $ZERO_OID $ZERO_OID refs/heads/main + $orig $ZERO_OID refs/heads/branch EOF cat >post-update.expect <<-EOF && - refs/heads/main + refs/heads/branch EOF test_cmp pre-receive.expect pre-receive.actual && diff --git a/t/t5600-clone-fail-cleanup.sh b/t/t5600-clone-fail-cleanup.sh index 5bf10261d3..34b3df4027 100755 --- a/t/t5600-clone-fail-cleanup.sh +++ b/t/t5600-clone-fail-cleanup.sh @@ -35,7 +35,9 @@ test_expect_success 'create a repo to clone' ' ' test_expect_success 'create objects in repo for later corruption' ' - test_commit -C foo file + test_commit -C foo file && + git -C foo checkout --detach && + test_commit -C foo detached ' # source repository given to git clone should be relative to the diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh index 6b4941980c..9b9f11a8e7 100755 --- a/t/t7900-maintenance.sh +++ b/t/t7900-maintenance.sh @@ -276,7 +276,7 @@ test_expect_success 'incremental-repack task' ' # Delete refs that have not been repacked in these packs. git for-each-ref --format="delete %(refname)" \ - refs/prefetch refs/tags >refs && + refs/prefetch refs/tags refs/remotes >refs && git update-ref --stdin packs-before && test_line_count = 3 packs-before && + # make sure we do not have any broken refs that were + # missed in the deletion above + git for-each-ref && + # the job repacks the two into a new pack, but does not # delete the old ones. git maintenance run --task=incremental-repack &&