diff options
Diffstat (limited to 't')
62 files changed, 2085 insertions, 182 deletions
@@ -379,6 +379,11 @@ GIT_TEST_COMMIT_GRAPH=<boolean>, when true, forces the commit-graph to be written after every 'git commit' command, and overrides the 'core.commitGraph' setting to true. +GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=<boolean>, when true, forces +commit-graph write to compute and write changed path Bloom filters for +every 'git commit-graph write', as if the `--changed-paths` option was +passed in. + GIT_TEST_FSMONITOR=$PWD/t7519/fsmonitor-all exercises the fsmonitor code path for utilizing a file system monitor to speed up detecting new or changed files. @@ -547,6 +552,41 @@ Here are the "do's:" reports "ok" or "not ok" to the end user running the tests. Under --verbose, they are shown to help debug the tests. + - Be careful when you loop + + You may need to verify multiple things in a loop, but the + following does not work correctly: + + test_expect_success 'test three things' ' + for i in one two three + do + test_something "$i" + done && + test_something_else + ' + + Because the status of the loop itself is the exit status of the + test_something in the last round, the loop does not fail when + "test_something" for "one" or "two" fails. This is not what you + want. + + Instead, you can break out of the loop immediately when you see a + failure. Because all test_expect_* snippets are executed inside + a function, "return 1" can be used to fail the test immediately + upon a failure: + + test_expect_success 'test three things' ' + for i in one two three + do + test_something "$i" || return 1 + done && + test_something_else + ' + + Note that we still &&-chain the loop to propagate failures from + earlier commands. + + And here are the "don'ts:" - Don't exit() within a <script> part. diff --git a/t/helper/test-bloom.c b/t/helper/test-bloom.c new file mode 100644 index 0000000000..77eb27adac --- /dev/null +++ b/t/helper/test-bloom.c @@ -0,0 +1,93 @@ +#include "git-compat-util.h" +#include "bloom.h" +#include "test-tool.h" +#include "commit.h" + +struct bloom_filter_settings settings = DEFAULT_BLOOM_FILTER_SETTINGS; + +static void add_string_to_filter(const char *data, struct bloom_filter *filter) { + struct bloom_key key; + int i; + + fill_bloom_key(data, strlen(data), &key, &settings); + printf("Hashes:"); + for (i = 0; i < settings.num_hashes; i++){ + printf("0x%08x|", key.hashes[i]); + } + printf("\n"); + add_key_to_filter(&key, filter, &settings); +} + +static void print_bloom_filter(struct bloom_filter *filter) { + int i; + + if (!filter) { + printf("No filter.\n"); + return; + } + printf("Filter_Length:%d\n", (int)filter->len); + printf("Filter_Data:"); + for (i = 0; i < filter->len; i++) { + printf("%02x|", filter->data[i]); + } + printf("\n"); +} + +static void get_bloom_filter_for_commit(const struct object_id *commit_oid) +{ + struct commit *c; + struct bloom_filter *filter; + setup_git_directory(); + c = lookup_commit(the_repository, commit_oid); + filter = get_bloom_filter(the_repository, c, 1); + print_bloom_filter(filter); +} + +static const char *bloom_usage = "\n" +" test-tool bloom get_murmer3 <string>\n" +" test-tool bloom generate_filter <string> [<string>...]\n" +" test-tool get_filter_for_commit <commit-hex>\n"; + +int cmd__bloom(int argc, const char **argv) +{ + if (argc < 2) + usage(bloom_usage); + + if (!strcmp(argv[1], "get_murmur3")) { + uint32_t hashed; + if (argc < 3) + usage(bloom_usage); + hashed = murmur3_seeded(0, argv[2], strlen(argv[2])); + printf("Murmur3 Hash with seed=0:0x%08x\n", hashed); + } + + if (!strcmp(argv[1], "generate_filter")) { + struct bloom_filter filter; + int i = 2; + filter.len = (settings.bits_per_entry + BITS_PER_WORD - 1) / BITS_PER_WORD; + filter.data = xcalloc(filter.len, sizeof(unsigned char)); + + if (argc - 1 < i) + usage(bloom_usage); + + while (argv[i]) { + add_string_to_filter(argv[i], &filter); + i++; + } + + print_bloom_filter(&filter); + } + + if (!strcmp(argv[1], "get_filter_for_commit")) { + struct object_id oid; + const char *end; + if (argc < 3) + usage(bloom_usage); + if (parse_oid_hex(argv[2], &oid, &end)) + die("cannot parse oid '%s'", argv[2]); + init_bloom_filters(); + get_bloom_filter_for_commit(&oid); + } + + return 0; +} diff --git a/t/helper/test-parse-pathspec-file.c b/t/helper/test-parse-pathspec-file.c index 02f4ccfd2a..b3e08cef4b 100644 --- a/t/helper/test-parse-pathspec-file.c +++ b/t/helper/test-parse-pathspec-file.c @@ -6,7 +6,7 @@ int cmd__parse_pathspec_file(int argc, const char **argv) { struct pathspec pathspec; - const char *pathspec_from_file = 0; + const char *pathspec_from_file = NULL; int pathspec_file_nul = 0, i; static const char *const usage[] = { @@ -20,9 +20,9 @@ int cmd__parse_pathspec_file(int argc, const char **argv) OPT_END() }; - parse_options(argc, argv, 0, options, usage, 0); + parse_options(argc, argv, NULL, options, usage, 0); - parse_pathspec_file(&pathspec, 0, 0, 0, pathspec_from_file, + parse_pathspec_file(&pathspec, 0, 0, NULL, pathspec_from_file, pathspec_file_nul); for (i = 0; i < pathspec.nr; i++) diff --git a/t/helper/test-pkt-line.c b/t/helper/test-pkt-line.c index 282d536384..12ca698e17 100644 --- a/t/helper/test-pkt-line.c +++ b/t/helper/test-pkt-line.c @@ -67,7 +67,7 @@ static void unpack_sideband(void) case PACKET_READ_NORMAL: band = reader.line[0] & 0xff; if (band < 1 || band > 2) - die("unexpected side band %d", band); + continue; /* skip non-sideband packets */ fd = band; write_or_die(fd, reader.line + 1, reader.pktlen - 1); diff --git a/t/helper/test-progress.c b/t/helper/test-progress.c index 42b96cb103..5d05cbe789 100644 --- a/t/helper/test-progress.c +++ b/t/helper/test-progress.c @@ -13,20 +13,13 @@ * * See 't0500-progress-display.sh' for examples. */ +#define GIT_TEST_PROGRESS_ONLY #include "test-tool.h" #include "gettext.h" #include "parse-options.h" #include "progress.h" #include "strbuf.h" -/* - * These are defined in 'progress.c', but are not exposed in 'progress.h', - * because they are exclusively for testing. - */ -extern int progress_testing; -extern uint64_t progress_test_ns; -void progress_test_force_update(void); - int cmd__progress(int argc, const char **argv) { int total = 0; diff --git a/t/helper/test-read-graph.c b/t/helper/test-read-graph.c index f8a461767c..6d0c962438 100644 --- a/t/helper/test-read-graph.c +++ b/t/helper/test-read-graph.c @@ -7,26 +7,15 @@ int cmd__read_graph(int argc, const char **argv) { struct commit_graph *graph = NULL; - char *graph_name; - int open_ok; - int fd; - struct stat st; struct object_directory *odb; setup_git_directory(); odb = the_repository->objects->odb; - graph_name = get_commit_graph_filename(odb); - - open_ok = open_commit_graph(graph_name, &fd, &st); - if (!open_ok) - die_errno(_("Could not open commit-graph '%s'"), graph_name); - - graph = load_commit_graph_one_fd_st(fd, &st, odb); + graph = read_commit_graph_one(the_repository, odb); if (!graph) return 1; - FREE_AND_NULL(graph_name); printf("header: %08x %d %d %d %d\n", ntohl(*(uint32_t*)graph->data), @@ -45,6 +34,10 @@ int cmd__read_graph(int argc, const char **argv) printf(" commit_metadata"); if (graph->chunk_extra_edges) printf(" extra_edges"); + if (graph->chunk_bloom_indexes) + printf(" bloom_indexes"); + if (graph->chunk_bloom_data) + printf(" bloom_data"); printf("\n"); UNLEAK(graph); diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c index 2ece4d1ebf..590b2efca7 100644 --- a/t/helper/test-tool.c +++ b/t/helper/test-tool.c @@ -15,6 +15,7 @@ struct test_cmd { static struct test_cmd cmds[] = { { "advise", cmd__advise_if_enabled }, + { "bloom", cmd__bloom }, { "chmtime", cmd__chmtime }, { "config", cmd__config }, { "ctype", cmd__ctype }, diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h index 1cbaec02f3..ddc8e990e9 100644 --- a/t/helper/test-tool.h +++ b/t/helper/test-tool.h @@ -5,6 +5,7 @@ #include "git-compat-util.h" int cmd__advise_if_enabled(int argc, const char **argv); +int cmd__bloom(int argc, const char **argv); int cmd__chmtime(int argc, const char **argv); int cmd__config(int argc, const char **argv); int cmd__ctype(int argc, const char **argv); diff --git a/t/perf/p9300-fast-import-export.sh b/t/perf/p9300-fast-import-export.sh new file mode 100755 index 0000000000..586161e9ad --- /dev/null +++ b/t/perf/p9300-fast-import-export.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +test_description='test fast-import and fast-export performance' +. ./perf-lib.sh + +test_perf_default_repo + +# Use --no-data here to produce a vastly smaller export file. +# This is much cheaper to work with but should still exercise +# fast-import pretty well (we'll still process all commits and +# trees, which account for 60% or more of objects in most repos). +# +# Use --reencode to avoid the default of aborting on non-utf8 commits, +# which lets this test run against a wider variety of sample repos. +test_perf 'export (no-blobs)' ' + git fast-export --reencode=yes --no-data HEAD >export +' + +test_perf 'import (no-blobs)' ' + git fast-import --force <export +' + +test_done diff --git a/t/t0006-date.sh b/t/t0006-date.sh index d9fcc829a9..75ee9a96b8 100755 --- a/t/t0006-date.sh +++ b/t/t0006-date.sh @@ -81,6 +81,11 @@ check_parse 2008-02 bad check_parse 2008-02-14 bad check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 +0000' check_parse '2008-02-14 20:30:45 -0500' '2008-02-14 20:30:45 -0500' +check_parse '2008.02.14 20:30:45 -0500' '2008-02-14 20:30:45 -0500' +check_parse '20080214T203045-04:00' '2008-02-14 20:30:45 -0400' +check_parse '20080214T203045 -04:00' '2008-02-14 20:30:45 -0400' +check_parse '20080214T203045.019-04:00' '2008-02-14 20:30:45 -0400' +check_parse '2008-02-14 20:30:45.019-04:00' '2008-02-14 20:30:45 -0400' check_parse '2008-02-14 20:30:45 -0015' '2008-02-14 20:30:45 -0015' check_parse '2008-02-14 20:30:45 -5' '2008-02-14 20:30:45 +0000' check_parse '2008-02-14 20:30:45 -5:' '2008-02-14 20:30:45 +0000' @@ -103,6 +108,7 @@ check_approxidate 5.seconds.ago '2009-08-30 19:19:55' check_approxidate 10.minutes.ago '2009-08-30 19:10:00' check_approxidate yesterday '2009-08-29 19:20:00' check_approxidate 3.days.ago '2009-08-27 19:20:00' +check_approxidate '12:34:56.3.days.ago' '2009-08-27 12:34:56' check_approxidate 3.weeks.ago '2009-08-09 19:20:00' check_approxidate 3.months.ago '2009-05-30 19:20:00' check_approxidate 2.years.3.months.ago '2007-05-30 19:20:00' diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index 3483b72db4..f8178ee4e3 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -54,7 +54,7 @@ Alias -A, --alias-source <string> get a string -Z, --alias-target <string> - get a string + alias of --alias-source EOF diff --git a/t/t0091-bugreport.sh b/t/t0091-bugreport.sh new file mode 100755 index 0000000000..2e73658a5c --- /dev/null +++ b/t/t0091-bugreport.sh @@ -0,0 +1,61 @@ +#!/bin/sh + +test_description='git bugreport' + +. ./test-lib.sh + +# Headers "[System Info]" will be followed by a non-empty line if we put some +# information there; we can make sure all our headers were followed by some +# information to check if the command was successful. +HEADER_PATTERN="^\[.*\]$" + +check_all_headers_populated () { + while read -r line + do + if test "$(grep "$HEADER_PATTERN" "$line")" + then + echo "$line" + read -r nextline + if test -z "$nextline"; then + return 1; + fi + fi + done +} + +test_expect_success 'creates a report with content in the right places' ' + test_when_finished rm git-bugreport-check-headers.txt && + git bugreport -s check-headers && + check_all_headers_populated <git-bugreport-check-headers.txt +' + +test_expect_success 'dies if file with same name as report already exists' ' + test_when_finished rm git-bugreport-duplicate.txt && + >>git-bugreport-duplicate.txt && + test_must_fail git bugreport --suffix duplicate +' + +test_expect_success '--output-directory puts the report in the provided dir' ' + test_when_finished rm -fr foo/ && + git bugreport -o foo/ && + test_path_is_file foo/git-bugreport-* +' + +test_expect_success 'incorrect arguments abort with usage' ' + test_must_fail git bugreport --false 2>output && + test_i18ngrep usage output && + test_path_is_missing git-bugreport-* +' + +test_expect_success 'runs outside of a git dir' ' + test_when_finished rm non-repo/git-bugreport-* && + nongit git bugreport +' + +test_expect_success 'can create leading directories outside of a git dir' ' + test_when_finished rm -fr foo/bar/baz && + nongit git bugreport -o foo/bar/baz +' + + +test_done diff --git a/t/t0095-bloom.sh b/t/t0095-bloom.sh new file mode 100755 index 0000000000..8f9eef116d --- /dev/null +++ b/t/t0095-bloom.sh @@ -0,0 +1,117 @@ +#!/bin/sh + +test_description='Testing the various Bloom filter computations in bloom.c' +. ./test-lib.sh + +test_expect_success 'compute unseeded murmur3 hash for empty string' ' + cat >expect <<-\EOF && + Murmur3 Hash with seed=0:0x00000000 + EOF + test-tool bloom get_murmur3 "" >actual && + test_cmp expect actual +' + +test_expect_success 'compute unseeded murmur3 hash for test string 1' ' + cat >expect <<-\EOF && + Murmur3 Hash with seed=0:0x627b0c2c + EOF + test-tool bloom get_murmur3 "Hello world!" >actual && + test_cmp expect actual +' + +test_expect_success 'compute unseeded murmur3 hash for test string 2' ' + cat >expect <<-\EOF && + Murmur3 Hash with seed=0:0x2e4ff723 + EOF + test-tool bloom get_murmur3 "The quick brown fox jumps over the lazy dog" >actual && + test_cmp expect actual +' + +test_expect_success 'compute bloom key for empty string' ' + cat >expect <<-\EOF && + Hashes:0x5615800c|0x5b966560|0x61174ab4|0x66983008|0x6c19155c|0x7199fab0|0x771ae004| + Filter_Length:2 + Filter_Data:11|11| + EOF + test-tool bloom generate_filter "" >actual && + test_cmp expect actual +' + +test_expect_success 'compute bloom key for whitespace' ' + cat >expect <<-\EOF && + Hashes:0xf178874c|0x5f3d6eb6|0xcd025620|0x3ac73d8a|0xa88c24f4|0x16510c5e|0x8415f3c8| + Filter_Length:2 + Filter_Data:51|55| + EOF + test-tool bloom generate_filter " " >actual && + test_cmp expect actual +' + +test_expect_success 'compute bloom key for test string 1' ' + cat >expect <<-\EOF && + Hashes:0xb270de9b|0x1bb6f26e|0x84fd0641|0xee431a14|0x57892de7|0xc0cf41ba|0x2a15558d| + Filter_Length:2 + Filter_Data:92|6c| + EOF + test-tool bloom generate_filter "Hello world!" >actual && + test_cmp expect actual +' + +test_expect_success 'compute bloom key for test string 2' ' + cat >expect <<-\EOF && + Hashes:0x20ab385b|0xf5237fe2|0xc99bc769|0x9e140ef0|0x728c5677|0x47049dfe|0x1b7ce585| + Filter_Length:2 + Filter_Data:a5|4a| + EOF + test-tool bloom generate_filter "file.txt" >actual && + test_cmp expect actual +' + +test_expect_success 'get bloom filters for commit with no changes' ' + git init && + git commit --allow-empty -m "c0" && + cat >expect <<-\EOF && + Filter_Length:0 + Filter_Data: + EOF + test-tool bloom get_filter_for_commit "$(git rev-parse HEAD)" >actual && + test_cmp expect actual +' + +test_expect_success 'get bloom filter for commit with 10 changes' ' + rm actual && + rm expect && + mkdir smallDir && + for i in $(test_seq 0 9) + do + echo $i >smallDir/$i + done && + git add smallDir && + git commit -m "commit with 10 changes" && + cat >expect <<-\EOF && + Filter_Length:25 + Filter_Data:82|a0|65|47|0c|92|90|c0|a1|40|02|a0|e2|40|e0|04|0a|9a|66|cf|80|19|85|42|23| + EOF + test-tool bloom get_filter_for_commit "$(git rev-parse HEAD)" >actual && + test_cmp expect actual +' + +test_expect_success EXPENSIVE 'get bloom filter for commit with 513 changes' ' + rm actual && + rm expect && + mkdir bigDir && + for i in $(test_seq 0 512) + do + echo $i >bigDir/$i + done && + git add bigDir && + git commit -m "commit with 513 changes" && + cat >expect <<-\EOF && + Filter_Length:0 + Filter_Data: + EOF + test-tool bloom get_filter_for_commit "$(git rev-parse HEAD)" >actual && + test_cmp expect actual +' + +test_done
\ No newline at end of file diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh index 48484cbcf6..91a007fbfa 100755 --- a/t/t0300-credentials.sh +++ b/t/t0300-credentials.sh @@ -366,6 +366,51 @@ test_expect_success 'match percent-encoded values' ' EOF ' +test_expect_success 'match percent-encoded UTF-8 values in path' ' + test_config credential.https://example.com.useHttpPath true && + test_config credential.https://example.com/perĂº.git.helper "$HELPER" && + check fill <<-\EOF + url=https://example.com/per%C3%BA.git + -- + protocol=https + host=example.com + path=perĂº.git + username=foo + password=bar + -- + EOF +' + +test_expect_success 'match percent-encoded values in username' ' + test_config credential.https://user%2fname@example.com/foo/bar.git.helper "$HELPER" && + check fill <<-\EOF + url=https://user%2fname@example.com/foo/bar.git + -- + protocol=https + host=example.com + username=foo + password=bar + -- + EOF +' + +test_expect_success 'fetch with multiple path components' ' + test_unconfig credential.helper && + test_config credential.https://example.com/foo/repo.git.helper "verbatim foo bar" && + check fill <<-\EOF + url=https://example.com/foo/repo.git + -- + protocol=https + host=example.com + username=foo + password=bar + -- + verbatim: get + verbatim: protocol=https + verbatim: host=example.com + EOF +' + test_expect_success 'pull username from config' ' test_config credential.https://example.com.username foo && check fill <<-\EOF diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh index eb44bafb59..63223e13bd 100755 --- a/t/t1011-read-tree-sparse-checkout.sh +++ b/t/t1011-read-tree-sparse-checkout.sh @@ -233,18 +233,19 @@ test_expect_success 'read-tree --reset removes outside worktree' ' test_must_be_empty result ' -test_expect_success 'print errors when failed to update worktree' ' +test_expect_success 'print warnings when some worktree updates disabled' ' echo sub >.git/info/sparse-checkout && git checkout -f init && mkdir sub && touch sub/added sub/addedtoo && - test_must_fail git checkout top 2>actual && + # Use -q to suppress "Previous HEAD position" and "Head is now at" msgs + git checkout -q top 2>actual && cat >expected <<\EOF && -error: The following untracked working tree files would be overwritten by checkout: +warning: The following paths were already present and thus not updated despite sparse patterns: sub/added sub/addedtoo -Please move or remove them before you switch branches. -Aborting + +After fixing the above paths, you may want to run `git sparse-checkout reapply`. EOF test_i18ncmp expected actual ' diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh index 44a91205d6..dee99eeec3 100755 --- a/t/t1091-sparse-checkout-builtin.sh +++ b/t/t1091-sparse-checkout-builtin.sh @@ -277,15 +277,23 @@ test_expect_success 'cone mode: add parent path' ' check_files repo a deep folder1 ' -test_expect_success 'revert to old sparse-checkout on bad update' ' +test_expect_success 'not-up-to-date does not block rest of sparsification' ' + test_when_finished git -C repo sparse-checkout disable && test_when_finished git -C repo reset --hard && git -C repo sparse-checkout set deep && + echo update >repo/deep/deeper2/a && cp repo/.git/info/sparse-checkout expect && - test_must_fail git -C repo sparse-checkout set deep/deeper1 2>err && - test_i18ngrep "cannot set sparse-checkout patterns" err && - test_cmp repo/.git/info/sparse-checkout expect && - check_files repo/deep a deeper1 deeper2 + test_write_lines "!/deep/*/" "/deep/deeper1/" >>expect && + + git -C repo sparse-checkout set deep/deeper1 2>err && + + test_i18ngrep "The following paths are not up to date" err && + test_cmp expect repo/.git/info/sparse-checkout && + check_files repo/deep a deeper1 deeper2 && + check_files repo/deep/deeper1 a deepest && + check_files repo/deep/deeper1/deepest a && + check_files repo/deep/deeper2 a ' test_expect_success 'revert to old sparse-checkout on empty update' ' @@ -315,19 +323,96 @@ test_expect_success '.gitignore should not warn about cone mode' ' test_i18ngrep ! "disabling cone patterns" err ' -test_expect_success 'sparse-checkout (init|set|disable) fails with dirty status' ' +test_expect_success 'sparse-checkout (init|set|disable) warns with dirty status' ' git clone repo dirty && echo dirty >dirty/folder1/a && - test_must_fail git -C dirty sparse-checkout init && - test_must_fail git -C dirty sparse-checkout set /folder2/* /deep/deeper1/* && - test_must_fail git -C dirty sparse-checkout disable && + + git -C dirty sparse-checkout init 2>err && + test_i18ngrep "warning.*The following paths are not up to date" err && + + git -C dirty sparse-checkout set /folder2/* /deep/deeper1/* 2>err && + test_i18ngrep "warning.*The following paths are not up to date" err && + test_path_is_file dirty/folder1/a && + + git -C dirty sparse-checkout disable 2>err && + test_must_be_empty err && + git -C dirty reset --hard && git -C dirty sparse-checkout init && git -C dirty sparse-checkout set /folder2/* /deep/deeper1/* && - git -C dirty sparse-checkout disable + test_path_is_missing dirty/folder1/a && + git -C dirty sparse-checkout disable && + test_path_is_file dirty/folder1/a +' + +test_expect_success 'sparse-checkout (init|set|disable) warns with unmerged status' ' + git clone repo unmerged && + + cat >input <<-EOF && + 0 0000000000000000000000000000000000000000 folder1/a + 100644 $(git -C unmerged rev-parse HEAD:folder1/a) 1 folder1/a + EOF + git -C unmerged update-index --index-info <input && + + git -C unmerged sparse-checkout init 2>err && + test_i18ngrep "warning.*The following paths are unmerged" err && + + git -C unmerged sparse-checkout set /folder2/* /deep/deeper1/* 2>err && + test_i18ngrep "warning.*The following paths are unmerged" err && + test_path_is_file dirty/folder1/a && + + git -C unmerged sparse-checkout disable 2>err && + test_i18ngrep "warning.*The following paths are unmerged" err && + + git -C unmerged reset --hard && + git -C unmerged sparse-checkout init && + git -C unmerged sparse-checkout set /folder2/* /deep/deeper1/* && + git -C unmerged sparse-checkout disable +' + +test_expect_success 'sparse-checkout reapply' ' + git clone repo tweak && + + echo dirty >tweak/deep/deeper2/a && + + cat >input <<-EOF && + 0 0000000000000000000000000000000000000000 folder1/a + 100644 $(git -C tweak rev-parse HEAD:folder1/a) 1 folder1/a + EOF + git -C tweak update-index --index-info <input && + + git -C tweak sparse-checkout init --cone 2>err && + test_i18ngrep "warning.*The following paths are not up to date" err && + test_i18ngrep "warning.*The following paths are unmerged" err && + + git -C tweak sparse-checkout set folder2 deep/deeper1 2>err && + test_i18ngrep "warning.*The following paths are not up to date" err && + test_i18ngrep "warning.*The following paths are unmerged" err && + + git -C tweak sparse-checkout reapply 2>err && + test_i18ngrep "warning.*The following paths are not up to date" err && + test_path_is_file tweak/deep/deeper2/a && + test_i18ngrep "warning.*The following paths are unmerged" err && + test_path_is_file tweak/folder1/a && + + git -C tweak checkout HEAD deep/deeper2/a && + git -C tweak sparse-checkout reapply 2>err && + test_i18ngrep ! "warning.*The following paths are not up to date" err && + test_path_is_missing tweak/deep/deeper2/a && + test_i18ngrep "warning.*The following paths are unmerged" err && + test_path_is_file tweak/folder1/a && + + git -C tweak add folder1/a && + git -C tweak sparse-checkout reapply 2>err && + test_must_be_empty err && + test_path_is_missing tweak/deep/deeper2/a && + test_path_is_missing tweak/folder1/a && + + git -C tweak sparse-checkout disable ' test_expect_success 'cone mode: set with core.ignoreCase=true' ' + rm repo/.git/info/sparse-checkout && git -C repo sparse-checkout init --cone && git -C repo -c core.ignoreCase=true sparse-checkout set folder1 && cat >expect <<-\EOF && diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index a6224ef65f..e1197ac818 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -1354,15 +1354,6 @@ test_expect_success 'fails with duplicate ref update via symref' ' test_cmp expect actual ' -run_with_limited_open_files () { - (ulimit -n 32 && "$@") -} - -test_lazy_prereq ULIMIT_FILE_DESCRIPTORS ' - test_have_prereq !MINGW,!CYGWIN && - run_with_limited_open_files true -' - test_expect_success ULIMIT_FILE_DESCRIPTORS 'large transaction creating branches does not burst open file limit' ' ( for i in $(test_seq 33) @@ -1404,4 +1395,135 @@ test_expect_success 'handle per-worktree refs in refs/bisect' ' ! test_cmp main-head worktree-head ' +test_expect_success 'transaction handles empty commit' ' + cat >stdin <<-EOF && + start + prepare + commit + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" start prepare commit >expect && + test_cmp expect actual +' + +test_expect_success 'transaction handles empty commit with missing prepare' ' + cat >stdin <<-EOF && + start + commit + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" start commit >expect && + test_cmp expect actual +' + +test_expect_success 'transaction handles sole commit' ' + cat >stdin <<-EOF && + commit + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" commit >expect && + test_cmp expect actual +' + +test_expect_success 'transaction handles empty abort' ' + cat >stdin <<-EOF && + start + prepare + abort + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" start prepare abort >expect && + test_cmp expect actual +' + +test_expect_success 'transaction exits on multiple aborts' ' + cat >stdin <<-EOF && + abort + abort + EOF + test_must_fail git update-ref --stdin <stdin >actual 2>err && + printf "%s: ok\n" abort >expect && + test_cmp expect actual && + grep "fatal: transaction is closed" err +' + +test_expect_success 'transaction exits on start after prepare' ' + cat >stdin <<-EOF && + prepare + start + EOF + test_must_fail git update-ref --stdin <stdin 2>err >actual && + printf "%s: ok\n" prepare >expect && + test_cmp expect actual && + grep "fatal: prepared transactions can only be closed" err +' + +test_expect_success 'transaction handles empty abort with missing prepare' ' + cat >stdin <<-EOF && + start + abort + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" start abort >expect && + test_cmp expect actual +' + +test_expect_success 'transaction handles sole abort' ' + cat >stdin <<-EOF && + abort + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" abort >expect && + test_cmp expect actual +' + +test_expect_success 'transaction can handle commit' ' + cat >stdin <<-EOF && + start + create $a HEAD + commit + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" start commit >expect && + test_cmp expect actual && + git rev-parse HEAD >expect && + git rev-parse $a >actual && + test_cmp expect actual +' + +test_expect_success 'transaction can handle abort' ' + cat >stdin <<-EOF && + start + create $b HEAD + abort + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" start abort >expect && + test_cmp expect actual && + test_path_is_missing .git/$b +' + +test_expect_success 'transaction aborts by default' ' + cat >stdin <<-EOF && + start + create $b HEAD + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" start >expect && + test_cmp expect actual && + test_path_is_missing .git/$b +' + +test_expect_success 'transaction with prepare aborts by default' ' + cat >stdin <<-EOF && + start + create $b HEAD + prepare + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" start prepare >expect && + test_cmp expect actual && + test_path_is_missing .git/$b +' + test_done diff --git a/t/t2018-checkout-branch.sh b/t/t2018-checkout-branch.sh index bbca7ef8da..21583154d8 100755 --- a/t/t2018-checkout-branch.sh +++ b/t/t2018-checkout-branch.sh @@ -238,4 +238,26 @@ test_expect_success 'checkout -b after clone --no-checkout does a checkout of HE test_path_is_file dest/a.t ' +test_expect_success 'checkout -b to a new branch preserves mergeable changes despite sparse-checkout' ' + test_when_finished " + git reset --hard && + git checkout branch1-scratch && + test_might_fail git branch -D branch3 && + git config core.sparseCheckout false && + rm .git/info/sparse-checkout" && + + test_commit file2 && + + echo stuff >>file1 && + echo file2 >.git/info/sparse-checkout && + git config core.sparseCheckout true && + + CURHEAD=$(git rev-parse HEAD) && + do_checkout branch3 $CURHEAD && + + echo file1 >expect && + git diff --name-only >actual && + test_cmp expect actual +' + test_done diff --git a/t/t3000-ls-files-others.sh b/t/t3000-ls-files-others.sh index 0aefadacb0..ffdfb16f58 100755 --- a/t/t3000-ls-files-others.sh +++ b/t/t3000-ls-files-others.sh @@ -91,4 +91,125 @@ test_expect_success SYMLINKS 'ls-files --others with symlinked submodule' ' test_cmp expect actual ' +test_expect_success 'setup nested pathspec search' ' + test_create_repo nested && + ( + cd nested && + + mkdir -p partially_tracked/untracked_dir && + > partially_tracked/content && + > partially_tracked/untracked_dir/file && + + mkdir -p untracked/deep && + > untracked/deep/path && + > untracked/deep/foo.c && + + git add partially_tracked/content + ) +' + +test_expect_success 'ls-files -o --directory with single deep dir pathspec' ' + ( + cd nested && + + git ls-files -o --directory untracked/deep/ >actual && + + cat <<-EOF >expect && + untracked/deep/ + EOF + + test_cmp expect actual + ) +' + +test_expect_success 'ls-files -o --directory with multiple dir pathspecs' ' + ( + cd nested && + + git ls-files -o --directory partially_tracked/ untracked/ >actual && + + cat <<-EOF >expect && + partially_tracked/untracked_dir/ + untracked/ + EOF + + test_cmp expect actual + ) +' + +test_expect_success 'ls-files -o --directory with mix dir/file pathspecs' ' + ( + cd nested && + + git ls-files -o --directory partially_tracked/ untracked/deep/path >actual && + + cat <<-EOF >expect && + partially_tracked/untracked_dir/ + untracked/deep/path + EOF + + test_cmp expect actual + ) +' + +test_expect_success 'ls-files --o --directory with glob filetype match' ' + ( + cd nested && + + # globs kinda defeat --directory, but only for that pathspec + git ls-files --others --directory partially_tracked "untracked/*.c" >actual && + + cat <<-EOF >expect && + partially_tracked/untracked_dir/ + untracked/deep/foo.c + EOF + + test_cmp expect actual + ) +' + +test_expect_success 'ls-files --o --directory with mix of tracked states' ' + ( + cd nested && + + # globs kinda defeat --directory, but only for that pathspec + git ls-files --others --directory partially_tracked/ "untracked/?*" >actual && + + cat <<-EOF >expect && + partially_tracked/untracked_dir/ + untracked/deep/ + EOF + + test_cmp expect actual + ) +' + +test_expect_success 'ls-files --o --directory with glob filetype match only' ' + ( + cd nested && + + git ls-files --others --directory "untracked/*.c" >actual && + + cat <<-EOF >expect && + untracked/deep/foo.c + EOF + + test_cmp expect actual + ) +' + +test_expect_success 'ls-files --o --directory to get immediate paths under one dir only' ' + ( + cd nested && + + git ls-files --others --directory "untracked/?*" >actual && + + cat <<-EOF >expect && + untracked/deep/ + EOF + + test_cmp expect actual + ) +' + test_done diff --git a/t/t3033-merge-toplevel.sh b/t/t3033-merge-toplevel.sh index d314599428..e29c284b9b 100755 --- a/t/t3033-merge-toplevel.sh +++ b/t/t3033-merge-toplevel.sh @@ -142,6 +142,17 @@ test_expect_success 'refuse two-project merge by default' ' test_must_fail git merge five ' +test_expect_success 'refuse two-project merge by default, quit before --autostash happens' ' + t3033_reset && + git reset --hard four && + echo change >>one.t && + git diff >expect && + test_must_fail git merge --autostash five 2>err && + test_i18ngrep ! "stash" err && + git diff >actual && + test_cmp expect actual +' + test_expect_success 'two-project merge with --allow-unrelated-histories' ' t3033_reset && git reset --hard four && @@ -149,4 +160,15 @@ test_expect_success 'two-project merge with --allow-unrelated-histories' ' git diff --exit-code five ' +test_expect_success 'two-project merge with --allow-unrelated-histories with --autostash' ' + t3033_reset && + git reset --hard four && + echo change >>one.t && + git diff one.t >expect && + git merge --allow-unrelated-histories --autostash five 2>err && + test_i18ngrep "Applied autostash." err && + git diff one.t >actual && + test_cmp expect actual +' + test_done diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh index bd808f87ed..e024cff65c 100755 --- a/t/t3206-range-diff.sh +++ b/t/t3206-range-diff.sh @@ -513,6 +513,16 @@ test_expect_success 'range-diff overrides diff.noprefix internally' ' git -c diff.noprefix=true range-diff HEAD^... ' +test_expect_success 'basic with modified format.pretty with suffix' ' + git -c format.pretty="format:commit %H%d%n" range-diff \ + master..topic master..unmodified +' + +test_expect_success 'basic with modified format.pretty without "commit "' ' + git -c format.pretty="format:%H%n" range-diff \ + master..topic master..unmodified +' + test_expect_success 'range-diff compares notes by default' ' git notes add -m "topic note" topic && git notes add -m "unmodified note" unmodified && diff --git a/t/t3420-rebase-autostash.sh b/t/t3420-rebase-autostash.sh index b97ea62363..ca331733fb 100755 --- a/t/t3420-rebase-autostash.sh +++ b/t/t3420-rebase-autostash.sh @@ -184,6 +184,26 @@ testrebase () { git checkout feature-branch ' + test_expect_success "rebase$type: --quit" ' + test_config rebase.autostash true && + git reset --hard && + git checkout -b rebased-feature-branch feature-branch && + test_when_finished git branch -D rebased-feature-branch && + echo dirty >>file3 && + git diff >expect && + test_must_fail git rebase$type related-onto-branch && + test_path_is_file $dotest/autostash && + test_path_is_missing file3 && + git rebase --quit && + test_when_finished git stash drop && + test_path_is_missing $dotest/autostash && + ! grep dirty file3 && + git stash show -p >actual && + test_cmp expect actual && + git reset --hard && + git checkout feature-branch + ' + test_expect_success "rebase$type: non-conflicting rebase, conflicting stash" ' test_config rebase.autostash true && git reset --hard && diff --git a/t/t3904-stash-patch.sh b/t/t3904-stash-patch.sh index 9546b6f8a4..accfe3845c 100755 --- a/t/t3904-stash-patch.sh +++ b/t/t3904-stash-patch.sh @@ -89,7 +89,7 @@ test_expect_success 'none of this moved HEAD' ' verify_saved_head ' -test_expect_failure 'stash -p with split hunk' ' +test_expect_success 'stash -p with split hunk' ' git reset --hard && cat >test <<-\EOF && aaa @@ -106,8 +106,8 @@ test_expect_failure 'stash -p with split hunk' ' ccc EOF printf "%s\n" s n y q | - test_might_fail git stash -p 2>error && - ! test_must_be_empty error && + git stash -p 2>error && + test_must_be_empty error && grep "added line 1" test && ! grep "added line 2" test ' diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index dde3f11fec..3f60f7d96c 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -95,6 +95,15 @@ test_expect_success setup ' git commit -m "update mode" && git checkout -f master && + GIT_AUTHOR_DATE="2006-06-26 00:06:00 +0000" && + GIT_COMMITTER_DATE="2006-06-26 00:06:00 +0000" && + export GIT_AUTHOR_DATE GIT_COMMITTER_DATE && + git checkout -b note initial && + git update-index --chmod=+x file2 && + git commit -m "update mode (file2)" && + git notes add -m "note" && + git checkout -f master && + # Same merge as master, but with parents reversed. Hide it in a # pseudo-ref to avoid impacting tests with --all. commit=$(echo reverse | @@ -398,6 +407,9 @@ diff --no-index --raw --no-abbrev dir2 dir diff-tree --pretty --root --stat --compact-summary initial diff-tree --pretty -R --root --stat --compact-summary initial +diff-tree --pretty note +diff-tree --pretty --notes note +diff-tree --format=%N note diff-tree --stat --compact-summary initial mode diff-tree -R --stat --compact-summary initial mode EOF diff --git a/t/t4013/diff.diff-tree_--format=%N_note b/t/t4013/diff.diff-tree_--format=%N_note new file mode 100644 index 0000000000..93042ed539 --- /dev/null +++ b/t/t4013/diff.diff-tree_--format=%N_note @@ -0,0 +1,6 @@ +$ git diff-tree --format=%N note +note + + +:100644 100755 01e79c32a8c99c557f0757da7cb6d65b3414466d 01e79c32a8c99c557f0757da7cb6d65b3414466d M file2 +$ diff --git a/t/t4013/diff.diff-tree_--pretty_--notes_note b/t/t4013/diff.diff-tree_--pretty_--notes_note new file mode 100644 index 0000000000..4d0bde601c --- /dev/null +++ b/t/t4013/diff.diff-tree_--pretty_--notes_note @@ -0,0 +1,12 @@ +$ git diff-tree --pretty --notes note +commit a6f364368ca320bc5a92e18912e16fa6b3dff598 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:06:00 2006 +0000 + + update mode (file2) + +Notes: + note + +:100644 100755 01e79c32a8c99c557f0757da7cb6d65b3414466d 01e79c32a8c99c557f0757da7cb6d65b3414466d M file2 +$ diff --git a/t/t4013/diff.diff-tree_--pretty_note b/t/t4013/diff.diff-tree_--pretty_note new file mode 100644 index 0000000000..1fa5967083 --- /dev/null +++ b/t/t4013/diff.diff-tree_--pretty_note @@ -0,0 +1,9 @@ +$ git diff-tree --pretty note +commit a6f364368ca320bc5a92e18912e16fa6b3dff598 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:06:00 2006 +0000 + + update mode (file2) + +:100644 100755 01e79c32a8c99c557f0757da7cb6d65b3414466d 01e79c32a8c99c557f0757da7cb6d65b3414466d M file2 +$ diff --git a/t/t4013/diff.log_--decorate=full_--all b/t/t4013/diff.log_--decorate=full_--all index 2afe91f116..3f9b872ece 100644 --- a/t/t4013/diff.log_--decorate=full_--all +++ b/t/t4013/diff.log_--decorate=full_--all @@ -5,12 +5,27 @@ Date: Mon Jun 26 00:06:00 2006 +0000 update mode +commit a6f364368ca320bc5a92e18912e16fa6b3dff598 (refs/heads/note) +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:06:00 2006 +0000 + + update mode (file2) + +Notes: + note + commit cd4e72fd96faed3f0ba949dc42967430374e2290 (refs/heads/rearrange) Author: A U Thor <author@example.com> Date: Mon Jun 26 00:06:00 2006 +0000 Rearranged lines in dir/sub +commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits) +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:06:00 2006 +0000 + + Notes added by 'git notes add' + commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/master) Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> diff --git a/t/t4013/diff.log_--decorate_--all b/t/t4013/diff.log_--decorate_--all index d0f308ab2b..f5e20e1e14 100644 --- a/t/t4013/diff.log_--decorate_--all +++ b/t/t4013/diff.log_--decorate_--all @@ -5,12 +5,27 @@ Date: Mon Jun 26 00:06:00 2006 +0000 update mode +commit a6f364368ca320bc5a92e18912e16fa6b3dff598 (note) +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:06:00 2006 +0000 + + update mode (file2) + +Notes: + note + commit cd4e72fd96faed3f0ba949dc42967430374e2290 (rearrange) Author: A U Thor <author@example.com> Date: Mon Jun 26 00:06:00 2006 +0000 Rearranged lines in dir/sub +commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits) +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:06:00 2006 +0000 + + Notes added by 'git notes add' + commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> master) Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> diff --git a/t/t4061-diff-indent.sh b/t/t4061-diff-indent.sh index 2affd7a100..0f7a6d97a8 100755 --- a/t/t4061-diff-indent.sh +++ b/t/t4061-diff-indent.sh @@ -17,7 +17,7 @@ compare_diff () { # Compare blame output using the expectation for a diff as reference. # Only look for the lines coming from non-boundary commits. compare_blame () { - sed -n -e "1,4d" -e "s/^\+//p" <"$1" >.tmp-1 + sed -n -e "1,4d" -e "s/^+//p" <"$1" >.tmp-1 sed -ne "s/^[^^][^)]*) *//p" <"$2" >.tmp-2 test_cmp .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 } diff --git a/t/t4067-diff-partial-clone.sh b/t/t4067-diff-partial-clone.sh index 4831ad35e6..c1ed1c2fc4 100755 --- a/t/t4067-diff-partial-clone.sh +++ b/t/t4067-diff-partial-clone.sh @@ -131,4 +131,52 @@ test_expect_success 'diff with rename detection batches blobs' ' test_line_count = 1 done_lines ' +test_expect_success 'diff does not fetch anything if inexact rename detection is not needed' ' + test_when_finished "rm -rf server client trace" && + + test_create_repo server && + echo a >server/a && + printf "b\nb\nb\nb\nb\n" >server/b && + git -C server add a b && + git -C server commit -m x && + mv server/b server/c && + git -C server add c && + git -C server commit -a -m x && + + test_config -C server uploadpack.allowfilter 1 && + test_config -C server uploadpack.allowanysha1inwant 1 && + git clone --bare --filter=blob:limit=0 "file://$(pwd)/server" client && + + # Ensure no fetches. + GIT_TRACE_PACKET="$(pwd)/trace" git -C client diff --raw -M HEAD^ HEAD && + ! test_path_exists trace +' + +test_expect_success 'diff --break-rewrites fetches only if necessary, and batches blobs if it does' ' + test_when_finished "rm -rf server client trace" && + + test_create_repo server && + echo a >server/a && + printf "b\nb\nb\nb\nb\n" >server/b && + git -C server add a b && + git -C server commit -m x && + printf "c\nc\nc\nc\nc\n" >server/b && + git -C server commit -a -m x && + + test_config -C server uploadpack.allowfilter 1 && + test_config -C server uploadpack.allowanysha1inwant 1 && + git clone --bare --filter=blob:limit=0 "file://$(pwd)/server" client && + + # Ensure no fetches. + GIT_TRACE_PACKET="$(pwd)/trace" git -C client diff --raw -M HEAD^ HEAD && + ! test_path_exists trace && + + # But with --break-rewrites, ensure that there is exactly 1 negotiation + # by checking that there is only 1 "done" line sent. ("done" marks the + # end of negotiation.) + GIT_TRACE_PACKET="$(pwd)/trace" git -C client diff --break-rewrites --raw -M HEAD^ HEAD && + grep "git> done" trace >done_lines && + test_line_count = 1 done_lines +' + test_done diff --git a/t/t4124-apply-ws-rule.sh b/t/t4124-apply-ws-rule.sh index 971a5a7512..0ca29821ec 100755 --- a/t/t4124-apply-ws-rule.sh +++ b/t/t4124-apply-ws-rule.sh @@ -52,6 +52,13 @@ test_fix () { # find touched lines $DIFF file target | sed -n -e "s/^> //p" >fixed + # busybox's diff(1) doesn't output normal format + if ! test -s fixed + then + $DIFF -u file target | + grep -v '^+++ target' | + sed -ne "/^+/s/+//p" >fixed + fi # the changed lines are all expected to change fixed_cnt=$(wc -l <fixed) diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 5eeb739f3e..f1ea7d97f5 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -742,7 +742,23 @@ test_expect_success 'decorate-refs with glob' ' octopus-a (octopus-a) reach EOF + cat >expect.no-decorate <<-\EOF && + Merge-tag-reach + Merge-tags-octopus-a-and-octopus-b + seventh + octopus-b + octopus-a + reach + EOF + git log -n6 --decorate=short --pretty="tformat:%f%d" \ + --decorate-refs="heads/octopus*" >actual && + test_cmp expect.decorate actual && git log -n6 --decorate=short --pretty="tformat:%f%d" \ + --decorate-refs-exclude="heads/octopus*" \ + --decorate-refs="heads/octopus*" >actual && + test_cmp expect.no-decorate actual && + git -c log.excludeDecoration="heads/octopus*" log \ + -n6 --decorate=short --pretty="tformat:%f%d" \ --decorate-refs="heads/octopus*" >actual && test_cmp expect.decorate actual ' @@ -787,6 +803,9 @@ test_expect_success 'decorate-refs-exclude with glob' ' EOF git log -n6 --decorate=short --pretty="tformat:%f%d" \ --decorate-refs-exclude="heads/octopus*" >actual && + test_cmp expect.decorate actual && + git -c log.excludeDecoration="heads/octopus*" log \ + -n6 --decorate=short --pretty="tformat:%f%d" >actual && test_cmp expect.decorate actual ' @@ -801,6 +820,9 @@ test_expect_success 'decorate-refs-exclude without globs' ' EOF git log -n6 --decorate=short --pretty="tformat:%f%d" \ --decorate-refs-exclude="tags/reach" >actual && + test_cmp expect.decorate actual && + git -c log.excludeDecoration="tags/reach" log \ + -n6 --decorate=short --pretty="tformat:%f%d" >actual && test_cmp expect.decorate actual ' @@ -816,11 +838,19 @@ test_expect_success 'multiple decorate-refs-exclude' ' git log -n6 --decorate=short --pretty="tformat:%f%d" \ --decorate-refs-exclude="heads/octopus*" \ --decorate-refs-exclude="tags/reach" >actual && + test_cmp expect.decorate actual && + git -c log.excludeDecoration="heads/octopus*" \ + -c log.excludeDecoration="tags/reach" log \ + -n6 --decorate=short --pretty="tformat:%f%d" >actual && + test_cmp expect.decorate actual && + git -c log.excludeDecoration="heads/octopus*" log \ + --decorate-refs-exclude="tags/reach" \ + -n6 --decorate=short --pretty="tformat:%f%d" >actual && test_cmp expect.decorate actual ' test_expect_success 'decorate-refs and decorate-refs-exclude' ' - cat >expect.decorate <<-\EOF && + cat >expect.no-decorate <<-\EOF && Merge-tag-reach (master) Merge-tags-octopus-a-and-octopus-b seventh @@ -831,6 +861,21 @@ test_expect_success 'decorate-refs and decorate-refs-exclude' ' git log -n6 --decorate=short --pretty="tformat:%f%d" \ --decorate-refs="heads/*" \ --decorate-refs-exclude="heads/oc*" >actual && + test_cmp expect.no-decorate actual +' + +test_expect_success 'deocrate-refs and log.excludeDecoration' ' + cat >expect.decorate <<-\EOF && + Merge-tag-reach (master) + Merge-tags-octopus-a-and-octopus-b + seventh + octopus-b (octopus-b) + octopus-a (octopus-a) + reach (reach) + EOF + git -c log.excludeDecoration="heads/oc*" log \ + --decorate-refs="heads/*" \ + -n6 --decorate=short --pretty="tformat:%f%d" >actual && test_cmp expect.decorate actual ' @@ -846,6 +891,10 @@ test_expect_success 'decorate-refs-exclude and simplify-by-decoration' ' git log -n6 --decorate=short --pretty="tformat:%f%d" \ --decorate-refs-exclude="*octopus*" \ --simplify-by-decoration >actual && + test_cmp expect.decorate actual && + git -c log.excludeDecoration="*octopus*" log \ + -n6 --decorate=short --pretty="tformat:%f%d" \ + --simplify-by-decoration >actual && test_cmp expect.decorate actual ' diff --git a/t/t4216-log-bloom.sh b/t/t4216-log-bloom.sh new file mode 100755 index 0000000000..c7011f33e2 --- /dev/null +++ b/t/t4216-log-bloom.sh @@ -0,0 +1,155 @@ +#!/bin/sh + +test_description='git log for a path with Bloom filters' +. ./test-lib.sh + +GIT_TEST_COMMIT_GRAPH=0 +GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0 + +test_expect_success 'setup test - repo, commits, commit graph, log outputs' ' + git init && + mkdir A A/B A/B/C && + test_commit c1 A/file1 && + test_commit c2 A/B/file2 && + test_commit c3 A/B/C/file3 && + test_commit c4 A/file1 && + test_commit c5 A/B/file2 && + test_commit c6 A/B/C/file3 && + test_commit c7 A/file1 && + test_commit c8 A/B/file2 && + test_commit c9 A/B/C/file3 && + test_commit c10 file_to_be_deleted && + git checkout -b side HEAD~4 && + test_commit side-1 file4 && + git checkout master && + git merge side && + test_commit c11 file5 && + mv file5 file5_renamed && + git add file5_renamed && + git commit -m "rename" && + rm file_to_be_deleted && + git add . && + git commit -m "file removed" && + git commit-graph write --reachable --changed-paths +' +graph_read_expect () { + NUM_CHUNKS=5 + cat >expect <<- EOF + header: 43475048 1 1 $NUM_CHUNKS 0 + num_commits: $1 + chunks: oid_fanout oid_lookup commit_metadata bloom_indexes bloom_data + EOF + test-tool read-graph >actual && + test_cmp expect actual +} + +test_expect_success 'commit-graph write wrote out the bloom chunks' ' + graph_read_expect 15 +' + +# Turn off any inherited trace2 settings for this test. +sane_unset GIT_TRACE2 GIT_TRACE2_PERF GIT_TRACE2_EVENT +sane_unset GIT_TRACE2_PERF_BRIEF +sane_unset GIT_TRACE2_CONFIG_PARAMS + +setup () { + rm "$TRASH_DIRECTORY/trace.perf" + git -c core.commitGraph=false log --pretty="format:%s" $1 >log_wo_bloom && + GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.perf" git -c core.commitGraph=true log --pretty="format:%s" $1 >log_w_bloom +} + +test_bloom_filters_used () { + log_args=$1 + bloom_trace_prefix="statistics:{\"filter_not_present\":0,\"zero_length_filter\":0,\"maybe\"" + setup "$log_args" && + grep -q "$bloom_trace_prefix" "$TRASH_DIRECTORY/trace.perf" && + test_cmp log_wo_bloom log_w_bloom && + test_path_is_file "$TRASH_DIRECTORY/trace.perf" +} + +test_bloom_filters_not_used () { + log_args=$1 + setup "$log_args" && + !(grep -q "statistics:{\"filter_not_present\":" "$TRASH_DIRECTORY/trace.perf") && + test_cmp log_wo_bloom log_w_bloom +} + +for path in A A/B A/B/C A/file1 A/B/file2 A/B/C/file3 file4 file5 file5_renamed file_to_be_deleted +do + for option in "" \ + "--all" \ + "--full-history" \ + "--full-history --simplify-merges" \ + "--simplify-merges" \ + "--simplify-by-decoration" \ + "--follow" \ + "--first-parent" \ + "--topo-order" \ + "--date-order" \ + "--author-date-order" \ + "--ancestry-path side..master" + do + test_expect_success "git log option: $option for path: $path" ' + test_bloom_filters_used "$option -- $path" + ' + done +done + +test_expect_success 'git log -- folder works with and without the trailing slash' ' + test_bloom_filters_used "-- A" && + test_bloom_filters_used "-- A/" +' + +test_expect_success 'git log for path that does not exist. ' ' + test_bloom_filters_used "-- path_does_not_exist" +' + +test_expect_success 'git log with --walk-reflogs does not use Bloom filters' ' + test_bloom_filters_not_used "--walk-reflogs -- A" +' + +test_expect_success 'git log -- multiple path specs does not use Bloom filters' ' + test_bloom_filters_not_used "-- file4 A/file1" +' + +test_expect_success 'git log with wildcard that resolves to a single path uses Bloom filters' ' + test_bloom_filters_used "-- *4" && + test_bloom_filters_used "-- *renamed" +' + +test_expect_success 'git log with wildcard that resolves to a multiple paths does not uses Bloom filters' ' + test_bloom_filters_not_used "-- *" && + test_bloom_filters_not_used "-- file*" +' + +test_expect_success 'setup - add commit-graph to the chain without Bloom filters' ' + test_commit c14 A/anotherFile2 && + test_commit c15 A/B/anotherFile2 && + test_commit c16 A/B/C/anotherFile2 && + GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0 git commit-graph write --reachable --split && + test_line_count = 2 .git/objects/info/commit-graphs/commit-graph-chain +' + +test_expect_success 'Do not use Bloom filters if the latest graph does not have Bloom filters.' ' + test_bloom_filters_not_used "-- A/B" +' + +test_expect_success 'setup - add commit-graph to the chain with Bloom filters' ' + test_commit c17 A/anotherFile3 && + git commit-graph write --reachable --changed-paths --split && + test_line_count = 3 .git/objects/info/commit-graphs/commit-graph-chain +' + +test_bloom_filters_used_when_some_filters_are_missing () { + log_args=$1 + bloom_trace_prefix="statistics:{\"filter_not_present\":3,\"zero_length_filter\":0,\"maybe\":8,\"definitely_not\":6" + setup "$log_args" && + grep -q "$bloom_trace_prefix" "$TRASH_DIRECTORY/trace.perf" && + test_cmp log_wo_bloom log_w_bloom +} + +test_expect_success 'Use Bloom filters if they exist in the latest but not all commit graphs in the chain.' ' + test_bloom_filters_used_when_some_filters_are_missing "-- A/B" +' + +test_done
\ No newline at end of file diff --git a/t/t4254-am-corrupt.sh b/t/t4254-am-corrupt.sh index fd3bdbfe2c..daf01c309d 100755 --- a/t/t4254-am-corrupt.sh +++ b/t/t4254-am-corrupt.sh @@ -3,6 +3,37 @@ test_description='git am with corrupt input' . ./test-lib.sh +make_mbox_with_nul () { + space=' ' + q_nul_in_subject= + q_nul_in_body= + while test $# -ne 0 + do + case "$1" in + subject) q_nul_in_subject='=00' ;; + body) q_nul_in_body='=00' ;; + esac && + shift + done && + cat <<-EOF + From ec7364544f690c560304f5a5de9428ea3b978b26 Mon Sep 17 00:00:00 2001 + From: A U Thor <author@example.com> + Date: Sun, 19 Apr 2020 13:42:07 +0700 + Subject: [PATCH] =?ISO-8859-1?q?=C4=CB${q_nul_in_subject}=D1=CF=D6?= + MIME-Version: 1.0 + Content-Type: text/plain; charset=ISO-8859-1 + Content-Transfer-Encoding: quoted-printable + + abc${q_nul_in_body}def + --- + diff --git a/afile b/afile + new file mode 100644 + index 0000000000..e69de29bb2 + --$space + 2.26.1 + EOF +} + test_expect_success setup ' # Note the missing "+++" line: cat >bad-patch.diff <<-\EOF && @@ -25,13 +56,27 @@ test_expect_success setup ' # fatal: unable to write file '(null)' mode 100644: Bad address # Also, it had the unwanted side-effect of deleting f. test_expect_success 'try to apply corrupted patch' ' - test_must_fail git -c advice.amWorkDir=false am bad-patch.diff 2>actual -' - -test_expect_success 'compare diagnostic; ensure file is still here' ' + test_when_finished "git am --abort" && + test_must_fail git -c advice.amWorkDir=false am bad-patch.diff 2>actual && echo "error: git diff header lacks filename information (line 4)" >expected && test_path_is_file f && test_i18ncmp expected actual ' +test_expect_success "NUL in commit message's body" ' + test_when_finished "git am --abort" && + make_mbox_with_nul body >body.patch && + test_must_fail git am body.patch 2>err && + grep "a NUL byte in commit log message not allowed" err +' + +test_expect_success "NUL in commit message's header" " + test_when_finished 'git am --abort' && + make_mbox_with_nul subject >subject.patch && + test_must_fail git mailinfo msg patch <subject.patch 2>err && + grep \"a NUL byte in 'Subject' is not allowed\" err && + test_must_fail git am subject.patch 2>err && + grep \"a NUL byte in 'Subject' is not allowed\" err +" + test_done diff --git a/t/t5003-archive-zip.sh b/t/t5003-archive-zip.sh index 106eddbd85..3b76d2eb65 100755 --- a/t/t5003-archive-zip.sh +++ b/t/t5003-archive-zip.sh @@ -7,12 +7,12 @@ test_description='git archive --format=zip test' SUBSTFORMAT=%H%n test_lazy_prereq UNZIP_SYMLINKS ' - ( - mkdir unzip-symlinks && - cd unzip-symlinks && - "$GIT_UNZIP" "$TEST_DIRECTORY"/t5003/infozip-symlinks.zip && - test -h symlink - ) + "$GIT_UNZIP" "$TEST_DIRECTORY"/t5003/infozip-symlinks.zip && + test -h symlink +' + +test_lazy_prereq UNZIP_CONVERT ' + "$GIT_UNZIP" -a "$TEST_DIRECTORY"/t5003/infozip-symlinks.zip ' check_zip() { @@ -39,33 +39,33 @@ check_zip() { extracted=${dir_with_prefix}a original=a - test_expect_success UNZIP " extract ZIP archive with EOL conversion" ' + test_expect_success UNZIP_CONVERT " extract ZIP archive with EOL conversion" ' (mkdir $dir && cd $dir && "$GIT_UNZIP" -a ../$zipfile) ' - test_expect_success UNZIP " validate that text files are converted" " + test_expect_success UNZIP_CONVERT " validate that text files are converted" " test_cmp_bin $extracted/text.cr $extracted/text.crlf && test_cmp_bin $extracted/text.cr $extracted/text.lf " - test_expect_success UNZIP " validate that binary files are unchanged" " + test_expect_success UNZIP_CONVERT " validate that binary files are unchanged" " test_cmp_bin $original/binary.cr $extracted/binary.cr && test_cmp_bin $original/binary.crlf $extracted/binary.crlf && test_cmp_bin $original/binary.lf $extracted/binary.lf " - test_expect_success UNZIP " validate that diff files are converted" " + test_expect_success UNZIP_CONVERT " validate that diff files are converted" " test_cmp_bin $extracted/diff.cr $extracted/diff.crlf && test_cmp_bin $extracted/diff.cr $extracted/diff.lf " - test_expect_success UNZIP " validate that -diff files are unchanged" " + test_expect_success UNZIP_CONVERT " validate that -diff files are unchanged" " test_cmp_bin $original/nodiff.cr $extracted/nodiff.cr && test_cmp_bin $original/nodiff.crlf $extracted/nodiff.crlf && test_cmp_bin $original/nodiff.lf $extracted/nodiff.lf " - test_expect_success UNZIP " validate that custom diff is unchanged " " + test_expect_success UNZIP_CONVERT " validate that custom diff is unchanged " " test_cmp_bin $original/custom.cr $extracted/custom.cr && test_cmp_bin $original/custom.crlf $extracted/custom.crlf && test_cmp_bin $original/custom.lf $extracted/custom.lf diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh index 9bf920ae17..39e2918a32 100755 --- a/t/t5318-commit-graph.sh +++ b/t/t5318-commit-graph.sh @@ -3,6 +3,8 @@ test_description='commit graph' . ./test-lib.sh +GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0 + test_expect_success 'setup full repo' ' mkdir full && cd "$TRASH_DIRECTORY/full" && @@ -43,7 +45,7 @@ test_expect_success 'create commits and repack' ' test_expect_success 'exit with correct error on bad input to --stdin-commits' ' cd "$TRASH_DIRECTORY/full" && echo HEAD | test_expect_code 1 git commit-graph write --stdin-commits 2>stderr && - test_i18ngrep "invalid commit object id" stderr && + test_i18ngrep "unexpected non-hex object ID: HEAD" stderr && # valid tree OID, but not a commit OID git rev-parse HEAD^{tree} | test_expect_code 1 git commit-graph write --stdin-commits 2>stderr && test_i18ngrep "invalid commit object id" stderr diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh index 22240fd30b..030a7222b2 100755 --- a/t/t5319-multi-pack-index.sh +++ b/t/t5319-multi-pack-index.sh @@ -526,10 +526,10 @@ test_expect_success 'repack with minimum size does not alter existing packs' ' cd dup && rm -rf .git/objects/pack && mv .git/objects/pack-backup .git/objects/pack && - touch -m -t 201901010000 .git/objects/pack/pack-D* && - touch -m -t 201901010001 .git/objects/pack/pack-C* && - touch -m -t 201901010002 .git/objects/pack/pack-B* && - touch -m -t 201901010003 .git/objects/pack/pack-A* && + test-tool chmtime =-5 .git/objects/pack/pack-D* && + test-tool chmtime =-4 .git/objects/pack/pack-C* && + test-tool chmtime =-3 .git/objects/pack/pack-B* && + test-tool chmtime =-2 .git/objects/pack/pack-A* && ls .git/objects/pack >expect && MINSIZE=$(test-tool path-utils file-size .git/objects/pack/*pack | sort -n | head -n 1) && git multi-pack-index repack --batch-size=$MINSIZE && diff --git a/t/t5324-split-commit-graph.sh b/t/t5324-split-commit-graph.sh index 53b2e6b455..594edb7307 100755 --- a/t/t5324-split-commit-graph.sh +++ b/t/t5324-split-commit-graph.sh @@ -4,6 +4,7 @@ test_description='split commit graph' . ./test-lib.sh GIT_TEST_COMMIT_GRAPH=0 +GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0 test_expect_success 'setup repo' ' git init && @@ -210,8 +211,14 @@ test_expect_success 'test merge stragety constants' ' git config core.commitGraph true && test_line_count = 2 $graphdir/commit-graph-chain && test_commit 15 && - git commit-graph write --reachable --split --size-multiple=10 --expire-time=1980-01-01 && + touch $graphdir/to-delete.graph $graphdir/to-keep.graph && + test-tool chmtime =1546362000 $graphdir/to-delete.graph && + test-tool chmtime =1546362001 $graphdir/to-keep.graph && + git commit-graph write --reachable --split --size-multiple=10 \ + --expire-time="2019-01-01 12:00 -05:00" && test_line_count = 1 $graphdir/commit-graph-chain && + test_path_is_missing $graphdir/to-delete.graph && + test_path_is_file $graphdir/to-keep.graph && ls $graphdir/graph-*.graph >graph-files && test_line_count = 3 graph-files ) && @@ -351,4 +358,47 @@ test_expect_success 'split across alternate where alternate is not split' ' test_cmp commit-graph .git/objects/info/commit-graph ' +test_expect_success '--split=no-merge always writes an incremental' ' + test_when_finished rm -rf a b && + rm -rf $graphdir $infodir/commit-graph && + git reset --hard commits/2 && + git rev-list HEAD~1 >a && + git rev-list HEAD >b && + git commit-graph write --split --stdin-commits <a && + git commit-graph write --split=no-merge --stdin-commits <b && + test_line_count = 2 $graphdir/commit-graph-chain +' + +test_expect_success '--split=replace replaces the chain' ' + rm -rf $graphdir $infodir/commit-graph && + git reset --hard commits/3 && + git rev-list -1 HEAD~2 >a && + git rev-list -1 HEAD~1 >b && + git rev-list -1 HEAD >c && + git commit-graph write --split=no-merge --stdin-commits <a && + git commit-graph write --split=no-merge --stdin-commits <b && + git commit-graph write --split=no-merge --stdin-commits <c && + test_line_count = 3 $graphdir/commit-graph-chain && + git commit-graph write --stdin-commits --split=replace <b && + test_path_is_missing $infodir/commit-graph && + test_path_is_file $graphdir/commit-graph-chain && + ls $graphdir/graph-*.graph >graph-files && + test_line_count = 1 graph-files && + verify_chain_files_exist $graphdir && + graph_read_expect 2 +' + +test_expect_success ULIMIT_FILE_DESCRIPTORS 'handles file descriptor exhaustion' ' + git init ulimit && + ( + cd ulimit && + for i in $(test_seq 64) + do + test_commit $i && + test_might_fail run_with_limited_open_files git commit-graph write \ + --split=no-merge --reachable || return 1 + done + ) +' + test_done diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh index baa1a99f45..52dd1a688c 100755 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@ -385,6 +385,54 @@ test_expect_success 'clone shallow with packed refs' ' test_cmp count8.expected count8.actual ' +test_expect_success 'in_vain not triggered before first ACK' ' + rm -rf myserver myclient trace && + git init myserver && + test_commit -C myserver foo && + git clone "file://$(pwd)/myserver" myclient && + + # MAX_IN_VAIN is 256. Because of batching, the client will send 496 + # (16+32+64+128+256) commits, not 256, before giving up. So create 496 + # irrelevant commits. + test_commit_bulk -C myclient 496 && + + # The new commit that the client wants to fetch. + test_commit -C myserver bar && + + GIT_TRACE_PACKET="$(pwd)/trace" git -C myclient fetch --progress origin && + test_i18ngrep "Total 3 " trace +' + +test_expect_success 'in_vain resetted upon ACK' ' + rm -rf myserver myclient trace && + git init myserver && + + # Linked list of commits on master. The first is common; the rest are + # not. + test_commit -C myserver first_master_commit && + git clone "file://$(pwd)/myserver" myclient && + test_commit_bulk -C myclient 255 && + + # Another linked list of commits on anotherbranch with no connection to + # master. The first is common; the rest are not. + git -C myserver checkout --orphan anotherbranch && + test_commit -C myserver first_anotherbranch_commit && + git -C myclient fetch origin anotherbranch:refs/heads/anotherbranch && + git -C myclient checkout anotherbranch && + test_commit_bulk -C myclient 255 && + + # The new commit that the client wants to fetch. + git -C myserver checkout master && + test_commit -C myserver to_fetch && + + # The client will send (as "have"s) all 256 commits in anotherbranch + # first. The 256th commit is common between the client and the server, + # and should reset in_vain. This allows negotiation to continue until + # the client reports that first_anotherbranch_commit is common. + GIT_TRACE_PACKET="$(pwd)/trace" git -C myclient fetch --progress origin master && + test_i18ngrep "Total 3 " trace +' + test_expect_success 'fetch in shallow repo unreachable shallow objects' ' ( git clone --bare --branch B --single-branch "file://$(pwd)/." no-reflog && diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh index 645b4c78d3..a32efe2b6c 100755 --- a/t/t5504-fetch-receive-strict.sh +++ b/t/t5504-fetch-receive-strict.sh @@ -65,6 +65,7 @@ test_expect_success 'fetch with transfer.fsckobjects' ' cat >exp <<EOF To dst ! refs/heads/master:refs/heads/test [remote rejected] (missing necessary objects) +Done EOF test_expect_success 'push without strict' ' diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 9ff041a093..9c6218f568 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -1066,6 +1066,7 @@ test_expect_success 'push --porcelain rejected' ' echo >.git/foo "To testrepo" && echo >>.git/foo "! refs/heads/master:refs/heads/master [remote rejected] (branch is currently checked out)" && + echo >>.git/foo "Done" && test_must_fail git push >.git/bar --porcelain testrepo refs/heads/master:refs/heads/master && test_cmp .git/foo .git/bar diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index 2f86fca042..37535d63a9 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -10,11 +10,13 @@ modify () { } test_pull_autostash () { + expect_parent_num="$1" && + shift && git reset --hard before-rebase && echo dirty >new_file && git add new_file && git pull "$@" . copy && - test_cmp_rev HEAD^ copy && + test_cmp_rev HEAD^"$expect_parent_num" copy && echo dirty >expect && test_cmp expect new_file && echo "modified again" >expect && @@ -26,7 +28,7 @@ test_pull_autostash_fail () { echo dirty >new_file && git add new_file && test_must_fail git pull "$@" . copy 2>err && - test_i18ngrep "uncommitted changes." err + test_i18ngrep "\(uncommitted changes.\)\|\(overwritten by merge:\)" err } test_expect_success setup ' @@ -369,22 +371,22 @@ test_expect_success '--rebase fails with multiple branches' ' test_expect_success 'pull --rebase succeeds with dirty working directory and rebase.autostash set' ' test_config rebase.autostash true && - test_pull_autostash --rebase + test_pull_autostash 1 --rebase ' test_expect_success 'pull --rebase --autostash & rebase.autostash=true' ' test_config rebase.autostash true && - test_pull_autostash --rebase --autostash + test_pull_autostash 1 --rebase --autostash ' test_expect_success 'pull --rebase --autostash & rebase.autostash=false' ' test_config rebase.autostash false && - test_pull_autostash --rebase --autostash + test_pull_autostash 1 --rebase --autostash ' test_expect_success 'pull --rebase --autostash & rebase.autostash unset' ' test_unconfig rebase.autostash && - test_pull_autostash --rebase --autostash + test_pull_autostash 1 --rebase --autostash ' test_expect_success 'pull --rebase --no-autostash & rebase.autostash=true' ' @@ -402,13 +404,40 @@ test_expect_success 'pull --rebase --no-autostash & rebase.autostash unset' ' test_pull_autostash_fail --rebase --no-autostash ' -for i in --autostash --no-autostash -do - test_expect_success "pull $i (without --rebase) is illegal" ' - test_must_fail git pull $i . copy 2>err && - test_i18ngrep "only valid with --rebase" err - ' -done +test_expect_success 'pull succeeds with dirty working directory and merge.autostash set' ' + test_config merge.autostash true && + test_pull_autostash 2 +' + +test_expect_success 'pull --autostash & merge.autostash=true' ' + test_config merge.autostash true && + test_pull_autostash 2 --autostash +' + +test_expect_success 'pull --autostash & merge.autostash=false' ' + test_config merge.autostash false && + test_pull_autostash 2 --autostash +' + +test_expect_success 'pull --autostash & merge.autostash unset' ' + test_unconfig merge.autostash && + test_pull_autostash 2 --autostash +' + +test_expect_success 'pull --no-autostash & merge.autostash=true' ' + test_config merge.autostash true && + test_pull_autostash_fail --no-autostash +' + +test_expect_success 'pull --no-autostash & merge.autostash=false' ' + test_config merge.autostash false && + test_pull_autostash_fail --no-autostash +' + +test_expect_success 'pull --no-autostash & merge.autostash unset' ' + test_unconfig merge.autostash && + test_pull_autostash_fail --no-autostash +' test_expect_success 'pull.rebase' ' git reset --hard before-rebase && @@ -422,7 +451,7 @@ test_expect_success 'pull.rebase' ' test_expect_success 'pull --autostash & pull.rebase=true' ' test_config pull.rebase true && - test_pull_autostash --autostash + test_pull_autostash 1 --autostash ' test_expect_success 'pull --no-autostash & pull.rebase=true' ' diff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh index b57209c84f..d427a2d7f7 100755 --- a/t/t5537-fetch-shallow.sh +++ b/t/t5537-fetch-shallow.sh @@ -16,7 +16,7 @@ test_expect_success 'setup' ' commit 3 && commit 4 && git config --global transfer.fsckObjects true && - test_oid_cache <<-EOF + test_oid_cache <<-\EOF perl sha1:s/0034shallow %s/0036unshallow %s/ perl sha256:s/004cshallow %s/004eunshallow %s/ EOF @@ -25,10 +25,7 @@ test_expect_success 'setup' ' test_expect_success 'setup shallow clone' ' git clone --no-local --depth=2 .git shallow && git --git-dir=shallow/.git log --format=%s >actual && - cat <<EOF >expect && -4 -3 -EOF + test_write_lines 4 3 >expect && test_cmp expect actual ' @@ -38,10 +35,7 @@ test_expect_success 'clone from shallow clone' ' cd shallow2 && git fsck && git log --format=%s >actual && - cat <<EOF >expect && -4 -3 -EOF + test_write_lines 4 3 >expect && test_cmp expect actual ) ' @@ -56,11 +50,7 @@ test_expect_success 'fetch from shallow clone' ' git fetch && git fsck && git log --format=%s origin/master >actual && - cat <<EOF >expect && -5 -4 -3 -EOF + test_write_lines 5 4 3 >expect && test_cmp expect actual ) ' @@ -75,10 +65,7 @@ test_expect_success 'fetch --depth from shallow clone' ' git fetch --depth=2 && git fsck && git log --format=%s origin/master >actual && - cat <<EOF >expect && -6 -5 -EOF + test_write_lines 6 5 >expect && test_cmp expect actual ) ' @@ -89,12 +76,7 @@ test_expect_success 'fetch --unshallow from shallow clone' ' git fetch --unshallow && git fsck && git log --format=%s origin/master >actual && - cat <<EOF >expect && -6 -5 -4 -3 -EOF + test_write_lines 6 5 4 3 >expect && test_cmp expect actual ) ' @@ -111,15 +93,10 @@ test_expect_success 'fetch something upstream has but hidden by clients shallow git fetch ../.git +refs/heads/master:refs/remotes/top/master && git fsck && git log --format=%s top/master >actual && - cat <<EOF >expect && -add-1-back -4 -3 -EOF + test_write_lines add-1-back 4 3 >expect && test_cmp expect actual ) && git --git-dir=shallow2/.git cat-file blob $(echo 1|git hash-object --stdin) >/dev/null - ' test_expect_success 'fetch that requires changes in .git/shallow is filtered' ' @@ -133,14 +110,10 @@ test_expect_success 'fetch that requires changes in .git/shallow is filtered' ' cd notshallow && git fetch ../shallow/.git refs/heads/*:refs/remotes/shallow/* && git for-each-ref --format="%(refname)" >actual.refs && - cat <<EOF >expect.refs && -refs/remotes/shallow/no-shallow -EOF + echo refs/remotes/shallow/no-shallow >expect.refs && test_cmp expect.refs actual.refs && git log --format=%s shallow/no-shallow >actual && - cat <<EOF >expect && -no-shallow -EOF + echo no-shallow >expect && test_cmp expect actual ) ' @@ -158,21 +131,44 @@ test_expect_success 'fetch --update-shallow' ' git fetch --update-shallow ../shallow/.git refs/heads/*:refs/remotes/shallow/* && git fsck && git for-each-ref --sort=refname --format="%(refname)" >actual.refs && - cat <<EOF >expect.refs && -refs/remotes/shallow/master -refs/remotes/shallow/no-shallow -refs/tags/heavy-tag -refs/tags/light-tag -EOF + cat <<-\EOF >expect.refs && + refs/remotes/shallow/master + refs/remotes/shallow/no-shallow + refs/tags/heavy-tag + refs/tags/light-tag + EOF + test_cmp expect.refs actual.refs && + git log --format=%s shallow/master >actual && + test_write_lines 7 6 5 4 3 >expect && + test_cmp expect actual + ) +' + +test_expect_success 'fetch --update-shallow (with fetch.writeCommitGraph)' ' + ( + cd shallow && + git checkout master && + commit 8 && + git tag -m foo heavy-tag-for-graph HEAD^ && + git tag light-tag-for-graph HEAD^:tracked + ) && + test_config -C notshallow fetch.writeCommitGraph true && + ( + cd notshallow && + git fetch --update-shallow ../shallow/.git refs/heads/*:refs/remotes/shallow/* && + git fsck && + git for-each-ref --sort=refname --format="%(refname)" >actual.refs && + cat <<-EOF >expect.refs && + refs/remotes/shallow/master + refs/remotes/shallow/no-shallow + refs/tags/heavy-tag + refs/tags/heavy-tag-for-graph + refs/tags/light-tag + refs/tags/light-tag-for-graph + EOF test_cmp expect.refs actual.refs && git log --format=%s shallow/master >actual && - cat <<EOF >expect && -7 -6 -5 -4 -3 -EOF + test_write_lines 8 7 6 5 4 3 >expect && test_cmp expect actual ) ' @@ -183,10 +179,7 @@ test_expect_success POSIXPERM,SANITY 'shallow fetch from a read-only repo' ' find read-only.git -print | xargs chmod -w && git clone --no-local --depth=2 read-only.git from-read-only && git --git-dir=from-read-only/.git log --format=%s >actual && - cat >expect <<EOF && -add-1-back -4 -EOF + test_write_lines add-1-back 4 >expect && test_cmp expect actual ' diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh index 23be8ce92d..afc680d5e3 100755 --- a/t/t5541-http-push-smart.sh +++ b/t/t5541-http-push-smart.sh @@ -177,6 +177,9 @@ test_expect_success 'push (chunked)' ' test $HEAD = $(git rev-parse --verify HEAD)) ' +## References of remote: atomic1(1) master(2) collateral(2) other(2) +## References of local : atomic2(2) master(1) collateral(3) other(2) collateral1(3) atomic(1) +## Atomic push : master(1) collateral(3) atomic(1) test_expect_success 'push --atomic also prevents branch creation, reports collateral' ' # Setup upstream repo - empty for now d=$HTTPD_DOCUMENT_ROOT_PATH/atomic-branches.git && @@ -189,7 +192,8 @@ test_expect_success 'push --atomic also prevents branch creation, reports collat test_commit atomic2 && git branch collateral && git branch other && - git push "$up" master collateral other && + git push "$up" atomic1 master collateral other && + git tag -d atomic1 && # collateral is a valid push, but should be failed by atomic push git checkout collateral && @@ -224,7 +228,11 @@ test_expect_success 'push --atomic also prevents branch creation, reports collat # the collateral failure refs should be indicated to the user grep "^ ! .*rejected.* atomic -> atomic .*atomic push failed" output && - grep "^ ! .*rejected.* collateral -> collateral .*atomic push failed" output + grep "^ ! .*rejected.* collateral -> collateral .*atomic push failed" output && + + # never report what we do not push + ! grep "^ ! .*rejected.* atomic1 " output && + ! grep "^ ! .*rejected.* other " output ' test_expect_success 'push --atomic fails on server-side errors' ' diff --git a/t/t5543-atomic-push.sh b/t/t5543-atomic-push.sh index 7079bcf9a0..620c30d58f 100755 --- a/t/t5543-atomic-push.sh +++ b/t/t5543-atomic-push.sh @@ -27,6 +27,12 @@ test_refs () { test_cmp expect actual } +fmt_status_report () { + sed -n \ + -e "/^To / { s/ */ /g; p; }" \ + -e "/^ ! / { s/ */ /g; p; }" +} + test_expect_success 'atomic push works for a single branch' ' mk_repo_pair && ( @@ -191,4 +197,87 @@ test_expect_success 'atomic push is not advertised if configured' ' test_refs master HEAD@{1} ' +# References in upstream : master(1) one(1) foo(1) +# References in workbench: master(2) foo(1) two(2) bar(2) +# Atomic push : master(2) two(2) bar(2) +test_expect_success 'atomic push reports (reject by update hook)' ' + mk_repo_pair && + ( + cd workbench && + test_commit one && + git branch foo && + git push up master one foo && + git tag -d one + ) && + ( + mkdir -p upstream/.git/hooks && + cat >upstream/.git/hooks/update <<-EOF && + #!/bin/sh + + if test "\$1" = "refs/heads/bar" + then + echo >&2 "Pusing to branch bar is prohibited" + exit 1 + fi + EOF + chmod a+x upstream/.git/hooks/update + ) && + ( + cd workbench && + test_commit two && + git branch bar + ) && + test_must_fail git -C workbench \ + push --atomic up master two bar >out 2>&1 && + fmt_status_report <out >actual && + cat >expect <<-EOF && + To ../upstream + ! [remote rejected] master -> master (atomic push failure) + ! [remote rejected] two -> two (atomic push failure) + ! [remote rejected] bar -> bar (hook declined) + EOF + test_cmp expect actual +' + +# References in upstream : master(1) one(1) foo(1) +# References in workbench: master(2) foo(1) two(2) bar(2) +test_expect_success 'atomic push reports (mirror, but reject by update hook)' ' + ( + cd workbench && + git remote remove up && + git remote add up ../upstream + ) && + test_must_fail git -C workbench \ + push --atomic --mirror up >out 2>&1 && + fmt_status_report <out >actual && + cat >expect <<-EOF && + To ../upstream + ! [remote rejected] master -> master (atomic push failure) + ! [remote rejected] one (atomic push failure) + ! [remote rejected] bar -> bar (hook declined) + ! [remote rejected] two -> two (atomic push failure) + EOF + test_cmp expect actual +' + +# References in upstream : master(2) one(1) foo(1) +# References in workbench: master(1) foo(1) two(2) bar(2) +test_expect_success 'atomic push reports (reject by non-ff)' ' + rm upstream/.git/hooks/update && + ( + cd workbench && + git push up master && + git reset --hard HEAD^ + ) && + test_must_fail git -C workbench \ + push --atomic up master foo bar >out 2>&1 && + fmt_status_report <out >actual && + cat >expect <<-EOF && + To ../upstream + ! [rejected] master -> master (non-fast-forward) + ! [rejected] bar -> bar (atomic push failed) + EOF + test_cmp expect actual +' + test_done diff --git a/t/t5548-push-porcelain.sh b/t/t5548-push-porcelain.sh new file mode 100755 index 0000000000..1b19b3ef55 --- /dev/null +++ b/t/t5548-push-porcelain.sh @@ -0,0 +1,279 @@ +#!/bin/sh +# +# Copyright (c) 2020 Jiang Xin +# +test_description='Test git push porcelain output' + +. ./test-lib.sh + +# Create commits in <repo> and assign each commit's oid to shell variables +# given in the arguments (A, B, and C). E.g.: +# +# create_commits_in <repo> A B C +# +# NOTE: Never calling this function from a subshell since variable +# assignments will disappear when subshell exits. +create_commits_in () { + repo="$1" && + if ! parent=$(git -C "$repo" rev-parse HEAD^{} --) + then + parent= + fi && + T=$(git -C "$repo" write-tree) && + shift && + while test $# -gt 0 + do + name=$1 && + test_tick && + if test -z "$parent" + then + oid=$(echo $name | git -C "$repo" commit-tree $T) + else + oid=$(echo $name | git -C "$repo" commit-tree -p $parent $T) + fi && + eval $name=$oid && + parent=$oid && + shift || + return 1 + done && + git -C "$repo" update-ref refs/heads/master $oid +} + +# Format the output of git-push, git-show-ref and other commands to make a +# user-friendly and stable text. We can easily prepare the expect text +# without having to worry about future changes of the commit ID and spaces +# of the output. +make_user_friendly_and_stable_output () { + sed \ + -e "s/ *\$//" \ + -e "s/ */ /g" \ + -e "s/ / /g" \ + -e "s/$A/<COMMIT-A>/g" \ + -e "s/$B/<COMMIT-B>/g" \ + -e "s/$ZERO_OID/<ZERO-OID>/g" \ + -e "s/$(echo $A | cut -c1-7)[0-9a-f]*/<OID-A>/g" \ + -e "s/$(echo $B | cut -c1-7)[0-9a-f]*/<OID-B>/g" \ + -e "s#To $URL_PREFIX/upstream.git#To <URL/of/upstream.git>#" +} + +setup_upstream_and_workbench () { + # Upstream after setup : master(B) foo(A) bar(A) baz(A) + # Workbench after setup : master(A) + test_expect_success "setup upstream repository and workbench" ' + rm -rf upstream.git workbench && + git init --bare upstream.git && + git init workbench && + create_commits_in workbench A B && + ( + cd workbench && + # Try to make a stable fixed width for abbreviated commit ID, + # this fixed-width oid will be replaced with "<OID>". + git config core.abbrev 7 && + git remote add origin ../upstream.git && + git update-ref refs/heads/master $A && + git push origin \ + $B:refs/heads/master \ + $A:refs/heads/foo \ + $A:refs/heads/bar \ + $A:refs/heads/baz + ) && + git -C "workbench" config advice.pushUpdateRejected false && + upstream=upstream.git + ' +} + +run_git_push_porcelain_output_test() { + case $1 in + http) + PROTOCOL="HTTP protocol" + URL_PREFIX="http://.*" + ;; + file) + PROTOCOL="builtin protocol" + URL_PREFIX="\.\." + ;; + esac + + # Refs of upstream : master(B) foo(A) bar(A) baz(A) + # Refs of workbench: master(A) baz(A) next(A) + # git-push : master(A) NULL (B) baz(A) next(A) + test_expect_success "porcelain output of successful git-push ($PROTOCOL)" ' + ( + cd workbench && + git update-ref refs/heads/master $A && + git update-ref refs/heads/baz $A && + git update-ref refs/heads/next $A && + git push --porcelain --force origin \ + master \ + :refs/heads/foo \ + $B:bar \ + baz \ + next + ) >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + To <URL/of/upstream.git> + = refs/heads/baz:refs/heads/baz [up to date] + <COMMIT-B>:refs/heads/bar <OID-A>..<OID-B> + - :refs/heads/foo [deleted] + + refs/heads/master:refs/heads/master <OID-B>...<OID-A> (forced update) + * refs/heads/next:refs/heads/next [new branch] + Done + EOF + test_cmp expect actual && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + <COMMIT-B> refs/heads/bar + <COMMIT-A> refs/heads/baz + <COMMIT-A> refs/heads/master + <COMMIT-A> refs/heads/next + EOF + test_cmp expect actual + ' + + # Refs of upstream : master(A) bar(B) baz(A) next(A) + # Refs of workbench: master(B) bar(A) baz(A) next(A) + # git-push : master(B) bar(A) NULL next(A) + test_expect_success "atomic push failed ($PROTOCOL)" ' + ( + cd workbench && + git update-ref refs/heads/master $B && + git update-ref refs/heads/bar $A && + test_must_fail git push --atomic --porcelain origin \ + master \ + bar \ + :baz \ + next + ) >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + To <URL/of/upstream.git> + = refs/heads/next:refs/heads/next [up to date] + ! refs/heads/bar:refs/heads/bar [rejected] (non-fast-forward) + ! (delete):refs/heads/baz [rejected] (atomic push failed) + ! refs/heads/master:refs/heads/master [rejected] (atomic push failed) + Done + EOF + test_cmp expect actual && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + <COMMIT-B> refs/heads/bar + <COMMIT-A> refs/heads/baz + <COMMIT-A> refs/heads/master + <COMMIT-A> refs/heads/next + EOF + test_cmp expect actual + ' + test_expect_success "prepare pre-receive hook ($PROTOCOL)" ' + write_script "$upstream/hooks/pre-receive" <<-EOF + exit 1 + EOF + ' + + # Refs of upstream : master(A) bar(B) baz(A) next(A) + # Refs of workbench: master(B) bar(A) baz(A) next(A) + # git-push : master(B) bar(A) NULL next(A) + test_expect_success "pre-receive hook declined ($PROTOCOL)" ' + ( + cd workbench && + git update-ref refs/heads/master $B && + git update-ref refs/heads/bar $A && + test_must_fail git push --porcelain --force origin \ + master \ + bar \ + :baz \ + next + ) >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + To <URL/of/upstream.git> + = refs/heads/next:refs/heads/next [up to date] + ! refs/heads/bar:refs/heads/bar [remote rejected] (pre-receive hook declined) + ! :refs/heads/baz [remote rejected] (pre-receive hook declined) + ! refs/heads/master:refs/heads/master [remote rejected] (pre-receive hook declined) + Done + EOF + test_cmp expect actual && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + <COMMIT-B> refs/heads/bar + <COMMIT-A> refs/heads/baz + <COMMIT-A> refs/heads/master + <COMMIT-A> refs/heads/next + EOF + test_cmp expect actual + ' + + test_expect_success "remove pre-receive hook ($PROTOCOL)" ' + rm "$upstream/hooks/pre-receive" + ' + + # Refs of upstream : master(A) bar(B) baz(A) next(A) + # Refs of workbench: master(B) bar(A) baz(A) next(A) + # git-push : master(B) bar(A) NULL next(A) + test_expect_success "non-fastforward push ($PROTOCOL)" ' + ( + cd workbench && + test_must_fail git push --porcelain origin \ + master \ + bar \ + :baz \ + next + ) >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + To <URL/of/upstream.git> + = refs/heads/next:refs/heads/next [up to date] + - :refs/heads/baz [deleted] + refs/heads/master:refs/heads/master <OID-A>..<OID-B> + ! refs/heads/bar:refs/heads/bar [rejected] (non-fast-forward) + Done + EOF + test_cmp expect actual && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + <COMMIT-B> refs/heads/bar + <COMMIT-B> refs/heads/master + <COMMIT-A> refs/heads/next + EOF + test_cmp expect actual + ' +} + +# Initialize the upstream repository and local workbench. +setup_upstream_and_workbench + +# Run git-push porcelain test on builtin protocol +run_git_push_porcelain_output_test file + +ROOT_PATH="$PWD" +. "$TEST_DIRECTORY"/lib-gpg.sh +. "$TEST_DIRECTORY"/lib-httpd.sh +. "$TEST_DIRECTORY"/lib-terminal.sh +start_httpd + +# Re-initialize the upstream repository and local workbench. +setup_upstream_and_workbench + +test_expect_success "setup for http" ' + git -C upstream.git config http.receivepack true && + upstream="$HTTPD_DOCUMENT_ROOT_PATH/upstream.git" && + mv upstream.git "$upstream" && + + git -C workbench remote set-url origin $HTTPD_URL/smart/upstream.git +' + +setup_askpass_helper + +# Run git-push porcelain test on HTTP protocol +run_git_push_porcelain_output_test http + +test_done diff --git a/t/t5616-partial-clone.sh b/t/t5616-partial-clone.sh index 8f0d81a27e..88002b24af 100755 --- a/t/t5616-partial-clone.sh +++ b/t/t5616-partial-clone.sh @@ -49,7 +49,7 @@ test_expect_success 'do partial clone 1' ' test_expect_success 'verify that .promisor file contains refs fetched' ' ls pc1/.git/objects/pack/pack-*.promisor >promisorlist && test_line_count = 1 promisorlist && - git -C srv.bare rev-list HEAD >headhash && + git -C srv.bare rev-parse --verify HEAD >headhash && grep "$(cat headhash) HEAD" $(cat promisorlist) && grep "$(cat headhash) refs/heads/master" $(cat promisorlist) ' diff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh index 7fba3063bf..a34460f7d8 100755 --- a/t/t5703-upload-pack-ref-in-want.sh +++ b/t/t5703-upload-pack-ref-in-want.sh @@ -13,10 +13,7 @@ get_actual_refs () { } get_actual_commits () { - sed -n -e '/packfile/,/0000/{ - /packfile/d - p - }' <out | test-tool pkt-line unpack-sideband >o.pack && + test-tool pkt-line unpack-sideband <out >o.pack && git index-pack o.pack && git verify-pack -v o.idx >objs && grep commit objs | cut -d" " -f1 | sort >actual_commits diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index 821a0c88cf..1313142564 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -148,7 +148,7 @@ test_expect_success 'bisect start: no ".git/BISECT_START" created if junk rev' ' test_must_fail git bisect start $HASH4 foo -- && git branch > branch.output && grep "* other" branch.output > /dev/null && - test_must_fail test -e .git/BISECT_START + test_path_is_missing .git/BISECT_START ' test_expect_success 'bisect start: existing ".git/BISECT_START" not modified if junk rev' ' @@ -166,7 +166,7 @@ test_expect_success 'bisect start: no ".git/BISECT_START" if mistaken rev' ' test_must_fail git bisect start $HASH1 $HASH4 -- && git branch > branch.output && grep "* other" branch.output > /dev/null && - test_must_fail test -e .git/BISECT_START + test_path_is_missing .git/BISECT_START ' test_expect_success 'bisect start: no ".git/BISECT_START" if checkout error' ' @@ -175,7 +175,7 @@ test_expect_success 'bisect start: no ".git/BISECT_START" if checkout error' ' git branch && git branch > branch.output && grep "* other" branch.output > /dev/null && - test_must_fail test -e .git/BISECT_START && + test_path_is_missing .git/BISECT_START && test -z "$(git for-each-ref "refs/bisect/*")" && git checkout HEAD hello ' @@ -485,7 +485,7 @@ test_expect_success 'optimized merge base checks' ' git bisect bad && git bisect good "$A_HASH" > my_bisect_log4.txt && test_i18ngrep "merge base must be tested" my_bisect_log4.txt && - test_must_fail test -f ".git/BISECT_ANCESTORS_OK" + test_path_is_missing ".git/BISECT_ANCESTORS_OK" ' # This creates another side branch called "parallel" with some files diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh index 190ae149cf..428cff9cf3 100755 --- a/t/t7063-status-untracked-cache.sh +++ b/t/t7063-status-untracked-cache.sh @@ -18,7 +18,7 @@ GIT_FORCE_UNTRACKED_CACHE=true export GIT_FORCE_UNTRACKED_CACHE sync_mtime () { - find . -type d -ls >/dev/null + find . -type d -exec ls -ld {} + >/dev/null } avoid_racy() { @@ -30,6 +30,30 @@ status_is_clean() { test_must_be_empty ../status.actual } +# Ignore_Untracked_Cache, abbreviated to 3 letters because then people can +# compare commands side-by-side, e.g. +# iuc status --porcelain >expect && +# git status --porcelain >actual && +# test_cmp expect actual +iuc () { + git ls-files -s >../current-index-entries + git ls-files -t | sed -ne s/^S.//p >../current-sparse-entries + + GIT_INDEX_FILE=.git/tmp_index + export GIT_INDEX_FILE + git update-index --index-info <../current-index-entries + git update-index --skip-worktree $(cat ../current-sparse-entries) + + git -c core.untrackedCache=false "$@" + ret=$? + + rm ../current-index-entries + rm $GIT_INDEX_FILE + unset GIT_INDEX_FILE + + return $ret +} + test_lazy_prereq UNTRACKED_CACHE ' { git update-index --test-untracked-cache; ret=$?; } && test $ret -ne 1 @@ -95,6 +119,8 @@ test_expect_success 'status first time (empty cache)' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../actual && + iuc status --porcelain >../status.iuc && + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../actual && cat >../trace.expect <<EOF && node creation: 3 @@ -115,6 +141,8 @@ test_expect_success 'status second time (fully populated cache)' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../actual && + iuc status --porcelain >../status.iuc && + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../actual && cat >../trace.expect <<EOF && node creation: 0 @@ -136,6 +164,7 @@ test_expect_success 'modify in root directory, one dir invalidation' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && A done/one A one @@ -145,6 +174,7 @@ A two ?? four ?? three EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../actual && cat >../trace.expect <<EOF && node creation: 0 @@ -183,6 +213,7 @@ test_expect_success 'new .gitignore invalidates recursively' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && A done/one A one @@ -192,6 +223,7 @@ A two ?? dtwo/ ?? three EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../actual && cat >../trace.expect <<EOF && node creation: 0 @@ -230,6 +262,7 @@ test_expect_success 'new info/exclude invalidates everything' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && A done/one A one @@ -237,6 +270,7 @@ A two ?? .gitignore ?? dtwo/ EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../actual && cat >../trace.expect <<EOF && node creation: 0 @@ -286,6 +320,7 @@ test_expect_success 'status after the move' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && A done/one A one @@ -293,6 +328,7 @@ A one ?? dtwo/ ?? two EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../actual && cat >../trace.expect <<EOF && node creation: 0 @@ -343,6 +379,7 @@ test_expect_success 'status after the move' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && A done/one A one @@ -350,6 +387,7 @@ A two ?? .gitignore ?? dtwo/ EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../actual && cat >../trace.expect <<EOF && node creation: 0 @@ -390,10 +428,12 @@ test_expect_success 'status after commit' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && ?? .gitignore ?? dtwo/ EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../actual && cat >../trace.expect <<EOF && node creation: 0 @@ -447,12 +487,14 @@ test_expect_success 'test sparse status with untracked cache' ' avoid_racy && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../status.actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && M done/two ?? .gitignore ?? done/five ?? dtwo/ EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../status.actual && cat >../trace.expect <<EOF && node creation: 0 @@ -487,12 +529,14 @@ test_expect_success 'test sparse status again with untracked cache' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../status.actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && M done/two ?? .gitignore ?? done/five ?? dtwo/ EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../status.actual && cat >../trace.expect <<EOF && node creation: 0 @@ -514,6 +558,7 @@ test_expect_success 'test sparse status with untracked cache and subdir' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../status.actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && M done/two ?? .gitignore @@ -521,6 +566,7 @@ test_expect_success 'test sparse status with untracked cache and subdir' ' ?? done/sub/ ?? dtwo/ EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../status.actual && cat >../trace.expect <<EOF && node creation: 2 @@ -560,6 +606,8 @@ test_expect_success 'test sparse status again with untracked cache and subdir' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../status.actual && + iuc status --porcelain >../status.iuc && + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../status.actual && cat >../trace.expect <<EOF && node creation: 0 @@ -573,6 +621,7 @@ EOF test_expect_success 'move entry in subdir from untracked to cached' ' git add dtwo/two && git status --porcelain >../status.actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && M done/two A dtwo/two @@ -580,12 +629,14 @@ A dtwo/two ?? done/five ?? done/sub/ EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../status.actual ' test_expect_success 'move entry in subdir from cached to untracked' ' git rm --cached dtwo/two && git status --porcelain >../status.actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && M done/two ?? .gitignore @@ -593,6 +644,7 @@ test_expect_success 'move entry in subdir from cached to untracked' ' ?? done/sub/ ?? dtwo/ EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../status.actual ' diff --git a/t/t7408-submodule-reference.sh b/t/t7408-submodule-reference.sh index 34ac28c056..a3892f494b 100755 --- a/t/t7408-submodule-reference.sh +++ b/t/t7408-submodule-reference.sh @@ -122,8 +122,8 @@ test_expect_success 'missing submodule alternate fails clone and submodule updat # update of the submodule succeeds test_must_fail git submodule update --init && # and we have no alternates: - test_must_fail test_alternate_is_used .git/modules/sub/objects/info/alternates sub && - test_must_fail test_path_is_file sub/file1 + test_path_is_missing .git/modules/sub/objects/info/alternates && + test_path_is_missing sub/file1 ) ' @@ -137,7 +137,7 @@ test_expect_success 'ignoring missing submodule alternates passes clone and subm # update of the submodule succeeds git submodule update --init && # and we have no alternates: - test_must_fail test_alternate_is_used .git/modules/sub/objects/info/alternates sub && + test_path_is_missing .git/modules/sub/objects/info/alternates && test_path_is_file sub/file1 ) ' @@ -182,7 +182,7 @@ check_that_two_of_three_alternates_are_used() { # immediate submodule has alternate: test_alternate_is_used .git/modules/subwithsub/objects/info/alternates subwithsub && # but nested submodule has no alternate: - test_must_fail test_alternate_is_used .git/modules/subwithsub/modules/sub/objects/info/alternates subwithsub/sub + test_path_is_missing .git/modules/subwithsub/modules/sub/objects/info/alternates } diff --git a/t/t7508-status.sh b/t/t7508-status.sh index 482ce3510e..8e969f3e36 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -1471,7 +1471,7 @@ test_expect_success '"status.branch=true" same as "-b"' ' test_expect_success '"status.branch=true" different from "--no-branch"' ' git status -s --no-branch >expected_nobranch && git -c status.branch=true status -s >actual && - test_must_fail test_cmp expected_nobranch actual + ! test_cmp expected_nobranch actual ' test_expect_success '"status.branch=true" weaker than "--no-branch"' ' diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh index 132608879a..5883a6adc3 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -29,15 +29,19 @@ Testing basic merge operations/option parsing. . ./test-lib.sh . "$TEST_DIRECTORY"/lib-gpg.sh -printf '%s\n' 1 2 3 4 5 6 7 8 9 >file -printf '%s\n' '1 X' 2 3 4 5 6 7 8 9 >file.1 -printf '%s\n' 1 2 3 4 '5 X' 6 7 8 9 >file.5 -printf '%s\n' 1 2 3 4 5 6 7 8 '9 X' >file.9 -printf '%s\n' 1 2 3 4 5 6 7 8 '9 Y' >file.9y -printf '%s\n' '1 X' 2 3 4 5 6 7 8 9 >result.1 -printf '%s\n' '1 X' 2 3 4 '5 X' 6 7 8 9 >result.1-5 -printf '%s\n' '1 X' 2 3 4 '5 X' 6 7 8 '9 X' >result.1-5-9 -printf '%s\n' 1 2 3 4 5 6 7 8 '9 Z' >result.9z +test_write_lines 1 2 3 4 5 6 7 8 9 >file +cp file file.orig +test_write_lines '1 X' 2 3 4 5 6 7 8 9 >file.1 +test_write_lines 1 2 '3 X' 4 5 6 7 8 9 >file.3 +test_write_lines 1 2 3 4 '5 X' 6 7 8 9 >file.5 +test_write_lines 1 2 3 4 5 6 7 8 '9 X' >file.9 +test_write_lines 1 2 3 4 5 6 7 8 '9 Y' >file.9y +test_write_lines '1 X' 2 3 4 5 6 7 8 9 >result.1 +test_write_lines '1 X' 2 3 4 '5 X' 6 7 8 9 >result.1-5 +test_write_lines '1 X' 2 3 4 5 6 7 8 '9 X' >result.1-9 +test_write_lines '1 X' 2 3 4 '5 X' 6 7 8 '9 X' >result.1-5-9 +test_write_lines '1 X' 2 '3 X' 4 '5 X' 6 7 8 '9 X' >result.1-3-5-9 +test_write_lines 1 2 3 4 5 6 7 8 '9 Z' >result.9z create_merge_msgs () { echo "Merge tag 'c2'" >msg.1-5 && @@ -81,7 +85,7 @@ verify_head () { } verify_parents () { - printf '%s\n' "$@" >parents.expected && + test_write_lines "$@" >parents.expected && >parents.actual && i=1 && while test $i -le $# @@ -95,7 +99,7 @@ verify_parents () { } verify_mergeheads () { - printf '%s\n' "$@" >mergehead.expected && + test_write_lines "$@" >mergehead.expected && while read sha1 rest do git rev-parse $sha1 @@ -675,6 +679,134 @@ test_expect_success 'refresh the index before merging' ' git merge c3 ' +test_expect_success 'merge with --autostash' ' + git reset --hard c1 && + git merge-file file file.orig file.9 && + git merge --autostash c2 2>err && + test_i18ngrep "Applied autostash." err && + git show HEAD:file >merge-result && + test_cmp result.1-5 merge-result && + test_cmp result.1-5-9 file +' + +test_expect_success 'merge with merge.autoStash' ' + test_config merge.autoStash true && + git reset --hard c1 && + git merge-file file file.orig file.9 && + git merge c2 2>err && + test_i18ngrep "Applied autostash." err && + git show HEAD:file >merge-result && + test_cmp result.1-5 merge-result && + test_cmp result.1-5-9 file +' + +test_expect_success 'fast-forward merge with --autostash' ' + git reset --hard c0 && + git merge-file file file.orig file.5 && + git merge --autostash c1 2>err && + test_i18ngrep "Applied autostash." err && + test_cmp result.1-5 file +' + +test_expect_success 'octopus merge with --autostash' ' + git reset --hard c1 && + git merge-file file file.orig file.3 && + git merge --autostash c2 c3 2>err && + test_i18ngrep "Applied autostash." err && + git show HEAD:file >merge-result && + test_cmp result.1-5-9 merge-result && + test_cmp result.1-3-5-9 file +' + +test_expect_success 'conflicted merge with --autostash, --abort restores stash' ' + git reset --hard c3 && + cp file.1 file && + test_must_fail git merge --autostash c7 && + git merge --abort 2>err && + test_i18ngrep "Applied autostash." err && + test_cmp file.1 file +' + +test_expect_success 'completed merge (git commit) with --no-commit and --autostash' ' + git reset --hard c1 && + git merge-file file file.orig file.9 && + git diff >expect && + git merge --no-commit --autostash c2 && + git stash show -p MERGE_AUTOSTASH >actual && + test_cmp expect actual && + git commit 2>err && + test_i18ngrep "Applied autostash." err && + git show HEAD:file >merge-result && + test_cmp result.1-5 merge-result && + test_cmp result.1-5-9 file +' + +test_expect_success 'completed merge (git merge --continue) with --no-commit and --autostash' ' + git reset --hard c1 && + git merge-file file file.orig file.9 && + git diff >expect && + git merge --no-commit --autostash c2 && + git stash show -p MERGE_AUTOSTASH >actual && + test_cmp expect actual && + git merge --continue 2>err && + test_i18ngrep "Applied autostash." err && + git show HEAD:file >merge-result && + test_cmp result.1-5 merge-result && + test_cmp result.1-5-9 file +' + +test_expect_success 'aborted merge (merge --abort) with --no-commit and --autostash' ' + git reset --hard c1 && + git merge-file file file.orig file.9 && + git diff >expect && + git merge --no-commit --autostash c2 && + git stash show -p MERGE_AUTOSTASH >actual && + test_cmp expect actual && + git merge --abort 2>err && + test_i18ngrep "Applied autostash." err && + git diff >actual && + test_cmp expect actual +' + +test_expect_success 'aborted merge (reset --hard) with --no-commit and --autostash' ' + git reset --hard c1 && + git merge-file file file.orig file.9 && + git diff >expect && + git merge --no-commit --autostash c2 && + git stash show -p MERGE_AUTOSTASH >actual && + test_cmp expect actual && + git reset --hard 2>err && + test_i18ngrep "Autostash exists; creating a new stash entry." err && + git diff --exit-code +' + +test_expect_success 'quit merge with --no-commit and --autostash' ' + git reset --hard c1 && + git merge-file file file.orig file.9 && + git diff >expect && + git merge --no-commit --autostash c2 && + git stash show -p MERGE_AUTOSTASH >actual && + test_cmp expect actual && + git diff HEAD >expect && + git merge --quit 2>err && + test_i18ngrep "Autostash exists; creating a new stash entry." err && + git diff HEAD >actual && + test_cmp expect actual +' + +test_expect_success 'merge with conflicted --autostash changes' ' + git reset --hard c1 && + git merge-file file file.orig file.9y && + git diff >expect && + test_when_finished "test_might_fail git stash drop" && + git merge --autostash c3 2>err && + test_i18ngrep "Applying autostash resulted in conflicts." err && + git show HEAD:file >merge-result && + test_cmp result.1-9 merge-result && + git stash show -p >actual && + test_cmp expect actual +' + cat >expected.branch <<\EOF Merge branch 'c5-branch' (early part) EOF diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index 7d7b396c23..991d5bd9c0 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -72,6 +72,11 @@ test_expect_success setup ' # Still a no-op. function dummy() {} EOF + if test_have_prereq FUNNYNAMES + then + echo unusual >"\"unusual\" pathname" && + echo unusual >"t/nested \"unusual\" pathname" + fi && git add . && test_tick && git commit -m initial @@ -481,6 +486,48 @@ do git grep --count -h -e b $H -- ab >actual && test_cmp expected actual ' + + test_expect_success FUNNYNAMES "grep $L should quote unusual pathnames" ' + cat >expected <<-EOF && + ${HC}"\"unusual\" pathname":unusual + ${HC}"t/nested \"unusual\" pathname":unusual + EOF + git grep unusual $H >actual && + test_cmp expected actual + ' + + test_expect_success FUNNYNAMES "grep $L in subdir should quote unusual relative pathnames" ' + cat >expected <<-EOF && + ${HC}"nested \"unusual\" pathname":unusual + EOF + ( + cd t && + git grep unusual $H + ) >actual && + test_cmp expected actual + ' + + test_expect_success FUNNYNAMES "grep -z $L with unusual pathnames" ' + cat >expected <<-EOF && + ${HC}"unusual" pathname:unusual + ${HC}t/nested "unusual" pathname:unusual + EOF + git grep -z unusual $H >actual && + tr "\0" ":" <actual >actual-replace-null && + test_cmp expected actual-replace-null + ' + + test_expect_success FUNNYNAMES "grep -z $L in subdir with unusual relative pathnames" ' + cat >expected <<-EOF && + ${HC}nested "unusual" pathname:unusual + EOF + ( + cd t && + git grep -z unusual $H + ) >actual && + tr "\0" ":" <actual >actual-replace-null && + test_cmp expected actual-replace-null + ' done cat >expected <<EOF diff --git a/t/t9141-git-svn-multiple-branches.sh b/t/t9141-git-svn-multiple-branches.sh index 8e7f7d68b7..bf168a3645 100755 --- a/t/t9141-git-svn-multiple-branches.sh +++ b/t/t9141-git-svn-multiple-branches.sh @@ -90,10 +90,10 @@ test_expect_success 'Multiple branch or tag paths require -d' ' ) && ( cd svn_project && svn_cmd up && - test_must_fail test -d b_one/Nope && - test_must_fail test -d b_two/Nope && - test_must_fail test -d tags_A/Tagless && - test_must_fail test -d tags_B/Tagless + test_path_is_missing b_one/Nope && + test_path_is_missing b_two/Nope && + test_path_is_missing tags_A/Tagless && + test_path_is_missing tags_B/Tagless ) ' diff --git a/t/t9160-git-svn-preserve-empty-dirs.sh b/t/t9160-git-svn-preserve-empty-dirs.sh index 0ede3cfedb..36c6b1a12f 100755 --- a/t/t9160-git-svn-preserve-empty-dirs.sh +++ b/t/t9160-git-svn-preserve-empty-dirs.sh @@ -86,8 +86,8 @@ test_expect_success 'remove non-last entry from directory' ' cd "$GIT_REPO" && git checkout HEAD~2 ) && - test_must_fail test -f "$GIT_REPO"/2/.gitignore && - test_must_fail test -f "$GIT_REPO"/3/.gitignore + test_path_is_missing "$GIT_REPO"/2/.gitignore && + test_path_is_missing "$GIT_REPO"/3/.gitignore ' # After re-cloning the repository with --placeholder-file specified, there diff --git a/t/t9164-git-svn-dcommit-concurrent.sh b/t/t9164-git-svn-dcommit-concurrent.sh index 90346ff4e9..8466269bf5 100755 --- a/t/t9164-git-svn-dcommit-concurrent.sh +++ b/t/t9164-git-svn-dcommit-concurrent.sh @@ -92,7 +92,7 @@ test_expect_success 'check if post-commit hook creates a concurrent commit' ' echo 1 >> file && svn_cmd commit -m "changing file" && svn_cmd up && - test_must_fail test_cmp auto_updated_file au_file_saved + ! test_cmp auto_updated_file au_file_saved ) ' @@ -103,7 +103,7 @@ test_expect_success 'check if pre-commit hook fails' ' echo 2 >> file && svn_cmd commit -m "changing file once again" && echo 3 >> file && - test_must_fail svn_cmd commit -m "this commit should fail" && + ! svn_cmd commit -m "this commit should fail" && svn_cmd revert file ) ' diff --git a/t/t9819-git-p4-case-folding.sh b/t/t9819-git-p4-case-folding.sh index 600ce1e0b0..b4d93f0c17 100755 --- a/t/t9819-git-p4-case-folding.sh +++ b/t/t9819-git-p4-case-folding.sh @@ -30,7 +30,7 @@ test_expect_success 'Check p4 is in case-folding mode' ' cd "$cli" && >lc/FILE.TXT && p4 add lc/FILE.TXT && - test_must_fail p4 submit -d "Cannot add file differing only in case" lc/FILE.TXT + ! p4 submit -d "Cannot add file differing only in case" lc/FILE.TXT ) ' diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh index 5505e5aa24..3c44af6940 100755 --- a/t/t9902-completion.sh +++ b/t/t9902-completion.sh @@ -1638,6 +1638,11 @@ test_expect_success 'complete files' ' echo modify > modified && test_completion "git add " "modified" && + mkdir -p some/deep && + touch some/deep/path && + test_completion "git add some/" "some/deep" && + git clean -f some && + touch untracked && : TODO .gitignore should not be here && diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index d9ef356a16..3103be8a32 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -905,7 +905,7 @@ test_expect_code () { # - not all diff versions understand "-u" test_cmp() { - $GIT_TEST_CMP "$@" + eval "$GIT_TEST_CMP" '"$@"' } # Check that the given config key has the expected value. diff --git a/t/test-lib.sh b/t/test-lib.sh index 0bb1105ec3..1b221951a8 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -675,6 +675,18 @@ die () { fi } +file_lineno () { + test -z "$GIT_TEST_FRAMEWORK_SELFTEST" && test -n "$BASH" || return 0 + local i + for i in ${!BASH_SOURCE[*]} + do + case $i,"${BASH_SOURCE[$i]##*/}" in + 0,t[0-9]*.sh) echo "t/${BASH_SOURCE[$i]}:$LINENO: ${1+$1: }"; return;; + *,t[0-9]*.sh) echo "t/${BASH_SOURCE[$i]}:${BASH_LINENO[$(($i-1))]}: ${1+$1: }"; return;; + esac + done +} + GIT_EXIT_OK= trap 'die' EXIT # Disable '-x' tracing, because with some shells, notably dash, it @@ -720,7 +732,7 @@ test_failure_ () { write_junit_xml_testcase "$1" " $junit_insert" fi test_failure=$(($test_failure + 1)) - say_color error "not ok $test_count - $1" + say_color error "$(file_lineno error)not ok $test_count - $1" shift printf '%s\n' "$*" | sed -e 's/^/# /' test "$immediate" = "" || { finalize_junit_xml; GIT_EXIT_OK=t; exit 1; } @@ -1654,6 +1666,15 @@ test_lazy_prereq ULIMIT_STACK_SIZE ' run_with_limited_stack true ' +run_with_limited_open_files () { + (ulimit -n 32 && "$@") +} + +test_lazy_prereq ULIMIT_FILE_DESCRIPTORS ' + test_have_prereq !MINGW,!CYGWIN && + run_with_limited_open_files true +' + build_option () { git version --build-options | sed -ne "s/^$1: //p" |