summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/git.txt19
-rw-r--r--builtin/branch.c2
-rw-r--r--builtin/for-each-ref.c2
-rw-r--r--builtin/prune.c1
-rw-r--r--builtin/repack.c3
-rw-r--r--builtin/rev-parse.c4
-rw-r--r--cache.h8
-rw-r--r--environment.c1
-rw-r--r--ls-refs.c2
-rw-r--r--ref-filter.c22
-rw-r--r--ref-filter.h1
-rw-r--r--refs.c42
-rw-r--r--refs.h9
-rw-r--r--refs/files-backend.c5
-rw-r--r--refs/refs-internal.h56
-rw-r--r--revision.c2
-rwxr-xr-xt/t1430-bad-ref-name.sh2
-rwxr-xr-xt/t5312-prune-corruption.sh48
-rwxr-xr-xt/t5516-fetch-push.sh19
-rwxr-xr-xt/t5600-clone-fail-cleanup.sh4
-rwxr-xr-xt/t7900-maintenance.sh6
21 files changed, 142 insertions, 116 deletions
diff --git a/Documentation/git.txt b/Documentation/git.txt
index abace9e..d63c65e 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 03c7b72..0b7ed82 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 89cb630..642b4b8 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 02c6ab7..485c9a3 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 c1a2090..cb9f4bf 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 22c4e1a..8480a59 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 3e5658c..1e2e6ee 100644
--- a/cache.h
+++ b/cache.h
@@ -995,14 +995,6 @@ 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).
*/
int use_optional_locks(void);
diff --git a/environment.c b/environment.c
index 43bb1b3..9da7f3c 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 73eb7da..5407832 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 93ce2a6..e15f0c4 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 c15dee8..b636f43 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 9339e99..2166f37 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 654310d..d5099d4 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 8d627ad..6a6ead0 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 ddd6d7f..7274640 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 7e7c41f..3ad217f 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 b1839e0..fa3aeb8 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 11423b3..ea889c0 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 4db8edd..8212ca5 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 5bf1026..34b3df4 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 6b49419..9b9f11a 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 <refs &&
# Replace the object directory with this pack layout.
@@ -285,6 +285,10 @@ test_expect_success 'incremental-repack task' '
ls $packDir/*.pack >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 &&