diff options
Diffstat (limited to 't')
108 files changed, 2103 insertions, 154 deletions
diff --git a/t/Makefile b/t/Makefile index 056ce55dcc..7f56e52f76 100644 --- a/t/Makefile +++ b/t/Makefile @@ -35,7 +35,6 @@ TEST_RESULTS_DIRECTORY_SQ = $(subst ','\'',$(TEST_RESULTS_DIRECTORY)) CHAINLINTTMP_SQ = $(subst ','\'',$(CHAINLINTTMP)) T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)) -TGITWEB = $(sort $(wildcard t95[0-9][0-9]-*.sh)) THELPERS = $(sort $(filter-out $(T),$(wildcard *.sh))) TPERF = $(sort $(wildcard perf/p[0-9][0-9][0-9][0-9]-*.sh)) CHAINLINTTESTS = $(sort $(patsubst chainlint/%.test,%,$(wildcard chainlint/*.test))) @@ -112,9 +111,6 @@ aggregate-results: echo "$$f"; \ done | '$(SHELL_PATH_SQ)' ./aggregate-results.sh -gitweb-test: - $(MAKE) $(TGITWEB) - valgrind: $(MAKE) GIT_TEST_OPTS="$(GIT_TEST_OPTS) --valgrind" diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh index cc01d89150..f1b9a6ce4d 100644 --- a/t/annotate-tests.sh +++ b/t/annotate-tests.sh @@ -153,7 +153,7 @@ test_expect_success 'blame evil merge' ' test_expect_success 'blame huge graft' ' test_when_finished "git checkout branch2" && - test_when_finished "rm -f .git/info/grafts" && + test_when_finished "rm -rf .git/info" && graft= && for i in 0 1 2 do @@ -168,6 +168,7 @@ test_expect_success 'blame huge graft' ' graft="$graft$commit " || return 1 done done && + mkdir .git/info && printf "%s " $graft >.git/info/grafts && check_count -h 00 01 1 10 1 ' diff --git a/t/helper/test-bloom.c b/t/helper/test-bloom.c index ad3ef1cd77..6c900ca668 100644 --- a/t/helper/test-bloom.c +++ b/t/helper/test-bloom.c @@ -16,6 +16,7 @@ static void add_string_to_filter(const char *data, struct bloom_filter *filter) } printf("\n"); add_key_to_filter(&key, filter, &settings); + clear_bloom_key(&key); } static void print_bloom_filter(struct bloom_filter *filter) { @@ -80,6 +81,7 @@ int cmd__bloom(int argc, const char **argv) } print_bloom_filter(&filter); + free(filter.data); } if (!strcmp(argv[1], "get_filter_for_commit")) { diff --git a/t/helper/test-delta.c b/t/helper/test-delta.c index e749a49c88..b15481ea59 100644 --- a/t/helper/test-delta.c +++ b/t/helper/test-delta.c @@ -20,8 +20,9 @@ int cmd__delta(int argc, const char **argv) { int fd; struct stat st; - void *from_buf, *data_buf, *out_buf; + void *from_buf = NULL, *data_buf = NULL, *out_buf = NULL; unsigned long from_size, data_size, out_size; + int ret = 1; if (argc != 5 || (strcmp(argv[1], "-d") && strcmp(argv[1], "-p"))) { fprintf(stderr, "usage: %s\n", usage_str); @@ -38,21 +39,21 @@ int cmd__delta(int argc, const char **argv) if (read_in_full(fd, from_buf, from_size) < 0) { perror(argv[2]); close(fd); - return 1; + goto cleanup; } close(fd); fd = open(argv[3], O_RDONLY); if (fd < 0 || fstat(fd, &st)) { perror(argv[3]); - return 1; + goto cleanup; } data_size = st.st_size; data_buf = xmalloc(data_size); if (read_in_full(fd, data_buf, data_size) < 0) { perror(argv[3]); close(fd); - return 1; + goto cleanup; } close(fd); @@ -66,14 +67,20 @@ int cmd__delta(int argc, const char **argv) &out_size); if (!out_buf) { fprintf(stderr, "delta operation failed (returned NULL)\n"); - return 1; + goto cleanup; } fd = open (argv[4], O_WRONLY|O_CREAT|O_TRUNC, 0666); if (fd < 0 || write_in_full(fd, out_buf, out_size) < 0) { perror(argv[4]); - return 1; + goto cleanup; } - return 0; + ret = 0; +cleanup: + free(from_buf); + free(data_buf); + free(out_buf); + + return ret; } diff --git a/t/helper/test-dump-cache-tree.c b/t/helper/test-dump-cache-tree.c index 6a3f88f5f5..0d6d7f1ecb 100644 --- a/t/helper/test-dump-cache-tree.c +++ b/t/helper/test-dump-cache-tree.c @@ -59,11 +59,16 @@ int cmd__dump_cache_tree(int ac, const char **av) { struct index_state istate; struct cache_tree *another = cache_tree(); + int ret; + setup_git_directory(); if (read_cache() < 0) die("unable to read index file"); istate = the_index; istate.cache_tree = another; cache_tree_update(&istate, WRITE_TREE_DRY_RUN); - return dump_cache_tree(active_cache_tree, another, ""); + ret = dump_cache_tree(active_cache_tree, another, ""); + cache_tree_free(&another); + + return ret; } diff --git a/t/helper/test-hash.c b/t/helper/test-hash.c index 261c545b9d..5860dab0ff 100644 --- a/t/helper/test-hash.c +++ b/t/helper/test-hash.c @@ -54,5 +54,6 @@ int cmd_hash_impl(int ac, const char **av, int algo) fwrite(hash, 1, algop->rawsz, stdout); else puts(hash_to_hex_algop(hash, algop)); + free(buffer); return 0; } diff --git a/t/helper/test-json-writer.c b/t/helper/test-json-writer.c index 37c452535f..8c3edacc00 100644 --- a/t/helper/test-json-writer.c +++ b/t/helper/test-json-writer.c @@ -181,12 +181,18 @@ static struct json_writer nest1 = JSON_WRITER_INIT; static void make_nest1(int pretty) { + make_obj1(0); + make_arr1(0); + jw_object_begin(&nest1, pretty); { jw_object_sub_jw(&nest1, "obj1", &obj1); jw_object_sub_jw(&nest1, "arr1", &arr1); } jw_end(&nest1); + + jw_release(&obj1); + jw_release(&arr1); } static char *expect_inline1 = @@ -313,6 +319,9 @@ static void make_mixed1(int pretty) jw_object_sub_jw(&mixed1, "arr1", &arr1); } jw_end(&mixed1); + + jw_release(&obj1); + jw_release(&arr1); } static void cmp(const char *test, const struct json_writer *jw, const char *exp) @@ -325,8 +334,8 @@ static void cmp(const char *test, const struct json_writer *jw, const char *exp) exit(1); } -#define t(v) do { make_##v(0); cmp(#v, &v, expect_##v); } while (0) -#define p(v) do { make_##v(1); cmp(#v, &v, pretty_##v); } while (0) +#define t(v) do { make_##v(0); cmp(#v, &v, expect_##v); jw_release(&v); } while (0) +#define p(v) do { make_##v(1); cmp(#v, &v, pretty_##v); jw_release(&v); } while (0) /* * Run some basic regression tests with some known patterns. @@ -381,7 +390,6 @@ static int unit_tests(void) /* mixed forms */ t(mixed1); - jw_init(&mixed1); p(mixed1); return 0; @@ -544,7 +552,7 @@ static int scripted(void) printf("%s\n", jw.json.buf); - strbuf_release(&jw.json); + jw_release(&jw); return 0; } diff --git a/t/helper/test-mergesort.c b/t/helper/test-mergesort.c index ebf68f7de8..202e54a7ff 100644 --- a/t/helper/test-mergesort.c +++ b/t/helper/test-mergesort.c @@ -13,19 +13,10 @@ struct line { struct line *next; }; -static void *get_next(const void *a) -{ - return ((const struct line *)a)->next; -} - -static void set_next(void *a, void *b) -{ - ((struct line *)a)->next = b; -} +DEFINE_LIST_SORT(static, sort_lines, struct line, next); -static int compare_strings(const void *a, const void *b) +static int compare_strings(const struct line *x, const struct line *y) { - const struct line *x = a, *y = b; return strcmp(x->text, y->text); } @@ -47,7 +38,7 @@ static int sort_stdin(void) p = line; } - lines = llist_mergesort(lines, get_next, set_next, compare_strings); + sort_lines(&lines, compare_strings); while (lines) { puts(lines->text); @@ -273,21 +264,11 @@ struct number { struct number *next; }; -static void *get_next_number(const void *a) -{ - stats.get_next++; - return ((const struct number *)a)->next; -} - -static void set_next_number(void *a, void *b) -{ - stats.set_next++; - ((struct number *)a)->next = b; -} +DEFINE_LIST_SORT_DEBUG(static, sort_numbers, struct number, next, + stats.get_next++, stats.set_next++); -static int compare_numbers(const void *av, const void *bv) +static int compare_numbers(const struct number *an, const struct number *bn) { - const struct number *an = av, *bn = bv; int a = an->value, b = bn->value; stats.compare++; return (a > b) - (a < b); @@ -325,8 +306,7 @@ static int test(const struct dist *dist, const struct mode *mode, int n, int m) *tail = NULL; stats.get_next = stats.set_next = stats.compare = 0; - list = llist_mergesort(list, get_next_number, set_next_number, - compare_numbers); + sort_numbers(&list, compare_numbers); QSORT(arr, n, compare_ints); for (i = 0, curr = list; i < n && curr; i++, curr = curr->next) { diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c index 229ed416b0..d20e1b7a18 100644 --- a/t/helper/test-path-utils.c +++ b/t/helper/test-path-utils.c @@ -296,9 +296,8 @@ int cmd__path_utils(int argc, const char **argv) if (argc == 3 && !strcmp(argv[1], "normalize_path_copy")) { char *buf = xmallocz(strlen(argv[2])); int rv = normalize_path_copy(buf, argv[2]); - if (rv) - buf = "++failed++"; - puts(buf); + puts(rv ? "++failed++" : buf); + free(buf); return 0; } @@ -356,7 +355,10 @@ int cmd__path_utils(int argc, const char **argv) int nongit_ok; setup_git_directory_gently(&nongit_ok); while (argc > 3) { - puts(prefix_path(prefix, prefix_len, argv[3])); + char *pfx = prefix_path(prefix, prefix_len, argv[3]); + + puts(pfx); + free(pfx); argc--; argv++; } @@ -366,6 +368,7 @@ int cmd__path_utils(int argc, const char **argv) if (argc == 4 && !strcmp(argv[1], "strip_path_suffix")) { char *prefix = strip_path_suffix(argv[2], argv[3]); printf("%s\n", prefix ? prefix : "(null)"); + free(prefix); return 0; } diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index 9646d85fc8..4d18bfb1ca 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -96,6 +96,7 @@ static const char **get_store(const char **argv, struct ref_store **refs) die("no such worktree: %s", gitdir); *refs = get_worktree_ref_store(*p); + free_worktrees(worktrees); } else die("unknown backend %s", argv[0]); diff --git a/t/helper/test-regex.c b/t/helper/test-regex.c index d6f28ca8d1..bd871a735b 100644 --- a/t/helper/test-regex.c +++ b/t/helper/test-regex.c @@ -34,6 +34,7 @@ static int test_regex_bug(void) if (m[0].rm_so == 3) /* matches '\n' when it should not */ die("regex bug confirmed: re-build git with NO_REGEX=1"); + regfree(&r); return 0; } @@ -94,18 +95,20 @@ int cmd__regex(int argc, const char **argv) die("failed regcomp() for pattern '%s' (%s)", pat, errbuf); } if (!str) - return 0; + goto cleanup; ret = regexec(&r, str, 1, m, 0); if (ret) { if (silent || ret == REG_NOMATCH) - return ret; + goto cleanup; regerror(ret, &r, errbuf, sizeof(errbuf)); die("failed regexec() for subject '%s' (%s)", str, errbuf); } - return 0; +cleanup: + regfree(&r); + return ret; usage: usage("\ttest-tool regex --bug\n" "\ttest-tool regex [--silent] <pattern>\n" diff --git a/t/helper/test-scrap-cache-tree.c b/t/helper/test-scrap-cache-tree.c index 393f1604ff..026c802479 100644 --- a/t/helper/test-scrap-cache-tree.c +++ b/t/helper/test-scrap-cache-tree.c @@ -12,6 +12,7 @@ int cmd__scrap_cache_tree(int ac, const char **av) hold_locked_index(&index_lock, LOCK_DIE_ON_ERROR); if (read_cache() < 0) die("unable to read index file"); + cache_tree_free(&active_cache_tree); active_cache_tree = NULL; if (write_locked_index(&the_index, &index_lock, COMMIT_LOCK)) die("unable to write index file"); diff --git a/t/helper/test-urlmatch-normalization.c b/t/helper/test-urlmatch-normalization.c index 8f4d67e646..86edd454f5 100644 --- a/t/helper/test-urlmatch-normalization.c +++ b/t/helper/test-urlmatch-normalization.c @@ -5,8 +5,9 @@ int cmd__urlmatch_normalization(int argc, const char **argv) { const char usage[] = "test-tool urlmatch-normalization [-p | -l] <url1> | <url1> <url2>"; - char *url1, *url2; + char *url1 = NULL, *url2 = NULL; int opt_p = 0, opt_l = 0; + int ret = 0; /* * For one url, succeed if url_normalize succeeds on it, fail otherwise. @@ -39,7 +40,7 @@ int cmd__urlmatch_normalization(int argc, const char **argv) printf("%s\n", url1); if (opt_l) printf("%u\n", (unsigned)info.url_len); - return 0; + goto cleanup; } if (opt_p || opt_l) @@ -47,5 +48,9 @@ int cmd__urlmatch_normalization(int argc, const char **argv) url1 = url_normalize(argv[1], NULL); url2 = url_normalize(argv[2], NULL); - return (url1 && url2 && !strcmp(url1, url2)) ? 0 : 1; + ret = (url1 && url2 && !strcmp(url1, url2)) ? 0 : 1; +cleanup: + free(url1); + free(url2); + return ret; } diff --git a/t/lib-parallel-checkout.sh b/t/lib-parallel-checkout.sh index 83b279a846..acaee9cbb6 100644 --- a/t/lib-parallel-checkout.sh +++ b/t/lib-parallel-checkout.sh @@ -25,7 +25,11 @@ test_checkout_workers () { local trace_file=trace-test-checkout-workers && rm -f "$trace_file" && - GIT_TRACE2="$(pwd)/$trace_file" "$@" 2>&8 && + ( + GIT_TRACE2="$(pwd)/$trace_file" && + export GIT_TRACE2 && + "$@" 2>&8 + ) && local workers="$(grep "child_start\[..*\] git checkout--worker" "$trace_file" | wc -l)" && test $workers -eq $expected_workers && diff --git a/t/lib-proto-disable.sh b/t/lib-proto-disable.sh index 83babe57d9..890622be81 100644 --- a/t/lib-proto-disable.sh +++ b/t/lib-proto-disable.sh @@ -1,7 +1,7 @@ # Test routines for checking protocol disabling. -# Test clone/fetch/push with GIT_ALLOW_PROTOCOL whitelist -test_whitelist () { +# Test clone/fetch/push with GIT_ALLOW_PROTOCOL environment variable +test_allow_var () { desc=$1 proto=$2 url=$3 @@ -183,7 +183,7 @@ test_config () { # $2 - machine-readable name of the protocol # $3 - the URL to try cloning test_proto () { - test_whitelist "$@" + test_allow_var "$@" test_config "$@" } diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh index ec6b9b107d..b57541356b 100644 --- a/t/lib-rebase.sh +++ b/t/lib-rebase.sh @@ -207,3 +207,18 @@ check_reworded_commits () { >reword-log && test_cmp reword-expected reword-log } + +# usage: set_replace_editor <file> +# +# Replace the todo file with the exact contents of the given file. +set_replace_editor () { + cat >script <<-\EOF && + cat FILENAME >"$1" + + echo 'rebase -i script after editing:' + cat "$1" + EOF + + sed -e "s/FILENAME/$1/g" <script | write_script fake-editor.sh && + test_set_editor "$(pwd)/fake-editor.sh" +} diff --git a/t/lib-submodule-update.sh b/t/lib-submodule-update.sh index f7c7df0ca4..03e0abbdb8 100644 --- a/t/lib-submodule-update.sh +++ b/t/lib-submodule-update.sh @@ -207,7 +207,7 @@ prolog () { # should be updated to an existing commit. reset_work_tree_to () { rm -rf submodule_update && - git clone submodule_update_repo submodule_update && + git clone --template= submodule_update_repo submodule_update && ( cd submodule_update && rm -rf sub1 && @@ -902,13 +902,14 @@ test_submodule_switch_recursing_with_args () { ' # ... but an ignored file is fine. test_expect_$RESULTOI "$command: added submodule removes an untracked ignored file" ' - test_when_finished "rm submodule_update/.git/info/exclude" && + test_when_finished "rm -rf submodule_update/.git/info" && prolog && reset_work_tree_to_interested no_submodule && ( cd submodule_update && git branch -t add_sub1 origin/add_sub1 && : >sub1 && + mkdir .git/info && echo sub1 >.git/info/exclude && $command add_sub1 && test_superproject_content origin/add_sub1 && @@ -951,7 +952,9 @@ test_submodule_switch_recursing_with_args () { reset_work_tree_to_interested add_sub1 && ( cd submodule_update && + rm -rf .git/modules/sub1/info && git branch -t replace_sub1_with_file origin/replace_sub1_with_file && + mkdir .git/modules/sub1/info && echo ignored >.git/modules/sub1/info/exclude && : >sub1/ignored && $command replace_sub1_with_file && diff --git a/t/perf/p0071-sort.sh b/t/perf/p0071-sort.sh index ed366e2e12..ae4ddac864 100755 --- a/t/perf/p0071-sort.sh +++ b/t/perf/p0071-sort.sh @@ -40,11 +40,11 @@ done for file in unsorted sorted reversed do - test_perf "llist_mergesort() $file" " + test_perf "DEFINE_LIST_SORT $file" " test-tool mergesort sort <$file >actual " - test_expect_success "llist_mergesort() $file sorts like sort(1)" " + test_expect_success "DEFINE_LIST_SORT $file sorts like sort(1)" " test_cmp_bin sorted actual " done diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index 143f100517..f7ee2f2ff0 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -3,6 +3,7 @@ test_description=gitattributes TEST_PASSES_SANITIZE_LEAK=true +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh attr_check_basic () { @@ -284,7 +285,7 @@ test_expect_success 'using --git-dir and --work-tree' ' ' test_expect_success 'setup bare' ' - git clone --bare . bare.git + git clone --template= --bare . bare.git ' test_expect_success 'bare repository: check that .gitattribute is ignored' ' @@ -315,6 +316,7 @@ test_expect_success 'bare repository: check that --cached honors index' ' test_expect_success 'bare repository: test info/attributes' ' ( cd bare.git && + mkdir info && ( echo "f test=f" && echo "a/i test=a/i" @@ -360,6 +362,7 @@ test_expect_success SYMLINKS 'symlinks respected in core.attributesFile' ' test_expect_success SYMLINKS 'symlinks respected in info/attributes' ' test_when_finished "rm .git/info/attributes" && + mkdir .git/info && ln -s ../../attr .git/info/attributes && attr_check file set ' diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh index 5575dade8e..c70d11bc91 100755 --- a/t/t0008-ignores.sh +++ b/t/t0008-ignores.sh @@ -3,6 +3,7 @@ test_description=check-ignore TEST_PASSES_SANITIZE_LEAK=true +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh init_vars () { @@ -225,7 +226,8 @@ test_expect_success 'setup' ' !globaltwo globalthree EOF - cat <<-\EOF >>.git/info/exclude + mkdir .git/info && + cat <<-\EOF >.git/info/exclude per-repo EOF ' @@ -543,9 +545,9 @@ test_expect_success_multi 'submodule from subdirectory' '' ' test_expect_success 'global ignore not yet enabled' ' expect_from_stdin <<-\EOF && - .git/info/exclude:7:per-repo per-repo + .git/info/exclude:1:per-repo per-repo a/.gitignore:2:*three a/globalthree - .git/info/exclude:7:per-repo a/per-repo + .git/info/exclude:1:per-repo a/per-repo EOF test_check_ignore "-v globalone per-repo a/globalthree a/per-repo not-ignored a/globaltwo" ' @@ -566,10 +568,10 @@ test_expect_success 'global ignore with -v' ' enable_global_excludes && expect_from_stdin <<-EOF && $global_excludes:1:globalone globalone - .git/info/exclude:7:per-repo per-repo + .git/info/exclude:1:per-repo per-repo $global_excludes:3:globalthree globalthree a/.gitignore:2:*three a/globalthree - .git/info/exclude:7:per-repo a/per-repo + .git/info/exclude:1:per-repo a/per-repo $global_excludes:2:!globaltwo globaltwo EOF test_check_ignore "-v globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo" diff --git a/t/t0015-hash.sh b/t/t0015-hash.sh index 086822fc45..0a087a1983 100755 --- a/t/t0015-hash.sh +++ b/t/t0015-hash.sh @@ -1,8 +1,9 @@ #!/bin/sh test_description='test basic hash implementation' -. ./test-lib.sh +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh test_expect_success 'test basic SHA-1 hash values' ' test-tool sha1 </dev/null >actual && diff --git a/t/t0019-json-writer.sh b/t/t0019-json-writer.sh index 3b0c336b38..19a730c29e 100755 --- a/t/t0019-json-writer.sh +++ b/t/t0019-json-writer.sh @@ -1,6 +1,8 @@ #!/bin/sh test_description='test json-writer JSON generation' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'unit test of json-writer routines' ' diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh index bad37abad2..1c840348bd 100755 --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@ -1132,4 +1132,26 @@ do ' done +test_expect_success PERL 'delayed checkout correctly reports the number of updated entries' ' + rm -rf repo && + git init repo && + ( + cd repo && + git config filter.delay.process "../rot13-filter.pl delayed.log clean smudge delay" && + git config filter.delay.required true && + + echo "*.a filter=delay" >.gitattributes && + echo a >test-delay10.a && + echo a >test-delay11.a && + git add . && + git commit -m files && + + rm *.a && + git checkout . 2>err && + grep "IN: smudge test-delay10.a .* \\[DELAYED\\]" delayed.log && + grep "IN: smudge test-delay11.a .* \\[DELAYED\\]" delayed.log && + grep "Updated 2 paths from the index" err + ) +' + test_done diff --git a/t/t0028-working-tree-encoding.sh b/t/t0028-working-tree-encoding.sh index 82905a2156..c196fdb0ee 100755 --- a/t/t0028-working-tree-encoding.sh +++ b/t/t0028-working-tree-encoding.sh @@ -5,6 +5,8 @@ test_description='working-tree-encoding conversion via gitattributes' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh . "$TEST_DIRECTORY/lib-encoding.sh" @@ -69,6 +71,7 @@ test_expect_success 'check $GIT_DIR/info/attributes support' ' test_when_finished "rm -f test.utf32.git" && test_when_finished "git reset --hard HEAD" && + mkdir .git/info && echo "*.utf32 text working-tree-encoding=utf-32" >.git/info/attributes && git add test.utf32 && diff --git a/t/t0033-safe-directory.sh b/t/t0033-safe-directory.sh index 3908597d42..f4d737dadd 100755 --- a/t/t0033-safe-directory.sh +++ b/t/t0033-safe-directory.sh @@ -16,24 +16,20 @@ test_expect_success 'safe.directory is not set' ' expect_rejected_dir ' -test_expect_success 'ignoring safe.directory on the command line' ' - test_must_fail git -c safe.directory="$(pwd)" status 2>err && - grep "dubious ownership" err +test_expect_success 'safe.directory on the command line' ' + git -c safe.directory="$(pwd)" status ' -test_expect_success 'ignoring safe.directory in the environment' ' - test_must_fail env GIT_CONFIG_COUNT=1 \ - GIT_CONFIG_KEY_0="safe.directory" \ - GIT_CONFIG_VALUE_0="$(pwd)" \ - git status 2>err && - grep "dubious ownership" err +test_expect_success 'safe.directory in the environment' ' + env GIT_CONFIG_COUNT=1 \ + GIT_CONFIG_KEY_0="safe.directory" \ + GIT_CONFIG_VALUE_0="$(pwd)" \ + git status ' -test_expect_success 'ignoring safe.directory in GIT_CONFIG_PARAMETERS' ' - test_must_fail env \ - GIT_CONFIG_PARAMETERS="${SQ}safe.directory${SQ}=${SQ}$(pwd)${SQ}" \ - git status 2>err && - grep "dubious ownership" err +test_expect_success 'safe.directory in GIT_CONFIG_PARAMETERS' ' + env GIT_CONFIG_PARAMETERS="${SQ}safe.directory${SQ}=${SQ}$(pwd)${SQ}" \ + git status ' test_expect_success 'ignoring safe.directory in repo config' ' diff --git a/t/t0035-safe-bare-repository.sh b/t/t0035-safe-bare-repository.sh new file mode 100755 index 0000000000..ecbdc8238d --- /dev/null +++ b/t/t0035-safe-bare-repository.sh @@ -0,0 +1,54 @@ +#!/bin/sh + +test_description='verify safe.bareRepository checks' + +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh + +pwd="$(pwd)" + +expect_accepted () { + git "$@" rev-parse --git-dir +} + +expect_rejected () { + test_must_fail git "$@" rev-parse --git-dir 2>err && + grep -F "cannot use bare repository" err +} + +test_expect_success 'setup bare repo in worktree' ' + git init outer-repo && + git init --bare outer-repo/bare-repo +' + +test_expect_success 'safe.bareRepository unset' ' + expect_accepted -C outer-repo/bare-repo +' + +test_expect_success 'safe.bareRepository=all' ' + test_config_global safe.bareRepository all && + expect_accepted -C outer-repo/bare-repo +' + +test_expect_success 'safe.bareRepository=explicit' ' + test_config_global safe.bareRepository explicit && + expect_rejected -C outer-repo/bare-repo +' + +test_expect_success 'safe.bareRepository in the repository' ' + # safe.bareRepository must not be "explicit", otherwise + # git config fails with "fatal: not in a git directory" (like + # safe.directory) + test_config -C outer-repo/bare-repo safe.bareRepository \ + all && + test_config_global safe.bareRepository explicit && + expect_rejected -C outer-repo/bare-repo +' + +test_expect_success 'safe.bareRepository on the command line' ' + test_config_global safe.bareRepository explicit && + expect_accepted -C outer-repo/bare-repo \ + -c safe.bareRepository=all +' + +test_done diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh index aa35350b6f..1f2007e62b 100755 --- a/t/t0060-path-utils.sh +++ b/t/t0060-path-utils.sh @@ -5,6 +5,7 @@ test_description='Test various path utilities' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh norm_path() { diff --git a/t/t0071-sort.sh b/t/t0071-sort.sh index 6f9a501c72..ba8ad1d1ca 100755 --- a/t/t0071-sort.sh +++ b/t/t0071-sort.sh @@ -5,7 +5,7 @@ test_description='verify sort functions' TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh -test_expect_success 'llist_mergesort()' ' +test_expect_success 'DEFINE_LIST_SORT_DEBUG' ' test-tool mergesort test ' diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh index 9067572648..d8e2fc42e1 100755 --- a/t/t0090-cache-tree.sh +++ b/t/t0090-cache-tree.sh @@ -5,6 +5,8 @@ test_description="Test whether cache-tree is properly updated Tests whether various commands properly update and/or rewrite the cache-tree extension. " + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh cmp_cache_tree () { diff --git a/t/t0095-bloom.sh b/t/t0095-bloom.sh index 5945973552..daeb4a5e3e 100755 --- a/t/t0095-bloom.sh +++ b/t/t0095-bloom.sh @@ -67,7 +67,7 @@ test_expect_success 'compute bloom key for test string 2' ' test_cmp expect actual ' -test_expect_success 'get bloom filters for commit with no changes' ' +test_expect_success !SANITIZE_LEAK 'get bloom filters for commit with no changes' ' git init && git commit --allow-empty -m "c0" && cat >expect <<-\EOF && diff --git a/t/t0110-urlmatch-normalization.sh b/t/t0110-urlmatch-normalization.sh index 4dc9fecf72..12d817fbd3 100755 --- a/t/t0110-urlmatch-normalization.sh +++ b/t/t0110-urlmatch-normalization.sh @@ -1,6 +1,8 @@ #!/bin/sh test_description='urlmatch URL normalization' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # The base name of the test url files diff --git a/t/t0212/parse_events.perl b/t/t0212/parse_events.perl index b6408560c0..30a9f51e9f 100644 --- a/t/t0212/parse_events.perl +++ b/t/t0212/parse_events.perl @@ -216,12 +216,19 @@ while (<>) { elsif ($event eq 'data') { my $cat = $line->{'category'}; - if ($cat eq 'test_category') { - - my $key = $line->{'key'}; - my $value = $line->{'value'}; - $processes->{$sid}->{'data'}->{$cat}->{$key} = $value; - } + my $key = $line->{'key'}; + my $value = $line->{'value'}; + $processes->{$sid}->{'data'}->{$cat}->{$key} = $value; + } + + elsif ($event eq 'data_json') { + # NEEDSWORK: Ignore due to + # compat/win32/trace2_win32_process_info.c, which should log a + # "cmd_ancestry" event instead. + } + + else { + push @{$processes->{$sid}->{$event}} => $line->{value}; } # This trace2 target does not emit 'printf' events. diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh index dadf3b1458..23b8942edb 100755 --- a/t/t1006-cat-file.sh +++ b/t/t1006-cat-file.sh @@ -88,7 +88,8 @@ done for opt in --buffer \ --follow-symlinks \ - --batch-all-objects + --batch-all-objects \ + -z do test_expect_success "usage: bad option combination: $opt without batch mode" ' test_incompatible_usage git cat-file $opt && @@ -100,6 +101,10 @@ echo_without_newline () { printf '%s' "$*" } +echo_without_newline_nul () { + echo_without_newline "$@" | tr '\n' '\0' +} + strlen () { echo_without_newline "$1" | wc -c | sed -e 's/^ *//' } @@ -398,6 +403,12 @@ test_expect_success '--batch with multiple sha1s gives correct format' ' test "$(maybe_remove_timestamp "$batch_output" 1)" = "$(maybe_remove_timestamp "$(echo_without_newline "$batch_input" | git cat-file --batch)" 1)" ' +test_expect_success '--batch, -z with multiple sha1s gives correct format' ' + echo_without_newline_nul "$batch_input" >in && + test "$(maybe_remove_timestamp "$batch_output" 1)" = \ + "$(maybe_remove_timestamp "$(git cat-file --batch -z <in)" 1)" +' + batch_check_input="$hello_sha1 $tree_sha1 $commit_sha1 @@ -418,6 +429,30 @@ test_expect_success "--batch-check with multiple sha1s gives correct format" ' "$(echo_without_newline "$batch_check_input" | git cat-file --batch-check)" ' +test_expect_success "--batch-check, -z with multiple sha1s gives correct format" ' + echo_without_newline_nul "$batch_check_input" >in && + test "$batch_check_output" = "$(git cat-file --batch-check -z <in)" +' + +test_expect_success FUNNYNAMES '--batch-check, -z with newline in input' ' + touch -- "newline${LF}embedded" && + git add -- "newline${LF}embedded" && + git commit -m "file with newline embedded" && + test_tick && + + printf "HEAD:newline${LF}embedded" >in && + git cat-file --batch-check -z <in >actual && + + echo "$(git rev-parse "HEAD:newline${LF}embedded") blob 0" >expect && + test_cmp expect actual +' + +batch_command_multiple_info="info $hello_sha1 +info $tree_sha1 +info $commit_sha1 +info $tag_sha1 +info deadbeef" + test_expect_success '--batch-command with multiple info calls gives correct format' ' cat >expect <<-EOF && $hello_sha1 blob $hello_size @@ -427,17 +462,23 @@ test_expect_success '--batch-command with multiple info calls gives correct form deadbeef missing EOF - git cat-file --batch-command --buffer >actual <<-EOF && - info $hello_sha1 - info $tree_sha1 - info $commit_sha1 - info $tag_sha1 - info deadbeef - EOF + echo "$batch_command_multiple_info" >in && + git cat-file --batch-command --buffer <in >actual && + + test_cmp expect actual && + + echo "$batch_command_multiple_info" | tr "\n" "\0" >in && + git cat-file --batch-command --buffer -z <in >actual && test_cmp expect actual ' +batch_command_multiple_contents="contents $hello_sha1 +contents $commit_sha1 +contents $tag_sha1 +contents deadbeef +flush" + test_expect_success '--batch-command with multiple command calls gives correct format' ' remove_timestamp >expect <<-EOF && $hello_sha1 blob $hello_size @@ -449,13 +490,14 @@ test_expect_success '--batch-command with multiple command calls gives correct f deadbeef missing EOF - git cat-file --batch-command --buffer >actual_raw <<-EOF && - contents $hello_sha1 - contents $commit_sha1 - contents $tag_sha1 - contents deadbeef - flush - EOF + echo "$batch_command_multiple_contents" >in && + git cat-file --batch-command --buffer <in >actual_raw && + + remove_timestamp <actual_raw >actual && + test_cmp expect actual && + + echo "$batch_command_multiple_contents" | tr "\n" "\0" >in && + git cat-file --batch-command --buffer -z <in >actual_raw && remove_timestamp <actual_raw >actual && test_cmp expect actual diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh index 63a553d7b3..742f0fa909 100755 --- a/t/t1011-read-tree-sparse-checkout.sh +++ b/t/t1011-read-tree-sparse-checkout.sh @@ -11,6 +11,7 @@ test_description='sparse checkout tests A init.t ' +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh . "$TEST_DIRECTORY"/lib-read-tree.sh @@ -53,6 +54,7 @@ test_expect_success 'read-tree without .git/info/sparse-checkout' ' ' test_expect_success 'read-tree with .git/info/sparse-checkout but disabled' ' + mkdir .git/info && echo >.git/info/sparse-checkout && read_tree_u_must_succeed -m -u HEAD && git ls-files -t >result && diff --git a/t/t1051-large-conversion.sh b/t/t1051-large-conversion.sh index 042b0e4429..f6709c9f56 100755 --- a/t/t1051-large-conversion.sh +++ b/t/t1051-large-conversion.sh @@ -1,6 +1,8 @@ #!/bin/sh test_description='test conversion filters on large files' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh set_attr() { diff --git a/t/t1090-sparse-checkout-scope.sh b/t/t1090-sparse-checkout-scope.sh index d1833c0f31..3a14218b24 100755 --- a/t/t1090-sparse-checkout-scope.sh +++ b/t/t1090-sparse-checkout-scope.sh @@ -5,6 +5,7 @@ test_description='sparse checkout scope tests' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh test_expect_success 'setup' ' @@ -25,6 +26,7 @@ test_expect_success 'create feature branch' ' test_expect_success 'perform sparse checkout of main' ' git config --local --bool core.sparsecheckout true && + mkdir .git/info && echo "!/*" >.git/info/sparse-checkout && echo "/a" >>.git/info/sparse-checkout && echo "/c" >>.git/info/sparse-checkout && @@ -73,7 +75,7 @@ test_expect_success 'skip-worktree on files outside sparse patterns' ' test_expect_success 'in partial clone, sparse checkout only fetches needed blobs' ' test_create_repo server && - git clone "file://$(pwd)/server" client && + git clone --template= "file://$(pwd)/server" client && test_config -C server uploadpack.allowfilter 1 && test_config -C server uploadpack.allowanysha1inwant 1 && @@ -85,6 +87,7 @@ test_expect_success 'in partial clone, sparse checkout only fetches needed blobs git -C server commit -m message && test_config -C client core.sparsecheckout 1 && + mkdir client/.git/info && echo "!/*" >client/.git/info/sparse-checkout && echo "/a" >>client/.git/info/sparse-checkout && git -C client fetch --filter=blob:none origin && diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh index f9f8c988bb..763c6cc684 100755 --- a/t/t1092-sparse-checkout-compatibility.sh +++ b/t/t1092-sparse-checkout-compatibility.sh @@ -1828,4 +1828,29 @@ test_expect_success 'checkout behaves oddly with df-conflict-2' ' test_cmp full-checkout-err sparse-index-err ' +test_expect_success 'mv directory from out-of-cone to in-cone' ' + init_repos && + + # <source> as a sparse directory (or SKIP_WORKTREE_DIR without enabling + # sparse index). + test_all_match git mv --sparse folder1 deep && + test_all_match git status --porcelain=v2 && + test_sparse_match git ls-files -t && + git -C sparse-checkout ls-files -t >actual && + grep -e "H deep/folder1/0/0/0" actual && + grep -e "H deep/folder1/0/1" actual && + grep -e "H deep/folder1/a" actual && + + test_all_match git reset --hard && + + # <source> as a directory deeper than sparse index boundary (where + # sparse index will expand). + test_sparse_match git mv --sparse folder1/0 deep && + test_sparse_match git status --porcelain=v2 && + test_sparse_match git ls-files -t && + git -C sparse-checkout ls-files -t >actual && + grep -e "H deep/0/0/0" actual && + grep -e "H deep/0/1" actual +' + test_done diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh index 84bf1970d8..93a2f91f8a 100755 --- a/t/t1301-shared-repo.sh +++ b/t/t1301-shared-repo.sh @@ -48,7 +48,7 @@ done test_expect_success 'shared=all' ' mkdir sub && cd sub && - git init --shared=all && + git init --template= --shared=all && test 2 = $(git config core.sharedrepository) ' @@ -57,6 +57,7 @@ test_expect_success POSIXPERM 'update-server-info honors core.sharedRepository' git add a1 && test_tick && git commit -m a1 && + mkdir .git/info && umask 0277 && git update-server-info && actual="$(ls -l .git/info/refs)" && diff --git a/t/t1402-check-ref-format.sh b/t/t1402-check-ref-format.sh index cabc516ae9..5ed9d7318e 100755 --- a/t/t1402-check-ref-format.sh +++ b/t/t1402-check-ref-format.sh @@ -2,6 +2,7 @@ test_description='Test git check-ref-format' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh valid_ref() { diff --git a/t/t2018-checkout-branch.sh b/t/t2018-checkout-branch.sh index 52e51b0726..771c3c3c50 100755 --- a/t/t2018-checkout-branch.sh +++ b/t/t2018-checkout-branch.sh @@ -2,6 +2,7 @@ test_description='checkout' +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh # Arguments: [!] <branch> <oid> [<checkout options>] @@ -257,11 +258,12 @@ test_expect_success 'checkout -b to a new branch preserves mergeable changes des git checkout branch1-scratch && test_might_fail git branch -D branch3 && git config core.sparseCheckout false && - rm .git/info/sparse-checkout" && + rm -rf .git/info" && test_commit file2 && echo stuff >>file1 && + mkdir .git/info && echo file2 >.git/info/sparse-checkout && git config core.sparseCheckout true && diff --git a/t/t2030-unresolve-info.sh b/t/t2030-unresolve-info.sh index f691e6d903..2d8c70b03a 100755 --- a/t/t2030-unresolve-info.sh +++ b/t/t2030-unresolve-info.sh @@ -194,4 +194,75 @@ test_expect_success 'rerere forget (add-add conflict)' ' test_i18ngrep "no remembered" actual ' +test_expect_success 'resolve-undo keeps blobs from gc' ' + git checkout -f main && + + # First make sure we do not have any cruft left in the object store + git repack -a -d && + git prune --expire=now && + git prune-packed && + git gc --prune=now && + git fsck --unreachable >cruft && + test_must_be_empty cruft && + + # Now add three otherwise unreferenced blob objects to the index + git reset --hard && + B1=$(echo "resolve undo test data 1" | git hash-object -w --stdin) && + B2=$(echo "resolve undo test data 2" | git hash-object -w --stdin) && + B3=$(echo "resolve undo test data 3" | git hash-object -w --stdin) && + git update-index --add --index-info <<-EOF && + 100644 $B1 1 frotz + 100644 $B2 2 frotz + 100644 $B3 3 frotz + EOF + + # These three blob objects are reachable (only) from the index + git fsck --unreachable >cruft && + test_must_be_empty cruft && + # and they should be protected from GC + git gc --prune=now && + git cat-file -e $B1 && + git cat-file -e $B2 && + git cat-file -e $B3 && + + # Now resolve the conflicted path + B0=$(echo "resolve undo test data 0" | git hash-object -w --stdin) && + git update-index --add --cacheinfo 100644,$B0,frotz && + + # These three blob objects are now reachable only from the resolve-undo + git fsck --unreachable >cruft && + test_must_be_empty cruft && + + # and they should survive GC + git gc --prune=now && + git cat-file -e $B0 && + git cat-file -e $B1 && + git cat-file -e $B2 && + git cat-file -e $B3 && + + # Now we switch away, which nukes resolve-undo, and + # blobs B0..B3 would become dangling. fsck should + # notice that they are now unreachable. + git checkout -f side && + git fsck --unreachable >cruft && + sort cruft >actual && + sort <<-EOF >expect && + unreachable blob $B0 + unreachable blob $B1 + unreachable blob $B2 + unreachable blob $B3 + EOF + test_cmp expect actual && + + # And they should go away when gc runs. + git gc --prune=now && + git fsck --unreachable >cruft && + test_must_be_empty cruft && + + test_must_fail git cat-file -e $B0 && + test_must_fail git cat-file -e $B1 && + test_must_fail git cat-file -e $B2 && + test_must_fail git cat-file -e $B3 +' + test_done diff --git a/t/t2080-parallel-checkout-basics.sh b/t/t2080-parallel-checkout-basics.sh index 3e0f8c675f..c683e60007 100755 --- a/t/t2080-parallel-checkout-basics.sh +++ b/t/t2080-parallel-checkout-basics.sh @@ -226,4 +226,52 @@ test_expect_success SYMLINKS 'parallel checkout checks for symlinks in leading d ) ' +# This test is here (and not in e.g. t2022-checkout-paths.sh), because we +# check the final report including sequential, parallel, and delayed entries +# all at the same time. So we must have finer control of the parallel checkout +# variables. +test_expect_success PERL '"git checkout ." report should not include failed entries' ' + write_script rot13-filter.pl "$PERL_PATH" \ + <"$TEST_DIRECTORY"/t0021/rot13-filter.pl && + + test_config_global filter.delay.process \ + "\"$(pwd)/rot13-filter.pl\" --always-delay delayed.log clean smudge delay" && + test_config_global filter.delay.required true && + test_config_global filter.cat.clean cat && + test_config_global filter.cat.smudge cat && + test_config_global filter.cat.required true && + + set_checkout_config 2 0 && + git init failed_entries && + ( + cd failed_entries && + cat >.gitattributes <<-EOF && + *delay* filter=delay + parallel-ineligible* filter=cat + EOF + echo a >missing-delay.a && + echo a >parallel-ineligible.a && + echo a >parallel-eligible.a && + echo b >success-delay.b && + echo b >parallel-ineligible.b && + echo b >parallel-eligible.b && + git add -A && + git commit -m files && + + a_blob="$(git rev-parse :parallel-ineligible.a)" && + rm .git/objects/$(test_oid_to_path $a_blob) && + rm *.a *.b && + + test_checkout_workers 2 test_must_fail git checkout . 2>err && + + # All *.b entries should succeed and all *.a entries should fail: + # - missing-delay.a: the delay filter will drop this path + # - parallel-*.a: the blob will be missing + # + grep "Updated 3 paths from the index" err && + test_stdout_line_count = 3 ls *.b && + ! ls *.a + ) +' + test_done diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh index 2f564d533d..f3242fef6b 100755 --- a/t/t2400-worktree-add.sh +++ b/t/t2400-worktree-add.sh @@ -5,6 +5,7 @@ test_description='test git worktree add' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh . "$TEST_DIRECTORY"/lib-rebase.sh @@ -229,6 +230,7 @@ test_expect_success 'checkout with grafts' ' SHA1=$(git rev-parse HEAD) && test_commit def && test_commit xyz && + mkdir .git/info && echo "$(git rev-parse HEAD) $SHA1" >.git/info/grafts && cat >expected <<-\EOF && xyz @@ -559,6 +561,8 @@ test_expect_success 'git worktree --no-guess-remote option overrides config' ' ' post_checkout_hook () { + test_when_finished "rm -rf .git/hooks" && + mkdir .git/hooks && test_hook -C "$1" post-checkout <<-\EOF { echo $* diff --git a/t/t2407-worktree-heads.sh b/t/t2407-worktree-heads.sh new file mode 100755 index 0000000000..50815acd3e --- /dev/null +++ b/t/t2407-worktree-heads.sh @@ -0,0 +1,180 @@ +#!/bin/sh + +test_description='test operations trying to overwrite refs at worktree HEAD' + +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit init && + + for i in 1 2 3 4 + do + git checkout -b conflict-$i && + echo "not I" >$i.t && + git add $i.t && + git commit -m "will conflict" && + + git checkout - && + test_commit $i && + git branch wt-$i && + git branch fake-$i && + git worktree add wt-$i wt-$i || return 1 + done && + + # Create a server that updates each branch by one commit + git init server && + test_commit -C server initial && + git remote add server ./server && + for i in 1 2 3 4 + do + git -C server checkout -b wt-$i && + test_commit -C server A-$i || return 1 + done && + for i in 1 2 + do + git -C server checkout -b fake-$i && + test_commit -C server f-$i || return 1 + done +' + +test_expect_success 'refuse to overwrite: checked out in worktree' ' + for i in 1 2 3 4 + do + test_must_fail git branch -f wt-$i HEAD 2>err + grep "cannot force update the branch" err && + + test_must_fail git branch -D wt-$i 2>err + grep "Cannot delete branch" err || return 1 + done +' + +test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in bisect' ' + test_when_finished git -C wt-4 bisect reset && + + # Set up a bisect so HEAD no longer points to wt-4. + git -C wt-4 bisect start && + git -C wt-4 bisect bad wt-4 && + git -C wt-4 bisect good wt-1 && + + test_must_fail git branch -f wt-4 HEAD 2>err && + grep "cannot force update the branch '\''wt-4'\'' checked out at.*wt-4" err +' + +test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (apply)' ' + test_when_finished git -C wt-2 rebase --abort && + + # This will fail part-way through due to a conflict. + test_must_fail git -C wt-2 rebase --apply conflict-2 && + + test_must_fail git branch -f wt-2 HEAD 2>err && + grep "cannot force update the branch '\''wt-2'\'' checked out at.*wt-2" err +' + +test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (merge)' ' + test_when_finished git -C wt-2 rebase --abort && + + # This will fail part-way through due to a conflict. + test_must_fail git -C wt-2 rebase conflict-2 && + + test_must_fail git branch -f wt-2 HEAD 2>err && + grep "cannot force update the branch '\''wt-2'\'' checked out at.*wt-2" err +' + +test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase with --update-refs' ' + test_when_finished git -C wt-3 rebase --abort && + + git branch -f can-be-updated wt-3 && + test_must_fail git -C wt-3 rebase --update-refs conflict-3 && + + for i in 3 4 + do + test_must_fail git branch -f can-be-updated HEAD 2>err && + grep "cannot force update the branch '\''can-be-updated'\'' checked out at.*wt-3" err || + return 1 + done +' + +test_expect_success !SANITIZE_LEAK 'refuse to fetch over ref: checked out' ' + test_must_fail git fetch server +refs/heads/wt-3:refs/heads/wt-3 2>err && + grep "refusing to fetch into branch '\''refs/heads/wt-3'\''" err && + + # General fetch into refs/heads/ will fail on first ref, + # so use a generic error message check. + test_must_fail git fetch server +refs/heads/*:refs/heads/* 2>err && + grep "refusing to fetch into branch" err +' + +test_expect_success !SANITIZE_LEAK 'refuse to fetch over ref: worktree in bisect' ' + test_when_finished git -C wt-4 bisect reset && + + # Set up a bisect so HEAD no longer points to wt-4. + git -C wt-4 bisect start && + git -C wt-4 bisect bad wt-4 && + git -C wt-4 bisect good wt-1 && + + test_must_fail git fetch server +refs/heads/wt-4:refs/heads/wt-4 2>err && + grep "refusing to fetch into branch" err +' + +test_expect_success !SANITIZE_LEAK 'refuse to fetch over ref: worktree in rebase' ' + test_when_finished git -C wt-3 rebase --abort && + + # This will fail part-way through due to a conflict. + test_must_fail git -C wt-3 rebase conflict-3 && + + test_must_fail git fetch server +refs/heads/wt-3:refs/heads/wt-3 2>err && + grep "refusing to fetch into branch" err +' + +test_expect_success 'refuse to overwrite when in error states' ' + test_when_finished rm -rf .git/worktrees/wt-*/rebase-merge && + test_when_finished rm -rf .git/worktrees/wt-*/BISECT_* && + + # Both branches are currently under rebase. + mkdir -p .git/worktrees/wt-3/rebase-merge && + touch .git/worktrees/wt-3/rebase-merge/interactive && + echo refs/heads/fake-1 >.git/worktrees/wt-3/rebase-merge/head-name && + echo refs/heads/fake-2 >.git/worktrees/wt-3/rebase-merge/onto && + mkdir -p .git/worktrees/wt-4/rebase-merge && + touch .git/worktrees/wt-4/rebase-merge/interactive && + echo refs/heads/fake-2 >.git/worktrees/wt-4/rebase-merge/head-name && + echo refs/heads/fake-1 >.git/worktrees/wt-4/rebase-merge/onto && + + # Both branches are currently under bisect. + touch .git/worktrees/wt-4/BISECT_LOG && + echo refs/heads/fake-2 >.git/worktrees/wt-4/BISECT_START && + touch .git/worktrees/wt-1/BISECT_LOG && + echo refs/heads/fake-1 >.git/worktrees/wt-1/BISECT_START && + + for i in 1 2 + do + test_must_fail git branch -f fake-$i HEAD 2>err && + grep "cannot force update the branch '\''fake-$i'\'' checked out at" err || + return 1 + done +' + +. "$TEST_DIRECTORY"/lib-rebase.sh + +test_expect_success !SANITIZE_LEAK 'refuse to overwrite during rebase with --update-refs' ' + git commit --fixup HEAD~2 --allow-empty && + ( + set_cat_todo_editor && + test_must_fail git rebase -i --update-refs HEAD~3 >todo && + ! grep "update-refs" todo + ) && + git branch -f allow-update HEAD~2 && + ( + set_cat_todo_editor && + test_must_fail git rebase -i --update-refs HEAD~3 >todo && + grep "update-ref refs/heads/allow-update" todo + ) +' + +# This must be the last test in this file +test_expect_success '$EDITOR and friends are unchanged' ' + test_editor_unchanged +' + +test_done diff --git a/t/t3013-ls-files-format.sh b/t/t3013-ls-files-format.sh new file mode 100755 index 0000000000..efb7450bf1 --- /dev/null +++ b/t/t3013-ls-files-format.sh @@ -0,0 +1,95 @@ +#!/bin/sh + +test_description='git ls-files --format test' + +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh + +for flag in -s -o -k -t --resolve-undo --deduplicate --eol +do + test_expect_success "usage: --format is incompatible with $flag" ' + test_expect_code 129 git ls-files --format="%(objectname)" $flag + ' +done + +test_expect_success 'setup' ' + printf "LINEONE\nLINETWO\nLINETHREE\n" >o1.txt && + printf "LINEONE\r\nLINETWO\r\nLINETHREE\r\n" >o2.txt && + printf "LINEONE\r\nLINETWO\nLINETHREE\n" >o3.txt && + git add o?.txt && + oid=$(git hash-object o1.txt) && + git update-index --add --cacheinfo 120000 $oid o4.txt && + git update-index --add --cacheinfo 160000 $oid o5.txt && + git update-index --add --cacheinfo 100755 $oid o6.txt && + git commit -m base +' + +test_expect_success 'git ls-files --format objectmode v.s. -s' ' + git ls-files -s >files && + cut -d" " -f1 files >expect && + git ls-files --format="%(objectmode)" >actual && + test_cmp expect actual +' + +test_expect_success 'git ls-files --format objectname v.s. -s' ' + git ls-files -s >files && + cut -d" " -f2 files >expect && + git ls-files --format="%(objectname)" >actual && + test_cmp expect actual +' + +test_expect_success 'git ls-files --format v.s. --eol' ' + git ls-files --eol >tmp && + sed -e "s/ / /g" -e "s/ */ /g" tmp >expect 2>err && + test_must_be_empty err && + git ls-files --format="i/%(eolinfo:index) w/%(eolinfo:worktree) attr/%(eolattr) %(path)" >actual 2>err && + test_must_be_empty err && + test_cmp expect actual +' + +test_expect_success 'git ls-files --format path v.s. -s' ' + git ls-files -s >files && + cut -f2 files >expect && + git ls-files --format="%(path)" >actual && + test_cmp expect actual +' + +test_expect_success 'git ls-files --format with -m' ' + echo change >o1.txt && + cat >expect <<-\EOF && + o1.txt + o4.txt + o5.txt + o6.txt + EOF + git ls-files --format="%(path)" -m >actual && + test_cmp expect actual +' + +test_expect_success 'git ls-files --format with -d' ' + echo o7 >o7.txt && + git add o7.txt && + rm o7.txt && + cat >expect <<-\EOF && + o4.txt + o5.txt + o6.txt + o7.txt + EOF + git ls-files --format="%(path)" -d >actual && + test_cmp expect actual +' + +test_expect_success 'git ls-files --format v.s -s' ' + git ls-files --stage >expect && + git ls-files --format="%(objectmode) %(objectname) %(stage)%x09%(path)" >actual && + test_cmp expect actual +' + +test_expect_success 'git ls-files --format with --debug' ' + git ls-files --debug >expect && + git ls-files --format="%(path)" --debug >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t3304-notes-mixed.sh b/t/t3304-notes-mixed.sh index 03dfcd3954..2c3a245266 100755 --- a/t/t3304-notes-mixed.sh +++ b/t/t3304-notes-mixed.sh @@ -5,6 +5,7 @@ test_description='Test notes trees that also contain non-notes' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh number_of_commits=100 diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index f31afd4a54..688b01e3eb 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -1743,6 +1743,279 @@ test_expect_success 'ORIG_HEAD is updated correctly' ' test_cmp_rev ORIG_HEAD test-orig-head@{1} ' +test_expect_success '--update-refs adds label and update-ref commands' ' + git checkout -b update-refs no-conflict-branch && + git branch -f base HEAD~4 && + git branch -f first HEAD~3 && + git branch -f second HEAD~3 && + git branch -f third HEAD~1 && + git commit --allow-empty --fixup=third && + git branch -f is-not-reordered && + git commit --allow-empty --fixup=HEAD~4 && + git branch -f shared-tip && + ( + set_cat_todo_editor && + + cat >expect <<-EOF && + pick $(git log -1 --format=%h J) J + fixup $(git log -1 --format=%h update-refs) fixup! J # empty + update-ref refs/heads/second + update-ref refs/heads/first + pick $(git log -1 --format=%h K) K + pick $(git log -1 --format=%h L) L + fixup $(git log -1 --format=%h is-not-reordered) fixup! L # empty + update-ref refs/heads/third + pick $(git log -1 --format=%h M) M + update-ref refs/heads/no-conflict-branch + update-ref refs/heads/is-not-reordered + update-ref refs/heads/shared-tip + EOF + + test_must_fail git rebase -i --autosquash --update-refs primary >todo && + test_cmp expect todo && + + test_must_fail git -c rebase.autosquash=true \ + -c rebase.updaterefs=true \ + rebase -i primary >todo && + + test_cmp expect todo + ) +' + +test_expect_success '--update-refs adds commands with --rebase-merges' ' + git checkout -b update-refs-with-merge no-conflict-branch && + git branch -f base HEAD~4 && + git branch -f first HEAD~3 && + git branch -f second HEAD~3 && + git branch -f third HEAD~1 && + git merge -m merge branch2 && + git branch -f merge-branch && + git commit --fixup=third --allow-empty && + ( + set_cat_todo_editor && + + cat >expect <<-EOF && + label onto + reset onto + pick $(git log -1 --format=%h branch2~1) F + pick $(git log -1 --format=%h branch2) I + update-ref refs/heads/branch2 + label merge + reset onto + pick $(git log -1 --format=%h refs/heads/second) J + update-ref refs/heads/second + update-ref refs/heads/first + pick $(git log -1 --format=%h refs/heads/third~1) K + pick $(git log -1 --format=%h refs/heads/third) L + fixup $(git log -1 --format=%h update-refs-with-merge) fixup! L # empty + update-ref refs/heads/third + pick $(git log -1 --format=%h HEAD~2) M + update-ref refs/heads/no-conflict-branch + merge -C $(git log -1 --format=%h HEAD~1) merge # merge + update-ref refs/heads/merge-branch + EOF + + test_must_fail git rebase -i --autosquash \ + --rebase-merges=rebase-cousins \ + --update-refs primary >todo && + + test_cmp expect todo && + + test_must_fail git -c rebase.autosquash=true \ + -c rebase.updaterefs=true \ + rebase -i \ + --rebase-merges=rebase-cousins \ + primary >todo && + + test_cmp expect todo + ) +' + +test_expect_success '--update-refs updates refs correctly' ' + git checkout -B update-refs no-conflict-branch && + git branch -f base HEAD~4 && + git branch -f first HEAD~3 && + git branch -f second HEAD~3 && + git branch -f third HEAD~1 && + test_commit extra2 fileX && + git commit --amend --fixup=L && + + git rebase -i --autosquash --update-refs primary 2>err && + + test_cmp_rev HEAD~3 refs/heads/first && + test_cmp_rev HEAD~3 refs/heads/second && + test_cmp_rev HEAD~1 refs/heads/third && + test_cmp_rev HEAD refs/heads/no-conflict-branch && + + cat >expect <<-\EOF && + Successfully rebased and updated refs/heads/update-refs. + Updated the following refs with --update-refs: + refs/heads/first + refs/heads/no-conflict-branch + refs/heads/second + refs/heads/third + EOF + + # Clear "Rebasing (X/Y)" progress lines and drop leading tabs. + sed -e "s/Rebasing.*Successfully/Successfully/g" -e "s/^\t//g" \ + <err >err.trimmed && + test_cmp expect err.trimmed +' + +test_expect_success 'respect user edits to update-ref steps' ' + git checkout -B update-refs-break no-conflict-branch && + git branch -f base HEAD~4 && + git branch -f first HEAD~3 && + git branch -f second HEAD~3 && + git branch -f third HEAD~1 && + git branch -f unseen base && + + # First, we will add breaks to the expected todo file + cat >fake-todo-1 <<-EOF && + pick $(git rev-parse HEAD~3) + break + update-ref refs/heads/second + update-ref refs/heads/first + + pick $(git rev-parse HEAD~2) + pick $(git rev-parse HEAD~1) + update-ref refs/heads/third + + pick $(git rev-parse HEAD) + update-ref refs/heads/no-conflict-branch + EOF + + # Second, we will drop some update-refs commands (and move one) + cat >fake-todo-2 <<-EOF && + update-ref refs/heads/second + + pick $(git rev-parse HEAD~2) + update-ref refs/heads/third + pick $(git rev-parse HEAD~1) + break + + pick $(git rev-parse HEAD) + EOF + + # Third, we will: + # * insert a new one (new-branch), + # * re-add an old one (first), and + # * add a second instance of a previously-stored one (second) + cat >fake-todo-3 <<-EOF && + update-ref refs/heads/unseen + update-ref refs/heads/new-branch + pick $(git rev-parse HEAD) + update-ref refs/heads/first + update-ref refs/heads/second + EOF + + ( + set_replace_editor fake-todo-1 && + git rebase -i --update-refs primary && + + # These branches are currently locked. + for b in first second third no-conflict-branch + do + test_must_fail git branch -f $b base || return 1 + done && + + set_replace_editor fake-todo-2 && + git rebase --edit-todo && + + # These branches are currently locked. + for b in second third + do + test_must_fail git branch -f $b base || return 1 + done && + + # These branches are currently unlocked for checkout. + for b in first no-conflict-branch + do + git worktree add wt-$b $b && + git worktree remove wt-$b || return 1 + done && + + git rebase --continue && + + set_replace_editor fake-todo-3 && + git rebase --edit-todo && + + # These branches are currently locked. + for b in second third first unseen + do + test_must_fail git branch -f $b base || return 1 + done && + + # These branches are currently unlocked for checkout. + for b in no-conflict-branch + do + git worktree add wt-$b $b && + git worktree remove wt-$b || return 1 + done && + + git rebase --continue + ) && + + test_cmp_rev HEAD~2 refs/heads/third && + test_cmp_rev HEAD~1 refs/heads/unseen && + test_cmp_rev HEAD~1 refs/heads/new-branch && + test_cmp_rev HEAD refs/heads/first && + test_cmp_rev HEAD refs/heads/second && + test_cmp_rev HEAD refs/heads/no-conflict-branch +' + +test_expect_success '--update-refs: check failed ref update' ' + git checkout -B update-refs-error no-conflict-branch && + git branch -f base HEAD~4 && + git branch -f first HEAD~3 && + git branch -f second HEAD~2 && + git branch -f third HEAD~1 && + + cat >fake-todo <<-EOF && + pick $(git rev-parse HEAD~3) + break + update-ref refs/heads/first + + pick $(git rev-parse HEAD~2) + update-ref refs/heads/second + + pick $(git rev-parse HEAD~1) + update-ref refs/heads/third + + pick $(git rev-parse HEAD) + update-ref refs/heads/no-conflict-branch + EOF + + ( + set_replace_editor fake-todo && + git rebase -i --update-refs base + ) && + + # At this point, the values of first, second, and third are + # recorded in the update-refs file. We will force-update the + # "second" ref, but "git branch -f" will not work because of + # the lock in the update-refs file. + git rev-parse third >.git/refs/heads/second && + + test_must_fail git rebase --continue 2>err && + grep "update_ref failed for ref '\''refs/heads/second'\''" err && + + cat >expect <<-\EOF && + Updated the following refs with --update-refs: + refs/heads/first + refs/heads/no-conflict-branch + refs/heads/third + Failed to update the following refs with --update-refs: + refs/heads/second + EOF + + # Clear "Rebasing (X/Y)" progress lines and drop leading tabs. + tail -n 6 err >err.last && + sed -e "s/Rebasing.*Successfully/Successfully/g" -e "s/^\t//g" \ + <err.last >err.trimmed && + test_cmp expect err.trimmed +' + # This must be the last test in this file test_expect_success '$EDITOR and friends are unchanged' ' test_editor_unchanged diff --git a/t/t3426-rebase-submodule.sh b/t/t3426-rebase-submodule.sh index 0ad3a07bf4..7a9f1127a4 100755 --- a/t/t3426-rebase-submodule.sh +++ b/t/t3426-rebase-submodule.sh @@ -35,6 +35,7 @@ git_rebase_interactive () { ls -1pR * >>actual && test_cmp expect actual && set_fake_editor && + mkdir .git/info && echo "fake-editor.sh" >.git/info/exclude && may_only_be_test_must_fail "$2" && $2 git rebase -i "$1" diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh index 979e843c65..f32799e046 100755 --- a/t/t3507-cherry-pick-conflict.sh +++ b/t/t3507-cherry-pick-conflict.sh @@ -12,6 +12,7 @@ test_description='test cherry-pick and revert with conflicts GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh pristine_detach () { @@ -558,6 +559,7 @@ test_expect_success 'cherry-pick preserves sparse-checkout' ' echo \"/*\" >.git/info/sparse-checkout git read-tree --reset -u HEAD rm .git/info/sparse-checkout" && + mkdir .git/info && echo /unrelated >.git/info/sparse-checkout && git read-tree --reset -u HEAD && test_must_fail git cherry-pick -Xours picked>actual && diff --git a/t/t4044-diff-index-unique-abbrev.sh b/t/t4044-diff-index-unique-abbrev.sh index 4701796d10..29e49d2290 100755 --- a/t/t4044-diff-index-unique-abbrev.sh +++ b/t/t4044-diff-index-unique-abbrev.sh @@ -1,6 +1,8 @@ #!/bin/sh test_description='test unique sha1 abbreviation on "index from..to" line' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t4140-apply-ita.sh b/t/t4140-apply-ita.sh index c614eaf04c..b375aca0d7 100755 --- a/t/t4140-apply-ita.sh +++ b/t/t4140-apply-ita.sh @@ -2,6 +2,7 @@ test_description='git apply of i-t-a file' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh index 9f8c76dffb..7025cfdae5 100755 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@ -365,9 +365,6 @@ test_expect_success 'set up an unresolved merge' ' test_might_fail git config --unset rerere.autoupdate && git reset --hard && git checkout version2 && - fifth=$(git rev-parse fifth) && - echo "$fifth branch fifth of ." | - git fmt-merge-msg >msg && ancestor=$(git merge-base version2 fifth) && test_must_fail git merge-recursive "$ancestor" -- HEAD fifth && diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh index 0b2d21ec55..cd1cab3e54 100755 --- a/t/t4203-mailmap.sh +++ b/t/t4203-mailmap.sh @@ -963,4 +963,63 @@ test_expect_success SYMLINKS 'symlinks not respected in-tree' ' test_cmp expect actual ' +test_expect_success 'prepare for cat-file --mailmap' ' + rm -f .mailmap && + git commit --allow-empty -m foo --author="Orig <orig@example.com>" +' + +test_expect_success '--no-use-mailmap disables mailmap in cat-file' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-EOF && + A U Thor <author@example.com> Orig <orig@example.com> + EOF + cat >expect <<-EOF && + author Orig <orig@example.com> + EOF + git cat-file --no-use-mailmap commit HEAD >log && + sed -n "/^author /s/\([^>]*>\).*/\1/p" log >actual && + test_cmp expect actual +' + +test_expect_success '--use-mailmap enables mailmap in cat-file' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-EOF && + A U Thor <author@example.com> Orig <orig@example.com> + EOF + cat >expect <<-EOF && + author A U Thor <author@example.com> + EOF + git cat-file --use-mailmap commit HEAD >log && + sed -n "/^author /s/\([^>]*>\).*/\1/p" log >actual && + test_cmp expect actual +' + +test_expect_success '--no-mailmap disables mailmap in cat-file for annotated tag objects' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-EOF && + Orig <orig@example.com> C O Mitter <committer@example.com> + EOF + cat >expect <<-EOF && + tagger C O Mitter <committer@example.com> + EOF + git tag -a -m "annotated tag" v1 && + git cat-file --no-mailmap -p v1 >log && + sed -n "/^tagger /s/\([^>]*>\).*/\1/p" log >actual && + test_cmp expect actual +' + +test_expect_success '--mailmap enables mailmap in cat-file for annotated tag objects' ' + test_when_finished "rm .mailmap" && + cat >.mailmap <<-EOF && + Orig <orig@example.com> C O Mitter <committer@example.com> + EOF + cat >expect <<-EOF && + tagger Orig <orig@example.com> + EOF + git tag -a -m "annotated tag" v2 && + git cat-file --mailmap -p v2 >log && + sed -n "/^tagger /s/\([^>]*>\).*/\1/p" log >actual && + test_cmp expect actual +' + test_done diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh new file mode 100755 index 0000000000..f091259a55 --- /dev/null +++ b/t/t4301-merge-tree-write-tree.sh @@ -0,0 +1,240 @@ +#!/bin/sh + +test_description='git merge-tree --write-tree' + +. ./test-lib.sh + +# This test is ort-specific +if test "$GIT_TEST_MERGE_ALGORITHM" != "ort" +then + skip_all="GIT_TEST_MERGE_ALGORITHM != ort" + test_done +fi + +test_expect_success setup ' + test_write_lines 1 2 3 4 5 >numbers && + echo hello >greeting && + echo foo >whatever && + git add numbers greeting whatever && + test_tick && + git commit -m initial && + + git branch side1 && + git branch side2 && + git branch side3 && + + git checkout side1 && + test_write_lines 1 2 3 4 5 6 >numbers && + echo hi >greeting && + echo bar >whatever && + git add numbers greeting whatever && + test_tick && + git commit -m modify-stuff && + + git checkout side2 && + test_write_lines 0 1 2 3 4 5 >numbers && + echo yo >greeting && + git rm whatever && + mkdir whatever && + >whatever/empty && + git add numbers greeting whatever/empty && + test_tick && + git commit -m other-modifications && + + git checkout side3 && + git mv numbers sequence && + test_tick && + git commit -m rename-numbers && + + git switch --orphan unrelated && + >something-else && + git add something-else && + test_tick && + git commit -m first-commit +' + +test_expect_success 'Clean merge' ' + TREE_OID=$(git merge-tree --write-tree side1 side3) && + q_to_tab <<-EOF >expect && + 100644 blob $(git rev-parse side1:greeting)Qgreeting + 100644 blob $(git rev-parse side1:numbers)Qsequence + 100644 blob $(git rev-parse side1:whatever)Qwhatever + EOF + + git ls-tree $TREE_OID >actual && + test_cmp expect actual +' + +test_expect_success 'Content merge and a few conflicts' ' + git checkout side1^0 && + test_must_fail git merge side2 && + expected_tree=$(git rev-parse AUTO_MERGE) && + + # We will redo the merge, while we are still in a conflicted state! + git ls-files -u >conflicted-file-info && + test_when_finished "git reset --hard" && + + test_expect_code 1 git merge-tree --write-tree side1 side2 >RESULT && + actual_tree=$(head -n 1 RESULT) && + + # Due to differences of e.g. "HEAD" vs "side1", the results will not + # exactly match. Dig into individual files. + + # Numbers should have three-way merged cleanly + test_write_lines 0 1 2 3 4 5 6 >expect && + git show ${actual_tree}:numbers >actual && + test_cmp expect actual && + + # whatever and whatever~<branch> should have same HASHES + git rev-parse ${expected_tree}:whatever ${expected_tree}:whatever~HEAD >expect && + git rev-parse ${actual_tree}:whatever ${actual_tree}:whatever~side1 >actual && + test_cmp expect actual && + + # greeting should have a merge conflict + git show ${expected_tree}:greeting >tmp && + sed -e s/HEAD/side1/ tmp >expect && + git show ${actual_tree}:greeting >actual && + test_cmp expect actual +' + +test_expect_success 'Barf on misspelled option, with exit code other than 0 or 1' ' + # Mis-spell with single "s" instead of double "s" + test_expect_code 129 git merge-tree --write-tree --mesages FOOBAR side1 side2 2>expect && + + grep "error: unknown option.*mesages" expect +' + +test_expect_success 'Barf on too many arguments' ' + test_expect_code 129 git merge-tree --write-tree side1 side2 invalid 2>expect && + + grep "^usage: git merge-tree" expect +' + +anonymize_hash() { + sed -e "s/[0-9a-f]\{40,\}/HASH/g" "$@" +} + +test_expect_success 'test conflict notices and such' ' + test_expect_code 1 git merge-tree --write-tree --name-only side1 side2 >out && + anonymize_hash out >actual && + + # Expected results: + # "greeting" should merge with conflicts + # "numbers" should merge cleanly + # "whatever" has *both* a modify/delete and a file/directory conflict + cat <<-EOF >expect && + HASH + greeting + whatever~side1 + + Auto-merging greeting + CONFLICT (content): Merge conflict in greeting + Auto-merging numbers + CONFLICT (file/directory): directory in the way of whatever from side1; moving it to whatever~side1 instead. + CONFLICT (modify/delete): whatever~side1 deleted in side2 and modified in side1. Version side1 of whatever~side1 left in tree. + EOF + + test_cmp expect actual +' + +for opt in $(git merge-tree --git-completion-helper-all) +do + if test $opt = "--trivial-merge" || test $opt = "--write-tree" + then + continue + fi + + test_expect_success "usage: --trivial-merge is incompatible with $opt" ' + test_expect_code 128 git merge-tree --trivial-merge $opt side1 side2 side3 + ' +done + +test_expect_success 'Just the conflicted files without the messages' ' + test_expect_code 1 git merge-tree --write-tree --no-messages --name-only side1 side2 >out && + anonymize_hash out >actual && + + test_write_lines HASH greeting whatever~side1 >expect && + + test_cmp expect actual +' + +test_expect_success 'Check conflicted oids and modes without messages' ' + test_expect_code 1 git merge-tree --write-tree --no-messages side1 side2 >out && + anonymize_hash out >actual && + + # Compare the basic output format + q_to_tab >expect <<-\EOF && + HASH + 100644 HASH 1Qgreeting + 100644 HASH 2Qgreeting + 100644 HASH 3Qgreeting + 100644 HASH 1Qwhatever~side1 + 100644 HASH 2Qwhatever~side1 + EOF + + test_cmp expect actual && + + # Check the actual hashes against the `ls-files -u` output too + tail -n +2 out | sed -e s/side1/HEAD/ >actual && + test_cmp conflicted-file-info actual +' + +test_expect_success 'NUL terminated conflicted file "lines"' ' + git checkout -b tweak1 side1 && + test_write_lines zero 1 2 3 4 5 6 >numbers && + git add numbers && + git mv numbers "Αυτά μου φαίνονται κινÎζικα" && + git commit -m "Renamed numbers" && + + test_expect_code 1 git merge-tree --write-tree -z tweak1 side2 >out && + anonymize_hash out >actual && + printf "\\n" >>actual && + + # Expected results: + # "greeting" should merge with conflicts + # "whatever" has *both* a modify/delete and a file/directory conflict + # "Αυτά μου φαίνονται κινÎζικα" should have a conflict + echo HASH | lf_to_nul >expect && + + q_to_tab <<-EOF | lf_to_nul >>expect && + 100644 HASH 1Qgreeting + 100644 HASH 2Qgreeting + 100644 HASH 3Qgreeting + 100644 HASH 1Qwhatever~tweak1 + 100644 HASH 2Qwhatever~tweak1 + 100644 HASH 1QΑυτά μου φαίνονται κινÎζικα + 100644 HASH 2QΑυτά μου φαίνονται κινÎζικα + 100644 HASH 3QΑυτά μου φαίνονται κινÎζικα + + EOF + + q_to_nul <<-EOF >>expect && + 1QgreetingQAuto-mergingQAuto-merging greeting + Q1QgreetingQCONFLICT (contents)QCONFLICT (content): Merge conflict in greeting + Q2Qwhatever~tweak1QwhateverQCONFLICT (file/directory)QCONFLICT (file/directory): directory in the way of whatever from tweak1; moving it to whatever~tweak1 instead. + Q1Qwhatever~tweak1QCONFLICT (modify/delete)QCONFLICT (modify/delete): whatever~tweak1 deleted in side2 and modified in tweak1. Version tweak1 of whatever~tweak1 left in tree. + Q1QΑυτά μου φαίνονται κινÎζικαQAuto-mergingQAuto-merging Αυτά μου φαίνονται κινÎζικα + Q1QΑυτά μου φαίνονται κινÎζικαQCONFLICT (contents)QCONFLICT (content): Merge conflict in Αυτά μου φαίνονται κινÎζικα + Q + EOF + + test_cmp expect actual +' + +test_expect_success 'error out by default for unrelated histories' ' + test_expect_code 128 git merge-tree --write-tree side1 unrelated 2>error && + + grep "refusing to merge unrelated histories" error +' + +test_expect_success 'can override merge of unrelated histories' ' + git merge-tree --write-tree --allow-unrelated-histories side1 unrelated >tree && + TREE=$(cat tree) && + + git rev-parse side1:numbers side1:greeting side1:whatever unrelated:something-else >expect && + git rev-parse $TREE:numbers $TREE:greeting $TREE:whatever $TREE:something-else >actual && + + test_cmp expect actual +' + +test_done diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh index 7f8d2ab0a7..eaa0b22ece 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -24,6 +24,7 @@ commit id embedding: ' +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh SUBSTFORMAT=%H%n @@ -143,6 +144,7 @@ test_expect_success 'populate workdir' ' test_expect_success \ 'add ignored file' \ 'echo ignore me >a/ignored && + mkdir .git/info && echo ignored export-ignore >.git/info/attributes' test_expect_success 'add files to repository' ' @@ -157,7 +159,8 @@ test_expect_success 'setup export-subst' ' ' test_expect_success 'create bare clone' ' - git clone --bare . bare.git && + git clone --template= --bare . bare.git && + mkdir bare.git/info && cp .git/info/attributes bare.git/info/attributes ' @@ -339,21 +342,21 @@ test_expect_success 'only enabled filters are available remotely' ' test_cmp_bin remote.bar config.bar ' -test_expect_success GZIP 'git archive --format=tgz' ' +test_expect_success 'git archive --format=tgz' ' git archive --format=tgz HEAD >j.tgz ' -test_expect_success GZIP 'git archive --format=tar.gz' ' +test_expect_success 'git archive --format=tar.gz' ' git archive --format=tar.gz HEAD >j1.tar.gz && test_cmp_bin j.tgz j1.tar.gz ' -test_expect_success GZIP 'infer tgz from .tgz filename' ' +test_expect_success 'infer tgz from .tgz filename' ' git archive --output=j2.tgz HEAD && test_cmp_bin j.tgz j2.tgz ' -test_expect_success GZIP 'infer tgz from .tar.gz filename' ' +test_expect_success 'infer tgz from .tar.gz filename' ' git archive --output=j3.tar.gz HEAD && test_cmp_bin j.tgz j3.tar.gz ' @@ -363,17 +366,33 @@ test_expect_success GZIP 'extract tgz file' ' test_cmp_bin b.tar j.tar ' -test_expect_success GZIP 'remote tar.gz is allowed by default' ' +test_expect_success 'remote tar.gz is allowed by default' ' git archive --remote=. --format=tar.gz HEAD >remote.tar.gz && test_cmp_bin j.tgz remote.tar.gz ' -test_expect_success GZIP 'remote tar.gz can be disabled' ' +test_expect_success 'remote tar.gz can be disabled' ' git config tar.tar.gz.remote false && test_must_fail git archive --remote=. --format=tar.gz HEAD \ >remote.tar.gz ' +test_expect_success GZIP 'git archive --format=tgz (external gzip)' ' + test_config tar.tgz.command "gzip -cn" && + git archive --format=tgz HEAD >external_gzip.tgz +' + +test_expect_success GZIP 'git archive --format=tar.gz (external gzip)' ' + test_config tar.tar.gz.command "gzip -cn" && + git archive --format=tar.gz HEAD >external_gzip.tar.gz && + test_cmp_bin external_gzip.tgz external_gzip.tar.gz +' + +test_expect_success GZIP 'extract tgz file (external gzip)' ' + gzip -d -c <external_gzip.tgz >external_gzip.tar && + test_cmp_bin b.tar external_gzip.tar +' + test_expect_success 'archive and :(glob)' ' git archive -v HEAD -- ":(glob)**/sh" >/dev/null 2>actual && cat >expect <<EOF && diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh index 712ae52299..2f6eef5e37 100755 --- a/t/t5001-archive-attr.sh +++ b/t/t5001-archive-attr.sh @@ -2,6 +2,7 @@ test_description='git archive attribute tests' +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh SUBSTFORMAT='%H (%h)%n' @@ -20,6 +21,7 @@ extract_tar_to_dir () { test_expect_success 'setup' ' echo ignored >ignored && + mkdir .git/info && echo ignored export-ignore >>.git/info/attributes && git add ignored && @@ -46,7 +48,8 @@ test_expect_success 'setup' ' git commit -m. && - git clone --bare . bare && + git clone --template= --bare . bare && + mkdir bare/info && cp .git/info/attributes bare/info/attributes ' diff --git a/t/t5002-archive-attr-pattern.sh b/t/t5002-archive-attr-pattern.sh index a66b5ba27e..78ab75f1bc 100755 --- a/t/t5002-archive-attr-pattern.sh +++ b/t/t5002-archive-attr-pattern.sh @@ -3,6 +3,7 @@ test_description='git archive attribute pattern tests' TEST_PASSES_SANITIZE_LEAK=true +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh test_expect_exists() { @@ -15,6 +16,7 @@ test_expect_missing() { test_expect_success 'setup' ' echo ignored >ignored && + mkdir .git/info && echo ignored export-ignore >>.git/info/attributes && git add ignored && @@ -54,7 +56,8 @@ test_expect_success 'setup' ' git commit -m. && - git clone --bare . bare && + git clone --template= --bare . bare && + mkdir bare/info && cp .git/info/attributes bare/info/attributes ' diff --git a/t/t5003-archive-zip.sh b/t/t5003-archive-zip.sh index 3992d08158..fc499cdff0 100755 --- a/t/t5003-archive-zip.sh +++ b/t/t5003-archive-zip.sh @@ -2,6 +2,7 @@ test_description='git archive --format=zip test' +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh SUBSTFORMAT=%H%n @@ -121,6 +122,7 @@ test_expect_success 'prepare file list' ' test_expect_success \ 'add ignored file' \ 'echo ignore me >a/ignored && + mkdir .git/info && echo ignored export-ignore >.git/info/attributes' test_expect_success 'add files to repository' ' @@ -139,7 +141,8 @@ test_expect_success 'setup export-subst and diff attributes' ' ' test_expect_success 'create bare clone' ' - git clone --bare . bare.git && + git clone --template= --bare . bare.git && + mkdir bare.git/info && cp .git/info/attributes bare.git/info/attributes && # Recreate our changes to .git/config rather than just copying it, as # we do not want to clobber core.bare or other settings. diff --git a/t/t5303-pack-corruption-resilience.sh b/t/t5303-pack-corruption-resilience.sh index 41e6dc4dcf..2926e8dfc4 100755 --- a/t/t5303-pack-corruption-resilience.sh +++ b/t/t5303-pack-corruption-resilience.sh @@ -4,6 +4,8 @@ # test_description='resilience to pack corruptions with redundant objects' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # Note: the test objects are created with knowledge of their pack encoding diff --git a/t/t5308-pack-detect-duplicates.sh b/t/t5308-pack-detect-duplicates.sh index 693b2411c8..655cafa054 100755 --- a/t/t5308-pack-detect-duplicates.sh +++ b/t/t5308-pack-detect-duplicates.sh @@ -1,6 +1,8 @@ #!/bin/sh test_description='handling of duplicate objects in incoming packfiles' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-pack.sh diff --git a/t/t5309-pack-delta-cycles.sh b/t/t5309-pack-delta-cycles.sh index 55b787630f..4e910c5b9d 100755 --- a/t/t5309-pack-delta-cycles.sh +++ b/t/t5309-pack-delta-cycles.sh @@ -1,6 +1,8 @@ #!/bin/sh test_description='test index-pack handling of delta cycles in packfiles' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-pack.sh diff --git a/t/t5314-pack-cycle-detection.sh b/t/t5314-pack-cycle-detection.sh index 0aec8619e2..73a241743a 100755 --- a/t/t5314-pack-cycle-detection.sh +++ b/t/t5314-pack-cycle-detection.sh @@ -49,9 +49,9 @@ Then no matter which order we start looking at the packs in, we know that we will always find a delta for "file", because its lookup will always come immediately after the lookup for "dummy". ' -. ./test-lib.sh - +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh # Create a pack containing the tree $1 and blob $1:file, with # the latter stored as a delta against $2:file. diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh index fbf0d64578..1b0cd82359 100755 --- a/t/t5318-commit-graph.sh +++ b/t/t5318-commit-graph.sh @@ -361,13 +361,14 @@ test_expect_success 'replace-objects invalidates commit-graph' ' test_expect_success 'commit grafts invalidate commit-graph' ' cd "$TRASH_DIRECTORY" && test_when_finished rm -rf graft && - git clone full graft && + git clone --template= full graft && ( cd graft && git commit-graph write --reachable && test_path_is_file .git/objects/info/commit-graph && H1=$(git rev-parse --verify HEAD~1) && H3=$(git rev-parse --verify HEAD~3) && + mkdir .git/info && echo "$H1 $H3" >.git/info/grafts && git -c core.commitGraph=false log >expect && git -c core.commitGraph=true log >actual && @@ -811,4 +812,31 @@ test_expect_success 'set up and verify repo with generation data overflow chunk' graph_git_behavior 'generation data overflow chunk repo' repo left right +test_expect_success 'overflow during generation version upgrade' ' + git init overflow-v2-upgrade && + ( + cd overflow-v2-upgrade && + + # This commit will have a date at two seconds past the Epoch, + # and a (v1) generation number of 1, since it is a root commit. + # + # The offset will then be computed as 1-2, which will underflow + # to 2^31, which is greater than the v2 offset small limit of + # 2^31-1. + # + # This is sufficient to need a large offset table for the v2 + # generation numbers. + test_commit --date "@2 +0000" base && + git repack -d && + + # Test that upgrading from generation v1 to v2 correctly + # produces the overflow table. + git -c commitGraph.generationVersion=1 commit-graph write && + git -c commitGraph.generationVersion=2 commit-graph write \ + --changed-paths && + + git rev-list --all + ) +' + test_done diff --git a/t/t5321-pack-large-objects.sh b/t/t5321-pack-large-objects.sh index 8a56d98a0e..70770fe274 100755 --- a/t/t5321-pack-large-objects.sh +++ b/t/t5321-pack-large-objects.sh @@ -6,6 +6,8 @@ test_description='git pack-object with "large" deltas ' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-pack.sh diff --git a/t/t5330-no-lazy-fetch-with-commit-graph.sh b/t/t5330-no-lazy-fetch-with-commit-graph.sh new file mode 100755 index 0000000000..2cc7fd7a47 --- /dev/null +++ b/t/t5330-no-lazy-fetch-with-commit-graph.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +test_description='test for no lazy fetch with the commit-graph' + +. ./test-lib.sh + +test_expect_success 'setup: prepare a repository with a commit' ' + git init with-commit && + test_commit -C with-commit the-commit && + oid=$(git -C with-commit rev-parse HEAD) +' + +test_expect_success 'setup: prepare a repository with commit-graph contains the commit' ' + git init with-commit-graph && + echo "$(pwd)/with-commit/.git/objects" \ + >with-commit-graph/.git/objects/info/alternates && + # create a ref that points to the commit in alternates + git -C with-commit-graph update-ref refs/ref_to_the_commit "$oid" && + # prepare some other objects to commit-graph + test_commit -C with-commit-graph something && + git -c gc.writeCommitGraph=true -C with-commit-graph gc && + test_path_is_file with-commit-graph/.git/objects/info/commit-graph +' + +test_expect_success 'setup: change the alternates to what without the commit' ' + git init --bare without-commit && + git -C with-commit-graph cat-file -e $oid && + echo "$(pwd)/without-commit/objects" \ + >with-commit-graph/.git/objects/info/alternates && + test_must_fail git -C with-commit-graph cat-file -e $oid +' + +test_expect_success 'fetch any commit from promisor with the usage of the commit graph' ' + # setup promisor and prepare any commit to fetch + git -C with-commit-graph remote add origin "$(pwd)/with-commit" && + git -C with-commit-graph config remote.origin.promisor true && + git -C with-commit-graph config remote.origin.partialclonefilter blob:none && + test_commit -C with-commit any-commit && + anycommit=$(git -C with-commit rev-parse HEAD) && + GIT_TRACE="$(pwd)/trace.txt" \ + git -C with-commit-graph fetch origin $anycommit 2>err && + ! grep "fatal: promisor-remote: unable to fork off fetch subprocess" err && + grep "git fetch origin" trace.txt >actual && + test_line_count = 1 actual +' + +test_done diff --git a/t/t5351-unpack-large-objects.sh b/t/t5351-unpack-large-objects.sh new file mode 100755 index 0000000000..e936f91c3b --- /dev/null +++ b/t/t5351-unpack-large-objects.sh @@ -0,0 +1,102 @@ +#!/bin/sh +# +# Copyright (c) 2022 Han Xin +# + +test_description='git unpack-objects with large objects' + +. ./test-lib.sh + +prepare_dest () { + test_when_finished "rm -rf dest.git" && + git init --bare dest.git && + git -C dest.git config core.bigFileThreshold "$1" +} + +test_expect_success "create large objects (1.5 MB) and PACK" ' + test-tool genrandom foo 1500000 >big-blob && + test_commit --append foo big-blob && + test-tool genrandom bar 1500000 >big-blob && + test_commit --append bar big-blob && + PACK=$(echo HEAD | git pack-objects --revs pack) && + git verify-pack -v pack-$PACK.pack >out && + sed -n -e "s/^\([0-9a-f][0-9a-f]*\).*\(commit\|tree\|blob\).*/\1/p" \ + <out >obj-list +' + +test_expect_success 'set memory limitation to 1MB' ' + GIT_ALLOC_LIMIT=1m && + export GIT_ALLOC_LIMIT +' + +test_expect_success 'unpack-objects failed under memory limitation' ' + prepare_dest 2m && + test_must_fail git -C dest.git unpack-objects <pack-$PACK.pack 2>err && + grep "fatal: attempting to allocate" err +' + +test_expect_success 'unpack-objects works with memory limitation in dry-run mode' ' + prepare_dest 2m && + git -C dest.git unpack-objects -n <pack-$PACK.pack && + test_stdout_line_count = 0 find dest.git/objects -type f && + test_dir_is_empty dest.git/objects/pack +' + +test_expect_success 'unpack big object in stream' ' + prepare_dest 1m && + git -C dest.git unpack-objects <pack-$PACK.pack && + test_dir_is_empty dest.git/objects/pack +' + +check_fsync_events () { + local trace="$1" && + shift && + + cat >expect && + sed -n \ + -e '/^{"event":"data",.*"category":"fsync",/ { + s/.*"category":"fsync",//; + s/}$//; + p; + }' \ + <"$trace" >actual && + test_cmp expect actual +} + +BATCH_CONFIGURATION='-c core.fsync=loose-object -c core.fsyncmethod=batch' + +test_expect_success 'unpack big object in stream (core.fsyncmethod=batch)' ' + prepare_dest 1m && + GIT_TRACE2_EVENT="$(pwd)/trace2.txt" \ + GIT_TEST_FSYNC=true \ + git -C dest.git $BATCH_CONFIGURATION unpack-objects <pack-$PACK.pack && + if grep "core.fsyncMethod = batch is unsupported" trace2.txt + then + flush_count=7 + else + flush_count=1 + fi && + check_fsync_events trace2.txt <<-EOF && + "key":"fsync/writeout-only","value":"6" + "key":"fsync/hardware-flush","value":"$flush_count" + EOF + + test_dir_is_empty dest.git/objects/pack && + git -C dest.git cat-file --batch-check="%(objectname)" <obj-list >current && + cmp obj-list current +' + +test_expect_success 'do not unpack existing large objects' ' + prepare_dest 1m && + git -C dest.git index-pack --stdin <pack-$PACK.pack && + git -C dest.git unpack-objects <pack-$PACK.pack && + + # The destination came up with the exact same pack... + DEST_PACK=$(echo dest.git/objects/pack/pack-*.pack) && + cmp pack-$PACK.pack $DEST_PACK && + + # ...and wrote no loose objects + test_stdout_line_count = 0 find dest.git/objects -type f ! -name "pack-*" +' + +test_done diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index fff14e13ed..6c7370f87f 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -302,6 +302,52 @@ test_expect_success 'show' ' ) ' +cat >expect <<EOF +* remote origin + Fetch URL: $(pwd)/one + Push URL: $(pwd)/one + HEAD branch: main + Remote branches: + main skipped + side tracked + Local branches configured for 'git pull': + ahead merges with remote main + main merges with remote main + Local refs configured for 'git push': + main pushes to main (local out of date) + main pushes to upstream (create) +EOF + +test_expect_success 'show with negative refspecs' ' + test_when_finished "git -C test config --unset-all --fixed-value remote.origin.fetch ^refs/heads/main" && + git -C test config --add remote.origin.fetch ^refs/heads/main && + git -C test remote show origin >output && + test_cmp expect output +' + +cat >expect <<EOF +* remote origin + Fetch URL: $(pwd)/one + Push URL: $(pwd)/one + HEAD branch: main + Remote branches: + main new (next fetch will store in remotes/origin) + side stale (use 'git remote prune' to remove) + Local branches configured for 'git pull': + ahead merges with remote main + main merges with remote main + Local refs configured for 'git push': + main pushes to main (local out of date) + main pushes to upstream (create) +EOF + +test_expect_failure 'show stale with negative refspecs' ' + test_when_finished "git -C test config --unset-all --fixed-value remote.origin.fetch ^refs/heads/side" && + git -C test config --add remote.origin.fetch ^refs/heads/side && + git -C test remote show origin >output && + test_cmp expect output +' + cat >test/expect <<EOF * remote origin Fetch URL: $(pwd)/one @@ -957,11 +1003,12 @@ test_expect_success 'migrate a remote from named file in $GIT_DIR/remotes' ' ' test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' ' - git clone one six && + git clone --template= one six && origin_url=$(pwd)/one && ( cd six && git remote rm origin && + mkdir .git/branches && echo "$origin_url#main" >.git/branches/origin && git remote rename origin origin && test_path_is_missing .git/branches/origin && @@ -972,10 +1019,11 @@ test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' ' ' test_expect_success 'migrate a remote from named file in $GIT_DIR/branches (2)' ' - git clone one seven && + git clone --template= one seven && ( cd seven && git remote rm origin && + mkdir .git/branches && echo "quux#foom" > .git/branches/origin && git remote rename origin origin && test_path_is_missing .git/branches/origin && diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 541adbb310..f3356f9ea8 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -18,6 +18,7 @@ This test checks the following functionality: GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh D=$(pwd) @@ -26,7 +27,8 @@ mk_empty () { repo_name="$1" test_when_finished "rm -rf \"$repo_name\"" && test_path_is_missing "$repo_name" && - git init "$repo_name" && + git init --template= "$repo_name" && + mkdir "$repo_name"/.git/hooks && git -C "$repo_name" config receive.denyCurrentBranch warn } @@ -78,7 +80,7 @@ mk_test_with_hooks() { mk_child() { test_when_finished "rm -rf \"$2\"" && - git clone "$1" "$2" + git clone --template= "$1" "$2" } check_push_result () { @@ -937,6 +939,7 @@ test_expect_success 'fetch with branches' ' mk_empty testrepo && git branch second $the_first_commit && git checkout second && + mkdir testrepo/.git/branches && echo ".." > testrepo/.git/branches/branch1 && ( cd testrepo && @@ -950,6 +953,7 @@ test_expect_success 'fetch with branches' ' test_expect_success 'fetch with branches containing #' ' mk_empty testrepo && + mkdir testrepo/.git/branches && echo "..#second" > testrepo/.git/branches/branch2 && ( cd testrepo && @@ -964,7 +968,11 @@ test_expect_success 'fetch with branches containing #' ' test_expect_success 'push with branches' ' mk_empty testrepo && git checkout second && + + test_when_finished "rm -rf .git/branches" && + mkdir .git/branches && echo "testrepo" > .git/branches/branch1 && + git push branch1 && ( cd testrepo && @@ -976,7 +984,11 @@ test_expect_success 'push with branches' ' test_expect_success 'push with branches containing #' ' mk_empty testrepo && + + test_when_finished "rm -rf .git/branches" && + mkdir .git/branches && echo "testrepo#branch3" > .git/branches/branch2 && + git push branch2 && ( cd testrepo && @@ -1865,4 +1877,26 @@ test_expect_success LIBCURL 'push warns or fails when using username:password' ' test_line_count = 1 warnings ' +test_expect_success 'push with config push.useBitmaps' ' + mk_test testrepo heads/main && + git checkout main && + test_unconfig push.useBitmaps && + GIT_TRACE2_EVENT="$PWD/default" \ + git push testrepo main:test && + test_subcommand git pack-objects --all-progress-implied --revs --stdout \ + --thin --delta-base-offset -q <default && + + test_config push.useBitmaps true && + GIT_TRACE2_EVENT="$PWD/true" \ + git push testrepo main:test2 && + test_subcommand git pack-objects --all-progress-implied --revs --stdout \ + --thin --delta-base-offset -q <true && + + test_config push.useBitmaps false && + GIT_TRACE2_EVENT="$PWD/false" \ + git push testrepo main:test3 && + test_subcommand git pack-objects --all-progress-implied --revs --stdout \ + --thin --delta-base-offset -q --no-use-bitmap-index <false +' + test_done diff --git a/t/t5524-pull-msg.sh b/t/t5524-pull-msg.sh index b2be3605f5..56716e29dd 100755 --- a/t/t5524-pull-msg.sh +++ b/t/t5524-pull-msg.sh @@ -2,6 +2,7 @@ test_description='git pull message generation' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh dollar='$Dollar' diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh index 2f09ff4fac..fbad2d5ff5 100755 --- a/t/t5541-http-push-smart.sh +++ b/t/t5541-http-push-smart.sh @@ -80,6 +80,25 @@ test_expect_success 'push to remote repository (standard)' ' test $HEAD = $(git rev-parse --verify HEAD)) ' +test_expect_success 'push to remote repository (standard) with sending Accept-Language' ' + cat >exp <<-\EOF && + => Send header: Accept-Language: ko-KR, *;q=0.9 + => Send header: Accept-Language: ko-KR, *;q=0.9 + EOF + + cd "$ROOT_PATH"/test_repo_clone && + : >path_lang && + git add path_lang && + test_tick && + git commit -m path_lang && + HEAD=$(git rev-parse --verify HEAD) && + GIT_TRACE_CURL=true LANGUAGE="ko_KR.UTF-8" git push -v -v 2>err && + ! grep "Expect: 100-continue" err && + + grep "=> Send header: Accept-Language:" err >err.language && + test_cmp exp err.language +' + test_expect_success 'push already up-to-date' ' git push ' diff --git a/t/t5544-pack-objects-hook.sh b/t/t5544-pack-objects-hook.sh index dd5f44d986..54f54f8d2e 100755 --- a/t/t5544-pack-objects-hook.sh +++ b/t/t5544-pack-objects-hook.sh @@ -56,7 +56,12 @@ test_expect_success 'hook does not run from repo config' ' ! grep "hook running" stderr && test_path_is_missing .git/hook.args && test_path_is_missing .git/hook.stdin && - test_path_is_missing .git/hook.stdout + test_path_is_missing .git/hook.stdout && + + # check that global config is used instead + test_config_global uploadpack.packObjectsHook ./hook && + git clone --no-local . dst2.git 2>stderr && + grep "hook running" stderr ' test_expect_success 'hook works with partial clone' ' diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh index f0d9cd584d..d7cf85ffea 100755 --- a/t/t5550-http-fetch-dumb.sh +++ b/t/t5550-http-fetch-dumb.sh @@ -369,7 +369,7 @@ ja;q=0.95, zh;q=0.94, sv;q=0.93, pt;q=0.92, nb;q=0.91, *;q=0.90" \ ko_KR.EUC-KR:en_US.UTF-8:fr_CA:de.UTF-8@euro:sr@latin:ja:zh:sv:pt:nb ' -test_expect_success 'git client does not send an empty Accept-Language' ' +test_expect_success 'git client send an empty Accept-Language' ' GIT_TRACE_CURL=true LANGUAGE= git ls-remote "$HTTPD_URL/dumb/repo.git" 2>stderr && ! grep "^=> Send header: Accept-Language:" stderr ' @@ -422,7 +422,8 @@ test_expect_success 'set up evil alternates scheme' ' sha1=$(git -C "$victim" rev-parse HEAD) && evil=$HTTPD_DOCUMENT_ROOT_PATH/evil.git && - git init --bare "$evil" && + git init --template= --bare "$evil" && + mkdir "$evil/info" && # do this by hand to avoid object existence check printf "%s\\t%s\\n" $sha1 refs/heads/main >"$evil/info/refs" ' diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh index b9351a732f..245532df88 100755 --- a/t/t5551-http-fetch-smart.sh +++ b/t/t5551-http-fetch-smart.sh @@ -31,6 +31,7 @@ test_expect_success 'clone http repository' ' > GET /smart/repo.git/info/refs?service=git-upload-pack HTTP/1.1 > Accept: */* > Accept-Encoding: ENCODINGS + > Accept-Language: ko-KR, *;q=0.9 > Pragma: no-cache < HTTP/1.1 200 OK < Pragma: no-cache @@ -40,13 +41,15 @@ test_expect_success 'clone http repository' ' > Accept-Encoding: ENCODINGS > Content-Type: application/x-git-upload-pack-request > Accept: application/x-git-upload-pack-result + > Accept-Language: ko-KR, *;q=0.9 > Content-Length: xxx < HTTP/1.1 200 OK < Pragma: no-cache < Cache-Control: no-cache, max-age=0, must-revalidate < Content-Type: application/x-git-upload-pack-result EOF - GIT_TRACE_CURL=true GIT_TEST_PROTOCOL_VERSION=0 \ + + GIT_TRACE_CURL=true GIT_TEST_PROTOCOL_VERSION=0 LANGUAGE="ko_KR.UTF-8" \ git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err && test_cmp file clone/file && tr '\''\015'\'' Q <err | @@ -94,7 +97,10 @@ test_expect_success 'clone http repository' ' test_cmp exp actual.smudged && grep "Accept-Encoding:.*gzip" actual >actual.gzip && - test_line_count = 2 actual.gzip + test_line_count = 2 actual.gzip && + + grep "Accept-Language: ko-KR, *" actual >actual.language && + test_line_count = 2 actual.language fi ' diff --git a/t/t5605-clone-local.sh b/t/t5605-clone-local.sh index 21ab619283..38b850c10e 100755 --- a/t/t5605-clone-local.sh +++ b/t/t5605-clone-local.sh @@ -21,7 +21,9 @@ test_expect_success 'preparing origin repository' ' git bundle create b2.bundle main && mkdir dir && cp b1.bundle dir/b3 && - cp b1.bundle b4 + cp b1.bundle b4 && + git branch not-main main && + git bundle create b5.bundle not-main ' test_expect_success 'local clone without .git suffix' ' @@ -83,11 +85,19 @@ test_expect_success 'bundle clone from b4.bundle that does not exist' ' test_must_fail git clone b4.bundle bb ' -test_expect_success 'bundle clone with nonexistent HEAD' ' +test_expect_success 'bundle clone with nonexistent HEAD (match default)' ' git clone b2.bundle b2 && (cd b2 && git fetch && - test_must_fail git rev-parse --verify refs/heads/main) + git rev-parse --verify refs/heads/main) +' + +test_expect_success 'bundle clone with nonexistent HEAD (no match default)' ' + git clone b5.bundle b5 && + (cd b5 && + git fetch && + test_must_fail git rev-parse --verify refs/heads/main && + test_must_fail git rev-parse --verify refs/heads/not-main) ' test_expect_success 'clone empty repository' ' diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index 00ce9aec23..5d42a355a8 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -250,6 +250,65 @@ test_expect_success 'bare clone propagates empty default branch' ' grep "refs/heads/mydefaultbranch" file_empty_child.git/HEAD ' +test_expect_success 'clone propagates unborn HEAD from non-empty repo' ' + test_when_finished "rm -rf file_unborn_parent file_unborn_child" && + + git init file_unborn_parent && + ( + cd file_unborn_parent && + git checkout -b branchwithstuff && + test_commit --no-tag stuff && + git symbolic-ref HEAD refs/heads/mydefaultbranch + ) && + + GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= \ + git -c init.defaultBranch=main -c protocol.version=2 \ + clone "file://$(pwd)/file_unborn_parent" \ + file_unborn_child 2>stderr && + grep "refs/heads/mydefaultbranch" file_unborn_child/.git/HEAD && + grep "warning: remote HEAD refers to nonexistent ref" stderr +' + +test_expect_success 'bare clone propagates unborn HEAD from non-empty repo' ' + test_when_finished "rm -rf file_unborn_parent file_unborn_child.git" && + + git init file_unborn_parent && + ( + cd file_unborn_parent && + git checkout -b branchwithstuff && + test_commit --no-tag stuff && + git symbolic-ref HEAD refs/heads/mydefaultbranch + ) && + + GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= \ + git -c init.defaultBranch=main -c protocol.version=2 \ + clone --bare "file://$(pwd)/file_unborn_parent" \ + file_unborn_child.git 2>stderr && + grep "refs/heads/mydefaultbranch" file_unborn_child.git/HEAD && + ! grep "warning:" stderr +' + +test_expect_success 'defaulted HEAD uses remote branch if available' ' + test_when_finished "rm -rf file_unborn_parent file_unborn_child" && + + git init file_unborn_parent && + ( + cd file_unborn_parent && + git config lsrefs.unborn ignore && + git checkout -b branchwithstuff && + test_commit --no-tag stuff && + git symbolic-ref HEAD refs/heads/mydefaultbranch + ) && + + GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= \ + git -c init.defaultBranch=branchwithstuff -c protocol.version=2 \ + clone "file://$(pwd)/file_unborn_parent" \ + file_unborn_child 2>stderr && + grep "refs/heads/branchwithstuff" file_unborn_child/.git/HEAD && + test_path_is_file file_unborn_child/stuff.t && + ! grep "warning:" stderr +' + test_expect_success 'fetch with file:// using protocol v2' ' test_when_finished "rm -f log" && diff --git a/t/t5812-proto-disable-http.sh b/t/t5812-proto-disable-http.sh index af8772fada..d8da5f58d1 100755 --- a/t/t5812-proto-disable-http.sh +++ b/t/t5812-proto-disable-http.sh @@ -16,7 +16,7 @@ test_expect_success 'create git-accessible repo' ' test_proto "smart http" http "$HTTPD_URL/smart/repo.git" -test_expect_success 'curl redirects respect whitelist' ' +test_expect_success 'http(s) transport respects GIT_ALLOW_PROTOCOL' ' test_must_fail env GIT_ALLOW_PROTOCOL=http:https \ GIT_SMART_HTTP=0 \ git clone "$HTTPD_URL/ftp-redir/repo.git" 2>stderr && diff --git a/t/t5815-submodule-protos.sh b/t/t5815-submodule-protos.sh index 06f55a1b8a..4d5956cc18 100755 --- a/t/t5815-submodule-protos.sh +++ b/t/t5815-submodule-protos.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='test protocol whitelisting with submodules' +test_description='test protocol filtering with submodules' . ./test-lib.sh . "$TEST_DIRECTORY"/lib-proto-disable.sh @@ -36,7 +36,7 @@ test_expect_success 'update of ext not allowed' ' test_must_fail git -C dst submodule update ext-module ' -test_expect_success 'user can override whitelist' ' +test_expect_success 'user can filter protocols with GIT_ALLOW_PROTOCOL' ' GIT_ALLOW_PROTOCOL=ext git -C dst submodule update ext-module ' diff --git a/t/t6001-rev-list-graft.sh b/t/t6001-rev-list-graft.sh index 7294147334..16635ecc33 100755 --- a/t/t6001-rev-list-graft.sh +++ b/t/t6001-rev-list-graft.sh @@ -99,6 +99,7 @@ do " test_expect_success 'with grafts' " + mkdir -p .git/info && echo '$B0 $A2' >.git/info/grafts && check $type $B2 -- $B2 $B1 $B0 $A2 $A1 $A0 " diff --git a/t/t6101-rev-parse-parents.sh b/t/t6101-rev-parse-parents.sh index a3a41c7a3e..d20723d627 100755 --- a/t/t6101-rev-parse-parents.sh +++ b/t/t6101-rev-parse-parents.sh @@ -9,6 +9,7 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME TEST_PASSES_SANITIZE_LEAK=true +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh test_cmp_rev_output () { @@ -26,6 +27,7 @@ test_expect_success 'setup' ' git merge -m next --allow-unrelated-histories start2 && test_commit final && + mkdir .git/info && test_seq 40 | while read i do diff --git a/t/t6402-merge-rename.sh b/t/t6402-merge-rename.sh index 3a32b1a45c..772238e582 100755 --- a/t/t6402-merge-rename.sh +++ b/t/t6402-merge-rename.sh @@ -210,7 +210,7 @@ test_expect_success 'updated working tree file should prevent the merge' ' echo >>M one line addition && cat M >M.saved && git update-index M && - test_expect_code 128 git pull --no-rebase . yellow && + test_expect_code 2 git pull --no-rebase . yellow && test_cmp M M.saved && rm -f M.saved ' diff --git a/t/t6403-merge-file.sh b/t/t6403-merge-file.sh index 2f421d967a..1a7082323d 100755 --- a/t/t6403-merge-file.sh +++ b/t/t6403-merge-file.sh @@ -1,6 +1,8 @@ #!/bin/sh test_description='RCS merge replacement: merge-file' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t6417-merge-ours-theirs.sh b/t/t6417-merge-ours-theirs.sh index 62d1406119..482b73a998 100755 --- a/t/t6417-merge-ours-theirs.sh +++ b/t/t6417-merge-ours-theirs.sh @@ -4,6 +4,7 @@ test_description='Merge-recursive ours and theirs variants' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' diff --git a/t/t6422-merge-rename-corner-cases.sh b/t/t6422-merge-rename-corner-cases.sh index bf4ce3c63d..9b65768aed 100755 --- a/t/t6422-merge-rename-corner-cases.sh +++ b/t/t6422-merge-rename-corner-cases.sh @@ -6,6 +6,7 @@ test_description="recursive merge corner cases w/ renames but not criss-crosses" GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-merge.sh diff --git a/t/t6424-merge-unrelated-index-changes.sh b/t/t6424-merge-unrelated-index-changes.sh index b6e424a427..a61f20c22f 100755 --- a/t/t6424-merge-unrelated-index-changes.sh +++ b/t/t6424-merge-unrelated-index-changes.sh @@ -114,6 +114,39 @@ test_expect_success 'resolve, non-trivial' ' test_path_is_missing .git/MERGE_HEAD ' +test_expect_success 'resolve, trivial, related file removed' ' + git reset --hard && + git checkout B^0 && + + git rm a && + test_path_is_missing a && + + test_must_fail git merge -s resolve C^0 && + + test_path_is_missing a && + test_path_is_missing .git/MERGE_HEAD +' + +test_expect_success 'resolve, non-trivial, related file removed' ' + git reset --hard && + git checkout B^0 && + + git rm a && + test_path_is_missing a && + + # We also ask for recursive in order to turn off the "allow_trivial" + # setting in builtin/merge.c, and ensure that resolve really does + # correctly fail the merge (I guess this also tests that recursive + # correctly fails the merge, but the main thing we are attempting + # to test here is resolve and are just using the side effect of + # adding recursive to ensure that resolve is actually tested rather + # than the trivial merge codepath) + test_must_fail git merge -s resolve -s recursive D^0 && + + test_path_is_missing a && + test_path_is_missing .git/MERGE_HEAD +' + test_expect_success 'recursive' ' git reset --hard && git checkout B^0 && @@ -242,4 +275,36 @@ test_expect_success 'subtree' ' test_path_is_missing .git/MERGE_HEAD ' +test_expect_success 'avoid failure due to stat-dirty files' ' + git reset --hard && + git checkout B^0 && + + # Make "a" be stat-dirty + test-tool chmtime =+1 a && + + # stat-dirty file should not prevent stash creation in builtin/merge.c + git merge -s resolve -s recursive D^0 +' + +test_expect_success 'with multiple strategies, recursive or ort failure do not early abort' ' + git reset --hard && + git checkout B^0 && + + test_seq 0 10 >a && + git add a && + git rev-parse :a >expect && + + sane_unset GIT_TEST_MERGE_ALGORITHM && + test_must_fail git merge -s recursive -s ort -s octopus C^0 >output 2>&1 && + + grep "Trying merge strategy recursive..." output && + grep "Trying merge strategy ort..." output && + grep "Trying merge strategy octopus..." output && + grep "No merge strategy handled the merge." output && + + # Changes to "a" should remain staged + git rev-parse :a >actual && + test_cmp expect actual +' + test_done diff --git a/t/t6435-merge-sparse.sh b/t/t6435-merge-sparse.sh index 74562e1235..fde4aa3cd1 100755 --- a/t/t6435-merge-sparse.sh +++ b/t/t6435-merge-sparse.sh @@ -2,6 +2,7 @@ test_description='merge with sparse files' +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh # test_file $filename $content @@ -26,6 +27,7 @@ test_expect_success 'setup' ' git rm modify_delete && test_commit_this ours && git config core.sparseCheckout true && + mkdir .git/info && echo "/checked-out" >.git/info/sparse-checkout && git reset --hard && test_must_fail git merge theirs diff --git a/t/t6437-submodule-merge.sh b/t/t6437-submodule-merge.sh index 178413c22f..c253bf759a 100755 --- a/t/t6437-submodule-merge.sh +++ b/t/t6437-submodule-merge.sh @@ -133,7 +133,7 @@ test_expect_success 'merging should conflict for non fast-forward' ' (cd merge-search && git checkout -b test-nonforward b && (cd sub && - git rev-parse sub-d > ../expect) && + git rev-parse --short sub-d > ../expect) && if test "$GIT_TEST_MERGE_ALGORITHM" = ort then test_must_fail git merge c >actual diff --git a/t/t6439-merge-co-error-msgs.sh b/t/t6439-merge-co-error-msgs.sh index 5bfb027099..52cf0c8769 100755 --- a/t/t6439-merge-co-error-msgs.sh +++ b/t/t6439-merge-co-error-msgs.sh @@ -47,6 +47,7 @@ test_expect_success 'untracked files overwritten by merge (fast and non-fast for export GIT_MERGE_VERBOSITY && test_must_fail git merge branch 2>out2 ) && + echo "Merge with strategy ${GIT_TEST_MERGE_ALGORITHM:-ort} failed." >>expect && test_cmp out2 expect && git reset --hard HEAD^ ' diff --git a/t/t7002-mv-sparse-checkout.sh b/t/t7002-mv-sparse-checkout.sh index f0f7cbfcdb..71fe29690f 100755 --- a/t/t7002-mv-sparse-checkout.sh +++ b/t/t7002-mv-sparse-checkout.sh @@ -4,6 +4,18 @@ test_description='git mv in sparse working trees' . ./test-lib.sh +setup_sparse_checkout () { + mkdir folder1 && + touch folder1/file1 && + git add folder1 && + git sparse-checkout set --cone sub +} + +cleanup_sparse_checkout () { + git sparse-checkout disable && + git reset --hard +} + test_expect_success 'setup' " mkdir -p sub/dir sub/dir2 && touch a b c sub/d sub/dir/e sub/dir2/e && @@ -196,6 +208,7 @@ test_expect_success 'can move files to non-sparse dir' ' ' test_expect_success 'refuse to move file to non-skip-worktree sparse path' ' + test_when_finished "cleanup_sparse_checkout" && git reset --hard && git sparse-checkout init --no-cone && git sparse-checkout set a !/x y/ !x/y/z && @@ -206,4 +219,75 @@ test_expect_success 'refuse to move file to non-skip-worktree sparse path' ' test_cmp expect stderr ' +test_expect_success 'refuse to move out-of-cone directory without --sparse' ' + test_when_finished "cleanup_sparse_checkout" && + setup_sparse_checkout && + + test_must_fail git mv folder1 sub 2>stderr && + cat sparse_error_header >expect && + echo folder1/file1 >>expect && + cat sparse_hint >>expect && + test_cmp expect stderr +' + +test_expect_success 'can move out-of-cone directory with --sparse' ' + test_when_finished "cleanup_sparse_checkout" && + setup_sparse_checkout && + + git mv --sparse folder1 sub 2>stderr && + test_must_be_empty stderr && + + test_path_is_dir sub/folder1 && + test_path_is_file sub/folder1/file1 +' + +test_expect_success 'refuse to move out-of-cone file without --sparse' ' + test_when_finished "cleanup_sparse_checkout" && + setup_sparse_checkout && + + test_must_fail git mv folder1/file1 sub 2>stderr && + cat sparse_error_header >expect && + echo folder1/file1 >>expect && + cat sparse_hint >>expect && + test_cmp expect stderr +' + +test_expect_success 'can move out-of-cone file with --sparse' ' + test_when_finished "cleanup_sparse_checkout" && + setup_sparse_checkout && + + git mv --sparse folder1/file1 sub 2>stderr && + test_must_be_empty stderr && + + test_path_is_file sub/file1 +' + +test_expect_success 'refuse to move sparse file to existing destination' ' + test_when_finished "cleanup_sparse_checkout" && + mkdir folder1 && + touch folder1/file1 && + touch sub/file1 && + git add folder1 sub/file1 && + git sparse-checkout set --cone sub && + + test_must_fail git mv --sparse folder1/file1 sub 2>stderr && + echo "fatal: destination exists, source=folder1/file1, destination=sub/file1" >expect && + test_cmp expect stderr +' + +test_expect_success 'move sparse file to existing destination with --force and --sparse' ' + test_when_finished "cleanup_sparse_checkout" && + mkdir folder1 && + touch folder1/file1 && + touch sub/file1 && + echo "overwrite" >folder1/file1 && + git add folder1 sub/file1 && + git sparse-checkout set --cone sub && + + git mv --sparse --force folder1/file1 sub 2>stderr && + test_must_be_empty stderr && + echo "overwrite" >expect && + test_cmp expect sub/file1 +' + test_done diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh index 9936cc329e..8929ef481f 100755 --- a/t/t7063-status-untracked-cache.sh +++ b/t/t7063-status-untracked-cache.sh @@ -86,7 +86,7 @@ test_expect_success 'core.untrackedCache is unset' ' ' test_expect_success 'setup' ' - git init worktree && + git init --template= worktree && cd worktree && mkdir done dtwo dthree && touch one two three done/one dtwo/two dthree/three && @@ -94,6 +94,7 @@ test_expect_success 'setup' ' test-tool chmtime =-300 done dtwo dthree && test-tool chmtime =-300 . && git add one two done/one && + mkdir .git/info && : >.git/info/exclude && git update-index --untracked-cache && test_oid_cache <<-EOF @@ -985,4 +986,9 @@ test_expect_success '"status" after file replacement should be clean with UC=fal status_is_clean ' +test_expect_success 'empty repo (no index) and core.untrackedCache' ' + git init emptyrepo && + git -C emptyrepo -c core.untrackedCache=true write-tree +' + test_done diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index 43f779d751..6cc07460dd 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -1074,7 +1074,7 @@ test_expect_success 'submodule update --quiet passes quietness to merge/rebase' git submodule update --rebase --quiet >out 2>err && test_must_be_empty out && test_must_be_empty err && - git submodule update --rebase -v >out 2>err && + git submodule update --rebase >out 2>err && test_file_not_empty out && test_must_be_empty err ) @@ -1116,4 +1116,66 @@ test_expect_success 'submodule update --filter sets partial clone settings' ' test_cmp_config -C super-filter/submodule blob:none remote.origin.partialclonefilter ' +# NEEDSWORK: Clean up the tests so that we can reuse the test setup. +# Don't reuse the existing repos because the earlier tests have +# intentionally disruptive configurations. +test_expect_success 'setup clean recursive superproject' ' + git init bottom && + test_commit -C bottom "bottom" && + git init middle && + git -C middle submodule add ../bottom bottom && + git -C middle commit -m "middle" && + git init top && + git -C top submodule add ../middle middle && + git -C top commit -m "top" && + git clone --recurse-submodules top top-clean +' + +test_expect_success 'submodule update should skip unmerged submodules' ' + test_when_finished "rm -fr top-cloned" && + cp -r top-clean top-cloned && + + # Create an upstream commit in each repo, starting with bottom + test_commit -C bottom upstream_commit && + # Create middle commit + git -C middle/bottom fetch && + git -C middle/bottom checkout -f FETCH_HEAD && + git -C middle add bottom && + git -C middle commit -m "upstream_commit" && + # Create top commit + git -C top/middle fetch && + git -C top/middle checkout -f FETCH_HEAD && + git -C top add middle && + git -C top commit -m "upstream_commit" && + + # Create a downstream conflict + test_commit -C top-cloned/middle/bottom downstream_commit && + git -C top-cloned/middle add bottom && + git -C top-cloned/middle commit -m "downstream_commit" && + git -C top-cloned/middle fetch --recurse-submodules origin && + test_must_fail git -C top-cloned/middle merge origin/main && + + # Make the update of "middle" a no-op, otherwise we error out + # because of its unmerged state + test_config -C top-cloned submodule.middle.update !true && + git -C top-cloned submodule update --recursive 2>actual.err && + cat >expect.err <<-\EOF && + Skipping unmerged submodule middle/bottom + EOF + test_cmp expect.err actual.err +' + +test_expect_success 'submodule update --recursive skip submodules with strategy=none' ' + test_when_finished "rm -fr top-cloned" && + cp -r top-clean top-cloned && + + test_commit -C top-cloned/middle/bottom downstream_commit && + git -C top-cloned/middle config submodule.bottom.update none && + git -C top-cloned submodule update --recursive 2>actual.err && + cat >expect.err <<-\EOF && + Skipping submodule '\''middle/bottom'\'' + EOF + test_cmp expect.err actual.err +' + test_done diff --git a/t/t7418-submodule-sparse-gitmodules.sh b/t/t7418-submodule-sparse-gitmodules.sh index f87e524d6d..57d7ab3ece 100755 --- a/t/t7418-submodule-sparse-gitmodules.sh +++ b/t/t7418-submodule-sparse-gitmodules.sh @@ -31,8 +31,9 @@ test_expect_success 'sparse checkout setup which hides .gitmodules' ' test_tick && git commit -m "Add submodule" ) && - git clone upstream super && + git clone --template= upstream super && (cd super && + mkdir .git/info && cat >.git/info/sparse-checkout <<-\EOF && /* !/.gitmodules diff --git a/t/t7607-merge-state.sh b/t/t7607-merge-state.sh new file mode 100755 index 0000000000..89a62ac53b --- /dev/null +++ b/t/t7607-merge-state.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +test_description="Test that merge state is as expected after failed merge" + +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +. ./test-lib.sh + +test_expect_success 'Ensure we restore original state if no merge strategy handles it' ' + test_commit --no-tag "Initial" base base && + + for b in branch1 branch2 branch3 + do + git checkout -b $b main && + test_commit --no-tag "Change on $b" base $b || return 1 + done && + + git checkout branch1 && + # This is a merge that octopus cannot handle. Note, that it does not + # just hit conflicts, it completely fails and says that it cannot + # handle this type of merge. + test_expect_code 2 git merge branch2 branch3 >output 2>&1 && + grep "fatal: merge program failed" output && + grep "Should not be doing an octopus" output && + + # Make sure we did not leave stray changes around when no appropriate + # merge strategy was found + git diff --exit-code --name-status && + test_path_is_missing .git/MERGE_HEAD +' + +test_done diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index 6935601171..0f937990a0 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -77,6 +77,7 @@ test_expect_success setup ' # Say hello. function hello() { echo "Hello world." + echo "Hello again." } # hello # Still a no-op. @@ -595,6 +596,92 @@ test_expect_success 'grep --files-without-match --quiet' ' test_must_be_empty actual ' +test_expect_success 'grep --max-count 0 (must exit with non-zero)' ' + test_must_fail git grep --max-count 0 foo >actual && + test_must_be_empty actual +' + +test_expect_success 'grep --max-count 3' ' + cat >expected <<-EOF && + file:foo mmap bar + file:foo_mmap bar + file:foo_mmap bar mmap + EOF + git grep --max-count 3 foo >actual && + test_cmp expected actual +' + +test_expect_success 'grep --max-count -1 (no limit)' ' + cat >expected <<-EOF && + file:foo mmap bar + file:foo_mmap bar + file:foo_mmap bar mmap + file:foo mmap bar_mmap + file:foo_mmap bar mmap baz + EOF + git grep --max-count -1 foo >actual && + test_cmp expected actual +' + +test_expect_success 'grep --max-count 1 --context 2' ' + cat >expected <<-EOF && + file-foo mmap bar + file:foo_mmap bar + file-foo_mmap bar mmap + EOF + git grep --max-count 1 --context 1 foo_mmap >actual && + test_cmp expected actual +' + +test_expect_success 'grep --max-count 1 --show-function' ' + cat >expected <<-EOF && + hello.ps1=function hello() { + hello.ps1: echo "Hello world." + EOF + git grep --max-count 1 --show-function Hello hello.ps1 >actual && + test_cmp expected actual +' + +test_expect_success 'grep --max-count 2 --show-function' ' + cat >expected <<-EOF && + hello.ps1=function hello() { + hello.ps1: echo "Hello world." + hello.ps1: echo "Hello again." + EOF + git grep --max-count 2 --show-function Hello hello.ps1 >actual && + test_cmp expected actual +' + +test_expect_success 'grep --max-count 1 --count' ' + cat >expected <<-EOF && + hello.ps1:1 + EOF + git grep --max-count 1 --count Hello hello.ps1 >actual && + test_cmp expected actual +' + +test_expect_success 'grep --max-count 1 (multiple files)' ' + cat >expected <<-EOF && + hello.c:#include <stdio.h> + hello.ps1:# No-op. + EOF + git grep --max-count 1 -e o -- hello.\* >actual && + test_cmp expected actual +' + +test_expect_success 'grep --max-count 1 --context 1 (multiple files)' ' + cat >expected <<-EOF && + hello.c-#include <assert.h> + hello.c:#include <stdio.h> + hello.c- + -- + hello.ps1:# No-op. + hello.ps1-function dummy() {} + EOF + git grep --max-count 1 --context 1 -e o -- hello.\* >actual && + test_cmp expected actual +' + cat >expected <<EOF file:foo mmap bar_mmap EOF diff --git a/t/t7812-grep-icase-non-ascii.sh b/t/t7812-grep-icase-non-ascii.sh index ac7be54714..31c66b63c2 100755 --- a/t/t7812-grep-icase-non-ascii.sh +++ b/t/t7812-grep-icase-non-ascii.sh @@ -2,6 +2,7 @@ test_description='grep icase on non-English locales' +TEST_PASSES_SANITIZE_LEAK=true . ./lib-gettext.sh doalarm () { diff --git a/t/t7814-grep-recurse-submodules.sh b/t/t7814-grep-recurse-submodules.sh index a4476dc492..3ad80526c4 100755 --- a/t/t7814-grep-recurse-submodules.sh +++ b/t/t7814-grep-recurse-submodules.sh @@ -6,6 +6,7 @@ This test verifies the recurse-submodules feature correctly greps across submodules. ' +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1 @@ -471,8 +472,10 @@ test_expect_failure 'grep --textconv: superproject .gitattributes (from index) d test_expect_failure 'grep --textconv: superproject .git/info/attributes does not affect submodules' ' reset_and_clean && test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" && - super_attr="$(git rev-parse --git-path info/attributes)" && + super_info="$(git rev-parse --git-path info)" && + super_attr="$super_info/attributes" && test_when_finished "rm -f \"$super_attr\"" && + mkdir "$super_info" && echo "a diff=d2x" >"$super_attr" && cat >expect <<-\EOF && @@ -516,7 +519,8 @@ test_expect_failure 'grep --textconv correctly reads submodule .git/info/attribu reset_and_clean && test_config_global diff.d2x.textconv "sed -e \"s/d/x/\"" && - submodule_attr="$(git -C submodule rev-parse --path-format=absolute --git-path info/attributes)" && + submodule_info="$(git -C submodule rev-parse --path-format=absolute --git-path info)" && + submodule_attr="$submodule_info/attributes" && test_when_finished "rm -f \"$submodule_attr\"" && echo "a diff=d2x" >"$submodule_attr" && diff --git a/t/t8001-annotate.sh b/t/t8001-annotate.sh index a536a621b2..d7167f5539 100755 --- a/t/t8001-annotate.sh +++ b/t/t8001-annotate.sh @@ -4,6 +4,7 @@ test_description='git annotate' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh PROG='git annotate' diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh index ee4fdd8f18..0147de304b 100755 --- a/t/t8002-blame.sh +++ b/t/t8002-blame.sh @@ -4,6 +4,7 @@ test_description='git blame' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh PROG='git blame -c' diff --git a/t/t8007-cat-file-textconv.sh b/t/t8007-cat-file-textconv.sh index b067983ba1..c8266f17f1 100755 --- a/t/t8007-cat-file-textconv.sh +++ b/t/t8007-cat-file-textconv.sh @@ -1,6 +1,8 @@ #!/bin/sh test_description='git cat-file textconv support' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh cat >helper <<'EOF' diff --git a/t/t8010-cat-file-filters.sh b/t/t8010-cat-file-filters.sh index 31de4b64dc..ca04242ca0 100755 --- a/t/t8010-cat-file-filters.sh +++ b/t/t8010-cat-file-filters.sh @@ -1,6 +1,8 @@ #!/bin/sh test_description='git cat-file filters support' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup ' ' diff --git a/t/t8012-blame-colors.sh b/t/t8012-blame-colors.sh index 90c75dbb28..c3a5f6d01f 100755 --- a/t/t8012-blame-colors.sh +++ b/t/t8012-blame-colors.sh @@ -4,6 +4,7 @@ test_description='colored git blame' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_CREATE_REPO_NO_TEMPLATE=1 . ./test-lib.sh PROG='git blame -c' diff --git a/t/t9101-git-svn-props.sh b/t/t9101-git-svn-props.sh index d043e80fc3..52046e60d5 100755 --- a/t/t9101-git-svn-props.sh +++ b/t/t9101-git-svn-props.sh @@ -5,7 +5,6 @@ test_description='git svn property tests' -TEST_FAILS_SANITIZE_LEAK=true . ./lib-git-svn.sh mkdir import diff --git a/t/t9104-git-svn-follow-parent.sh b/t/t9104-git-svn-follow-parent.sh index 5cf2ef4b8b..85d735861f 100755 --- a/t/t9104-git-svn-follow-parent.sh +++ b/t/t9104-git-svn-follow-parent.sh @@ -5,7 +5,6 @@ test_description='git svn fetching' -TEST_FAILS_SANITIZE_LEAK=true . ./lib-git-svn.sh test_expect_success 'initialize repo' ' diff --git a/t/t9132-git-svn-broken-symlink.sh b/t/t9132-git-svn-broken-symlink.sh index 4d8d0584b7..aeceffaf7b 100755 --- a/t/t9132-git-svn-broken-symlink.sh +++ b/t/t9132-git-svn-broken-symlink.sh @@ -2,7 +2,6 @@ test_description='test that git handles an svn repository with empty symlinks' -TEST_FAILS_SANITIZE_LEAK=true . ./lib-git-svn.sh test_expect_success 'load svn dumpfile' ' svnadmin load "$rawsvnrepo" <<EOF diff --git a/t/t9301-fast-import-notes.sh b/t/t9301-fast-import-notes.sh index 1ae4d7c0d3..58413221e6 100755 --- a/t/t9301-fast-import-notes.sh +++ b/t/t9301-fast-import-notes.sh @@ -7,6 +7,7 @@ test_description='test git fast-import of notes objects' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh index 210ddf09e3..379b19f2f8 100755 --- a/t/t9400-git-cvsserver-server.sh +++ b/t/t9400-git-cvsserver-server.sh @@ -221,7 +221,7 @@ test_expect_success 'req_Root (export-all)' \ 'cat request-anonymous | git-cvsserver --export-all pserver "$WORKDIR" >log 2>&1 && sed -ne \$p log | grep "^I LOVE YOU\$"' -test_expect_success 'req_Root failure (export-all w/o whitelist)' \ +test_expect_success 'req_Root failure (export-all w/o directory list)' \ '! (cat request-anonymous | git-cvsserver --export-all pserver >log 2>&1 || false)' test_expect_success 'req_Root (everything together)' \ diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh index 31526e6b64..43de868b80 100755 --- a/t/t9902-completion.sh +++ b/t/t9902-completion.sh @@ -2485,6 +2485,13 @@ test_expect_success 'git config - section' ' EOF ' +test_expect_success 'git config - section include, includeIf' ' + test_completion "git config inclu" <<-\EOF + include.Z + includeIf.Z + EOF +' + test_expect_success 'git config - variable name' ' test_completion "git config log.d" <<-\EOF log.date Z @@ -2493,6 +2500,12 @@ test_expect_success 'git config - variable name' ' EOF ' +test_expect_success 'git config - variable name include' ' + test_completion "git config include.p" <<-\EOF + include.path Z + EOF +' + test_expect_success 'git config - value' ' test_completion "git config color.pager " <<-\EOF false Z diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index 6da7273f1d..8c44856eae 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -651,8 +651,7 @@ test_set_prereq () { # test_unset_prereq() !*) ;; - # (Temporary?) whitelist of things we can't easily - # pretend not to support + # List of things we can't easily pretend to not support SYMLINKS) ;; # Inspecting whether GIT_TEST_FAIL_PREREQS is on diff --git a/t/test-lib.sh b/t/test-lib.sh index 8cabb4d10f..7726d1da88 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -1456,7 +1456,9 @@ remove_trash_directory "$TRASH_DIRECTORY" || { remove_trash=t if test -z "$TEST_NO_CREATE_REPO" then - git init "$TRASH_DIRECTORY" >&3 2>&4 || + git init \ + ${TEST_CREATE_REPO_NO_TEMPLATE:+--template=} \ + "$TRASH_DIRECTORY" >&3 2>&4 || error "cannot run git init" else mkdir -p "$TRASH_DIRECTORY" |