From 93db6eef04539e822b6786ae12f1ea4db75635bb Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Tue, 7 Dec 2021 13:38:13 +0000 Subject: [PATCH 1/8] test-ref-store: remove force-create argument for create-reflog Nobody uses force_create=0, so this flag is unnecessary. Signed-off-by: Han-Wen Nienhuys Signed-off-by: Junio C Hamano --- t/helper/test-ref-store.c | 2 +- t/t1405-main-ref-store.sh | 5 ++--- t/t1406-submodule-ref-store.sh | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index 3986665037a..b795a56eedf 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -182,9 +182,9 @@ static int cmd_reflog_exists(struct ref_store *refs, const char **argv) static int cmd_create_reflog(struct ref_store *refs, const char **argv) { const char *refname = notnull(*argv++, "refname"); - int force_create = arg_flags(*argv++, "force-create"); struct strbuf err = STRBUF_INIT; int ret; + int force_create = 1; ret = refs_create_reflog(refs, refname, force_create, &err); if (err.len) diff --git a/t/t1405-main-ref-store.sh b/t/t1405-main-ref-store.sh index 49718b7ea7f..5e0f7073286 100755 --- a/t/t1405-main-ref-store.sh +++ b/t/t1405-main-ref-store.sh @@ -35,8 +35,7 @@ test_expect_success 'delete_refs(FOO, refs/tags/new-tag)' ' git rev-parse FOO -- && git rev-parse refs/tags/new-tag -- && m=$(git rev-parse main) && - REF_NO_DEREF=1 && - $RUN delete-refs $REF_NO_DEREF nothing FOO refs/tags/new-tag && + $RUN delete-refs REF_NO_DEREF nothing FOO refs/tags/new-tag && test_must_fail git rev-parse --symbolic-full-name FOO && test_must_fail git rev-parse FOO -- && test_must_fail git rev-parse refs/tags/new-tag -- @@ -108,7 +107,7 @@ test_expect_success 'delete_reflog(HEAD)' ' ' test_expect_success 'create-reflog(HEAD)' ' - $RUN create-reflog HEAD 1 && + $RUN create-reflog HEAD && git reflog exists HEAD ' diff --git a/t/t1406-submodule-ref-store.sh b/t/t1406-submodule-ref-store.sh index 0a87058971e..f1e57a9c051 100755 --- a/t/t1406-submodule-ref-store.sh +++ b/t/t1406-submodule-ref-store.sh @@ -92,7 +92,7 @@ test_expect_success 'delete_reflog() not allowed' ' ' test_expect_success 'create-reflog() not allowed' ' - test_must_fail $RUN create-reflog HEAD 1 + test_must_fail $RUN create-reflog HEAD ' test_done From cd2d40fb7f1f9e12b13937789bbf5573f2041cde Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Tue, 7 Dec 2021 13:38:14 +0000 Subject: [PATCH 2/8] test-ref-store: parse symbolic flag constants This lets tests use REF_XXXX constants instead of hardcoded integers. The flag names should be separated by a ','. Signed-off-by: Han-Wen Nienhuys Signed-off-by: Junio C Hamano --- t/helper/test-ref-store.c | 66 ++++++++++++++++++++++++++++++++++----- t/t1405-main-ref-store.sh | 3 +- 2 files changed, 60 insertions(+), 9 deletions(-) diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index b795a56eedf..abb0ba101ae 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -5,6 +5,48 @@ #include "object-store.h" #include "repository.h" +struct flag_definition { + const char *name; + uint64_t mask; +}; + +#define FLAG_DEF(x) \ + { \ +#x, (x) \ + } + +static unsigned int parse_flags(const char *str, struct flag_definition *defs) +{ + struct string_list masks = STRING_LIST_INIT_DUP; + int i = 0; + unsigned int result = 0; + + if (!strcmp(str, "0")) + return 0; + + string_list_split(&masks, str, ',', 64); + for (; i < masks.nr; i++) { + const char *name = masks.items[i].string; + struct flag_definition *def = defs; + int found = 0; + while (def->name) { + if (!strcmp(def->name, name)) { + result |= def->mask; + found = 1; + break; + } + def++; + } + if (!found) + die("unknown flag \"%s\"", name); + } + + string_list_clear(&masks, 0); + return result; +} + +static struct flag_definition empty_flags[] = { { NULL, 0 } }; + static const char *notnull(const char *arg, const char *name) { if (!arg) @@ -12,9 +54,10 @@ static const char *notnull(const char *arg, const char *name) return arg; } -static unsigned int arg_flags(const char *arg, const char *name) +static unsigned int arg_flags(const char *arg, const char *name, + struct flag_definition *defs) { - return atoi(notnull(arg, name)); + return parse_flags(notnull(arg, name), defs); } static const char **get_store(const char **argv, struct ref_store **refs) @@ -64,10 +107,13 @@ static const char **get_store(const char **argv, struct ref_store **refs) return argv + 1; } +static struct flag_definition pack_flags[] = { FLAG_DEF(PACK_REFS_PRUNE), + FLAG_DEF(PACK_REFS_ALL), + { NULL, 0 } }; static int cmd_pack_refs(struct ref_store *refs, const char **argv) { - unsigned int flags = arg_flags(*argv++, "flags"); + unsigned int flags = arg_flags(*argv++, "flags", pack_flags); return refs_pack_refs(refs, flags); } @@ -81,9 +127,15 @@ static int cmd_create_symref(struct ref_store *refs, const char **argv) return refs_create_symref(refs, refname, target, logmsg); } +static struct flag_definition transaction_flags[] = { + FLAG_DEF(REF_NO_DEREF), + FLAG_DEF(REF_FORCE_CREATE_REFLOG), + { NULL, 0 } +}; + static int cmd_delete_refs(struct ref_store *refs, const char **argv) { - unsigned int flags = arg_flags(*argv++, "flags"); + unsigned int flags = arg_flags(*argv++, "flags", transaction_flags); const char *msg = *argv++; struct string_list refnames = STRING_LIST_INIT_NODUP; @@ -120,7 +172,7 @@ static int cmd_resolve_ref(struct ref_store *refs, const char **argv) { struct object_id oid = *null_oid(); const char *refname = notnull(*argv++, "refname"); - int resolve_flags = arg_flags(*argv++, "resolve-flags"); + int resolve_flags = arg_flags(*argv++, "resolve-flags", empty_flags); int flags; const char *ref; int ignore_errno; @@ -209,7 +261,7 @@ static int cmd_delete_ref(struct ref_store *refs, const char **argv) const char *msg = notnull(*argv++, "msg"); const char *refname = notnull(*argv++, "refname"); const char *sha1_buf = notnull(*argv++, "old-sha1"); - unsigned int flags = arg_flags(*argv++, "flags"); + unsigned int flags = arg_flags(*argv++, "flags", transaction_flags); struct object_id old_oid; if (get_oid_hex(sha1_buf, &old_oid)) @@ -224,7 +276,7 @@ static int cmd_update_ref(struct ref_store *refs, const char **argv) const char *refname = notnull(*argv++, "refname"); const char *new_sha1_buf = notnull(*argv++, "new-sha1"); const char *old_sha1_buf = notnull(*argv++, "old-sha1"); - unsigned int flags = arg_flags(*argv++, "flags"); + unsigned int flags = arg_flags(*argv++, "flags", transaction_flags); struct object_id old_oid; struct object_id new_oid; diff --git a/t/t1405-main-ref-store.sh b/t/t1405-main-ref-store.sh index 5e0f7073286..63e0ae82bdf 100755 --- a/t/t1405-main-ref-store.sh +++ b/t/t1405-main-ref-store.sh @@ -17,8 +17,7 @@ test_expect_success 'setup' ' test_expect_success REFFILES 'pack_refs(PACK_REFS_ALL | PACK_REFS_PRUNE)' ' N=`find .git/refs -type f | wc -l` && test "$N" != 0 && - ALL_OR_PRUNE_FLAG=3 && - $RUN pack-refs ${ALL_OR_PRUNE_FLAG} && + $RUN pack-refs PACK_REFS_PRUNE,PACK_REFS_ALL && N=`find .git/refs -type f` && test -z "$N" ' From df25a19d7287798a4ab2b5df08377fe7492a3846 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Tue, 7 Dec 2021 13:38:15 +0000 Subject: [PATCH 3/8] test-ref-store: plug memory leak in cmd_delete_refs Signed-off-by: Han-Wen Nienhuys Signed-off-by: Junio C Hamano --- t/helper/test-ref-store.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index abb0ba101ae..8fee3cfce1a 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -138,11 +138,14 @@ static int cmd_delete_refs(struct ref_store *refs, const char **argv) unsigned int flags = arg_flags(*argv++, "flags", transaction_flags); const char *msg = *argv++; struct string_list refnames = STRING_LIST_INIT_NODUP; + int result; while (*argv) string_list_append(&refnames, *argv++); - return refs_delete_refs(refs, msg, &refnames, flags); + result = refs_delete_refs(refs, msg, &refnames, flags); + string_list_clear(&refnames, 0); + return result; } static int cmd_rename_ref(struct ref_store *refs, const char **argv) From 0464d0a134df97c3f9475c58e536c3b685a3ff7d Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Tue, 7 Dec 2021 13:38:16 +0000 Subject: [PATCH 4/8] refs: update comment. REF_IS_PRUNING is right below this comment, so it clearly does not belong in this comment. This was apparently introduced in commit 5ac95fee (Nov 5, 2017 "refs: tidy up and adjust visibility of the `ref_update` flags"). Signed-off-by: Han-Wen Nienhuys Signed-off-by: Junio C Hamano --- refs/files-backend.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/refs/files-backend.c b/refs/files-backend.c index 4b14f30d48f..37329b98cca 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -16,8 +16,7 @@ * This backend uses the following flags in `ref_update::flags` for * internal bookkeeping purposes. Their numerical values must not * conflict with REF_NO_DEREF, REF_FORCE_CREATE_REFLOG, REF_HAVE_NEW, - * REF_HAVE_OLD, or REF_IS_PRUNING, which are also stored in - * `ref_update::flags`. + * or REF_HAVE_OLD, which are also stored in `ref_update::flags`. */ /* From e9706a188f8598ea4d8afac1f70360abb77d4d8d Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Tue, 7 Dec 2021 13:38:17 +0000 Subject: [PATCH 5/8] refs: introduce REF_SKIP_OID_VERIFICATION flag This lets the ref-store test helper write non-existent or unparsable objects into the ref storage. Use this to make t1006 and t3800 independent of the files storage backend. Signed-off-by: Han-Wen Nienhuys Signed-off-by: Junio C Hamano --- refs.h | 8 ++++++- refs/files-backend.c | 50 +++++++++++++++++++++++---------------- t/helper/test-ref-store.c | 1 + t/t1006-cat-file.sh | 5 ++-- t/t3800-mktag.sh | 6 +++-- 5 files changed, 43 insertions(+), 27 deletions(-) diff --git a/refs.h b/refs.h index 45c34e99e3a..76efc589cca 100644 --- a/refs.h +++ b/refs.h @@ -615,12 +615,18 @@ struct ref_transaction *ref_transaction_begin(struct strbuf *err); */ #define REF_FORCE_CREATE_REFLOG (1 << 1) +/* + * Blindly write an object_id. This is useful for testing data corruption + * scenarios. + */ +#define REF_SKIP_OID_VERIFICATION (1 << 10) + /* * Bitmask of all of the flags that are allowed to be passed in to * ref_transaction_update() and friends: */ #define REF_TRANSACTION_UPDATE_ALLOWED_FLAGS \ - (REF_NO_DEREF | REF_FORCE_CREATE_REFLOG) + (REF_NO_DEREF | REF_FORCE_CREATE_REFLOG | REF_SKIP_OID_VERIFICATION) /* * Add a reference update to transaction. `new_oid` is the value that diff --git a/refs/files-backend.c b/refs/files-backend.c index 37329b98cca..d0019fcd8b7 100644 --- a/refs/files-backend.c +++ b/refs/files-backend.c @@ -1353,7 +1353,8 @@ static int rename_tmp_log(struct files_ref_store *refs, const char *newrefname) } static int write_ref_to_lockfile(struct ref_lock *lock, - const struct object_id *oid, struct strbuf *err); + const struct object_id *oid, + int skip_oid_verification, struct strbuf *err); static int commit_ref_update(struct files_ref_store *refs, struct ref_lock *lock, const struct object_id *oid, const char *logmsg, @@ -1500,7 +1501,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store, } oidcpy(&lock->old_oid, &orig_oid); - if (write_ref_to_lockfile(lock, &orig_oid, &err) || + if (write_ref_to_lockfile(lock, &orig_oid, 0, &err) || commit_ref_update(refs, lock, &orig_oid, logmsg, &err)) { error("unable to write current sha1 into %s: %s", newrefname, err.buf); strbuf_release(&err); @@ -1520,7 +1521,7 @@ static int files_copy_or_rename_ref(struct ref_store *ref_store, flag = log_all_ref_updates; log_all_ref_updates = LOG_REFS_NONE; - if (write_ref_to_lockfile(lock, &orig_oid, &err) || + if (write_ref_to_lockfile(lock, &orig_oid, 0, &err) || commit_ref_update(refs, lock, &orig_oid, NULL, &err)) { error("unable to write current sha1 into %s: %s", oldrefname, err.buf); strbuf_release(&err); @@ -1756,26 +1757,31 @@ static int files_log_ref_write(struct files_ref_store *refs, * errors, rollback the lockfile, fill in *err and return -1. */ static int write_ref_to_lockfile(struct ref_lock *lock, - const struct object_id *oid, struct strbuf *err) + const struct object_id *oid, + int skip_oid_verification, struct strbuf *err) { static char term = '\n'; struct object *o; int fd; - o = parse_object(the_repository, oid); - if (!o) { - strbuf_addf(err, - "trying to write ref '%s' with nonexistent object %s", - lock->ref_name, oid_to_hex(oid)); - unlock_ref(lock); - return -1; - } - if (o->type != OBJ_COMMIT && is_branch(lock->ref_name)) { - strbuf_addf(err, - "trying to write non-commit object %s to branch '%s'", - oid_to_hex(oid), lock->ref_name); - unlock_ref(lock); - return -1; + if (!skip_oid_verification) { + o = parse_object(the_repository, oid); + if (!o) { + strbuf_addf( + err, + "trying to write ref '%s' with nonexistent object %s", + lock->ref_name, oid_to_hex(oid)); + unlock_ref(lock); + return -1; + } + if (o->type != OBJ_COMMIT && is_branch(lock->ref_name)) { + strbuf_addf( + err, + "trying to write non-commit object %s to branch '%s'", + oid_to_hex(oid), lock->ref_name); + unlock_ref(lock); + return -1; + } } fd = get_lock_file_fd(&lock->lk); if (write_in_full(fd, oid_to_hex(oid), the_hash_algo->hexsz) < 0 || @@ -2189,7 +2195,7 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator) } static int files_reflog_iterator_peel(struct ref_iterator *ref_iterator, - struct object_id *peeled) + struct object_id *peeled) { BUG("ref_iterator_peel() called for reflog_iterator"); } @@ -2575,8 +2581,10 @@ static int lock_ref_for_update(struct files_ref_store *refs, * The reference already has the desired * value, so we don't need to write it. */ - } else if (write_ref_to_lockfile(lock, &update->new_oid, - err)) { + } else if (write_ref_to_lockfile( + lock, &update->new_oid, + update->flags & REF_SKIP_OID_VERIFICATION, + err)) { char *write_err = strbuf_detach(err, NULL); /* diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index 8fee3cfce1a..0f3aa84c9f0 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -130,6 +130,7 @@ static int cmd_create_symref(struct ref_store *refs, const char **argv) static struct flag_definition transaction_flags[] = { FLAG_DEF(REF_NO_DEREF), FLAG_DEF(REF_FORCE_CREATE_REFLOG), + FLAG_DEF(REF_SKIP_OID_VERIFICATION), { NULL, 0 } }; diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh index 658628375c8..0d4c55f74ec 100755 --- a/t/t1006-cat-file.sh +++ b/t/t1006-cat-file.sh @@ -452,9 +452,8 @@ test_expect_success 'the --allow-unknown-type option does not consider replaceme # Create it manually, as "git replace" will die on bogus # types. head=$(git rev-parse --verify HEAD) && - test_when_finished "rm -rf .git/refs/replace" && - mkdir -p .git/refs/replace && - echo $head >.git/refs/replace/$bogus_short_sha1 && + test_when_finished "test-tool ref-store main delete-refs 0 msg refs/replace/$bogus_short_sha1" && + test-tool ref-store main update-ref msg "refs/replace/$bogus_short_sha1" $head $ZERO_OID REF_SKIP_OID_VERIFICATION && cat >expect <<-EOF && commit diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh index 0544d58a6ea..e3cf0ffbe59 100755 --- a/t/t3800-mktag.sh +++ b/t/t3800-mktag.sh @@ -72,7 +72,8 @@ check_verify_failure () { # Manually create the broken, we cannot do it with # update-ref - echo "$bad_tag" >"bad-tag/$tag_ref" && + test-tool -C bad-tag ref-store main delete-refs 0 msg "$tag_ref" && + test-tool -C bad-tag ref-store main update-ref msg "$tag_ref" $bad_tag $ZERO_OID REF_SKIP_OID_VERIFICATION && # Unlike fsck-ing unreachable content above, this # will always fail. @@ -83,7 +84,8 @@ check_verify_failure () { # Make sure the earlier test created it for us git rev-parse "$bad_tag" && - echo "$bad_tag" >"bad-tag/$tag_ref" && + test-tool -C bad-tag ref-store main delete-refs 0 msg "$tag_ref" && + test-tool -C bad-tag ref-store main update-ref msg "$tag_ref" $bad_tag $ZERO_OID REF_SKIP_OID_VERIFICATION && printf "%s tag\t%s\n" "$bad_tag" "$tag_ref" >expected && git -C bad-tag for-each-ref "$tag_ref" >actual && From 3c966c7b4e97a5399662f85ab73af08a6419a303 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Tue, 7 Dec 2021 13:38:18 +0000 Subject: [PATCH 6/8] refs: introduce REF_SKIP_REFNAME_VERIFICATION flag Use this flag with the test-helper in t1430, to avoid direct writes to the ref database. Signed-off-by: Han-Wen Nienhuys Signed-off-by: Junio C Hamano --- refs.c | 7 +++-- refs.h | 10 +++++-- t/helper/test-ref-store.c | 1 + t/t1430-bad-ref-name.sh | 59 +++++++++++++++++++++------------------ 4 files changed, 45 insertions(+), 32 deletions(-) diff --git a/refs.c b/refs.c index 996ac271641..93bfe5b30cf 100644 --- a/refs.c +++ b/refs.c @@ -1083,9 +1083,10 @@ int ref_transaction_update(struct ref_transaction *transaction, { assert(err); - if ((new_oid && !is_null_oid(new_oid)) ? - check_refname_format(refname, REFNAME_ALLOW_ONELEVEL) : - !refname_is_safe(refname)) { + if (!(flags & REF_SKIP_REFNAME_VERIFICATION) && + ((new_oid && !is_null_oid(new_oid)) ? + check_refname_format(refname, REFNAME_ALLOW_ONELEVEL) : + !refname_is_safe(refname))) { strbuf_addf(err, _("refusing to update ref with bad name '%s'"), refname); return -1; diff --git a/refs.h b/refs.h index 76efc589cca..65017ceaefc 100644 --- a/refs.h +++ b/refs.h @@ -621,12 +621,18 @@ struct ref_transaction *ref_transaction_begin(struct strbuf *err); */ #define REF_SKIP_OID_VERIFICATION (1 << 10) +/* + * Skip verifying refname. This is useful for testing data corruption scenarios. + */ +#define REF_SKIP_REFNAME_VERIFICATION (1 << 11) + /* * Bitmask of all of the flags that are allowed to be passed in to * ref_transaction_update() and friends: */ -#define REF_TRANSACTION_UPDATE_ALLOWED_FLAGS \ - (REF_NO_DEREF | REF_FORCE_CREATE_REFLOG | REF_SKIP_OID_VERIFICATION) +#define REF_TRANSACTION_UPDATE_ALLOWED_FLAGS \ + (REF_NO_DEREF | REF_FORCE_CREATE_REFLOG | REF_SKIP_OID_VERIFICATION | \ + REF_SKIP_REFNAME_VERIFICATION) /* * Add a reference update to transaction. `new_oid` is the value that diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index 0f3aa84c9f0..8bca4f2af1b 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -131,6 +131,7 @@ static struct flag_definition transaction_flags[] = { FLAG_DEF(REF_NO_DEREF), FLAG_DEF(REF_FORCE_CREATE_REFLOG), FLAG_DEF(REF_SKIP_OID_VERIFICATION), + FLAG_DEF(REF_SKIP_REFNAME_VERIFICATION), { NULL, 0 } }; diff --git a/t/t1430-bad-ref-name.sh b/t/t1430-bad-ref-name.sh index 4c77cf89a6c..326e5bd5e80 100755 --- a/t/t1430-bad-ref-name.sh +++ b/t/t1430-bad-ref-name.sh @@ -9,7 +9,8 @@ TEST_PASSES_SANITIZE_LEAK=true test_expect_success setup ' test_commit one && - test_commit two + test_commit two && + main_sha1=$(git rev-parse refs/heads/main) ' test_expect_success 'fast-import: fail on invalid branch name ".badbranchname"' ' @@ -43,16 +44,16 @@ test_expect_success 'fast-import: fail on invalid branch name "bad[branch]name"' ' test_expect_success 'git branch shows badly named ref as warning' ' - cp .git/refs/heads/main .git/refs/heads/broken...ref && - test_when_finished "rm -f .git/refs/heads/broken...ref" && + test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && git branch >output 2>error && test_i18ngrep -e "ignoring ref with broken name refs/heads/broken\.\.\.ref" error && ! grep -e "broken\.\.\.ref" output ' test_expect_success 'branch -d can delete badly named ref' ' - cp .git/refs/heads/main .git/refs/heads/broken...ref && - test_when_finished "rm -f .git/refs/heads/broken...ref" && + test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && git branch -d broken...ref && git branch >output 2>error && ! grep -e "broken\.\.\.ref" error && @@ -60,8 +61,8 @@ test_expect_success 'branch -d can delete badly named ref' ' ' test_expect_success 'branch -D can delete badly named ref' ' - cp .git/refs/heads/main .git/refs/heads/broken...ref && - test_when_finished "rm -f .git/refs/heads/broken...ref" && + test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && git branch -D broken...ref && git branch >output 2>error && ! grep -e "broken\.\.\.ref" error && @@ -90,7 +91,7 @@ test_expect_success 'branch -D cannot delete absolute path' ' ' test_expect_success 'git branch cannot create a badly named ref' ' - test_when_finished "rm -f .git/refs/heads/broken...ref" && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && test_must_fail git branch broken...ref && git branch >output 2>error && ! grep -e "broken\.\.\.ref" error && @@ -98,7 +99,7 @@ test_expect_success 'git branch cannot create a badly named ref' ' ' test_expect_success 'branch -m cannot rename to a bad ref name' ' - test_when_finished "rm -f .git/refs/heads/broken...ref" && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && test_might_fail git branch -D goodref && git branch goodref && test_must_fail git branch -m goodref broken...ref && @@ -109,8 +110,9 @@ test_expect_success 'branch -m cannot rename to a bad ref name' ' ' test_expect_failure 'branch -m can rename from a bad ref name' ' - cp .git/refs/heads/main .git/refs/heads/broken...ref && - test_when_finished "rm -f .git/refs/heads/broken...ref" && + test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && + + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && git branch -m broken...ref renamed && test_cmp_rev main renamed && git branch >output 2>error && @@ -119,7 +121,7 @@ test_expect_failure 'branch -m can rename from a bad ref name' ' ' test_expect_success 'push cannot create a badly named ref' ' - test_when_finished "rm -f .git/refs/heads/broken...ref" && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && test_must_fail git push "file://$(pwd)" HEAD:refs/heads/broken...ref && git branch >output 2>error && ! grep -e "broken\.\.\.ref" error && @@ -139,7 +141,7 @@ test_expect_failure 'push --mirror can delete badly named ref' ' cd dest && test_commit two && git checkout --detach && - cp .git/refs/heads/main .git/refs/heads/broken...ref + test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION ) && git -C src push --mirror "file://$top/dest" && git -C dest branch >output 2>error && @@ -148,9 +150,9 @@ test_expect_failure 'push --mirror can delete badly named ref' ' ' test_expect_success 'rev-parse skips symref pointing to broken name' ' - test_when_finished "rm -f .git/refs/heads/broken...ref" && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && git branch shadow one && - cp .git/refs/heads/main .git/refs/heads/broken...ref && + test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && printf "ref: refs/heads/broken...ref\n" >.git/refs/tags/shadow && test_when_finished "rm -f .git/refs/tags/shadow" && git rev-parse --verify one >expect && @@ -160,8 +162,8 @@ test_expect_success 'rev-parse skips symref pointing to broken name' ' ' test_expect_success 'for-each-ref emits warnings for broken names' ' - cp .git/refs/heads/main .git/refs/heads/broken...ref && - test_when_finished "rm -f .git/refs/heads/broken...ref" && + test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && printf "ref: refs/heads/broken...ref\n" >.git/refs/heads/badname && test_when_finished "rm -f .git/refs/heads/badname" && printf "ref: refs/heads/main\n" >.git/refs/heads/broken...symref && @@ -176,8 +178,8 @@ test_expect_success 'for-each-ref emits warnings for broken names' ' ' test_expect_success 'update-ref -d can delete broken name' ' - cp .git/refs/heads/main .git/refs/heads/broken...ref && - test_when_finished "rm -f .git/refs/heads/broken...ref" && + test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && git update-ref -d refs/heads/broken...ref >output 2>error && test_must_be_empty output && test_must_be_empty error && @@ -187,8 +189,8 @@ test_expect_success 'update-ref -d can delete broken name' ' ' test_expect_success 'branch -d can delete broken name' ' - cp .git/refs/heads/main .git/refs/heads/broken...ref && - test_when_finished "rm -f .git/refs/heads/broken...ref" && + test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && git branch -d broken...ref >output 2>error && test_i18ngrep "Deleted branch broken...ref (was broken)" output && test_must_be_empty error && @@ -198,8 +200,9 @@ test_expect_success 'branch -d can delete broken name' ' ' test_expect_success 'update-ref --no-deref -d can delete symref to broken name' ' - cp .git/refs/heads/main .git/refs/heads/broken...ref && - test_when_finished "rm -f .git/refs/heads/broken...ref" && + test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && + + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && printf "ref: refs/heads/broken...ref\n" >.git/refs/heads/badname && test_when_finished "rm -f .git/refs/heads/badname" && git update-ref --no-deref -d refs/heads/badname >output 2>error && @@ -209,8 +212,9 @@ test_expect_success 'update-ref --no-deref -d can delete symref to broken name' ' test_expect_success 'branch -d can delete symref to broken name' ' - cp .git/refs/heads/main .git/refs/heads/broken...ref && - test_when_finished "rm -f .git/refs/heads/broken...ref" && + test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && + + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && printf "ref: refs/heads/broken...ref\n" >.git/refs/heads/badname && test_when_finished "rm -f .git/refs/heads/badname" && git branch -d badname >output 2>error && @@ -238,8 +242,9 @@ test_expect_success 'branch -d can delete dangling symref to broken name' ' ' test_expect_success 'update-ref -d can delete broken name through symref' ' - cp .git/refs/heads/main .git/refs/heads/broken...ref && - test_when_finished "rm -f .git/refs/heads/broken...ref" && + test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && + + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && printf "ref: refs/heads/broken...ref\n" >.git/refs/heads/badname && test_when_finished "rm -f .git/refs/heads/badname" && git update-ref -d refs/heads/badname >output 2>error && From e39ceeb475ea019e91a3cccacce7ccd807c55bca Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Tue, 7 Dec 2021 13:38:19 +0000 Subject: [PATCH 7/8] t1430: remove refs using test-tool Signed-off-by: Han-Wen Nienhuys Signed-off-by: Junio C Hamano --- t/t1430-bad-ref-name.sh | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/t/t1430-bad-ref-name.sh b/t/t1430-bad-ref-name.sh index 326e5bd5e80..84e912777c5 100755 --- a/t/t1430-bad-ref-name.sh +++ b/t/t1430-bad-ref-name.sh @@ -154,7 +154,7 @@ test_expect_success 'rev-parse skips symref pointing to broken name' ' git branch shadow one && test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && printf "ref: refs/heads/broken...ref\n" >.git/refs/tags/shadow && - test_when_finished "rm -f .git/refs/tags/shadow" && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/tags/shadow" && git rev-parse --verify one >expect && git rev-parse --verify shadow >actual 2>err && test_cmp expect actual && @@ -165,9 +165,9 @@ test_expect_success 'for-each-ref emits warnings for broken names' ' test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && printf "ref: refs/heads/broken...ref\n" >.git/refs/heads/badname && - test_when_finished "rm -f .git/refs/heads/badname" && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/badname" && printf "ref: refs/heads/main\n" >.git/refs/heads/broken...symref && - test_when_finished "rm -f .git/refs/heads/broken...symref" && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...symref" && git for-each-ref >output 2>error && ! grep -e "broken\.\.\.ref" output && ! grep -e "badname" output && @@ -204,7 +204,7 @@ test_expect_success 'update-ref --no-deref -d can delete symref to broken name' test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && printf "ref: refs/heads/broken...ref\n" >.git/refs/heads/badname && - test_when_finished "rm -f .git/refs/heads/badname" && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/badname" && git update-ref --no-deref -d refs/heads/badname >output 2>error && test_path_is_missing .git/refs/heads/badname && test_must_be_empty output && @@ -216,7 +216,7 @@ test_expect_success 'branch -d can delete symref to broken name' ' test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && printf "ref: refs/heads/broken...ref\n" >.git/refs/heads/badname && - test_when_finished "rm -f .git/refs/heads/badname" && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/badname" && git branch -d badname >output 2>error && test_path_is_missing .git/refs/heads/badname && test_i18ngrep "Deleted branch badname (was refs/heads/broken\.\.\.ref)" output && @@ -225,7 +225,7 @@ test_expect_success 'branch -d can delete symref to broken name' ' test_expect_success 'update-ref --no-deref -d can delete dangling symref to broken name' ' printf "ref: refs/heads/broken...ref\n" >.git/refs/heads/badname && - test_when_finished "rm -f .git/refs/heads/badname" && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/badname" && git update-ref --no-deref -d refs/heads/badname >output 2>error && test_path_is_missing .git/refs/heads/badname && test_must_be_empty output && @@ -234,7 +234,7 @@ test_expect_success 'update-ref --no-deref -d can delete dangling symref to brok test_expect_success 'branch -d can delete dangling symref to broken name' ' printf "ref: refs/heads/broken...ref\n" >.git/refs/heads/badname && - test_when_finished "rm -f .git/refs/heads/badname" && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/badname" && git branch -d badname >output 2>error && test_path_is_missing .git/refs/heads/badname && test_i18ngrep "Deleted branch badname (was refs/heads/broken\.\.\.ref)" output && @@ -246,7 +246,7 @@ test_expect_success 'update-ref -d can delete broken name through symref' ' test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && printf "ref: refs/heads/broken...ref\n" >.git/refs/heads/badname && - test_when_finished "rm -f .git/refs/heads/badname" && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/badname" && git update-ref -d refs/heads/badname >output 2>error && test_path_is_missing .git/refs/heads/broken...ref && test_must_be_empty output && @@ -255,7 +255,7 @@ test_expect_success 'update-ref -d can delete broken name through symref' ' test_expect_success 'update-ref --no-deref -d can delete symref with broken name' ' printf "ref: refs/heads/main\n" >.git/refs/heads/broken...symref && - test_when_finished "rm -f .git/refs/heads/broken...symref" && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...symref" && git update-ref --no-deref -d refs/heads/broken...symref >output 2>error && test_path_is_missing .git/refs/heads/broken...symref && test_must_be_empty output && @@ -264,7 +264,7 @@ test_expect_success 'update-ref --no-deref -d can delete symref with broken name test_expect_success 'branch -d can delete symref with broken name' ' printf "ref: refs/heads/main\n" >.git/refs/heads/broken...symref && - test_when_finished "rm -f .git/refs/heads/broken...symref" && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...symref" && git branch -d broken...symref >output 2>error && test_path_is_missing .git/refs/heads/broken...symref && test_i18ngrep "Deleted branch broken...symref (was refs/heads/main)" output && @@ -273,7 +273,7 @@ test_expect_success 'branch -d can delete symref with broken name' ' test_expect_success 'update-ref --no-deref -d can delete dangling symref with broken name' ' printf "ref: refs/heads/idonotexist\n" >.git/refs/heads/broken...symref && - test_when_finished "rm -f .git/refs/heads/broken...symref" && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...symref" && git update-ref --no-deref -d refs/heads/broken...symref >output 2>error && test_path_is_missing .git/refs/heads/broken...symref && test_must_be_empty output && @@ -282,7 +282,7 @@ test_expect_success 'update-ref --no-deref -d can delete dangling symref with br test_expect_success 'branch -d can delete dangling symref with broken name' ' printf "ref: refs/heads/idonotexist\n" >.git/refs/heads/broken...symref && - test_when_finished "rm -f .git/refs/heads/broken...symref" && + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...symref" && git branch -d broken...symref >output 2>error && test_path_is_missing .git/refs/heads/broken...symref && test_i18ngrep "Deleted branch broken...symref (was refs/heads/idonotexist)" output && From 9912391402ad1b910c6d712565553d7e5b22d7e1 Mon Sep 17 00:00:00 2001 From: Han-Wen Nienhuys Date: Tue, 7 Dec 2021 13:38:20 +0000 Subject: [PATCH 8/8] t1430: create valid symrefs using test-helper This still leaves some other direct filesystem access. Currently, the files backend does not allow invalidly named symrefs. Fixes for this are currently in the 'seen' branch Signed-off-by: Han-Wen Nienhuys Signed-off-by: Junio C Hamano --- t/t1430-bad-ref-name.sh | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/t/t1430-bad-ref-name.sh b/t/t1430-bad-ref-name.sh index 84e912777c5..ff1c967d550 100755 --- a/t/t1430-bad-ref-name.sh +++ b/t/t1430-bad-ref-name.sh @@ -153,7 +153,7 @@ test_expect_success 'rev-parse skips symref pointing to broken name' ' test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && git branch shadow one && test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && - printf "ref: refs/heads/broken...ref\n" >.git/refs/tags/shadow && + test-tool ref-store main create-symref refs/tags/shadow refs/heads/broken...ref msg && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/tags/shadow" && git rev-parse --verify one >expect && git rev-parse --verify shadow >actual 2>err && @@ -203,7 +203,7 @@ test_expect_success 'update-ref --no-deref -d can delete symref to broken name' test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && - printf "ref: refs/heads/broken...ref\n" >.git/refs/heads/badname && + test-tool ref-store main create-symref refs/heads/badname refs/heads/broken...ref msg && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/badname" && git update-ref --no-deref -d refs/heads/badname >output 2>error && test_path_is_missing .git/refs/heads/badname && @@ -213,9 +213,8 @@ test_expect_success 'update-ref --no-deref -d can delete symref to broken name' test_expect_success 'branch -d can delete symref to broken name' ' test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && - test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && - printf "ref: refs/heads/broken...ref\n" >.git/refs/heads/badname && + test-tool ref-store main create-symref refs/heads/badname refs/heads/broken...ref msg && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/badname" && git branch -d badname >output 2>error && test_path_is_missing .git/refs/heads/badname && @@ -224,7 +223,7 @@ test_expect_success 'branch -d can delete symref to broken name' ' ' test_expect_success 'update-ref --no-deref -d can delete dangling symref to broken name' ' - printf "ref: refs/heads/broken...ref\n" >.git/refs/heads/badname && + test-tool ref-store main create-symref refs/heads/badname refs/heads/broken...ref msg && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/badname" && git update-ref --no-deref -d refs/heads/badname >output 2>error && test_path_is_missing .git/refs/heads/badname && @@ -233,7 +232,7 @@ test_expect_success 'update-ref --no-deref -d can delete dangling symref to brok ' test_expect_success 'branch -d can delete dangling symref to broken name' ' - printf "ref: refs/heads/broken...ref\n" >.git/refs/heads/badname && + test-tool ref-store main create-symref refs/heads/badname refs/heads/broken...ref msg && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/badname" && git branch -d badname >output 2>error && test_path_is_missing .git/refs/heads/badname && @@ -243,9 +242,8 @@ test_expect_success 'branch -d can delete dangling symref to broken name' ' test_expect_success 'update-ref -d can delete broken name through symref' ' test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && - test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && - printf "ref: refs/heads/broken...ref\n" >.git/refs/heads/badname && + test-tool ref-store main create-symref refs/heads/badname refs/heads/broken...ref msg && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/badname" && git update-ref -d refs/heads/badname >output 2>error && test_path_is_missing .git/refs/heads/broken...ref &&