diff options
Diffstat (limited to 't')
43 files changed, 1836 insertions, 209 deletions
diff --git a/t/helper/test-bitmap.c b/t/helper/test-bitmap.c index af43ee1cb5..6af2b42678 100644 --- a/t/helper/test-bitmap.c +++ b/t/helper/test-bitmap.c @@ -13,21 +13,41 @@ static int bitmap_dump_hashes(void) return test_bitmap_hashes(the_repository); } +static int bitmap_dump_pseudo_merges(void) +{ + return test_bitmap_pseudo_merges(the_repository); +} + +static int bitmap_dump_pseudo_merge_commits(uint32_t n) +{ + return test_bitmap_pseudo_merge_commits(the_repository, n); +} + +static int bitmap_dump_pseudo_merge_objects(uint32_t n) +{ + return test_bitmap_pseudo_merge_objects(the_repository, n); +} + int cmd__bitmap(int argc, const char **argv) { setup_git_directory(); - if (argc != 2) - goto usage; - - if (!strcmp(argv[1], "list-commits")) + if (argc == 2 && !strcmp(argv[1], "list-commits")) return bitmap_list_commits(); - if (!strcmp(argv[1], "dump-hashes")) + if (argc == 2 && !strcmp(argv[1], "dump-hashes")) return bitmap_dump_hashes(); + if (argc == 2 && !strcmp(argv[1], "dump-pseudo-merges")) + return bitmap_dump_pseudo_merges(); + if (argc == 3 && !strcmp(argv[1], "dump-pseudo-merge-commits")) + return bitmap_dump_pseudo_merge_commits(atoi(argv[2])); + if (argc == 3 && !strcmp(argv[1], "dump-pseudo-merge-objects")) + return bitmap_dump_pseudo_merge_objects(atoi(argv[2])); -usage: usage("\ttest-tool bitmap list-commits\n" - "\ttest-tool bitmap dump-hashes"); + "\ttest-tool bitmap dump-hashes\n" + "\ttest-tool bitmap dump-pseudo-merges\n" + "\ttest-tool bitmap dump-pseudo-merge-commits <n>\n" + "\ttest-tool bitmap dump-pseudo-merge-objects <n>"); return -1; } diff --git a/t/helper/test-hashmap.c b/t/helper/test-hashmap.c index 0eb0b3d49c..2912899558 100644 --- a/t/helper/test-hashmap.c +++ b/t/helper/test-hashmap.c @@ -36,7 +36,8 @@ static int test_entry_cmp(const void *cmp_data, } static struct test_entry *alloc_test_entry(unsigned int hash, - char *key, char *value) + const char *key, + const char *value) { size_t klen = strlen(key); size_t vlen = strlen(value); diff --git a/t/helper/test-json-writer.c b/t/helper/test-json-writer.c index afe393f597..ed52eb76bf 100644 --- a/t/helper/test-json-writer.c +++ b/t/helper/test-json-writer.c @@ -174,7 +174,7 @@ static void make_arr4(int pretty) jw_end(&arr4); } -static char *expect_nest1 = +static const char *expect_nest1 = "{\"obj1\":{\"a\":\"abc\",\"b\":42,\"c\":true},\"arr1\":[\"abc\",42,true]}"; static struct json_writer nest1 = JSON_WRITER_INIT; @@ -195,10 +195,10 @@ static void make_nest1(int pretty) jw_release(&arr1); } -static char *expect_inline1 = +static const char *expect_inline1 = "{\"obj1\":{\"a\":\"abc\",\"b\":42,\"c\":true},\"arr1\":[\"abc\",42,true]}"; -static char *pretty_inline1 = +static const char *pretty_inline1 = ("{\n" " \"obj1\": {\n" " \"a\": \"abc\",\n" @@ -236,10 +236,10 @@ static void make_inline1(int pretty) jw_end(&inline1); } -static char *expect_inline2 = +static const char *expect_inline2 = "[[1,2],[3,4],{\"a\":\"abc\"}]"; -static char *pretty_inline2 = +static const char *pretty_inline2 = ("[\n" " [\n" " 1,\n" diff --git a/t/helper/test-oidtree.c b/t/helper/test-oidtree.c deleted file mode 100644 index c7a1d4c642..0000000000 --- a/t/helper/test-oidtree.c +++ /dev/null @@ -1,54 +0,0 @@ -#include "test-tool.h" -#include "hex.h" -#include "oidtree.h" -#include "setup.h" -#include "strbuf.h" - -static enum cb_next print_oid(const struct object_id *oid, void *data UNUSED) -{ - puts(oid_to_hex(oid)); - return CB_CONTINUE; -} - -int cmd__oidtree(int argc UNUSED, const char **argv UNUSED) -{ - struct oidtree ot; - struct strbuf line = STRBUF_INIT; - int nongit_ok; - int algo = GIT_HASH_UNKNOWN; - - oidtree_init(&ot); - setup_git_directory_gently(&nongit_ok); - - while (strbuf_getline(&line, stdin) != EOF) { - const char *arg; - struct object_id oid; - - if (skip_prefix(line.buf, "insert ", &arg)) { - if (get_oid_hex_any(arg, &oid) == GIT_HASH_UNKNOWN) - die("insert not a hexadecimal oid: %s", arg); - algo = oid.algo; - oidtree_insert(&ot, &oid); - } else if (skip_prefix(line.buf, "contains ", &arg)) { - if (get_oid_hex(arg, &oid)) - die("contains not a hexadecimal oid: %s", arg); - printf("%d\n", oidtree_contains(&ot, &oid)); - } else if (skip_prefix(line.buf, "each ", &arg)) { - char buf[GIT_MAX_HEXSZ + 1] = { '0' }; - memset(&oid, 0, sizeof(oid)); - memcpy(buf, arg, strlen(arg)); - buf[hash_algos[algo].hexsz] = '\0'; - get_oid_hex_any(buf, &oid); - oid.algo = algo; - oidtree_each(&ot, &oid, strlen(arg), print_oid, NULL); - } else if (!strcmp(line.buf, "clear")) { - oidtree_clear(&ot); - } else { - die("unknown command: %s", line.buf); - } - } - - strbuf_release(&line); - - return 0; -} diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index c9efd74c2b..ad24300170 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -126,6 +126,7 @@ static struct flag_definition transaction_flags[] = { FLAG_DEF(REF_FORCE_CREATE_REFLOG), FLAG_DEF(REF_SKIP_OID_VERIFICATION), FLAG_DEF(REF_SKIP_REFNAME_VERIFICATION), + FLAG_DEF(REF_SKIP_CREATE_REFLOG), { NULL, 0 } }; diff --git a/t/helper/test-regex.c b/t/helper/test-regex.c index 80042eafc2..366bd70976 100644 --- a/t/helper/test-regex.c +++ b/t/helper/test-regex.c @@ -20,8 +20,8 @@ static struct reg_flag reg_flags[] = { static int test_regex_bug(void) { - char *pat = "[^={} \t]+"; - char *str = "={}\nfred"; + const char *pat = "[^={} \t]+"; + const char *str = "={}\nfred"; regex_t r; regmatch_t m[1]; diff --git a/t/helper/test-rot13-filter.c b/t/helper/test-rot13-filter.c index f8d564c622..7e1d9e0ee4 100644 --- a/t/helper/test-rot13-filter.c +++ b/t/helper/test-rot13-filter.c @@ -136,7 +136,7 @@ static void free_delay_entries(void) strmap_clear(&delay, 0); } -static void add_delay_entry(char *pathname, int count, int requested) +static void add_delay_entry(const char *pathname, int count, int requested) { struct delay_entry *entry = xcalloc(1, sizeof(*entry)); entry->count = count; @@ -189,7 +189,8 @@ static void reply_list_available_blobs_cmd(void) static void command_loop(void) { for (;;) { - char *buf, *output; + char *buf; + const char *output; char *pathname; struct delay_entry *entry; struct strbuf input = STRBUF_INIT; diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c index 1304336fe8..93436a82ae 100644 --- a/t/helper/test-tool.c +++ b/t/helper/test-tool.c @@ -45,7 +45,6 @@ static struct test_cmd cmds[] = { { "mktemp", cmd__mktemp }, { "oid-array", cmd__oid_array }, { "oidmap", cmd__oidmap }, - { "oidtree", cmd__oidtree }, { "online-cpus", cmd__online_cpus }, { "pack-mtimes", cmd__pack_mtimes }, { "parse-options", cmd__parse_options }, diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h index 93a125d21a..d9033d14e1 100644 --- a/t/helper/test-tool.h +++ b/t/helper/test-tool.h @@ -38,7 +38,6 @@ int cmd__match_trees(int argc, const char **argv); int cmd__mergesort(int argc, const char **argv); int cmd__mktemp(int argc, const char **argv); int cmd__oidmap(int argc, const char **argv); -int cmd__oidtree(int argc, const char **argv); int cmd__online_cpus(int argc, const char **argv); int cmd__pack_mtimes(int argc, const char **argv); int cmd__parse_options(int argc, const char **argv); diff --git a/t/perf/p5333-pseudo-merge-bitmaps.sh b/t/perf/p5333-pseudo-merge-bitmaps.sh new file mode 100755 index 0000000000..2e8b1d2635 --- /dev/null +++ b/t/perf/p5333-pseudo-merge-bitmaps.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +test_description='pseudo-merge bitmaps' +. ./perf-lib.sh + +test_perf_large_repo + +test_expect_success 'setup' ' + git \ + -c bitmapPseudoMerge.all.pattern="refs/" \ + -c bitmapPseudoMerge.all.threshold=now \ + -c bitmapPseudoMerge.all.stableThreshold=never \ + -c bitmapPseudoMerge.all.maxMerges=64 \ + -c pack.writeBitmapLookupTable=true \ + repack -adb +' + +test_perf 'git rev-list --count --all --objects (no bitmaps)' ' + git rev-list --objects --all +' + +test_perf 'git rev-list --count --all --objects (no pseudo-merges)' ' + GIT_TEST_USE_PSEUDO_MERGES=0 \ + git rev-list --objects --all --use-bitmap-index +' + +test_perf 'git rev-list --count --all --objects (with pseudo-merges)' ' + GIT_TEST_USE_PSEUDO_MERGES=1 \ + git rev-list --objects --all --use-bitmap-index +' + +test_done diff --git a/t/t0069-oidtree.sh b/t/t0069-oidtree.sh deleted file mode 100755 index 889db50818..0000000000 --- a/t/t0069-oidtree.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/sh - -test_description='basic tests for the oidtree implementation' -TEST_PASSES_SANITIZE_LEAK=true -. ./test-lib.sh - -maxhexsz=$(test_oid hexsz) -echoid () { - prefix="${1:+$1 }" - shift - while test $# -gt 0 - do - shortoid="$1" - shift - difference=$(($maxhexsz - ${#shortoid})) - printf "%s%s%0${difference}d\\n" "$prefix" "$shortoid" "0" - done -} - -test_expect_success 'oidtree insert and contains' ' - cat >expect <<-\EOF && - 0 - 0 - 0 - 1 - 1 - 0 - EOF - { - echoid insert 444 1 2 3 4 5 a b c d e && - echoid contains 44 441 440 444 4440 4444 && - echo clear - } | test-tool oidtree >actual && - test_cmp expect actual -' - -test_expect_success 'oidtree each' ' - echoid "" 123 321 321 >expect && - { - echoid insert f 9 8 123 321 a b c d e && - echo each 12300 && - echo each 3211 && - echo each 3210 && - echo each 32100 && - echo clear - } | test-tool oidtree >actual && - test_cmp expect actual -' - -test_done diff --git a/t/t0600-reffiles-backend.sh b/t/t0600-reffiles-backend.sh index 92f570313d..b2a771ff2b 100755 --- a/t/t0600-reffiles-backend.sh +++ b/t/t0600-reffiles-backend.sh @@ -468,4 +468,36 @@ test_expect_success POSIXPERM 'git reflog expire honors core.sharedRepository' ' esac ' +test_expect_success SYMLINKS 'symref transaction supports symlinks' ' + test_when_finished "git symbolic-ref -d TEST_SYMREF_HEAD" && + git update-ref refs/heads/new @ && + test_config core.prefersymlinkrefs true && + cat >stdin <<-EOF && + start + symref-create TEST_SYMREF_HEAD refs/heads/new + prepare + commit + EOF + git update-ref --no-deref --stdin <stdin && + test_path_is_symlink .git/TEST_SYMREF_HEAD && + test "$(test_readlink .git/TEST_SYMREF_HEAD)" = refs/heads/new +' + +test_expect_success 'symref transaction supports false symlink config' ' + test_when_finished "git symbolic-ref -d TEST_SYMREF_HEAD" && + git update-ref refs/heads/new @ && + test_config core.prefersymlinkrefs false && + cat >stdin <<-EOF && + start + symref-create TEST_SYMREF_HEAD refs/heads/new + prepare + commit + EOF + git update-ref --no-deref --stdin <stdin && + test_path_is_file .git/TEST_SYMREF_HEAD && + git symbolic-ref TEST_SYMREF_HEAD >actual && + echo refs/heads/new >expect && + test_cmp expect actual +' + test_done diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index bbee2783ab..eb1691860d 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -892,17 +892,23 @@ test_expect_success 'stdin update/create/verify combination works' ' ' test_expect_success 'stdin verify succeeds for correct value' ' + test-tool ref-store main for-each-reflog-ent $m >before && git rev-parse $m >expect && echo "verify $m $m" >stdin && git update-ref --stdin <stdin && git rev-parse $m >actual && - test_cmp expect actual + test_cmp expect actual && + test-tool ref-store main for-each-reflog-ent $m >after && + test_cmp before after ' test_expect_success 'stdin verify succeeds for missing reference' ' + test-tool ref-store main for-each-reflog-ent $m >before && echo "verify refs/heads/missing $Z" >stdin && git update-ref --stdin <stdin && - test_must_fail git rev-parse --verify -q refs/heads/missing + test_must_fail git rev-parse --verify -q refs/heads/missing && + test-tool ref-store main for-each-reflog-ent $m >after && + test_cmp before after ' test_expect_success 'stdin verify treats no value as missing' ' @@ -1356,6 +1362,7 @@ test_expect_success 'fails with duplicate HEAD update' ' ' test_expect_success 'fails with duplicate ref update via symref' ' + test_when_finished "git symbolic-ref -d refs/heads/symref2" && git branch target2 $A && git symbolic-ref refs/heads/symref2 refs/heads/target2 && cat >stdin <<-EOF && @@ -1643,4 +1650,423 @@ test_expect_success PIPE 'transaction flushes status updates' ' test_cmp expected actual ' +format_command () { + if test "$1" = "-z" + then + shift + printf "$F" "$@" + else + echo "$@" + fi +} + +for type in "" "-z" +do + + test_expect_success "stdin $type symref-verify fails without --no-deref" ' + git symbolic-ref refs/heads/symref $a && + format_command $type "symref-verify refs/heads/symref" "$a" >stdin && + test_must_fail git update-ref --stdin $type <stdin 2>err && + grep "fatal: symref-verify: cannot operate with deref mode" err + ' + + test_expect_success "stdin $type symref-verify fails with too many arguments" ' + format_command $type "symref-verify refs/heads/symref" "$a" "$a" >stdin && + test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err && + if test "$type" = "-z" + then + grep "fatal: unknown command: $a" err + else + grep "fatal: symref-verify refs/heads/symref: extra input: $a" err + fi + ' + + test_expect_success "stdin $type symref-verify succeeds for correct value" ' + git symbolic-ref refs/heads/symref >expect && + test-tool ref-store main for-each-reflog-ent refs/heads/symref >before && + format_command $type "symref-verify refs/heads/symref" "$a" >stdin && + git update-ref --stdin $type --no-deref <stdin && + git symbolic-ref refs/heads/symref >actual && + test_cmp expect actual && + test-tool ref-store main for-each-reflog-ent refs/heads/symref >after && + test_cmp before after + ' + + test_expect_success "stdin $type symref-verify fails with no value" ' + git symbolic-ref refs/heads/symref >expect && + format_command $type "symref-verify refs/heads/symref" "" >stdin && + test_must_fail git update-ref --stdin $type --no-deref <stdin + ' + + test_expect_success "stdin $type symref-verify succeeds for dangling reference" ' + test_when_finished "git symbolic-ref -d refs/heads/symref2" && + test_must_fail git symbolic-ref refs/heads/nonexistent && + git symbolic-ref refs/heads/symref2 refs/heads/nonexistent && + format_command $type "symref-verify refs/heads/symref2" "refs/heads/nonexistent" >stdin && + git update-ref --stdin $type --no-deref <stdin + ' + + test_expect_success "stdin $type symref-verify fails for missing reference" ' + test-tool ref-store main for-each-reflog-ent refs/heads/symref >before && + format_command $type "symref-verify refs/heads/missing" "refs/heads/unknown" >stdin && + test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err && + grep "fatal: cannot lock ref ${SQ}refs/heads/missing${SQ}: unable to resolve reference ${SQ}refs/heads/missing${SQ}" err && + test_must_fail git rev-parse --verify -q refs/heads/missing && + test-tool ref-store main for-each-reflog-ent refs/heads/symref >after && + test_cmp before after + ' + + test_expect_success "stdin $type symref-verify fails for wrong value" ' + git symbolic-ref refs/heads/symref >expect && + format_command $type "symref-verify refs/heads/symref" "$b" >stdin && + test_must_fail git update-ref --stdin $type --no-deref <stdin && + git symbolic-ref refs/heads/symref >actual && + test_cmp expect actual + ' + + test_expect_success "stdin $type symref-verify fails for mistaken null value" ' + git symbolic-ref refs/heads/symref >expect && + format_command $type "symref-verify refs/heads/symref" "$Z" >stdin && + test_must_fail git update-ref --stdin $type --no-deref <stdin && + git symbolic-ref refs/heads/symref >actual && + test_cmp expect actual + ' + + test_expect_success "stdin $type symref-delete fails without --no-deref" ' + git symbolic-ref refs/heads/symref $a && + format_command $type "symref-delete refs/heads/symref" "$a" >stdin && + test_must_fail git update-ref --stdin $type <stdin 2>err && + grep "fatal: symref-delete: cannot operate with deref mode" err + ' + + test_expect_success "stdin $type symref-delete fails with no ref" ' + format_command $type "symref-delete " >stdin && + test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err && + grep "fatal: symref-delete: missing <ref>" err + ' + + test_expect_success "stdin $type symref-delete fails deleting regular ref" ' + test_when_finished "git update-ref -d refs/heads/regularref" && + git update-ref refs/heads/regularref $a && + format_command $type "symref-delete refs/heads/regularref" "$a" >stdin && + test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err && + grep "fatal: cannot lock ref ${SQ}refs/heads/regularref${SQ}: expected symref with target ${SQ}$a${SQ}: but is a regular ref" err + ' + + test_expect_success "stdin $type symref-delete fails with too many arguments" ' + format_command $type "symref-delete refs/heads/symref" "$a" "$a" >stdin && + test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err && + if test "$type" = "-z" + then + grep "fatal: unknown command: $a" err + else + grep "fatal: symref-delete refs/heads/symref: extra input: $a" err + fi + ' + + test_expect_success "stdin $type symref-delete fails with wrong old value" ' + format_command $type "symref-delete refs/heads/symref" "$m" >stdin && + test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err && + grep "fatal: verifying symref target: ${SQ}refs/heads/symref${SQ}: is at $a but expected refs/heads/main" err && + git symbolic-ref refs/heads/symref >expect && + echo $a >actual && + test_cmp expect actual + ' + + test_expect_success "stdin $type symref-delete works with right old value" ' + format_command $type "symref-delete refs/heads/symref" "$a" >stdin && + git update-ref --stdin $type --no-deref <stdin && + test_must_fail git rev-parse --verify -q refs/heads/symref + ' + + test_expect_success "stdin $type symref-delete works with empty old value" ' + git symbolic-ref refs/heads/symref $a >stdin && + format_command $type "symref-delete refs/heads/symref" "" >stdin && + git update-ref --stdin $type --no-deref <stdin && + test_must_fail git rev-parse --verify -q $b + ' + + test_expect_success "stdin $type symref-delete succeeds for dangling reference" ' + test_must_fail git symbolic-ref refs/heads/nonexistent && + git symbolic-ref refs/heads/symref2 refs/heads/nonexistent && + format_command $type "symref-delete refs/heads/symref2" "refs/heads/nonexistent" >stdin && + git update-ref --stdin $type --no-deref <stdin && + test_must_fail git symbolic-ref -d refs/heads/symref2 + ' + + test_expect_success "stdin $type symref-delete deletes regular ref without target" ' + git update-ref refs/heads/regularref $a && + format_command $type "symref-delete refs/heads/regularref" >stdin && + git update-ref --stdin $type --no-deref <stdin + ' + + test_expect_success "stdin $type symref-create fails with too many arguments" ' + format_command $type "symref-create refs/heads/symref" "$a" "$a" >stdin && + test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err && + if test "$type" = "-z" + then + grep "fatal: unknown command: $a" err + else + grep "fatal: symref-create refs/heads/symref: extra input: $a" err + fi + ' + + test_expect_success "stdin $type symref-create fails with no target" ' + format_command $type "symref-create refs/heads/symref" >stdin && + test_must_fail git update-ref --stdin $type --no-deref <stdin + ' + + test_expect_success "stdin $type symref-create fails with empty target" ' + format_command $type "symref-create refs/heads/symref" "" >stdin && + test_must_fail git update-ref --stdin $type --no-deref <stdin + ' + + test_expect_success "stdin $type symref-create works" ' + test_when_finished "git symbolic-ref -d refs/heads/symref" && + format_command $type "symref-create refs/heads/symref" "$a" >stdin && + git update-ref --stdin $type --no-deref <stdin && + git symbolic-ref refs/heads/symref >expect && + echo $a >actual && + test_cmp expect actual + ' + + test_expect_success "stdin $type symref-create works with --no-deref" ' + test_when_finished "git symbolic-ref -d refs/heads/symref" && + format_command $type "symref-create refs/heads/symref" "$a" && + git update-ref --stdin $type <stdin 2>err + ' + + test_expect_success "stdin $type create dangling symref ref works" ' + test_when_finished "git symbolic-ref -d refs/heads/symref" && + format_command $type "symref-create refs/heads/symref" "refs/heads/unkown" >stdin && + git update-ref --stdin $type --no-deref <stdin && + git symbolic-ref refs/heads/symref >expect && + echo refs/heads/unkown >actual && + test_cmp expect actual + ' + + test_expect_success "stdin $type symref-create does not create reflogs by default" ' + test_when_finished "git symbolic-ref -d refs/symref" && + format_command $type "symref-create refs/symref" "$a" >stdin && + git update-ref --stdin $type --no-deref <stdin && + git symbolic-ref refs/symref >expect && + echo $a >actual && + test_cmp expect actual && + test_must_fail git reflog exists refs/symref + ' + + test_expect_success "stdin $type symref-create reflogs with --create-reflog" ' + test_when_finished "git symbolic-ref -d refs/heads/symref" && + format_command $type "symref-create refs/heads/symref" "$a" >stdin && + git update-ref --create-reflog --stdin $type --no-deref <stdin && + git symbolic-ref refs/heads/symref >expect && + echo $a >actual && + test_cmp expect actual && + git reflog exists refs/heads/symref + ' + + test_expect_success "stdin $type symref-update fails with too many arguments" ' + format_command $type "symref-update refs/heads/symref" "$a" "ref" "$a" "$a" >stdin && + test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err && + if test "$type" = "-z" + then + grep "fatal: unknown command: $a" err + else + grep "fatal: symref-update refs/heads/symref: extra input: $a" err + fi + ' + + test_expect_success "stdin $type symref-update fails with wrong old value argument" ' + format_command $type "symref-update refs/heads/symref" "$a" "foo" "$a" "$a" >stdin && + test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err && + grep "fatal: symref-update refs/heads/symref: invalid arg ${SQ}foo${SQ} for old value" err + ' + + test_expect_success "stdin $type symref-update creates with zero old value" ' + test_when_finished "git symbolic-ref -d refs/heads/symref" && + format_command $type "symref-update refs/heads/symref" "$a" "oid" "$Z" >stdin && + git update-ref --stdin $type --no-deref <stdin && + echo $a >expect && + git symbolic-ref refs/heads/symref >actual && + test_cmp expect actual + ' + + test_expect_success "stdin $type symref-update creates with no old value" ' + test_when_finished "git symbolic-ref -d refs/heads/symref" && + format_command $type "symref-update refs/heads/symref" "$a" >stdin && + git update-ref --stdin $type --no-deref <stdin && + echo $a >expect && + git symbolic-ref refs/heads/symref >actual && + test_cmp expect actual + ' + + test_expect_success "stdin $type symref-update creates dangling" ' + test_when_finished "git symbolic-ref -d refs/heads/symref" && + test_must_fail git rev-parse refs/heads/nonexistent && + format_command $type "symref-update refs/heads/symref" "refs/heads/nonexistent" >stdin && + git update-ref --stdin $type --no-deref <stdin && + echo refs/heads/nonexistent >expect && + git symbolic-ref refs/heads/symref >actual && + test_cmp expect actual + ' + + test_expect_success "stdin $type symref-update fails with wrong old value" ' + test_when_finished "git symbolic-ref -d refs/heads/symref" && + git symbolic-ref refs/heads/symref $a && + format_command $type "symref-update refs/heads/symref" "$m" "ref" "$b" >stdin && + test_must_fail git update-ref --stdin $type --no-deref <stdin 2>err && + grep "fatal: verifying symref target: ${SQ}refs/heads/symref${SQ}: is at $a but expected $b" err && + test_must_fail git rev-parse --verify -q $c + ' + + test_expect_success "stdin $type symref-update updates dangling ref" ' + test_when_finished "git symbolic-ref -d refs/heads/symref" && + test_must_fail git rev-parse refs/heads/nonexistent && + git symbolic-ref refs/heads/symref refs/heads/nonexistent && + format_command $type "symref-update refs/heads/symref" "$a" >stdin && + git update-ref --stdin $type --no-deref <stdin && + echo $a >expect && + git symbolic-ref refs/heads/symref >actual && + test_cmp expect actual + ' + + test_expect_success "stdin $type symref-update updates dangling ref with old value" ' + test_when_finished "git symbolic-ref -d refs/heads/symref" && + test_must_fail git rev-parse refs/heads/nonexistent && + git symbolic-ref refs/heads/symref refs/heads/nonexistent && + format_command $type "symref-update refs/heads/symref" "$a" "ref" "refs/heads/nonexistent" >stdin && + git update-ref --stdin $type --no-deref <stdin && + echo $a >expect && + git symbolic-ref refs/heads/symref >actual && + test_cmp expect actual + ' + + test_expect_success "stdin $type symref-update fails update dangling ref with wrong old value" ' + test_when_finished "git symbolic-ref -d refs/heads/symref" && + test_must_fail git rev-parse refs/heads/nonexistent && + git symbolic-ref refs/heads/symref refs/heads/nonexistent && + format_command $type "symref-update refs/heads/symref" "$a" "ref" "refs/heads/wrongref" >stdin && + test_must_fail git update-ref --stdin $type --no-deref <stdin && + echo refs/heads/nonexistent >expect && + git symbolic-ref refs/heads/symref >actual && + test_cmp expect actual + ' + + test_expect_success "stdin $type symref-update works with right old value" ' + test_when_finished "git symbolic-ref -d refs/heads/symref" && + git symbolic-ref refs/heads/symref $a && + format_command $type "symref-update refs/heads/symref" "$m" "ref" "$a" >stdin && + git update-ref --stdin $type --no-deref <stdin && + echo $m >expect && + git symbolic-ref refs/heads/symref >actual && + test_cmp expect actual + ' + + test_expect_success "stdin $type symref-update works with no old value" ' + test_when_finished "git symbolic-ref -d refs/heads/symref" && + git symbolic-ref refs/heads/symref $a && + format_command $type "symref-update refs/heads/symref" "$m" >stdin && + git update-ref --stdin $type --no-deref <stdin && + echo $m >expect && + git symbolic-ref refs/heads/symref >actual && + test_cmp expect actual + ' + + test_expect_success "stdin $type symref-update fails with empty old ref-target" ' + test_when_finished "git symbolic-ref -d refs/heads/symref" && + git symbolic-ref refs/heads/symref $a && + format_command $type "symref-update refs/heads/symref" "$m" "ref" "" >stdin && + test_must_fail git update-ref --stdin $type --no-deref <stdin && + echo $a >expect && + git symbolic-ref refs/heads/symref >actual && + test_cmp expect actual + ' + + test_expect_success "stdin $type symref-update creates (with deref)" ' + test_when_finished "git symbolic-ref -d refs/heads/symref" && + format_command $type "symref-update refs/heads/symref" "$a" >stdin && + git update-ref --stdin $type <stdin && + echo $a >expect && + git symbolic-ref --no-recurse refs/heads/symref >actual && + test_cmp expect actual && + test-tool ref-store main for-each-reflog-ent refs/heads/symref >actual && + grep "$Z $(git rev-parse $a)" actual + ' + + test_expect_success "stdin $type symref-update regular ref to symref with correct old-oid" ' + test_when_finished "git symbolic-ref -d --no-recurse refs/heads/regularref" && + git update-ref --no-deref refs/heads/regularref $a && + format_command $type "symref-update refs/heads/regularref" "$a" "oid" "$(git rev-parse $a)" >stdin && + git update-ref --stdin $type <stdin && + echo $a >expect && + git symbolic-ref --no-recurse refs/heads/regularref >actual && + test_cmp expect actual && + test-tool ref-store main for-each-reflog-ent refs/heads/regularref >actual && + grep "$(git rev-parse $a) $(git rev-parse $a)" actual + ' + + test_expect_success "stdin $type symref-update regular ref to symref fails with wrong old-oid" ' + test_when_finished "git update-ref -d refs/heads/regularref" && + git update-ref --no-deref refs/heads/regularref $a && + format_command $type "symref-update refs/heads/regularref" "$a" "oid" "$(git rev-parse refs/heads/target2)" >stdin && + test_must_fail git update-ref --stdin $type <stdin 2>err && + grep "fatal: cannot lock ref ${SQ}refs/heads/regularref${SQ}: is at $(git rev-parse $a) but expected $(git rev-parse refs/heads/target2)" err && + echo $(git rev-parse $a) >expect && + git rev-parse refs/heads/regularref >actual && + test_cmp expect actual + ' + + test_expect_success "stdin $type symref-update regular ref to symref fails with invalid old-oid" ' + test_when_finished "git update-ref -d refs/heads/regularref" && + git update-ref --no-deref refs/heads/regularref $a && + format_command $type "symref-update refs/heads/regularref" "$a" "oid" "not-a-ref-oid" >stdin && + test_must_fail git update-ref --stdin $type <stdin 2>err && + grep "fatal: symref-update refs/heads/regularref: invalid oid: not-a-ref-oid" err && + echo $(git rev-parse $a) >expect && + git rev-parse refs/heads/regularref >actual && + test_cmp expect actual + ' + + test_expect_success "stdin $type symref-update existing symref with zero old-oid" ' + test_when_finished "git symbolic-ref -d --no-recurse refs/heads/symref" && + git symbolic-ref refs/heads/symref refs/heads/target2 && + format_command $type "symref-update refs/heads/symref" "$a" "oid" "$Z" >stdin && + test_must_fail git update-ref --stdin $type <stdin 2>err && + grep "fatal: cannot lock ref ${SQ}refs/heads/symref${SQ}: reference already exists" err && + echo refs/heads/target2 >expect && + git symbolic-ref refs/heads/symref >actual && + test_cmp expect actual + ' + + test_expect_success "stdin $type symref-update regular ref to symref (with deref)" ' + test_when_finished "git symbolic-ref -d refs/heads/symref" && + test_when_finished "git update-ref -d --no-deref refs/heads/symref2" && + git update-ref refs/heads/symref2 $a && + git symbolic-ref --no-recurse refs/heads/symref refs/heads/symref2 && + format_command $type "symref-update refs/heads/symref" "$a" >stdin && + git update-ref $type --stdin <stdin && + echo $a >expect && + git symbolic-ref --no-recurse refs/heads/symref2 >actual && + test_cmp expect actual && + echo refs/heads/symref2 >expect && + git symbolic-ref --no-recurse refs/heads/symref >actual && + test_cmp expect actual && + test-tool ref-store main for-each-reflog-ent refs/heads/symref >actual && + grep "$(git rev-parse $a) $(git rev-parse $a)" actual + ' + + test_expect_success "stdin $type symref-update regular ref to symref" ' + test_when_finished "git symbolic-ref -d --no-recurse refs/heads/regularref" && + git update-ref --no-deref refs/heads/regularref $a && + format_command $type "symref-update refs/heads/regularref" "$a" >stdin && + git update-ref $type --stdin <stdin && + echo $a >expect && + git symbolic-ref --no-recurse refs/heads/regularref >actual && + test_cmp expect actual && + test-tool ref-store main for-each-reflog-ent refs/heads/regularref >actual && + grep "$(git rev-parse $a) $(git rev-parse $a)" actual + ' + +done + test_done diff --git a/t/t1403-show-ref.sh b/t/t1403-show-ref.sh index 33fb7a38ff..403f6b8f7d 100755 --- a/t/t1403-show-ref.sh +++ b/t/t1403-show-ref.sh @@ -121,13 +121,13 @@ test_expect_success 'show-ref -d' ' ' -test_expect_success 'show-ref --heads, --tags, --head, pattern' ' +test_expect_success 'show-ref --branches, --tags, --head, pattern' ' for branch in B main side do echo $(git rev-parse refs/heads/$branch) refs/heads/$branch || return 1 - done >expect.heads && - git show-ref --heads >actual && - test_cmp expect.heads actual && + done >expect.branches && + git show-ref --branches >actual && + test_cmp expect.branches actual && for tag in A B C do @@ -136,15 +136,15 @@ test_expect_success 'show-ref --heads, --tags, --head, pattern' ' git show-ref --tags >actual && test_cmp expect.tags actual && - cat expect.heads expect.tags >expect && - git show-ref --heads --tags >actual && + cat expect.branches expect.tags >expect && + git show-ref --branches --tags >actual && test_cmp expect actual && { echo $(git rev-parse HEAD) HEAD && - cat expect.heads expect.tags + cat expect.branches expect.tags } >expect && - git show-ref --heads --tags --head >actual && + git show-ref --branches --tags --head >actual && test_cmp expect actual && { @@ -165,6 +165,14 @@ test_expect_success 'show-ref --heads, --tags, --head, pattern' ' test_cmp expect actual ' +test_expect_success 'show-ref --heads is deprecated and hidden' ' + test_expect_code 129 git show-ref -h >short-help && + test_grep ! -e --heads short-help && + git show-ref --heads >actual 2>warning && + test_grep ! deprecated warning && + test_cmp expect.branches actual +' + test_expect_success 'show-ref --verify HEAD' ' echo $(git rev-parse HEAD) HEAD >expect && git show-ref --verify HEAD >actual && diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh index 067fd57290..5a812ca3c0 100755 --- a/t/t1416-ref-transaction-hooks.sh +++ b/t/t1416-ref-transaction-hooks.sh @@ -157,4 +157,58 @@ test_expect_success 'hook captures git-symbolic-ref updates' ' test_cmp expect actual ' +test_expect_success 'hook gets all queued symref updates' ' + test_when_finished "rm actual" && + + git update-ref refs/heads/branch $POST_OID && + git symbolic-ref refs/heads/symref refs/heads/main && + git symbolic-ref refs/heads/symrefd refs/heads/main && + git symbolic-ref refs/heads/symrefu refs/heads/main && + + test_hook reference-transaction <<-\EOF && + echo "$*" >>actual + while read -r line + do + printf "%s\n" "$line" + done >>actual + EOF + + # In the files backend, "delete" also triggers an additional transaction + # update on the packed-refs backend, which constitutes additional reflog + # entries. + if test_have_prereq REFFILES + then + cat >expect <<-EOF + aborted + $ZERO_OID $ZERO_OID refs/heads/symrefd + EOF + else + >expect + fi && + + cat >>expect <<-EOF && + prepared + ref:refs/heads/main $ZERO_OID refs/heads/symref + ref:refs/heads/main $ZERO_OID refs/heads/symrefd + $ZERO_OID ref:refs/heads/main refs/heads/symrefc + ref:refs/heads/main ref:refs/heads/branch refs/heads/symrefu + committed + ref:refs/heads/main $ZERO_OID refs/heads/symref + ref:refs/heads/main $ZERO_OID refs/heads/symrefd + $ZERO_OID ref:refs/heads/main refs/heads/symrefc + ref:refs/heads/main ref:refs/heads/branch refs/heads/symrefu + EOF + + git update-ref --no-deref --stdin <<-EOF && + start + symref-verify refs/heads/symref refs/heads/main + symref-delete refs/heads/symrefd refs/heads/main + symref-create refs/heads/symrefc refs/heads/main + symref-update refs/heads/symrefu refs/heads/branch ref refs/heads/main + prepare + commit + EOF + test_cmp expect actual +' + test_done diff --git a/t/t1460-refs-migrate.sh b/t/t1460-refs-migrate.sh new file mode 100755 index 0000000000..f7c0783d30 --- /dev/null +++ b/t/t1460-refs-migrate.sh @@ -0,0 +1,243 @@ +#!/bin/sh + +test_description='migration of ref storage backends' + +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh + +test_migration () { + git -C "$1" for-each-ref --include-root-refs \ + --format='%(refname) %(objectname) %(symref)' >expect && + git -C "$1" refs migrate --ref-format="$2" && + git -C "$1" for-each-ref --include-root-refs \ + --format='%(refname) %(objectname) %(symref)' >actual && + test_cmp expect actual && + + git -C "$1" rev-parse --show-ref-format >actual && + echo "$2" >expect && + test_cmp expect actual +} + +test_expect_success 'setup' ' + rm -rf .git && + # The migration does not yet support reflogs. + git config --global core.logAllRefUpdates false +' + +test_expect_success "superfluous arguments" ' + test_when_finished "rm -rf repo" && + git init repo && + test_must_fail git -C repo refs migrate foo 2>err && + cat >expect <<-EOF && + usage: too many arguments + EOF + test_cmp expect err +' + +test_expect_success "missing ref storage format" ' + test_when_finished "rm -rf repo" && + git init repo && + test_must_fail git -C repo refs migrate 2>err && + cat >expect <<-EOF && + usage: missing --ref-format=<format> + EOF + test_cmp expect err +' + +test_expect_success "unknown ref storage format" ' + test_when_finished "rm -rf repo" && + git init repo && + test_must_fail git -C repo refs migrate \ + --ref-format=unknown 2>err && + cat >expect <<-EOF && + error: unknown ref storage format ${SQ}unknown${SQ} + EOF + test_cmp expect err +' + +ref_formats="files reftable" +for from_format in $ref_formats +do + for to_format in $ref_formats + do + if test "$from_format" = "$to_format" + then + continue + fi + + test_expect_success "$from_format: migration to same format fails" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_must_fail git -C repo refs migrate \ + --ref-format=$from_format 2>err && + cat >expect <<-EOF && + error: repository already uses ${SQ}$from_format${SQ} format + EOF + test_cmp expect err + ' + + test_expect_success "$from_format -> $to_format: migration with reflog fails" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_config -C repo core.logAllRefUpdates true && + test_commit -C repo logged && + test_must_fail git -C repo refs migrate \ + --ref-format=$to_format 2>err && + cat >expect <<-EOF && + error: migrating reflogs is not supported yet + EOF + test_cmp expect err + ' + + test_expect_success "$from_format -> $to_format: migration with worktree fails" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + git -C repo worktree add wt && + test_must_fail git -C repo refs migrate \ + --ref-format=$to_format 2>err && + cat >expect <<-EOF && + error: migrating repositories with worktrees is not supported yet + EOF + test_cmp expect err + ' + + test_expect_success "$from_format -> $to_format: unborn HEAD" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_migration repo "$to_format" + ' + + test_expect_success "$from_format -> $to_format: single ref" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_commit -C repo initial && + test_migration repo "$to_format" + ' + + test_expect_success "$from_format -> $to_format: bare repository" ' + test_when_finished "rm -rf repo repo.git" && + git init --ref-format=$from_format repo && + test_commit -C repo initial && + git clone --ref-format=$from_format --mirror repo repo.git && + test_migration repo.git "$to_format" + ' + + test_expect_success "$from_format -> $to_format: dangling symref" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_commit -C repo initial && + git -C repo symbolic-ref BROKEN_HEAD refs/heads/nonexistent && + test_migration repo "$to_format" && + echo refs/heads/nonexistent >expect && + git -C repo symbolic-ref BROKEN_HEAD >actual && + test_cmp expect actual + ' + + test_expect_success "$from_format -> $to_format: broken ref" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_commit -C repo initial && + test-tool -C repo ref-store main update-ref "" refs/heads/broken \ + "$(test_oid 001)" "$ZERO_OID" REF_SKIP_CREATE_REFLOG,REF_SKIP_OID_VERIFICATION && + test_migration repo "$to_format" && + test_oid 001 >expect && + git -C repo rev-parse refs/heads/broken >actual && + test_cmp expect actual + ' + + test_expect_success "$from_format -> $to_format: pseudo-refs" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_commit -C repo initial && + git -C repo update-ref FOO_HEAD HEAD && + test_migration repo "$to_format" + ' + + test_expect_success "$from_format -> $to_format: special refs are left alone" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_commit -C repo initial && + git -C repo rev-parse HEAD >repo/.git/MERGE_HEAD && + git -C repo rev-parse MERGE_HEAD && + test_migration repo "$to_format" && + test_path_is_file repo/.git/MERGE_HEAD + ' + + test_expect_success "$from_format -> $to_format: a bunch of refs" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + + test_commit -C repo initial && + cat >input <<-EOF && + create FOO_HEAD HEAD + create refs/heads/branch-1 HEAD + create refs/heads/branch-2 HEAD + create refs/heads/branch-3 HEAD + create refs/heads/branch-4 HEAD + create refs/tags/tag-1 HEAD + create refs/tags/tag-2 HEAD + EOF + git -C repo update-ref --stdin <input && + test_migration repo "$to_format" + ' + + test_expect_success "$from_format -> $to_format: dry-run migration does not modify repository" ' + test_when_finished "rm -rf repo" && + git init --ref-format=$from_format repo && + test_commit -C repo initial && + git -C repo refs migrate --dry-run \ + --ref-format=$to_format >output && + grep "Finished dry-run migration of refs" output && + test_path_is_dir repo/.git/ref_migration.* && + echo $from_format >expect && + git -C repo rev-parse --show-ref-format >actual && + test_cmp expect actual + ' + done +done + +test_expect_success 'migrating from files format deletes backend files' ' + test_when_finished "rm -rf repo" && + git init --ref-format=files repo && + test_commit -C repo first && + git -C repo pack-refs --all && + test_commit -C repo second && + git -C repo update-ref ORIG_HEAD HEAD && + git -C repo rev-parse HEAD >repo/.git/FETCH_HEAD && + + test_path_is_file repo/.git/HEAD && + test_path_is_file repo/.git/ORIG_HEAD && + test_path_is_file repo/.git/refs/heads/main && + test_path_is_file repo/.git/packed-refs && + + test_migration repo reftable && + + echo "ref: refs/heads/.invalid" >expect && + test_cmp expect repo/.git/HEAD && + echo "this repository uses the reftable format" >expect && + test_cmp expect repo/.git/refs/heads && + test_path_is_file repo/.git/FETCH_HEAD && + test_path_is_missing repo/.git/ORIG_HEAD && + test_path_is_missing repo/.git/refs/heads/main && + test_path_is_missing repo/.git/logs && + test_path_is_missing repo/.git/packed-refs +' + +test_expect_success 'migrating from reftable format deletes backend files' ' + test_when_finished "rm -rf repo" && + git init --ref-format=reftable repo && + test_commit -C repo first && + + test_path_is_dir repo/.git/reftable && + test_migration repo files && + + test_path_is_missing repo/.git/reftable && + echo "ref: refs/heads/main" >expect && + test_cmp expect repo/.git/HEAD && + test_path_is_file repo/.git/refs/heads/main +' + +test_done diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh index 7b05bf3961..a767c3520e 100755 --- a/t/t3206-range-diff.sh +++ b/t/t3206-range-diff.sh @@ -545,6 +545,20 @@ do ' done +test_expect_success "--range-diff implies --cover-letter for multi-patch series" ' + test_when_finished "rm -f v2-000?-*" && + git format-patch -v2 --range-diff=topic main..unmodified && + test_grep "^Range-diff against v1:$" v2-0000-cover-letter.patch +' + +test_expect_success "explicit --no-cover-letter defeats implied --cover-letter" ' + test_when_finished "rm -f v2-000?-*" && + test_must_fail git format-patch --no-cover-letter \ + -v2 --range-diff=topic main..unmodified && + test_must_fail git -c format.coverLetter=no format-patch \ + -v2 --range-diff=topic main..unmodified +' + test_expect_success 'format-patch --range-diff as commentary' ' git format-patch --range-diff=HEAD~1 HEAD~1 >actual && test_when_finished "rm 0001-*" && diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index d1bead61fa..f92baad138 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -2215,6 +2215,51 @@ test_expect_success 'bad labels and refs rejected when parsing todo list' ' test_path_is_missing execed ' +test_expect_success 'non-merge commands reject merge commits' ' + test_when_finished "test_might_fail git rebase --abort" && + git checkout E && + git merge I && + oid=$(git rev-parse HEAD) && + cat >todo <<-EOF && + pick $oid + reword $oid + edit $oid + fixup $oid + squash $oid + EOF + ( + set_replace_editor todo && + test_must_fail git rebase -i HEAD 2>actual + ) && + cat >expect <<-EOF && + error: ${SQ}pick${SQ} does not accept merge commits + hint: ${SQ}pick${SQ} does not take a merge commit. If you wanted to + hint: replay the merge, use ${SQ}merge -C${SQ} on the commit. + hint: Disable this message with "git config advice.rebaseTodoError false" + error: invalid line 1: pick $oid + error: ${SQ}reword${SQ} does not accept merge commits + hint: ${SQ}reword${SQ} does not take a merge commit. If you wanted to + hint: replay the merge and reword the commit message, use + hint: ${SQ}merge -c${SQ} on the commit + hint: Disable this message with "git config advice.rebaseTodoError false" + error: invalid line 2: reword $oid + error: ${SQ}edit${SQ} does not accept merge commits + hint: ${SQ}edit${SQ} does not take a merge commit. If you wanted to + hint: replay the merge, use ${SQ}merge -C${SQ} on the commit, and then + hint: ${SQ}break${SQ} to give the control back to you so that you can + hint: do ${SQ}git commit --amend && git rebase --continue${SQ}. + hint: Disable this message with "git config advice.rebaseTodoError false" + error: invalid line 3: edit $oid + error: cannot squash merge commit into another commit + error: invalid line 4: fixup $oid + error: cannot squash merge commit into another commit + error: invalid line 5: squash $oid + You can fix this with ${SQ}git rebase --edit-todo${SQ} and then run ${SQ}git rebase --continue${SQ}. + Or you can abort the rebase with ${SQ}git rebase --abort${SQ}. + EOF + test_cmp expect actual +' + # This must be the last test in this file test_expect_success '$EDITOR and friends are unchanged' ' test_editor_unchanged diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index 6624a4f7c0..5d78868ac1 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -43,21 +43,6 @@ force_color () { ) } -test_expect_success 'warn about add.interactive.useBuiltin' ' - cat >expect <<-\EOF && - warning: the add.interactive.useBuiltin setting has been removed! - See its entry in '\''git help config'\'' for details. - EOF - echo "No changes." >expect.out && - - for v in = =true =false - do - git -c "add.interactive.useBuiltin$v" add -p >out 2>actual && - test_cmp expect.out out && - test_cmp expect actual || return 1 - done -' - test_expect_success 'unknown command' ' test_when_finished "git reset --hard; rm -f command" && echo W >command && diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh index f27d09cfd9..db7b403bc1 100755 --- a/t/t3900-i18n-commit.sh +++ b/t/t3900-i18n-commit.sh @@ -5,6 +5,7 @@ test_description='commit and log output encodings' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh compare_with () { diff --git a/t/t3901-i18n-patch.sh b/t/t3901-i18n-patch.sh index 4b37f78829..5f0b9afc3f 100755 --- a/t/t3901-i18n-patch.sh +++ b/t/t3901-i18n-patch.sh @@ -8,6 +8,7 @@ test_description='i18n settings and format-patch | am pipe' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh check_encoding () { diff --git a/t/t3910-mac-os-precompose.sh b/t/t3910-mac-os-precompose.sh index 898267a6bd..6d5918c8fe 100755 --- a/t/t3910-mac-os-precompose.sh +++ b/t/t3910-mac-os-precompose.sh @@ -37,6 +37,27 @@ Alongc=$Alongc$Alongc$Alongc$Alongc$Alongc #50 Byte Alongc=$Alongc$Alongc$Alongc$Alongc$Alongc #250 Byte Alongc=$Alongc$AEligatu$AEligatu #254 Byte + +ls_files_nfc_nfd () { + test_when_finished "git config --global --unset core.precomposeunicode" && + prglbl=$1 + prlocl=$2 + aumlcreat=$3 + aumllist=$4 + git config --global core.precomposeunicode $prglbl && + ( + rm -rf .git && + mkdir -p "somewhere/$prglbl/$prlocl/$aumlcreat" && + mypwd=$PWD && + cd "somewhere/$prglbl/$prlocl/$aumlcreat" && + git init && + git config core.precomposeunicode $prlocl && + git --literal-pathspecs ls-files "$mypwd/somewhere/$prglbl/$prlocl/$aumllist" 2>err && + >expected && + test_cmp expected err + ) +} + test_expect_success "detect if nfd needed" ' precomposeunicode=$(git config core.precomposeunicode) && test "$precomposeunicode" = true && @@ -211,8 +232,8 @@ test_expect_success "unicode decomposed: git restore -p . " ' ' # Test if the global core.precomposeunicode stops autosensing -# Must be the last test case test_expect_success "respect git config --global core.precomposeunicode" ' + test_when_finished "git config --global --unset core.precomposeunicode" && git config --global core.precomposeunicode true && rm -rf .git && git init && @@ -220,4 +241,20 @@ test_expect_success "respect git config --global core.precomposeunicode" ' test "$precomposeunicode" = "true" ' +test_expect_success "ls-files false false nfd nfd" ' + ls_files_nfc_nfd false false $Adiarnfd $Adiarnfd +' + +test_expect_success "ls-files false true nfd nfd" ' + ls_files_nfc_nfd false true $Adiarnfd $Adiarnfd +' + +test_expect_success "ls-files true false nfd nfd" ' + ls_files_nfc_nfd true false $Adiarnfd $Adiarnfd +' + +test_expect_success "ls-files true true nfd nfd" ' + ls_files_nfc_nfd true true $Adiarnfd $Adiarnfd +' + test_done diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index ba85b582c5..884f83fb8a 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -820,8 +820,8 @@ test_expect_success 'format-patch --notes --signoff' ' ' test_expect_success 'format-patch notes output control' ' + test_when_finished "git notes remove HEAD || :" && git notes add -m "notes config message" HEAD && - test_when_finished git notes remove HEAD && git format-patch -1 --stdout >out && ! grep "notes config message" out && @@ -848,10 +848,10 @@ test_expect_success 'format-patch notes output control' ' ' test_expect_success 'format-patch with multiple notes refs' ' + test_when_finished "git notes --ref note1 remove HEAD; + git notes --ref note2 remove HEAD || :" && git notes --ref note1 add -m "this is note 1" HEAD && - test_when_finished git notes --ref note1 remove HEAD && git notes --ref note2 add -m "this is note 2" HEAD && - test_when_finished git notes --ref note2 remove HEAD && git format-patch -1 --stdout >out && ! grep "this is note 1" out && @@ -892,10 +892,10 @@ test_expect_success 'format-patch with multiple notes refs' ' test_expect_success 'format-patch with multiple notes refs in config' ' test_when_finished "test_unconfig format.notes" && + test_when_finished "git notes --ref note1 remove HEAD; + git notes --ref note2 remove HEAD || :" && git notes --ref note1 add -m "this is note 1" HEAD && - test_when_finished git notes --ref note1 remove HEAD && git notes --ref note2 add -m "this is note 2" HEAD && - test_when_finished git notes --ref note2 remove HEAD && git config format.notes note1 && git format-patch -1 --stdout >out && @@ -2482,16 +2482,55 @@ test_expect_success 'interdiff: reroll-count with a integer' ' ' test_expect_success 'interdiff: solo-patch' ' - cat >expect <<-\EOF && - +fleep - - EOF git format-patch --interdiff=boop~2 -1 boop && - test_grep "^Interdiff:$" 0001-fleep.patch && - sed "1,/^ @@ /d; /^$/q" 0001-fleep.patch >actual && + + # remove up to the last "patch" output line, + # and remove everything below the signature mark. + sed -e "1,/^+fleep\$/d" -e "/^-- /,\$d" 0001-fleep.patch >actual && + + # fabricate Interdiff output. + git diff boop~2 boop >inter && + { + echo && + echo "Interdiff:" && + sed -e "s/^/ /" inter + } >expect && test_cmp expect actual ' +test_expect_success 'range-diff: solo-patch' ' + git format-patch --creation-factor=999 \ + --range-diff=boop~2..boop~1 -1 boop && + + # remove up to the last "patch" output line, + # and remove everything below the signature mark. + sed -e "1,/^+fleep\$/d" -e "/^-- /,\$d" 0001-fleep.patch >actual && + + # fabricate range-diff output. + { + echo && + echo "Range-diff:" && + git range-diff --creation-factor=999 \ + boop~2..boop~1 boop~1..boop + } >expect && + test_cmp expect actual +' + +test_expect_success 'interdiff: multi-patch, implicit --cover-letter' ' + test_when_finished "rm -f v23-0*.patch" && + git format-patch --interdiff=boop~2 -2 -v23 && + test_grep "^Interdiff against v22:$" v23-0000-cover-letter.patch && + test_cmp expect actual +' + +test_expect_success 'interdiff: explicit --no-cover-letter defeats implied --cover-letter' ' + test_when_finished "rm -f v23-0*.patch" && + test_must_fail git format-patch --no-cover-letter \ + --interdiff=boop~2 -2 -v23 && + test_must_fail git -c format.coverLetter=no format-patch \ + --interdiff=boop~2 -2 -v23 +' + test_expect_success 'format-patch does not respect diff.noprefix' ' git -c diff.noprefix format-patch -1 --stdout >actual && grep "^--- a/blorp" actual diff --git a/t/t4020-diff-external.sh b/t/t4020-diff-external.sh index fdd865f7c3..3baa52a9bf 100755 --- a/t/t4020-diff-external.sh +++ b/t/t4020-diff-external.sh @@ -172,6 +172,72 @@ test_expect_success 'no diff with -diff' ' grep Binary out ' +check_external_diff () { + expect_code=$1 + expect_out=$2 + expect_err=$3 + command_code=$4 + trust_exit_code=$5 + shift 5 + options="$@" + + command="echo output; exit $command_code;" + desc="external diff '$command' with trustExitCode=$trust_exit_code" + with_options="${options:+ with }$options" + + test_expect_success "$desc via attribute$with_options" " + test_config diff.foo.command \"$command\" && + test_config diff.foo.trustExitCode $trust_exit_code && + echo \"file diff=foo\" >.gitattributes && + test_expect_code $expect_code git diff $options >out 2>err && + test_cmp $expect_out out && + test_cmp $expect_err err + " + + test_expect_success "$desc via diff.external$with_options" " + test_config diff.external \"$command\" && + test_config diff.trustExitCode $trust_exit_code && + >.gitattributes && + test_expect_code $expect_code git diff $options >out 2>err && + test_cmp $expect_out out && + test_cmp $expect_err err + " + + test_expect_success "$desc via GIT_EXTERNAL_DIFF$with_options" " + >.gitattributes && + test_expect_code $expect_code env \ + GIT_EXTERNAL_DIFF=\"$command\" \ + GIT_EXTERNAL_DIFF_TRUST_EXIT_CODE=$trust_exit_code \ + git diff $options >out 2>err && + test_cmp $expect_out out && + test_cmp $expect_err err + " +} + +test_expect_success 'setup output files' ' + : >empty && + echo output >output && + echo "fatal: external diff died, stopping at file" >error +' + +check_external_diff 0 output empty 0 off +check_external_diff 128 output error 1 off +check_external_diff 0 output empty 0 on +check_external_diff 0 output empty 1 on +check_external_diff 128 output error 2 on + +check_external_diff 1 output empty 0 off --exit-code +check_external_diff 128 output error 1 off --exit-code +check_external_diff 0 output empty 0 on --exit-code +check_external_diff 1 output empty 1 on --exit-code +check_external_diff 128 output error 2 on --exit-code + +check_external_diff 1 empty empty 0 off --quiet +check_external_diff 1 empty empty 1 off --quiet # we don't even call the program +check_external_diff 0 empty empty 0 on --quiet +check_external_diff 1 empty empty 1 on --quiet +check_external_diff 128 empty error 2 on --quiet + echo NULZbetweenZwords | perl -pe 'y/Z/\000/' > file test_expect_success 'force diff with "diff"' ' diff --git a/t/t4153-am-resume-override-opts.sh b/t/t4153-am-resume-override-opts.sh index 4add7c7757..a32cec42aa 100755 --- a/t/t4153-am-resume-override-opts.sh +++ b/t/t4153-am-resume-override-opts.sh @@ -3,7 +3,6 @@ test_description='git-am command-line options override saved options' . ./test-lib.sh -. "$TEST_DIRECTORY"/lib-terminal.sh format_patch () { git format-patch --stdout -1 "$1" >"$1".eml @@ -27,7 +26,12 @@ test_expect_success 'setup' ' format_patch side2 ' -test_expect_success TTY '--3way overrides --no-3way' ' +test_expect_success '--retry fails without in-progress operation' ' + test_must_fail git am --retry 2>err && + test_grep "operation not in progress" err +' + +test_expect_success '--3way overrides --no-3way' ' rm -fr .git/rebase-apply && git reset --hard && git checkout renamed-file && @@ -40,7 +44,7 @@ test_expect_success TTY '--3way overrides --no-3way' ' # Applying side1 with am --3way will succeed due to the threeway-merge. # Applying side2 will fail as --3way does not apply to it. - test_must_fail test_terminal git am --3way </dev/zero && + test_must_fail git am --retry --3way && test_path_is_dir .git/rebase-apply && test side1 = "$(cat file2)" ' @@ -84,7 +88,7 @@ test_expect_success '--signoff overrides --no-signoff' ' test $(git cat-file commit HEAD | grep -c "Signed-off-by:") -eq 0 ' -test_expect_success TTY '--reject overrides --no-reject' ' +test_expect_success '--reject overrides --no-reject' ' rm -fr .git/rebase-apply && git reset --hard && git checkout first && @@ -94,7 +98,7 @@ test_expect_success TTY '--reject overrides --no-reject' ' test_path_is_dir .git/rebase-apply && test_path_is_missing file.rej && - test_must_fail test_terminal git am --reject </dev/zero && + test_must_fail git am --retry --reject </dev/zero && test_path_is_dir .git/rebase-apply && test_path_is_file file.rej ' diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 86c695eb0a..51f7beb59f 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -1237,6 +1237,30 @@ test_expect_success 'log.abbrevCommit configuration' ' test_cmp expect.whatchanged.full actual ' +test_expect_success '--abbrev-commit with core.abbrev=false' ' + git log --no-abbrev >expect && + git -c core.abbrev=false log --abbrev-commit >actual && + test_cmp expect actual +' + +test_expect_success '--abbrev-commit with --no-abbrev' ' + git log --no-abbrev >expect && + git log --abbrev-commit --no-abbrev >actual && + test_cmp expect actual +' + +test_expect_success '--abbrev-commit with core.abbrev=9000' ' + git log --no-abbrev >expect && + git -c core.abbrev=9000 log --abbrev-commit >actual && + test_cmp expect actual +' + +test_expect_success '--abbrev-commit with --abbrev=9000' ' + git log --no-abbrev >expect && + git log --abbrev-commit --abbrev=9000 >actual && + test_cmp expect actual +' + test_expect_success 'show added path under "--follow -M"' ' # This tests for a regression introduced in v1.7.2-rc0~103^2~2 test_create_repo regression && diff --git a/t/t5324-split-commit-graph.sh b/t/t5324-split-commit-graph.sh index 281266f788..77e91547ea 100755 --- a/t/t5324-split-commit-graph.sh +++ b/t/t5324-split-commit-graph.sh @@ -13,7 +13,8 @@ test_expect_success 'setup repo' ' git init && git config core.commitGraph true && git config gc.writeCommitGraph false && - infodir=".git/objects/info" && + objdir=".git/objects" && + infodir="$objdir/info" && graphdir="$infodir/commit-graphs" && test_oid_cache <<-EOM shallow sha1:2132 @@ -718,4 +719,27 @@ test_expect_success 'write generation data chunk when commit-graph chain is repl ) ' +test_expect_success 'temporary graph layer is discarded upon failure' ' + git init layer-discard && + ( + cd layer-discard && + + test_commit A && + test_commit B && + + # Intentionally remove commit "A" from the object store + # so that the commit-graph machinery fails to parse the + # parents of "B". + # + # This takes place after the commit-graph machinery has + # initialized a new temporary file to store the contents + # of the new graph layer, so will allow us to ensure + # that the temporary file is discarded upon failure. + rm $objdir/$(test_oid_to_path $(git rev-parse HEAD^)) && + + test_must_fail git commit-graph write --reachable --split && + test_dir_is_empty $graphdir + ) +' + test_done diff --git a/t/t5326-multi-pack-bitmaps.sh b/t/t5326-multi-pack-bitmaps.sh index cc7220b6c0..916da389b6 100755 --- a/t/t5326-multi-pack-bitmaps.sh +++ b/t/t5326-multi-pack-bitmaps.sh @@ -551,4 +551,34 @@ do ' done +test_expect_success 'remove one packfile between MIDX bitmap writes' ' + git init remove-pack-between-writes && + ( + cd remove-pack-between-writes && + + test_commit A && + test_commit B && + test_commit C && + + # Create packs with the prefix "pack-A", "pack-B", + # "pack-C" to impose a lexicographic order on these + # packs so the pack being removed is always from the + # middle. + packdir=.git/objects/pack && + A="$(echo A | git pack-objects $packdir/pack-A --revs)" && + B="$(echo B | git pack-objects $packdir/pack-B --revs)" && + C="$(echo C | git pack-objects $packdir/pack-C --revs)" && + + git multi-pack-index write --bitmap && + + cat >in <<-EOF && + pack-A-$A.idx + pack-C-$C.idx + EOF + git multi-pack-index write --bitmap --stdin-packs <in && + + git rev-list --test-bitmap HEAD + ) +' + test_done diff --git a/t/t5332-multi-pack-reuse.sh b/t/t5332-multi-pack-reuse.sh index 3c20738bce..ed823f37bc 100755 --- a/t/t5332-multi-pack-reuse.sh +++ b/t/t5332-multi-pack-reuse.sh @@ -204,4 +204,30 @@ test_expect_success 'omit delta from uninteresting base (cross pack)' ' test_pack_objects_reused_all $(($objects_nr - 1)) $packs_nr ' +test_expect_success 'non-omitted delta in MIDX preferred pack' ' + test_config pack.allowPackReuse single && + + cat >p1.objects <<-EOF && + $(git rev-parse $base) + ^$(git rev-parse $delta^) + EOF + cat >p2.objects <<-EOF && + $(git rev-parse F) + EOF + + p1="$(git pack-objects --revs $packdir/pack <p1.objects)" && + p2="$(git pack-objects --revs $packdir/pack <p2.objects)" && + + cat >in <<-EOF && + pack-$p1.idx + pack-$p2.idx + EOF + git multi-pack-index write --bitmap --stdin-packs \ + --preferred-pack=pack-$p1.pack <in && + + git show-index <$packdir/pack-$p1.idx >expect && + + test_pack_objects_reused_all $(wc -l <expect) 1 +' + test_done diff --git a/t/t5333-pseudo-merge-bitmaps.sh b/t/t5333-pseudo-merge-bitmaps.sh new file mode 100755 index 0000000000..f052f395a7 --- /dev/null +++ b/t/t5333-pseudo-merge-bitmaps.sh @@ -0,0 +1,393 @@ +#!/bin/sh + +test_description='pseudo-merge bitmaps' + +GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 + +. ./test-lib.sh + +test_pseudo_merges () { + test-tool bitmap dump-pseudo-merges +} + +test_pseudo_merge_commits () { + test-tool bitmap dump-pseudo-merge-commits "$1" +} + +test_pseudo_merges_satisfied () { + test_trace2_data bitmap pseudo_merges_satisfied "$1" +} + +test_pseudo_merges_cascades () { + test_trace2_data bitmap pseudo_merges_cascades "$1" +} + +test_pseudo_merges_reused () { + test_trace2_data pack-bitmap-write building_bitmaps_pseudo_merge_reused "$1" +} + +tag_everything () { + git rev-list --all --no-object-names >in && + perl -lne ' + print "create refs/tags/" . $. . " " . $1 if /([0-9a-f]+)/ + ' <in | git update-ref --stdin +} + +test_expect_success 'setup' ' + test_commit_bulk 512 && + tag_everything +' + +test_expect_success 'bitmap traversal without pseudo-merges' ' + git repack -adb && + + git rev-list --count --all --objects >expect && + + : >trace2.txt && + GIT_TRACE2_EVENT=$PWD/trace2.txt \ + git rev-list --count --all --objects --use-bitmap-index >actual && + + test_pseudo_merges_satisfied 0 <trace2.txt && + test_pseudo_merges_cascades 0 <trace2.txt && + test_pseudo_merges >merges && + test_must_be_empty merges && + test_cmp expect actual +' + +test_expect_success 'pseudo-merges accurately represent their objects' ' + test_config bitmapPseudoMerge.test.pattern "refs/tags/" && + test_config bitmapPseudoMerge.test.maxMerges 8 && + test_config bitmapPseudoMerge.test.stableThreshold never && + + git repack -adb && + + test_pseudo_merges >merges && + test_line_count = 8 merges && + + for i in $(test_seq 0 $(($(wc -l <merges)-1))) + do + test-tool bitmap dump-pseudo-merge-commits $i >commits && + + git rev-list --objects --no-object-names --stdin <commits >expect.raw && + test-tool bitmap dump-pseudo-merge-objects $i >actual.raw && + + sort -u <expect.raw >expect && + sort -u <actual.raw >actual && + + test_cmp expect actual || return 1 + done +' + +test_expect_success 'bitmap traversal with pseudo-merges' ' + : >trace2.txt && + GIT_TRACE2_EVENT=$PWD/trace2.txt \ + git rev-list --count --all --objects --use-bitmap-index >actual && + git rev-list --count --all --objects >expect && + + test_pseudo_merges_satisfied 8 <trace2.txt && + test_pseudo_merges_cascades 1 <trace2.txt && + test_cmp expect actual +' + +test_expect_success 'stale bitmap traversal with pseudo-merges' ' + test_commit other && + + : >trace2.txt && + GIT_TRACE2_EVENT=$PWD/trace2.txt \ + git rev-list --count --all --objects --use-bitmap-index >actual && + git rev-list --count --all --objects >expect && + + test_pseudo_merges_satisfied 8 <trace2.txt && + test_pseudo_merges_cascades 1 <trace2.txt && + test_cmp expect actual +' + +test_expect_success 'bitmapPseudoMerge.sampleRate adjusts commit selection rate' ' + test_config bitmapPseudoMerge.test.pattern "refs/tags/" && + test_config bitmapPseudoMerge.test.maxMerges 1 && + test_config bitmapPseudoMerge.test.stableThreshold never && + + commits_nr=$(git rev-list --all --count) && + + for rate in 1.0 0.5 0.25 + do + git -c bitmapPseudoMerge.test.sampleRate=$rate repack -adb && + + test_pseudo_merges >merges && + test_line_count = 1 merges && + test_pseudo_merge_commits 0 >commits && + + test-tool bitmap list-commits >bitmaps && + bitmaps_nr="$(wc -l <bitmaps)" && + + perl -MPOSIX -e "print ceil(\$ARGV[0]*(\$ARGV[1]-\$ARGV[2]))" \ + "$rate" "$commits_nr" "$bitmaps_nr" >expect && + + test $(cat expect) -eq $(wc -l <commits) || return 1 + done +' + +test_expect_success 'bitmapPseudoMerge.threshold excludes newer commits' ' + git init pseudo-merge-threshold && + ( + cd pseudo-merge-threshold && + + new="1672549200" && # 2023-01-01 + old="1641013200" && # 2022-01-01 + + GIT_COMMITTER_DATE="$new +0000" && + export GIT_COMMITTER_DATE && + test_commit_bulk --message="new" --notick 128 && + + GIT_COMMITTER_DATE="$old +0000" && + export GIT_COMMITTER_DATE && + test_commit_bulk --message="old" --notick 128 && + + tag_everything && + + git \ + -c bitmapPseudoMerge.test.pattern="refs/tags/" \ + -c bitmapPseudoMerge.test.maxMerges=1 \ + -c bitmapPseudoMerge.test.threshold=$(($new - 1)) \ + -c bitmapPseudoMerge.test.stableThreshold=never \ + repack -adb && + + test_pseudo_merges >merges && + test_line_count = 1 merges && + + test_pseudo_merge_commits 0 >oids && + git cat-file --batch <oids >commits && + + test $(wc -l <oids) = $(grep -c "^committer.*$old +0000$" commits) + ) +' + +test_expect_success 'bitmapPseudoMerge.stableThreshold creates stable groups' ' + ( + cd pseudo-merge-threshold && + + new="1672549200" && # 2023-01-01 + mid="1654059600" && # 2022-06-01 + old="1641013200" && # 2022-01-01 + + GIT_COMMITTER_DATE="$mid +0000" && + export GIT_COMMITTER_DATE && + test_commit_bulk --message="mid" --notick 128 && + + git for-each-ref --format="delete %(refname)" refs/tags >in && + git update-ref --stdin <in && + + tag_everything && + + git \ + -c bitmapPseudoMerge.test.pattern="refs/tags/" \ + -c bitmapPseudoMerge.test.maxMerges=1 \ + -c bitmapPseudoMerge.test.threshold=$(($new - 1)) \ + -c bitmapPseudoMerge.test.stableThreshold=$(($mid - 1)) \ + -c bitmapPseudoMerge.test.stableSize=10 \ + repack -adb && + + test_pseudo_merges >merges && + merges_nr="$(wc -l <merges)" && + + for i in $(test_seq $(($merges_nr - 1))) + do + test_pseudo_merge_commits 0 >oids && + git cat-file --batch <oids >commits && + + expect="$(grep -c "^committer.*$old +0000$" commits)" && + actual="$(wc -l <oids)" && + + test $expect = $actual || return 1 + done && + + test_pseudo_merge_commits $(($merges_nr - 1)) >oids && + git cat-file --batch <oids >commits && + test $(wc -l <oids) = $(grep -c "^committer.*$mid +0000$" commits) + ) +' + +test_expect_success 'out of order thresholds are rejected' ' + test_must_fail git \ + -c bitmapPseudoMerge.test.pattern="refs/*" \ + -c bitmapPseudoMerge.test.threshold=1.month.ago \ + -c bitmapPseudoMerge.test.stableThreshold=1.week.ago \ + repack -adb 2>err && + + cat >expect <<-EOF && + fatal: pseudo-merge group ${SQ}test${SQ} has unstable threshold before stable one + EOF + + test_cmp expect err +' + +test_expect_success 'pseudo-merge pattern with capture groups' ' + git init pseudo-merge-captures && + ( + cd pseudo-merge-captures && + + test_commit_bulk 128 && + tag_everything && + + for r in $(test_seq 8) + do + test_commit_bulk 16 && + + git rev-list HEAD~16.. >in && + + perl -lne "print \"create refs/remotes/$r/tags/\$. \$_\"" <in | + git update-ref --stdin || return 1 + done && + + git \ + -c bitmapPseudoMerge.tags.pattern="refs/remotes/([0-9]+)/tags/" \ + -c bitmapPseudoMerge.tags.maxMerges=1 \ + repack -adb && + + git for-each-ref --format="%(objectname) %(refname)" >refs && + + test_pseudo_merges >merges && + for m in $(test_seq 0 $(($(wc -l <merges) - 1))) + do + test_pseudo_merge_commits $m >oids && + grep -f oids refs | + perl -lne "print \$1 if /refs\/remotes\/([0-9]+)/" | + sort -u || return 1 + done >remotes && + + test $(wc -l <remotes) -eq $(sort -u <remotes | wc -l) + ) +' + +test_expect_success 'pseudo-merge overlap setup' ' + git init pseudo-merge-overlap && + ( + cd pseudo-merge-overlap && + + test_commit_bulk 256 && + tag_everything && + + git \ + -c bitmapPseudoMerge.all.pattern="refs/" \ + -c bitmapPseudoMerge.all.maxMerges=1 \ + -c bitmapPseudoMerge.all.stableThreshold=never \ + -c bitmapPseudoMerge.tags.pattern="refs/tags/" \ + -c bitmapPseudoMerge.tags.maxMerges=1 \ + -c bitmapPseudoMerge.tags.stableThreshold=never \ + repack -adb + ) +' + +test_expect_success 'pseudo-merge overlap generates overlapping groups' ' + ( + cd pseudo-merge-overlap && + + test_pseudo_merges >merges && + test_line_count = 2 merges && + + test_pseudo_merge_commits 0 >commits-0.raw && + test_pseudo_merge_commits 1 >commits-1.raw && + + sort commits-0.raw >commits-0 && + sort commits-1.raw >commits-1 && + + comm -12 commits-0 commits-1 >overlap && + + test_line_count -gt 0 overlap + ) +' + +test_expect_success 'pseudo-merge overlap traversal' ' + ( + cd pseudo-merge-overlap && + + : >trace2.txt && + GIT_TRACE2_EVENT=$PWD/trace2.txt \ + git rev-list --count --all --objects --use-bitmap-index >actual && + git rev-list --count --all --objects >expect && + + test_pseudo_merges_satisfied 2 <trace2.txt && + test_pseudo_merges_cascades 1 <trace2.txt && + test_cmp expect actual + ) +' + +test_expect_success 'pseudo-merge overlap stale traversal' ' + ( + cd pseudo-merge-overlap && + + test_commit other && + + : >trace2.txt && + GIT_TRACE2_EVENT=$PWD/trace2.txt \ + git rev-list --count --all --objects --use-bitmap-index >actual && + git rev-list --count --all --objects >expect && + + test_pseudo_merges_satisfied 2 <trace2.txt && + test_pseudo_merges_cascades 1 <trace2.txt && + test_cmp expect actual + ) +' + +test_expect_success 'pseudo-merge reuse' ' + git init pseudo-merge-reuse && + ( + cd pseudo-merge-reuse && + + stable="1641013200" && # 2022-01-01 + unstable="1672549200" && # 2023-01-01 + + GIT_COMMITTER_DATE="$stable +0000" && + export GIT_COMMITTER_DATE && + test_commit_bulk --notick 128 && + GIT_COMMITTER_DATE="$unstable +0000" && + export GIT_COMMITTER_DATE && + test_commit_bulk --notick 128 && + + tag_everything && + + git \ + -c bitmapPseudoMerge.test.pattern="refs/tags/" \ + -c bitmapPseudoMerge.test.maxMerges=1 \ + -c bitmapPseudoMerge.test.threshold=now \ + -c bitmapPseudoMerge.test.stableThreshold=$(($unstable - 1)) \ + -c bitmapPseudoMerge.test.stableSize=512 \ + repack -adb && + + test_pseudo_merges >merges && + test_line_count = 2 merges && + + test_pseudo_merge_commits 0 >stable-oids.before && + test_pseudo_merge_commits 1 >unstable-oids.before && + + : >trace2.txt && + GIT_TRACE2_EVENT=$PWD/trace2.txt git \ + -c bitmapPseudoMerge.test.pattern="refs/tags/" \ + -c bitmapPseudoMerge.test.maxMerges=2 \ + -c bitmapPseudoMerge.test.threshold=now \ + -c bitmapPseudoMerge.test.stableThreshold=$(($unstable - 1)) \ + -c bitmapPseudoMerge.test.stableSize=512 \ + repack -adb && + + test_pseudo_merges_reused 1 <trace2.txt && + + test_pseudo_merges >merges && + test_line_count = 3 merges && + + test_pseudo_merge_commits 0 >stable-oids.after && + for i in 1 2 + do + test_pseudo_merge_commits $i || return 1 + done >unstable-oids.after && + + sort -u <stable-oids.before >expect && + sort -u <stable-oids.after >actual && + test_cmp expect actual && + + sort -u <unstable-oids.before >expect && + sort -u <unstable-oids.after >actual && + test_cmp expect actual + ) +' + +test_done diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh index 1bc15a3f08..585ea0ee16 100755 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@ -993,6 +993,16 @@ test_expect_success 'ensure bogus fetch.negotiationAlgorithm yields error' ' fetch origin server_has both_have_2 ' +test_expect_success 'fetch-pack with fsckObjects and keep-file does not segfault' ' + rm -rf server client && + test_create_repo server && + test_commit -C server one && + + test_create_repo client && + git -c fetch.fsckObjects=true \ + -C client fetch-pack -k -k ../server HEAD +' + test_expect_success 'filtering by size' ' rm -rf server client && test_create_repo server && @@ -1046,7 +1056,7 @@ fetch_filter_blob_limit_zero () { # Ensure that commit is fetched, but blob is not commit=$(git -C "$SERVER" rev-parse two) && - blob=$(git hash-object server/two.t) && + blob=$(git hash-object "$SERVER/two.t") && git -C client rev-list --objects --missing=allow-any "$commit" >oids && grep "$commit" oids && ! grep "$blob" oids diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh index 5dbe107ce8..42e77eb5a9 100755 --- a/t/t5512-ls-remote.sh +++ b/t/t5512-ls-remote.sh @@ -47,6 +47,7 @@ test_expect_success setup ' git show-ref -d >refs && sed -e "s/ / /" refs >>expected.all && + grep refs/heads/ expected.all >expected.branches && git remote add self "$(pwd)/.git" && git remote add self2 "." ' @@ -71,6 +72,27 @@ test_expect_success 'ls-remote self' ' test_cmp expected.all actual ' +test_expect_success 'ls-remote --branches self' ' + git ls-remote --branches self >actual && + test_cmp expected.branches actual && + git ls-remote -b self >actual && + test_cmp expected.branches actual +' + +test_expect_success 'ls-remote -h is deprecated w/o warning' ' + git ls-remote -h self >actual 2>warning && + test_cmp expected.branches actual && + test_grep ! deprecated warning +' + +test_expect_success 'ls-remote --heads is deprecated and hidden w/o warning' ' + test_expect_code 129 git ls-remote -h >short-help && + test_grep ! -e --head short-help && + git ls-remote --heads self >actual 2>warning && + test_cmp expected.branches actual && + test_grep ! deprecated warning +' + test_expect_success 'ls-remote --sort="version:refname" --tags self' ' generate_references \ refs/tags/mark \ @@ -275,7 +297,7 @@ test_expect_success 'ls-remote with filtered symref (refname)' ' test_cmp expect actual ' -test_expect_success 'ls-remote with filtered symref (--heads)' ' +test_expect_success 'ls-remote with filtered symref (--branches)' ' git symbolic-ref refs/heads/foo refs/tags/mark && cat >expect.v2 <<-EOF && ref: refs/tags/mark refs/heads/foo @@ -283,9 +305,9 @@ test_expect_success 'ls-remote with filtered symref (--heads)' ' $rev refs/heads/main EOF grep -v "^ref: refs/tags/" <expect.v2 >expect.v0 && - git -c protocol.version=0 ls-remote --symref --heads . >actual.v0 && + git -c protocol.version=0 ls-remote --symref --branches . >actual.v0 && test_cmp expect.v0 actual.v0 && - git -c protocol.version=2 ls-remote --symref --heads . >actual.v2 && + git -c protocol.version=2 ls-remote --symref --branches . >actual.v2 && test_cmp expect.v2 actual.v2 ' @@ -335,9 +357,9 @@ test_expect_success 'ls-remote patterns work with all protocol versions' ' test_expect_success 'ls-remote prefixes work with all protocol versions' ' git for-each-ref --format="%(objectname) %(refname)" \ refs/heads/ refs/tags/ >expect && - git -c protocol.version=0 ls-remote --heads --tags . >actual.v0 && + git -c protocol.version=0 ls-remote --branches --tags . >actual.v0 && test_cmp expect actual.v0 && - git -c protocol.version=2 ls-remote --heads --tags . >actual.v2 && + git -c protocol.version=2 ls-remote --branches --tags . >actual.v2 && test_cmp expect actual.v2 ' diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index cc0b953f14..5d7ea147f1 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -46,6 +46,13 @@ test_expect_success 'output from clone' ' test $(grep Clon output | wc -l) = 1 ' +test_expect_success 'output from clone with core.abbrev does not crash' ' + rm -fr dst && + echo "Cloning into ${SQ}dst${SQ}..." >expect && + git -c core.abbrev=12 clone -n "file://$(pwd)/src" dst >actual 2>&1 && + test_cmp expect actual +' + test_expect_success 'clone does not keep pack' ' rm -fr dst && diff --git a/t/t5605-clone-local.sh b/t/t5605-clone-local.sh index a3055869bc..339d8c786f 100755 --- a/t/t5605-clone-local.sh +++ b/t/t5605-clone-local.sh @@ -163,7 +163,7 @@ test_expect_success REFFILES 'local clone from repo with corrupt refs fails grac echo a >corrupt/.git/refs/heads/topic && test_must_fail git clone corrupt working 2>err && - grep "has a null OID" err + grep "has neither a valid OID nor a target" err ' test_done diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh index 43d40175f8..1b5909d1b7 100755 --- a/t/t6500-gc.sh +++ b/t/t6500-gc.sh @@ -158,7 +158,7 @@ test_expect_success TTY 'with TTY: gc --no-quiet' ' git -c gc.writeCommitGraph=true gc --no-quiet >stdout 2>stderr && test_must_be_empty stdout && test_grep "Enumerating objects" stderr && - test_grep "Computing commit graph generation numbers" stderr + test_grep "Computing commit graph generation numbers: 100% (4/4), done." stderr ' test_expect_success 'gc --quiet' ' diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh index e5ff073099..ef54cff4fa 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -236,6 +236,16 @@ test_expect_success 'merge c1 with c2' ' verify_parents $c1 $c2 ' +test_expect_success 'merge c1 with c2 when index.lock exists' ' + test_when_finished rm .git/index.lock && + git reset --hard c1 && + >.git/index.lock && + test_must_fail git merge c2 && + test_path_is_missing .git/MERGE_HEAD && + test_path_is_missing .git/MERGE_MODE && + test_path_is_missing .git/MERGE_MSG +' + test_expect_success 'merge --squash c3 with c7' ' git reset --hard c3 && test_must_fail git merge --squash c7 && diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index 862d80c974..427b375b39 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -458,6 +458,7 @@ test_commit_bulk () { indir=. ref=HEAD n=1 + notick= message='commit %s' filename='%s.t' contents='content %s' @@ -488,6 +489,9 @@ test_commit_bulk () { filename="${1#--*=}-%s.t" contents="${1#--*=} %s" ;; + --notick) + notick=yes + ;; -*) BUG "invalid test_commit_bulk option: $1" ;; @@ -507,7 +511,10 @@ test_commit_bulk () { while test "$total" -gt 0 do - test_tick && + if test -z "$notick" + then + test_tick + fi && echo "commit $ref" printf 'author %s <%s> %s\n' \ "$GIT_AUTHOR_NAME" \ diff --git a/t/test-terminal.perl b/t/test-terminal.perl index 3810e9bb43..b8fd6a4f13 100755 --- a/t/test-terminal.perl +++ b/t/test-terminal.perl @@ -5,17 +5,15 @@ use warnings; use IO::Pty; use File::Copy; -# Run @$argv in the background with stdio redirected to $in, $out and $err. +# Run @$argv in the background with stdio redirected to $out and $err. sub start_child { - my ($argv, $in, $out, $err) = @_; + my ($argv, $out, $err) = @_; my $pid = fork; if (not defined $pid) { die "fork failed: $!" } elsif ($pid == 0) { - open STDIN, "<&", $in; open STDOUT, ">&", $out; open STDERR, ">&", $err; - close $in; close $out; exec(@$argv) or die "cannot exec '$argv->[0]': $!" } @@ -51,17 +49,6 @@ sub xsendfile { copy($in, $out, 4096) or $!{EIO} or die "cannot copy from child: $!"; } -sub copy_stdin { - my ($in) = @_; - my $pid = fork; - if (!$pid) { - xsendfile($in, \*STDIN); - exit 0; - } - close($in); - return $pid; -} - sub copy_stdio { my ($out, $err) = @_; my $pid = fork; @@ -81,25 +68,15 @@ if ($#ARGV < 1) { die "usage: test-terminal program args"; } $ENV{TERM} = 'vt100'; -my $parent_in = new IO::Pty; my $parent_out = new IO::Pty; my $parent_err = new IO::Pty; -$parent_in->set_raw(); $parent_out->set_raw(); $parent_err->set_raw(); -$parent_in->slave->set_raw(); $parent_out->slave->set_raw(); $parent_err->slave->set_raw(); -my $pid = start_child(\@ARGV, $parent_in->slave, $parent_out->slave, $parent_err->slave); -close $parent_in->slave; +my $pid = start_child(\@ARGV, $parent_out->slave, $parent_err->slave); close $parent_out->slave; close $parent_err->slave; -my $in_pid = copy_stdin($parent_in); copy_stdio($parent_out, $parent_err); my $ret = finish_child($pid); -# If the child process terminates before our copy_stdin() process is able to -# write all of its data to $parent_in, the copy_stdin() process could stall. -# Send SIGTERM to it to ensure it terminates. -kill 'TERM', $in_pid; -finish_child($in_pid); exit($ret); diff --git a/t/unit-tests/lib-oid.c b/t/unit-tests/lib-oid.c new file mode 100644 index 0000000000..37105f0a8f --- /dev/null +++ b/t/unit-tests/lib-oid.c @@ -0,0 +1,52 @@ +#include "test-lib.h" +#include "lib-oid.h" +#include "strbuf.h" +#include "hex.h" + +static int init_hash_algo(void) +{ + static int algo = -1; + + if (algo < 0) { + const char *algo_name = getenv("GIT_TEST_DEFAULT_HASH"); + algo = algo_name ? hash_algo_by_name(algo_name) : GIT_HASH_SHA1; + + if (!check(algo != GIT_HASH_UNKNOWN)) + test_msg("BUG: invalid GIT_TEST_DEFAULT_HASH value ('%s')", + algo_name); + } + return algo; +} + +static int get_oid_arbitrary_hex_algop(const char *hex, struct object_id *oid, + const struct git_hash_algo *algop) +{ + int ret; + size_t sz = strlen(hex); + struct strbuf buf = STRBUF_INIT; + + if (!check(sz <= algop->hexsz)) { + test_msg("BUG: hex string (%s) bigger than maximum allowed (%lu)", + hex, (unsigned long)algop->hexsz); + return -1; + } + + strbuf_add(&buf, hex, sz); + strbuf_addchars(&buf, '0', algop->hexsz - sz); + + ret = get_oid_hex_algop(buf.buf, oid, algop); + if (!check_int(ret, ==, 0)) + test_msg("BUG: invalid hex input (%s) provided", hex); + + strbuf_release(&buf); + return ret; +} + +int get_oid_arbitrary_hex(const char *hex, struct object_id *oid) +{ + int hash_algo = init_hash_algo(); + + if (!check_int(hash_algo, !=, GIT_HASH_UNKNOWN)) + return -1; + return get_oid_arbitrary_hex_algop(hex, oid, &hash_algos[hash_algo]); +} diff --git a/t/unit-tests/lib-oid.h b/t/unit-tests/lib-oid.h new file mode 100644 index 0000000000..bfde639190 --- /dev/null +++ b/t/unit-tests/lib-oid.h @@ -0,0 +1,17 @@ +#ifndef LIB_OID_H +#define LIB_OID_H + +#include "hash-ll.h" + +/* + * Convert arbitrary hex string to object_id. + * For example, passing "abc12" will generate + * "abc1200000000000000000000000000000000000" hex of length 40 for SHA-1 and + * create object_id with that. + * WARNING: passing a string of length more than the hexsz of respective hash + * algo is not allowed. The hash algo is decided based on GIT_TEST_DEFAULT_HASH + * environment variable. + */ +int get_oid_arbitrary_hex(const char *s, struct object_id *oid); + +#endif /* LIB_OID_H */ diff --git a/t/unit-tests/t-oidtree.c b/t/unit-tests/t-oidtree.c new file mode 100644 index 0000000000..a38754b066 --- /dev/null +++ b/t/unit-tests/t-oidtree.c @@ -0,0 +1,122 @@ +#include "test-lib.h" +#include "lib-oid.h" +#include "oidtree.h" +#include "hash.h" +#include "hex.h" +#include "strvec.h" + +#define FILL_TREE(tree, ...) \ + do { \ + const char *hexes[] = { __VA_ARGS__ }; \ + if (fill_tree_loc(tree, hexes, ARRAY_SIZE(hexes))) \ + return; \ + } while (0) + +static int fill_tree_loc(struct oidtree *ot, const char *hexes[], size_t n) +{ + for (size_t i = 0; i < n; i++) { + struct object_id oid; + if (!check_int(get_oid_arbitrary_hex(hexes[i], &oid), ==, 0)) + return -1; + oidtree_insert(ot, &oid); + } + return 0; +} + +static void check_contains(struct oidtree *ot, const char *hex, int expected) +{ + struct object_id oid; + + if (!check_int(get_oid_arbitrary_hex(hex, &oid), ==, 0)) + return; + if (!check_int(oidtree_contains(ot, &oid), ==, expected)) + test_msg("oid: %s", oid_to_hex(&oid)); +} + +struct expected_hex_iter { + size_t i; + struct strvec expected_hexes; + const char *query; +}; + +static enum cb_next check_each_cb(const struct object_id *oid, void *data) +{ + struct expected_hex_iter *hex_iter = data; + struct object_id expected; + + if (!check_int(hex_iter->i, <, hex_iter->expected_hexes.nr)) { + test_msg("error: extraneous callback for query: ('%s'), object_id: ('%s')", + hex_iter->query, oid_to_hex(oid)); + return CB_BREAK; + } + + if (!check_int(get_oid_arbitrary_hex(hex_iter->expected_hexes.v[hex_iter->i], + &expected), ==, 0)) + ; /* the data is bogus and cannot be used */ + else if (!check(oideq(oid, &expected))) + test_msg("expected: %s\n got: %s\n query: %s", + oid_to_hex(&expected), oid_to_hex(oid), hex_iter->query); + + hex_iter->i += 1; + return CB_CONTINUE; +} + +LAST_ARG_MUST_BE_NULL +static void check_each(struct oidtree *ot, const char *query, ...) +{ + struct object_id oid; + struct expected_hex_iter hex_iter = { .expected_hexes = STRVEC_INIT, + .query = query }; + const char *arg; + va_list hex_args; + + va_start(hex_args, query); + while ((arg = va_arg(hex_args, const char *))) + strvec_push(&hex_iter.expected_hexes, arg); + va_end(hex_args); + + if (!check_int(get_oid_arbitrary_hex(query, &oid), ==, 0)) + return; + oidtree_each(ot, &oid, strlen(query), check_each_cb, &hex_iter); + + if (!check_int(hex_iter.i, ==, hex_iter.expected_hexes.nr)) + test_msg("error: could not find some 'object_id's for query ('%s')", query); + strvec_clear(&hex_iter.expected_hexes); +} + +static void setup(void (*f)(struct oidtree *ot)) +{ + struct oidtree ot; + + oidtree_init(&ot); + f(&ot); + oidtree_clear(&ot); +} + +static void t_contains(struct oidtree *ot) +{ + FILL_TREE(ot, "444", "1", "2", "3", "4", "5", "a", "b", "c", "d", "e"); + check_contains(ot, "44", 0); + check_contains(ot, "441", 0); + check_contains(ot, "440", 0); + check_contains(ot, "444", 1); + check_contains(ot, "4440", 1); + check_contains(ot, "4444", 0); +} + +static void t_each(struct oidtree *ot) +{ + FILL_TREE(ot, "f", "9", "8", "123", "321", "320", "a", "b", "c", "d", "e"); + check_each(ot, "12300", "123", NULL); + check_each(ot, "3211", NULL); /* should not reach callback */ + check_each(ot, "3210", "321", NULL); + check_each(ot, "32100", "321", NULL); + check_each(ot, "32", "320", "321", NULL); +} + +int cmd_main(int argc UNUSED, const char **argv UNUSED) +{ + TEST(setup(t_contains), "oidtree insert and contains works"); + TEST(setup(t_each), "oidtree each works"); + return test_done(); +} diff --git a/t/unit-tests/t-reftable-basics.c b/t/unit-tests/t-reftable-basics.c index 529049af12..4e80bdf16d 100644 --- a/t/unit-tests/t-reftable-basics.c +++ b/t/unit-tests/t-reftable-basics.c @@ -54,15 +54,15 @@ static void test_binsearch(void) static void test_names_length(void) { - char *a[] = { "a", "b", NULL }; + const char *a[] = { "a", "b", NULL }; check_int(names_length(a), ==, 2); } static void test_names_equal(void) { - char *a[] = { "a", "b", "c", NULL }; - char *b[] = { "a", "b", "d", NULL }; - char *c[] = { "a", "b", NULL }; + const char *a[] = { "a", "b", "c", NULL }; + const char *b[] = { "a", "b", "d", NULL }; + const char *c[] = { "a", "b", NULL }; check(names_equal(a, a)); check(!names_equal(a, b)); diff --git a/t/unit-tests/t-strbuf.c b/t/unit-tests/t-strbuf.c index de434a4441..6027dafef7 100644 --- a/t/unit-tests/t-strbuf.c +++ b/t/unit-tests/t-strbuf.c @@ -2,7 +2,8 @@ #include "strbuf.h" /* wrapper that supplies tests with an empty, initialized strbuf */ -static void setup(void (*f)(struct strbuf*, void*), void *data) +static void setup(void (*f)(struct strbuf*, const void*), + const void *data) { struct strbuf buf = STRBUF_INIT; @@ -13,7 +14,8 @@ static void setup(void (*f)(struct strbuf*, void*), void *data) } /* wrapper that supplies tests with a populated, initialized strbuf */ -static void setup_populated(void (*f)(struct strbuf*, void*), char *init_str, void *data) +static void setup_populated(void (*f)(struct strbuf*, const void*), + const char *init_str, const void *data) { struct strbuf buf = STRBUF_INIT; @@ -64,7 +66,7 @@ static void t_dynamic_init(void) strbuf_release(&buf); } -static void t_addch(struct strbuf *buf, void *data) +static void t_addch(struct strbuf *buf, const void *data) { const char *p_ch = data; const char ch = *p_ch; @@ -83,7 +85,7 @@ static void t_addch(struct strbuf *buf, void *data) check_char(buf->buf[buf->len], ==, '\0'); } -static void t_addstr(struct strbuf *buf, void *data) +static void t_addstr(struct strbuf *buf, const void *data) { const char *text = data; size_t len = strlen(text); |
