diff options
Diffstat (limited to 't')
521 files changed, 17905 insertions, 5943 deletions
diff --git a/t/.gitattributes b/t/.gitattributes index 9930e28351..b9cea1795d 100644 --- a/t/.gitattributes +++ b/t/.gitattributes @@ -22,3 +22,4 @@ t[0-9][0-9][0-9][0-9]/* -whitespace /t7500/* eol=lf /t8005/*.txt eol=lf /t9*/*.dump eol=lf +/t0040*.sh whitespace=-indent-with-non-tab diff --git a/t/Makefile b/t/Makefile index 2c2b252240..225aaf78ed 100644 --- a/t/Makefile +++ b/t/Makefile @@ -17,6 +17,7 @@ TAR ?= $(TAR) RM ?= rm -f PROVE ?= prove DEFAULT_TEST_TARGET ?= test +DEFAULT_UNIT_TEST_TARGET ?= unit-tests-raw TEST_LINT ?= test-lint ifdef TEST_OUTPUT_DIRECTORY @@ -41,11 +42,12 @@ TPERF = $(sort $(wildcard perf/p[0-9][0-9][0-9][0-9]-*.sh)) TINTEROP = $(sort $(wildcard interop/i[0-9][0-9][0-9][0-9]-*.sh)) CHAINLINTTESTS = $(sort $(patsubst chainlint/%.test,%,$(wildcard chainlint/*.test))) CHAINLINT = '$(PERL_PATH_SQ)' chainlint.pl +UNIT_TESTS = $(sort $(filter-out %.pdb unit-tests/bin/t-basic%,$(wildcard unit-tests/bin/t-*))) # `test-chainlint` (which is a dependency of `test-lint`, `test` and `prove`) # checks all tests in all scripts via a single invocation, so tell individual -# scripts not to "chainlint" themselves -CHAINLINTSUPPRESS = GIT_TEST_CHAIN_LINT=0 && export GIT_TEST_CHAIN_LINT && +# scripts not to run the external "chainlint.pl" script themselves +CHAINLINTSUPPRESS = GIT_TEST_EXT_CHAIN_LINT=0 && export GIT_TEST_EXT_CHAIN_LINT && all: $(DEFAULT_TEST_TARGET) @@ -65,6 +67,17 @@ prove: pre-clean check-chainlint $(TEST_LINT) $(T): @echo "*** $@ ***"; '$(TEST_SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS) +$(UNIT_TESTS): + @echo "*** $@ ***"; $@ + +.PHONY: unit-tests unit-tests-raw unit-tests-prove +unit-tests: $(DEFAULT_UNIT_TEST_TARGET) + +unit-tests-raw: $(UNIT_TESTS) + +unit-tests-prove: + @echo "*** prove - unit tests ***"; $(PROVE) $(GIT_PROVE_OPTS) $(UNIT_TESTS) + pre-clean: $(RM) -r '$(TEST_RESULTS_DIRECTORY_SQ)' @@ -140,9 +153,7 @@ aggregate-results-and-cleanup: $(T) $(MAKE) clean aggregate-results: - for f in '$(TEST_RESULTS_DIRECTORY_SQ)'/t*-*.counts; do \ - echo "$$f"; \ - done | '$(SHELL_PATH_SQ)' ./aggregate-results.sh + @'$(SHELL_PATH_SQ)' ./aggregate-results.sh '$(TEST_RESULTS_DIRECTORY_SQ)' valgrind: $(MAKE) GIT_TEST_OPTS="$(GIT_TEST_OPTS) --valgrind" @@ -151,4 +162,4 @@ perf: $(MAKE) -C perf/ all .PHONY: pre-clean $(T) aggregate-results clean valgrind perf \ - check-chainlint clean-chainlint test-chainlint + check-chainlint clean-chainlint test-chainlint $(UNIT_TESTS) @@ -32,7 +32,7 @@ the tests. ok 2 - plain with GIT_WORK_TREE ok 3 - plain bare -Since the tests all output TAP (see http://testanything.org) they can +Since the tests all output TAP (see https://testanything.org) they can be run with any TAP harness. Here's an example of parallel testing powered by a recent version of prove(1): @@ -262,8 +262,8 @@ The argument for --run, <test-selector>, is a list of description substrings or globs or individual test numbers or ranges with an optional negation prefix (of '!') that define what tests in a test suite to include (or exclude, if negated) in the run. A range is two -numbers separated with a dash and matches a range of tests with both -ends been included. You may omit the first or the second number to +numbers separated with a dash and specifies an inclusive range of tests +to run. You may omit the first or the second number to mean "from the first test" or "up to the very last test" respectively. The argument to --run is split on commas into separate strings, @@ -274,10 +274,10 @@ text that you want to match includes a comma, use the glob character on all tests that match either the glob *rebase* or the glob *merge?cherry-pick*. -If --run starts with an unprefixed number or range the initial -set of tests to run is empty. If the first item starts with '!' +If --run starts with an unprefixed number or range, the initial +set of tests to run is empty. If the first item starts with '!', all the tests are added to the initial set. After initial set is -determined every test number or range is added or excluded from +determined, every test number or range is added or excluded from the set one by one, from left to right. For example, to run only tests up to a specific test (21), one @@ -442,6 +442,10 @@ GIT_TEST_INDEX_VERSION=<n> exercises the index read/write code path for the index version specified. Can be set to any valid version (currently 2, 3, or 4). +GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL=<boolean> if enabled will +use the boundary-based bitmap traversal algorithm. See the documentation +of `pack.useBitmapBoundaryTraversal` for more details. + GIT_TEST_PACK_SPARSE=<boolean> if disabled will default the pack-objects builtin to use the non-sparse object walk. This can still be overridden by the --sparse command-line argument. @@ -475,7 +479,7 @@ GIT_TEST_DEFAULT_HASH=<hash-algo> specifies which hash algorithm to use in the test scripts. Recognized values for <hash-algo> are "sha1" and "sha256". -GIT_TEST_WRITE_REV_INDEX=<boolean>, when true enables the +GIT_TEST_NO_WRITE_REV_INDEX=<boolean>, when true disables the 'pack.writeReverseIndex' setting. GIT_TEST_SPARSE_INDEX=<boolean>, when true enables index writes to use the @@ -575,11 +579,11 @@ This test harness library does the following things: Recommended style ----------------- -Here are some recommented styles when writing test case. - - Keep test title the same line with test helper function itself. + - Keep the test_expect_* function call and test title on + the same line. - Take test_expect_success helper for example, write it like: + For example, with test_expect_success, write it like: test_expect_success 'test title' ' ... test body ... @@ -591,10 +595,9 @@ Here are some recommented styles when writing test case. 'test title' \ '... test body ...' + - End the line with an opening single quote. - - End the line with a single quote. - - - Indent the body of here-document, and use "<<-" instead of "<<" + - Indent here-document bodies, and use "<<-" instead of "<<" to strip leading TABs used for indentation: test_expect_success 'test something' ' @@ -620,7 +623,7 @@ Here are some recommented styles when writing test case. ' - Quote or escape the EOF delimiter that begins a here-document if - there is no parameter and other expansion in it, to signal readers + there is no parameter or other expansion in it, to signal readers that they can skim it more casually: cmd <<-\EOF @@ -634,7 +637,7 @@ Do's & don'ts Here are a few examples of things you probably should and shouldn't do when writing tests. -Here are the "do's:" +The "do's:" - Put all code inside test_expect_success and other assertions. @@ -884,7 +887,7 @@ see test-lib-functions.sh for the full list and their options. rare case where your test depends on more than one: test_expect_success PERL,PYTHON 'yo dawg' \ - ' test $(perl -E 'print eval "1 +" . qx[python -c "print 2"]') == "4" ' + ' test $(perl -E '\''print eval "1 +" . qx[python -c "print(2)"]'\'') = "4" ' - test_expect_failure [<prereq>] <message> <script> @@ -1098,6 +1101,12 @@ see test-lib-functions.sh for the full list and their options. the symbolic link in the file system and a part that does; then only the latter part need be protected by a SYMLINKS prerequisite (see below). + - test_path_is_executable + + This tests whether a file is executable and prints an error message + if not. This must be used only under the POSIXPERM prerequisite + (see below). + - test_oid_init This function loads facts and useful object IDs related to the hash @@ -1227,8 +1236,8 @@ and it knows that the object ID of an empty tree is a certain because the things the very basic core test tries to achieve is to serve as a basis for people who are changing the Git internals drastically. For these people, after making certain changes, -not seeing failures from the basic test _is_ a failure. And -such drastic changes to the core Git that even changes these +not seeing failures from the basic test _is_ a failure. Any +Git core changes so drastic that they change even these otherwise supposedly stable object IDs should be accompanied by an update to t0000-basic.sh. @@ -1238,7 +1247,7 @@ knowledge of the core Git internals. If all the test scripts hardcoded the object IDs like t0000-basic.sh does, that defeats the purpose of t0000-basic.sh, which is to isolate that level of validation in one place. Your test also ends up needing -updating when such a change to the internal happens, so do _not_ +an update whenever the internals change, so do _not_ do it and leave the low level of validation to t0000-basic.sh. Test coverage @@ -1269,7 +1278,7 @@ Devel::Cover module. To install it do: sudo aptitude install libdevel-cover-perl # From the CPAN with cpanminus - curl -L http://cpanmin.us | perl - --sudo --self-upgrade + curl -L https://cpanmin.us/ | perl - --sudo --self-upgrade cpanm --sudo Devel::Cover Then, at the top-level: diff --git a/t/aggregate-results.sh b/t/aggregate-results.sh index 7f2b83bdc8..6e3bcc4aec 100755 --- a/t/aggregate-results.sh +++ b/t/aggregate-results.sh @@ -8,7 +8,7 @@ broken=0 total=0 missing_prereq= -while read file +for file in "$1"/t*-*.counts do while read type value do diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh index f1b9a6ce4d..5e21e84f38 100644 --- a/t/annotate-tests.sh +++ b/t/annotate-tests.sh @@ -72,6 +72,32 @@ test_expect_success 'blame 1 author' ' check_count A 2 ' +test_expect_success 'blame working copy' ' + test_when_finished "git restore file" && + echo "1A quick brown fox jumps over the" >file && + echo "another lazy dog" >>file && + check_count A 1 "Not Committed Yet" 1 +' + +test_expect_success 'blame with --contents' ' + check_count --contents=file A 2 +' + +test_expect_success 'blame with --contents in a bare repo' ' + git clone --bare . bare-contents.git && + ( + cd bare-contents.git && + echo "1A quick brown fox jumps over the" >contents && + check_count --contents=contents A 1 + ) +' + +test_expect_success 'blame with --contents changed' ' + echo "1A quick brown fox jumps over the" >contents && + echo "another lazy dog" >>contents && + check_count --contents=contents A 1 "External file (--contents)" 1 +' + test_expect_success 'blame in a bare repo without starting commit' ' git clone --bare . bare.git && ( @@ -98,6 +124,10 @@ test_expect_success 'blame 2 authors' ' check_count A 2 B 2 ' +test_expect_success 'blame with --contents and revision' ' + check_count -h testTag --contents=file A 2 "External file (--contents)" 2 +' + test_expect_success 'setup B1 lines (branch1)' ' git checkout -b branch1 main && echo "3A slow green fox jumps into the" >>file && diff --git a/t/chainlint.pl b/t/chainlint.pl index e966412999..556ee91a15 100755 --- a/t/chainlint.pl +++ b/t/chainlint.pl @@ -80,7 +80,8 @@ sub scan_heredoc_tag { return "<<$indented" unless $token; my $tag = $token->[0]; $tag =~ s/['"\\]//g; - push(@{$self->{heretags}}, $indented ? "\t$tag" : "$tag"); + $$token[0] = $indented ? "\t$tag" : "$tag"; + push(@{$self->{heretags}}, $token); return "<<$indented$tag"; } @@ -169,10 +170,18 @@ sub swallow_heredocs { my $tags = $self->{heretags}; while (my $tag = shift @$tags) { my $start = pos($$b); - my $indent = $tag =~ s/^\t// ? '\\s*' : ''; - $$b =~ /(?:\G|\n)$indent\Q$tag\E(?:\n|\z)/gc; + my $indent = $$tag[0] =~ s/^\t// ? '\\s*' : ''; + $$b =~ /(?:\G|\n)$indent\Q$$tag[0]\E(?:\n|\z)/gc; + if (pos($$b) > $start) { + my $body = substr($$b, $start, pos($$b) - $start); + $self->{lineno} += () = $body =~ /\n/sg; + next; + } + push(@{$self->{parser}->{problems}}, ['UNCLOSED-HEREDOC', $tag]); + $$b =~ /(?:\G|\n).*\z/gc; # consume rest of input my $body = substr($$b, $start, pos($$b) - $start); $self->{lineno} += () = $body =~ /\n/sg; + last; } } diff --git a/t/chainlint/unclosed-here-doc-indent.expect b/t/chainlint/unclosed-here-doc-indent.expect new file mode 100644 index 0000000000..7c30a1a024 --- /dev/null +++ b/t/chainlint/unclosed-here-doc-indent.expect @@ -0,0 +1,4 @@ +command_which_is_run && +cat >expect <<-\EOF ?!UNCLOSED-HEREDOC?! && +we forget to end the here-doc +command_which_is_gobbled diff --git a/t/chainlint/unclosed-here-doc-indent.test b/t/chainlint/unclosed-here-doc-indent.test new file mode 100644 index 0000000000..5c841a9dfd --- /dev/null +++ b/t/chainlint/unclosed-here-doc-indent.test @@ -0,0 +1,4 @@ +command_which_is_run && +cat >expect <<-\EOF && +we forget to end the here-doc +command_which_is_gobbled diff --git a/t/chainlint/unclosed-here-doc.expect b/t/chainlint/unclosed-here-doc.expect new file mode 100644 index 0000000000..d65e50f78d --- /dev/null +++ b/t/chainlint/unclosed-here-doc.expect @@ -0,0 +1,7 @@ +command_which_is_run && +cat >expect <<\EOF ?!UNCLOSED-HEREDOC?! && + we try to end the here-doc below, + but the indentation throws us off + since the operator is not "<<-". + EOF +command_which_is_gobbled diff --git a/t/chainlint/unclosed-here-doc.test b/t/chainlint/unclosed-here-doc.test new file mode 100644 index 0000000000..69d3786c34 --- /dev/null +++ b/t/chainlint/unclosed-here-doc.test @@ -0,0 +1,7 @@ +command_which_is_run && +cat >expect <<\EOF && + we try to end the here-doc below, + but the indentation throws us off + since the operator is not "<<-". + EOF +command_which_is_gobbled diff --git a/t/helper/test-advise.c b/t/helper/test-advise.c index cb881139f7..8a3fd0009a 100644 --- a/t/helper/test-advise.c +++ b/t/helper/test-advise.c @@ -1,7 +1,7 @@ #include "test-tool.h" -#include "cache.h" #include "advice.h" #include "config.h" +#include "setup.h" int cmd__advise_if_enabled(int argc, const char **argv) { diff --git a/t/helper/test-bitmap.c b/t/helper/test-bitmap.c index ff35f5999b..af43ee1cb5 100644 --- a/t/helper/test-bitmap.c +++ b/t/helper/test-bitmap.c @@ -1,6 +1,7 @@ #include "test-tool.h" -#include "cache.h" +#include "git-compat-util.h" #include "pack-bitmap.h" +#include "setup.h" static int bitmap_list_commits(void) { diff --git a/t/helper/test-bloom.c b/t/helper/test-bloom.c index 6c900ca668..1281e66876 100644 --- a/t/helper/test-bloom.c +++ b/t/helper/test-bloom.c @@ -1,7 +1,9 @@ -#include "git-compat-util.h" -#include "bloom.h" #include "test-tool.h" +#include "bloom.h" +#include "hex.h" #include "commit.h" +#include "repository.h" +#include "setup.h" static struct bloom_filter_settings settings = DEFAULT_BLOOM_FILTER_SETTINGS; @@ -38,7 +40,6 @@ 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_or_compute_bloom_filter(the_repository, c, 1, &settings, diff --git a/t/helper/test-bundle-uri.c b/t/helper/test-bundle-uri.c index b18e760310..475058592d 100644 --- a/t/helper/test-bundle-uri.c +++ b/t/helper/test-bundle-uri.c @@ -1,6 +1,7 @@ #include "test-tool.h" #include "parse-options.h" #include "bundle-uri.h" +#include "gettext.h" #include "strbuf.h" #include "string-list.h" #include "transport.h" diff --git a/t/helper/test-cache-tree.c b/t/helper/test-cache-tree.c index 9159a17301..e7236392c8 100644 --- a/t/helper/test-cache-tree.c +++ b/t/helper/test-cache-tree.c @@ -1,9 +1,13 @@ #define USE_THE_INDEX_VARIABLE #include "test-tool.h" -#include "cache.h" +#include "gettext.h" +#include "hex.h" #include "tree.h" #include "cache-tree.h" #include "parse-options.h" +#include "read-cache-ll.h" +#include "repository.h" +#include "setup.h" static char const * const test_cache_tree_usage[] = { N_("test-tool cache-tree <options> (control|prime|update)"), diff --git a/t/helper/test-chmtime.c b/t/helper/test-chmtime.c index dc28890a18..0e5538833a 100644 --- a/t/helper/test-chmtime.c +++ b/t/helper/test-chmtime.c @@ -94,7 +94,7 @@ int cmd__chmtime(int argc, const char **argv) if (timespec_arg(argv[i], &set_time, &set_eq)) { ++i; } else { - if (get == 0) { + if (get == 0 && verbose == 0) { fprintf(stderr, "Not a base-10 integer: %s\n", argv[i] + 1); goto usage; } diff --git a/t/helper/test-config.c b/t/helper/test-config.c index 4ba9eb6560..ed444ca4c2 100644 --- a/t/helper/test-config.c +++ b/t/helper/test-config.c @@ -1,6 +1,6 @@ #include "test-tool.h" -#include "cache.h" #include "config.h" +#include "setup.h" #include "string-list.h" /* @@ -14,6 +14,8 @@ * get_value_multi -> prints all values for the entered key in increasing order * of priority * + * get -> print return value for the entered key + * * get_int -> print integer value for the entered key or die * * get_bool -> print bool value for the entered key or die @@ -30,6 +32,9 @@ * iterate -> iterate over all values using git_config(), and print some * data for each * + * git_config_int -> iterate over all values using git_config() and print the + * integer value for the entered key or die + * * Examples: * * To print the value with highest priority for key "foo.bAr Baz.rock": @@ -37,8 +42,11 @@ * */ -static int iterate_cb(const char *var, const char *value, void *data UNUSED) +static int iterate_cb(const char *var, const char *value, + const struct config_context *ctx, + void *data UNUSED) { + const struct key_value_info *kvi = ctx->kvi; static int nr; if (nr++) @@ -46,15 +54,29 @@ static int iterate_cb(const char *var, const char *value, void *data UNUSED) printf("key=%s\n", var); printf("value=%s\n", value ? value : "(null)"); - printf("origin=%s\n", current_config_origin_type()); - printf("name=%s\n", current_config_name()); - printf("lno=%d\n", current_config_line()); - printf("scope=%s\n", config_scope_name(current_config_scope())); + printf("origin=%s\n", config_origin_type_name(kvi->origin_type)); + printf("name=%s\n", kvi->filename ? kvi->filename : ""); + printf("lno=%d\n", kvi->linenr); + printf("scope=%s\n", config_scope_name(kvi->scope)); return 0; } -static int early_config_cb(const char *var, const char *value, void *vdata) +static int parse_int_cb(const char *var, const char *value, + const struct config_context *ctx, void *data) +{ + const char *key_to_match = data; + + if (!strcmp(key_to_match, var)) { + int parsed = git_config_int(value, value, ctx->kvi); + printf("%d\n", parsed); + } + return 0; +} + +static int early_config_cb(const char *var, const char *value, + const struct config_context *ctx UNUSED, + void *vdata) { const char *key = vdata; @@ -95,8 +117,7 @@ int cmd__config(int argc, const char **argv) goto exit1; } } else if (argc == 3 && !strcmp(argv[1], "get_value_multi")) { - strptr = git_config_get_value_multi(argv[2]); - if (strptr) { + if (!git_config_get_value_multi(argv[2], &strptr)) { for (i = 0; i < strptr->nr; i++) { v = strptr->items[i].string; if (!v) @@ -109,6 +130,26 @@ int cmd__config(int argc, const char **argv) printf("Value not found for \"%s\"\n", argv[2]); goto exit1; } + } else if (argc == 3 && !strcmp(argv[1], "get")) { + int ret; + + if (!(ret = git_config_get(argv[2]))) + goto exit0; + else if (ret == 1) + printf("Value not found for \"%s\"\n", argv[2]); + else if (ret == -CONFIG_INVALID_KEY) + printf("Key \"%s\" is invalid\n", argv[2]); + else if (ret == -CONFIG_NO_SECTION_OR_NAME) + printf("Key \"%s\" has no section\n", argv[2]); + else + /* + * A normal caller should just check "ret < + * 0", but for our own tests let's BUG() if + * our whitelist of git_config_parse_key() + * return values isn't exhaustive. + */ + BUG("Key \"%s\" has unknown return %d", argv[2], ret); + goto exit1; } else if (argc == 3 && !strcmp(argv[1], "get_int")) { if (!git_config_get_int(argv[2], &val)) { printf("%d\n", val); @@ -141,7 +182,7 @@ int cmd__config(int argc, const char **argv) goto exit2; } } - if (!git_configset_get_value(&cs, argv[2], &v)) { + if (!git_configset_get_value(&cs, argv[2], &v, NULL)) { if (!v) printf("(NULL)\n"); else @@ -159,8 +200,7 @@ int cmd__config(int argc, const char **argv) goto exit2; } } - strptr = git_configset_get_value_multi(&cs, argv[2]); - if (strptr) { + if (!git_configset_get_value_multi(&cs, argv[2], &strptr)) { for (i = 0; i < strptr->nr; i++) { v = strptr->items[i].string; if (!v) @@ -176,6 +216,9 @@ int cmd__config(int argc, const char **argv) } else if (!strcmp(argv[1], "iterate")) { git_config(iterate_cb, NULL); goto exit0; + } else if (argc == 3 && !strcmp(argv[1], "git_config_int")) { + git_config(parse_int_cb, (void *) argv[2]); + goto exit0; } die("%s: Please check the syntax and the function name", argv[0]); diff --git a/t/helper/test-crontab.c b/t/helper/test-crontab.c index e6c1b1e22b..597027a96e 100644 --- a/t/helper/test-crontab.c +++ b/t/helper/test-crontab.c @@ -1,5 +1,4 @@ #include "test-tool.h" -#include "cache.h" /* * Usage: test-tool crontab <file> -l|<input> diff --git a/t/helper/test-ctype.c b/t/helper/test-ctype.c index b21bd672d9..e5659df40b 100644 --- a/t/helper/test-ctype.c +++ b/t/helper/test-ctype.c @@ -1,5 +1,4 @@ #include "test-tool.h" -#include "cache.h" static int rc; @@ -28,6 +27,8 @@ static int is_in(const char *s, int ch) if (is_in(s, i) != t(i)) \ report_error(#t, i); \ } \ + if (t(EOF)) \ + report_error(#t, EOF); \ } #define DIGIT "0123456789" @@ -48,7 +49,7 @@ static int is_in(const char *s, int ch) "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" \ "\x7f" -int cmd__ctype(int argc, const char **argv) +int cmd__ctype(int argc UNUSED, const char **argv UNUSED) { TEST_CLASS(isdigit, DIGIT); TEST_CLASS(isspace, " \n\r\t"); diff --git a/t/helper/test-date.c b/t/helper/test-date.c index 45951b1df8..0683d46574 100644 --- a/t/helper/test-date.c +++ b/t/helper/test-date.c @@ -1,6 +1,6 @@ #include "test-tool.h" -#include "cache.h" #include "date.h" +#include "trace.h" static const char *usage_msg = "\n" " test-tool date relative [time_t]...\n" @@ -81,7 +81,7 @@ static void parse_approxidate(const char **argv) { for (; *argv; argv++) { timestamp_t t; - t = approxidate_relative(*argv); + t = approxidate(*argv); printf("%s -> %s\n", *argv, show_date(t, 0, DATE_MODE(ISO8601))); } } @@ -90,7 +90,7 @@ static void parse_approx_timestamp(const char **argv) { for (; *argv; argv++) { timestamp_t t; - t = approxidate_relative(*argv); + t = approxidate(*argv); printf("%s -> %"PRItime"\n", *argv, t); } } @@ -104,7 +104,7 @@ static void getnanos(const char **argv) printf("%lf\n", seconds); } -int cmd__date(int argc, const char **argv) +int cmd__date(int argc UNUSED, const char **argv) { const char *x; diff --git a/t/helper/test-delta.c b/t/helper/test-delta.c index b15481ea59..6bc787a474 100644 --- a/t/helper/test-delta.c +++ b/t/helper/test-delta.c @@ -11,7 +11,6 @@ #include "test-tool.h" #include "git-compat-util.h" #include "delta.h" -#include "cache.h" static const char usage_str[] = "test-tool delta (-d|-p) <from_file> <data_file> <out_file>"; diff --git a/t/helper/test-drop-caches.c b/t/helper/test-drop-caches.c index e37396dd9c..73e551cfc2 100644 --- a/t/helper/test-drop-caches.c +++ b/t/helper/test-drop-caches.c @@ -155,7 +155,7 @@ static int cmd_dropcaches(void) #endif -int cmd__drop_caches(int argc, const char **argv) +int cmd__drop_caches(int argc UNUSED, const char **argv UNUSED) { cmd_sync(); return cmd_dropcaches(); diff --git a/t/helper/test-dump-cache-tree.c b/t/helper/test-dump-cache-tree.c index 454f17b1a0..c38f546e4f 100644 --- a/t/helper/test-dump-cache-tree.c +++ b/t/helper/test-dump-cache-tree.c @@ -1,9 +1,12 @@ #define USE_THE_INDEX_VARIABLE #include "test-tool.h" -#include "cache.h" +#include "hash.h" +#include "hex.h" #include "tree.h" #include "cache-tree.h" - +#include "read-cache-ll.h" +#include "repository.h" +#include "setup.h" static void dump_one(struct cache_tree *it, const char *pfx, const char *x) { @@ -56,7 +59,7 @@ static int dump_cache_tree(struct cache_tree *it, return errs; } -int cmd__dump_cache_tree(int ac, const char **av) +int cmd__dump_cache_tree(int ac UNUSED, const char **av UNUSED) { struct index_state istate; struct cache_tree *another = cache_tree(); diff --git a/t/helper/test-dump-fsmonitor.c b/t/helper/test-dump-fsmonitor.c index 975f0ac890..4f215fea02 100644 --- a/t/helper/test-dump-fsmonitor.c +++ b/t/helper/test-dump-fsmonitor.c @@ -1,7 +1,9 @@ #include "test-tool.h" -#include "cache.h" +#include "read-cache-ll.h" +#include "repository.h" +#include "setup.h" -int cmd__dump_fsmonitor(int ac, const char **av) +int cmd__dump_fsmonitor(int ac UNUSED, const char **av UNUSED) { struct index_state *istate = the_repository->index; int i; diff --git a/t/helper/test-dump-split-index.c b/t/helper/test-dump-split-index.c index 0ea97b8407..f29d18ef94 100644 --- a/t/helper/test-dump-split-index.c +++ b/t/helper/test-dump-split-index.c @@ -1,15 +1,18 @@ #define USE_THE_INDEX_VARIABLE #include "test-tool.h" -#include "cache.h" +#include "hex.h" +#include "read-cache-ll.h" +#include "repository.h" +#include "setup.h" #include "split-index.h" #include "ewah/ewok.h" -static void show_bit(size_t pos, void *data) +static void show_bit(size_t pos, void *data UNUSED) { printf(" %d", (int)pos); } -int cmd__dump_split_index(int ac, const char **av) +int cmd__dump_split_index(int ac UNUSED, const char **av) { struct split_index *si; int i; diff --git a/t/helper/test-dump-untracked-cache.c b/t/helper/test-dump-untracked-cache.c index 6d53683f13..b4af9712fe 100644 --- a/t/helper/test-dump-untracked-cache.c +++ b/t/helper/test-dump-untracked-cache.c @@ -1,7 +1,10 @@ #define USE_THE_INDEX_VARIABLE #include "test-tool.h" -#include "cache.h" #include "dir.h" +#include "hex.h" +#include "read-cache-ll.h" +#include "repository.h" +#include "setup.h" static int compare_untracked(const void *a_, const void *b_) { @@ -40,7 +43,7 @@ static void dump(struct untracked_cache_dir *ucd, struct strbuf *base) strbuf_setlen(base, len); } -int cmd__dump_untracked_cache(int ac, const char **av) +int cmd__dump_untracked_cache(int ac UNUSED, const char **av UNUSED) { struct untracked_cache *uc; struct strbuf base = STRBUF_INIT; diff --git a/t/helper/test-env-helper.c b/t/helper/test-env-helper.c index 66c88b8ff3..1c486888a4 100644 --- a/t/helper/test-env-helper.c +++ b/t/helper/test-env-helper.c @@ -1,5 +1,5 @@ #include "test-tool.h" -#include "config.h" +#include "parse.h" #include "parse-options.h" static char const * const env__helper_usage[] = { diff --git a/t/helper/test-example-decorate.c b/t/helper/test-example-decorate.c index b9d1200eb9..8f59f6be4c 100644 --- a/t/helper/test-example-decorate.c +++ b/t/helper/test-example-decorate.c @@ -1,9 +1,10 @@ #include "test-tool.h" -#include "cache.h" +#include "git-compat-util.h" #include "object.h" #include "decorate.h" +#include "repository.h" -int cmd__example_decorate(int argc, const char **argv) +int cmd__example_decorate(int argc UNUSED, const char **argv UNUSED) { struct decoration n; struct object_id one_oid = { {1} }; @@ -71,5 +72,7 @@ int cmd__example_decorate(int argc, const char **argv) if (objects_noticed != 2) BUG("should have 2 objects"); + clear_decoration(&n, NULL); + return 0; } diff --git a/t/helper/test-fast-rebase.c b/t/helper/test-fast-rebase.c deleted file mode 100644 index efc82dd80c..0000000000 --- a/t/helper/test-fast-rebase.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * "git fast-rebase" builtin command - * - * FAST: Forking Any Subprocesses (is) Taboo - * - * This is meant SOLELY as a demo of what is possible. sequencer.c and - * rebase.c should be refactored to use the ideas here, rather than attempting - * to extend this file to replace those (unless Phillip or Dscho say that - * refactoring is too hard and we need a clean slate, but I'm guessing that - * refactoring is the better route). - */ - -#define USE_THE_INDEX_VARIABLE -#include "test-tool.h" - -#include "cache-tree.h" -#include "commit.h" -#include "lockfile.h" -#include "merge-ort.h" -#include "refs.h" -#include "revision.h" -#include "sequencer.h" -#include "strvec.h" -#include "tree.h" - -static const char *short_commit_name(struct commit *commit) -{ - return find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV); -} - -static struct commit *peel_committish(const char *name) -{ - struct object *obj; - struct object_id oid; - - if (get_oid(name, &oid)) - return NULL; - obj = parse_object(the_repository, &oid); - return (struct commit *)peel_to_type(name, 0, obj, OBJ_COMMIT); -} - -static char *get_author(const char *message) -{ - size_t len; - const char *a; - - a = find_commit_header(message, "author", &len); - if (a) - return xmemdupz(a, len); - - return NULL; -} - -static struct commit *create_commit(struct tree *tree, - struct commit *based_on, - struct commit *parent) -{ - struct object_id ret; - struct object *obj; - struct commit_list *parents = NULL; - char *author; - char *sign_commit = NULL; - struct commit_extra_header *extra; - struct strbuf msg = STRBUF_INIT; - const char *out_enc = get_commit_output_encoding(); - const char *message = logmsg_reencode(based_on, NULL, out_enc); - const char *orig_message = NULL; - const char *exclude_gpgsig[] = { "gpgsig", NULL }; - - commit_list_insert(parent, &parents); - extra = read_commit_extra_headers(based_on, exclude_gpgsig); - find_commit_subject(message, &orig_message); - strbuf_addstr(&msg, orig_message); - author = get_author(message); - reset_ident_date(); - if (commit_tree_extended(msg.buf, msg.len, &tree->object.oid, parents, - &ret, author, NULL, sign_commit, extra)) { - error(_("failed to write commit object")); - return NULL; - } - free(author); - strbuf_release(&msg); - - obj = parse_object(the_repository, &ret); - return (struct commit *)obj; -} - -int cmd__fast_rebase(int argc, const char **argv) -{ - struct commit *onto; - struct commit *last_commit = NULL, *last_picked_commit = NULL; - struct object_id head; - struct lock_file lock = LOCK_INIT; - struct strvec rev_walk_args = STRVEC_INIT; - struct rev_info revs; - struct commit *commit; - struct merge_options merge_opt; - struct tree *next_tree, *base_tree, *head_tree; - struct merge_result result; - struct strbuf reflog_msg = STRBUF_INIT; - struct strbuf branch_name = STRBUF_INIT; - int ret = 0; - - /* - * test-tool stuff doesn't set up the git directory by default; need to - * do that manually. - */ - setup_git_directory(); - - if (argc == 2 && !strcmp(argv[1], "-h")) { - printf("Sorry, I am not a psychiatrist; I can not give you the help you need. Oh, you meant usage...\n"); - exit(129); - } - - if (argc != 5 || strcmp(argv[1], "--onto")) - die("usage: read the code, figure out how to use it, then do so"); - - onto = peel_committish(argv[2]); - strbuf_addf(&branch_name, "refs/heads/%s", argv[4]); - - /* Sanity check */ - if (get_oid("HEAD", &head)) - die(_("Cannot read HEAD")); - assert(oideq(&onto->object.oid, &head)); - - repo_hold_locked_index(the_repository, &lock, LOCK_DIE_ON_ERROR); - if (repo_read_index(the_repository) < 0) - BUG("Could not read index"); - - repo_init_revisions(the_repository, &revs, NULL); - revs.verbose_header = 1; - revs.max_parents = 1; - revs.cherry_mark = 1; - revs.limited = 1; - revs.reverse = 1; - revs.right_only = 1; - revs.sort_order = REV_SORT_IN_GRAPH_ORDER; - revs.topo_order = 1; - strvec_pushl(&rev_walk_args, "", argv[4], "--not", argv[3], NULL); - - if (setup_revisions(rev_walk_args.nr, rev_walk_args.v, &revs, NULL) > 1) { - ret = error(_("unhandled options")); - goto cleanup; - } - - strvec_clear(&rev_walk_args); - - if (prepare_revision_walk(&revs) < 0) { - ret = error(_("error preparing revisions")); - goto cleanup; - } - - init_merge_options(&merge_opt, the_repository); - memset(&result, 0, sizeof(result)); - merge_opt.show_rename_progress = 1; - merge_opt.branch1 = "HEAD"; - head_tree = get_commit_tree(onto); - result.tree = head_tree; - last_commit = onto; - while ((commit = get_revision(&revs))) { - struct commit *base; - - fprintf(stderr, "Rebasing %s...\r", - oid_to_hex(&commit->object.oid)); - assert(commit->parents && !commit->parents->next); - base = commit->parents->item; - - next_tree = get_commit_tree(commit); - base_tree = get_commit_tree(base); - - merge_opt.branch2 = short_commit_name(commit); - merge_opt.ancestor = xstrfmt("parent of %s", merge_opt.branch2); - - merge_incore_nonrecursive(&merge_opt, - base_tree, - result.tree, - next_tree, - &result); - - free((char*)merge_opt.ancestor); - merge_opt.ancestor = NULL; - if (!result.clean) - break; - last_picked_commit = commit; - last_commit = create_commit(result.tree, commit, last_commit); - } - - merge_switch_to_result(&merge_opt, head_tree, &result, 1, !result.clean); - - if (result.clean < 0) - exit(128); - - if (result.clean) { - fprintf(stderr, "\nDone.\n"); - strbuf_addf(&reflog_msg, "finish rebase %s onto %s", - oid_to_hex(&last_picked_commit->object.oid), - oid_to_hex(&last_commit->object.oid)); - if (update_ref(reflog_msg.buf, branch_name.buf, - &last_commit->object.oid, - &last_picked_commit->object.oid, - REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR)) { - error(_("could not update %s"), argv[4]); - die("Failed to update %s", argv[4]); - } - if (create_symref("HEAD", branch_name.buf, reflog_msg.buf) < 0) - die(_("unable to update HEAD")); - - prime_cache_tree(the_repository, the_repository->index, - result.tree); - } else { - fprintf(stderr, "\nAborting: Hit a conflict.\n"); - strbuf_addf(&reflog_msg, "rebase progress up to %s", - oid_to_hex(&last_picked_commit->object.oid)); - if (update_ref(reflog_msg.buf, "HEAD", - &last_commit->object.oid, - &head, - REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR)) { - error(_("could not update %s"), argv[4]); - die("Failed to update %s", argv[4]); - } - } - if (write_locked_index(&the_index, &lock, - COMMIT_LOCK | SKIP_IF_UNCHANGED)) - die(_("unable to write %s"), get_index_file()); - - ret = (result.clean == 0); -cleanup: - strbuf_release(&reflog_msg); - strbuf_release(&branch_name); - release_revisions(&revs); - return ret; -} diff --git a/t/helper/test-find-pack.c b/t/helper/test-find-pack.c new file mode 100644 index 0000000000..e8bd793e58 --- /dev/null +++ b/t/helper/test-find-pack.c @@ -0,0 +1,50 @@ +#include "test-tool.h" +#include "object-name.h" +#include "object-store.h" +#include "packfile.h" +#include "parse-options.h" +#include "setup.h" + +/* + * Display the path(s), one per line, of the packfile(s) containing + * the given object. + * + * If '--check-count <n>' is passed, then error out if the number of + * packfiles containing the object is not <n>. + */ + +static const char *find_pack_usage[] = { + "test-tool find-pack [--check-count <n>] <object>", + NULL +}; + +int cmd__find_pack(int argc, const char **argv) +{ + struct object_id oid; + struct packed_git *p; + int count = -1, actual_count = 0; + const char *prefix = setup_git_directory(); + + struct option options[] = { + OPT_INTEGER('c', "check-count", &count, "expected number of packs"), + OPT_END(), + }; + + argc = parse_options(argc, argv, prefix, options, find_pack_usage, 0); + if (argc != 1) + usage(find_pack_usage[0]); + + if (repo_get_oid(the_repository, argv[0], &oid)) + die("cannot parse %s as an object name", argv[0]); + + for (p = get_all_packs(the_repository); p; p = p->next) + if (find_pack_entry_one(oid.hash, p)) { + printf("%s\n", p->pack_name); + actual_count++; + } + + if (count > -1 && count != actual_count) + die("bad packfile count %d instead of %d", actual_count, count); + + return 0; +} diff --git a/t/helper/test-fsmonitor-client.c b/t/helper/test-fsmonitor-client.c index 54a4856c48..8280984d08 100644 --- a/t/helper/test-fsmonitor-client.c +++ b/t/helper/test-fsmonitor-client.c @@ -4,14 +4,16 @@ */ #include "test-tool.h" -#include "cache.h" #include "parse-options.h" #include "fsmonitor-ipc.h" +#include "read-cache-ll.h" +#include "repository.h" +#include "setup.h" #include "thread-utils.h" #include "trace2.h" #ifndef HAVE_FSMONITOR_DAEMON_BACKEND -int cmd__fsmonitor_client(int argc, const char **argv) +int cmd__fsmonitor_client(int argc UNUSED, const char **argv UNUSED) { die("fsmonitor--daemon not available on this platform"); } diff --git a/t/helper/test-hash-speed.c b/t/helper/test-hash-speed.c index f40d9ad0c2..b235da594f 100644 --- a/t/helper/test-hash-speed.c +++ b/t/helper/test-hash-speed.c @@ -1,5 +1,5 @@ #include "test-tool.h" -#include "cache.h" +#include "hash-ll.h" #define NUM_SECONDS 3 diff --git a/t/helper/test-hash.c b/t/helper/test-hash.c index 5860dab0ff..45d829c908 100644 --- a/t/helper/test-hash.c +++ b/t/helper/test-hash.c @@ -1,5 +1,5 @@ #include "test-tool.h" -#include "cache.h" +#include "hex.h" int cmd_hash_impl(int ac, const char **av, int algo) { diff --git a/t/helper/test-hashmap.c b/t/helper/test-hashmap.c index 36ff07bd4b..0eb0b3d49c 100644 --- a/t/helper/test-hashmap.c +++ b/t/helper/test-hashmap.c @@ -2,6 +2,7 @@ #include "git-compat-util.h" #include "hashmap.h" #include "strbuf.h" +#include "string-list.h" struct test_entry { @@ -150,6 +151,7 @@ static void perf_hashmap(unsigned int method, unsigned int rounds) */ int cmd__hashmap(int argc, const char **argv) { + struct string_list parts = STRING_LIST_INIT_NODUP; struct strbuf line = STRBUF_INIT; int icase; struct hashmap map = HASHMAP_INIT(test_entry_cmp, &icase); @@ -159,21 +161,26 @@ int cmd__hashmap(int argc, const char **argv) /* process commands from stdin */ while (strbuf_getline(&line, stdin) != EOF) { - char *cmd, *p1 = NULL, *p2 = NULL; + char *cmd, *p1, *p2; unsigned int hash = 0; struct test_entry *entry; /* break line into command and up to two parameters */ - cmd = strtok(line.buf, DELIM); + string_list_setlen(&parts, 0); + string_list_split_in_place(&parts, line.buf, DELIM, 2); + string_list_remove_empty_items(&parts, 0); + /* ignore empty lines */ - if (!cmd || *cmd == '#') + if (!parts.nr) + continue; + if (!*parts.items[0].string || *parts.items[0].string == '#') continue; - p1 = strtok(NULL, DELIM); - if (p1) { + cmd = parts.items[0].string; + p1 = parts.nr >= 1 ? parts.items[1].string : NULL; + p2 = parts.nr >= 2 ? parts.items[2].string : NULL; + if (p1) hash = icase ? strihash(p1) : strhash(p1); - p2 = strtok(NULL, DELIM); - } if (!strcmp("add", cmd) && p1 && p2) { @@ -260,6 +267,7 @@ int cmd__hashmap(int argc, const char **argv) } } + string_list_clear(&parts, 0); strbuf_release(&line); hashmap_clear_and_free(&map, struct test_entry, ent); return 0; diff --git a/t/helper/test-hexdump.c b/t/helper/test-hexdump.c index 811e89c1bc..05f55eca21 100644 --- a/t/helper/test-hexdump.c +++ b/t/helper/test-hexdump.c @@ -4,7 +4,7 @@ /* * Read stdin and print a hexdump to stdout. */ -int cmd__hexdump(int argc, const char **argv) +int cmd__hexdump(int argc UNUSED, const char **argv UNUSED) { char buf[1024]; ssize_t i, len; diff --git a/t/helper/test-index-version.c b/t/helper/test-index-version.c deleted file mode 100644 index fcd10968cc..0000000000 --- a/t/helper/test-index-version.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "test-tool.h" -#include "cache.h" - -int cmd__index_version(int argc, const char **argv) -{ - struct cache_header hdr; - int version; - - memset(&hdr,0,sizeof(hdr)); - if (read(0, &hdr, sizeof(hdr)) != sizeof(hdr)) - return 0; - version = ntohl(hdr.hdr_version); - printf("%d\n", version); - return 0; -} diff --git a/t/helper/test-json-writer.c b/t/helper/test-json-writer.c index 8c3edacc00..afe393f597 100644 --- a/t/helper/test-json-writer.c +++ b/t/helper/test-json-writer.c @@ -1,6 +1,6 @@ #include "test-tool.h" -#include "cache.h" #include "json-writer.h" +#include "string-list.h" static const char *expect_obj1 = "{\"a\":\"abc\",\"b\":42,\"c\":true}"; static const char *expect_obj2 = "{\"a\":-1,\"b\":2147483647,\"c\":0}"; @@ -395,35 +395,41 @@ static int unit_tests(void) return 0; } -static void get_s(int line_nr, char **s_in) +struct line { + struct string_list *parts; + size_t consumed_nr; + int nr; +}; + +static void get_s(struct line *line, char **s_in) { - *s_in = strtok(NULL, " "); - if (!*s_in) - die("line[%d]: expected: <s>", line_nr); + if (line->consumed_nr > line->parts->nr) + die("line[%d]: expected: <s>", line->nr); + *s_in = line->parts->items[line->consumed_nr++].string; } -static void get_i(int line_nr, intmax_t *s_in) +static void get_i(struct line *line, intmax_t *s_in) { char *s; char *endptr; - get_s(line_nr, &s); + get_s(line, &s); *s_in = strtol(s, &endptr, 10); if (*endptr || errno == ERANGE) - die("line[%d]: invalid integer value", line_nr); + die("line[%d]: invalid integer value", line->nr); } -static void get_d(int line_nr, double *s_in) +static void get_d(struct line *line, double *s_in) { char *s; char *endptr; - get_s(line_nr, &s); + get_s(line, &s); *s_in = strtod(s, &endptr); if (*endptr || errno == ERANGE) - die("line[%d]: invalid float value", line_nr); + die("line[%d]: invalid float value", line->nr); } static int pretty; @@ -454,6 +460,7 @@ static char *get_trimmed_line(char *buf, int buf_size) static int scripted(void) { + struct string_list parts = STRING_LIST_INIT_NODUP; struct json_writer jw = JSON_WRITER_INIT; char buf[MAX_LINE_LENGTH]; char *line; @@ -471,66 +478,77 @@ static int scripted(void) die("expected first line to be 'object' or 'array'"); while ((line = get_trimmed_line(buf, MAX_LINE_LENGTH)) != NULL) { + struct line state = { 0 }; char *verb; char *key; char *s_value; intmax_t i_value; double d_value; - line_nr++; + state.parts = &parts; + state.nr = ++line_nr; + + /* break line into command and zero or more tokens */ + string_list_setlen(&parts, 0); + string_list_split_in_place(&parts, line, " ", -1); + string_list_remove_empty_items(&parts, 0); + + /* ignore empty lines */ + if (!parts.nr || !*parts.items[0].string) + continue; - verb = strtok(line, " "); + verb = parts.items[state.consumed_nr++].string; if (!strcmp(verb, "end")) { jw_end(&jw); } else if (!strcmp(verb, "object-string")) { - get_s(line_nr, &key); - get_s(line_nr, &s_value); + get_s(&state, &key); + get_s(&state, &s_value); jw_object_string(&jw, key, s_value); } else if (!strcmp(verb, "object-int")) { - get_s(line_nr, &key); - get_i(line_nr, &i_value); + get_s(&state, &key); + get_i(&state, &i_value); jw_object_intmax(&jw, key, i_value); } else if (!strcmp(verb, "object-double")) { - get_s(line_nr, &key); - get_i(line_nr, &i_value); - get_d(line_nr, &d_value); + get_s(&state, &key); + get_i(&state, &i_value); + get_d(&state, &d_value); jw_object_double(&jw, key, i_value, d_value); } else if (!strcmp(verb, "object-true")) { - get_s(line_nr, &key); + get_s(&state, &key); jw_object_true(&jw, key); } else if (!strcmp(verb, "object-false")) { - get_s(line_nr, &key); + get_s(&state, &key); jw_object_false(&jw, key); } else if (!strcmp(verb, "object-null")) { - get_s(line_nr, &key); + get_s(&state, &key); jw_object_null(&jw, key); } else if (!strcmp(verb, "object-object")) { - get_s(line_nr, &key); + get_s(&state, &key); jw_object_inline_begin_object(&jw, key); } else if (!strcmp(verb, "object-array")) { - get_s(line_nr, &key); + get_s(&state, &key); jw_object_inline_begin_array(&jw, key); } else if (!strcmp(verb, "array-string")) { - get_s(line_nr, &s_value); + get_s(&state, &s_value); jw_array_string(&jw, s_value); } else if (!strcmp(verb, "array-int")) { - get_i(line_nr, &i_value); + get_i(&state, &i_value); jw_array_intmax(&jw, i_value); } else if (!strcmp(verb, "array-double")) { - get_i(line_nr, &i_value); - get_d(line_nr, &d_value); + get_i(&state, &i_value); + get_d(&state, &d_value); jw_array_double(&jw, i_value, d_value); } else if (!strcmp(verb, "array-true")) @@ -553,6 +571,7 @@ static int scripted(void) printf("%s\n", jw.json.buf); jw_release(&jw); + string_list_clear(&parts, 0); return 0; } diff --git a/t/helper/test-lazy-init-name-hash.c b/t/helper/test-lazy-init-name-hash.c index ab86c14c8b..187a115d57 100644 --- a/t/helper/test-lazy-init-name-hash.c +++ b/t/helper/test-lazy-init-name-hash.c @@ -1,7 +1,12 @@ #define USE_THE_INDEX_VARIABLE #include "test-tool.h" -#include "cache.h" +#include "environment.h" +#include "name-hash.h" #include "parse-options.h" +#include "read-cache-ll.h" +#include "repository.h" +#include "setup.h" +#include "trace.h" static int single; static int multi; diff --git a/t/helper/test-match-trees.c b/t/helper/test-match-trees.c index 4079fdee06..d0db5ff26f 100644 --- a/t/helper/test-match-trees.c +++ b/t/helper/test-match-trees.c @@ -1,17 +1,21 @@ #include "test-tool.h" -#include "cache.h" +#include "hex.h" +#include "match-trees.h" +#include "object-name.h" +#include "repository.h" +#include "setup.h" #include "tree.h" -int cmd__match_trees(int ac, const char **av) +int cmd__match_trees(int ac UNUSED, const char **av) { struct object_id hash1, hash2, shifted; struct tree *one, *two; setup_git_directory(); - if (get_oid(av[1], &hash1)) + if (repo_get_oid(the_repository, av[1], &hash1)) die("cannot parse %s as an object name", av[1]); - if (get_oid(av[2], &hash2)) + if (repo_get_oid(the_repository, av[2], &hash2)) die("cannot parse %s as an object name", av[2]); one = parse_tree_indirect(&hash1); if (!one) diff --git a/t/helper/test-mergesort.c b/t/helper/test-mergesort.c index 335e5bb3a9..42ccc87051 100644 --- a/t/helper/test-mergesort.c +++ b/t/helper/test-mergesort.c @@ -1,6 +1,7 @@ #include "test-tool.h" -#include "cache.h" +#include "mem-pool.h" #include "mergesort.h" +#include "strbuf.h" static uint32_t minstd_rand(uint32_t *state) { diff --git a/t/helper/test-oid-array.c b/t/helper/test-oid-array.c index d1324d086a..aafe398ef0 100644 --- a/t/helper/test-oid-array.c +++ b/t/helper/test-oid-array.c @@ -1,14 +1,16 @@ #include "test-tool.h" -#include "cache.h" +#include "hex.h" #include "oid-array.h" +#include "setup.h" +#include "strbuf.h" -static int print_oid(const struct object_id *oid, void *data) +static int print_oid(const struct object_id *oid, void *data UNUSED) { puts(oid_to_hex(oid)); return 0; } -int cmd__oid_array(int argc, const char **argv) +int cmd__oid_array(int argc UNUSED, const char **argv UNUSED) { struct oid_array array = OID_ARRAY_INIT; struct strbuf line = STRBUF_INIT; diff --git a/t/helper/test-oidmap.c b/t/helper/test-oidmap.c index 0acf99931e..bd30244a54 100644 --- a/t/helper/test-oidmap.c +++ b/t/helper/test-oidmap.c @@ -1,7 +1,11 @@ #include "test-tool.h" -#include "cache.h" +#include "hex.h" +#include "object-name.h" #include "oidmap.h" +#include "repository.h" +#include "setup.h" #include "strbuf.h" +#include "string-list.h" /* key is an oid and value is a name (could be a refname for example) */ struct test_entry { @@ -21,8 +25,9 @@ struct test_entry { * iterate -> oidkey1 namevalue1\noidkey2 namevalue2\n... * */ -int cmd__oidmap(int argc, const char **argv) +int cmd__oidmap(int argc UNUSED, const char **argv UNUSED) { + struct string_list parts = STRING_LIST_INIT_NODUP; struct strbuf line = STRBUF_INIT; struct oidmap map = OIDMAP_INIT; @@ -33,23 +38,28 @@ int cmd__oidmap(int argc, const char **argv) /* process commands from stdin */ while (strbuf_getline(&line, stdin) != EOF) { - char *cmd, *p1 = NULL, *p2 = NULL; + char *cmd, *p1, *p2; struct test_entry *entry; struct object_id oid; /* break line into command and up to two parameters */ - cmd = strtok(line.buf, DELIM); + string_list_setlen(&parts, 0); + string_list_split_in_place(&parts, line.buf, DELIM, 2); + string_list_remove_empty_items(&parts, 0); + /* ignore empty lines */ - if (!cmd || *cmd == '#') + if (!parts.nr) + continue; + if (!*parts.items[0].string || *parts.items[0].string == '#') continue; - p1 = strtok(NULL, DELIM); - if (p1) - p2 = strtok(NULL, DELIM); + cmd = parts.items[0].string; + p1 = parts.nr >= 1 ? parts.items[1].string : NULL; + p2 = parts.nr >= 2 ? parts.items[2].string : NULL; if (!strcmp("put", cmd) && p1 && p2) { - if (get_oid(p1, &oid)) { + if (repo_get_oid(the_repository, p1, &oid)) { printf("Unknown oid: %s\n", p1); continue; } @@ -67,7 +77,7 @@ int cmd__oidmap(int argc, const char **argv) } else if (!strcmp("get", cmd) && p1) { - if (get_oid(p1, &oid)) { + if (repo_get_oid(the_repository, p1, &oid)) { printf("Unknown oid: %s\n", p1); continue; } @@ -80,7 +90,7 @@ int cmd__oidmap(int argc, const char **argv) } else if (!strcmp("remove", cmd) && p1) { - if (get_oid(p1, &oid)) { + if (repo_get_oid(the_repository, p1, &oid)) { printf("Unknown oid: %s\n", p1); continue; } @@ -106,6 +116,7 @@ int cmd__oidmap(int argc, const char **argv) } } + string_list_clear(&parts, 0); strbuf_release(&line); oidmap_free(&map, 1); return 0; diff --git a/t/helper/test-oidtree.c b/t/helper/test-oidtree.c index d48a409f4e..c7a1d4c642 100644 --- a/t/helper/test-oidtree.c +++ b/t/helper/test-oidtree.c @@ -1,14 +1,16 @@ #include "test-tool.h" -#include "cache.h" +#include "hex.h" #include "oidtree.h" +#include "setup.h" +#include "strbuf.h" -static enum cb_next print_oid(const struct object_id *oid, void *data) +static enum cb_next print_oid(const struct object_id *oid, void *data UNUSED) { puts(oid_to_hex(oid)); return CB_CONTINUE; } -int cmd__oidtree(int argc, const char **argv) +int cmd__oidtree(int argc UNUSED, const char **argv UNUSED) { struct oidtree ot; struct strbuf line = STRBUF_INIT; diff --git a/t/helper/test-online-cpus.c b/t/helper/test-online-cpus.c index 8cb0d53840..47dc211711 100644 --- a/t/helper/test-online-cpus.c +++ b/t/helper/test-online-cpus.c @@ -2,7 +2,7 @@ #include "git-compat-util.h" #include "thread-utils.h" -int cmd__online_cpus(int argc, const char **argv) +int cmd__online_cpus(int argc UNUSED, const char **argv UNUSED) { printf("%d\n", online_cpus()); return 0; diff --git a/t/helper/test-pack-mtimes.c b/t/helper/test-pack-mtimes.c index f7b79daf4c..67a964ef90 100644 --- a/t/helper/test-pack-mtimes.c +++ b/t/helper/test-pack-mtimes.c @@ -1,9 +1,10 @@ -#include "git-compat-util.h" #include "test-tool.h" +#include "hex.h" #include "strbuf.h" -#include "object-store.h" +#include "object-store-ll.h" #include "packfile.h" #include "pack-mtimes.h" +#include "setup.h" static void dump_mtimes(struct packed_git *p) { diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c index 506835521a..ded8116cc5 100644 --- a/t/helper/test-parse-options.c +++ b/t/helper/test-parse-options.c @@ -1,6 +1,6 @@ #include "test-tool.h" -#include "cache.h" #include "parse-options.h" +#include "strbuf.h" #include "string-list.h" #include "trace2.h" @@ -21,6 +21,19 @@ static struct { int unset; } length_cb; +static int mode34_callback(const struct option *opt, const char *arg, int unset) +{ + if (unset) + *(int *)opt->value = 0; + else if (!strcmp(arg, "3")) + *(int *)opt->value = 3; + else if (!strcmp(arg, "4")) + *(int *)opt->value = 4; + else + return error("invalid value for '%s': '%s'", "--mode34", arg); + return 0; +} + static int length_callback(const struct option *opt, const char *arg, int unset) { length_cb.called = 1; @@ -124,6 +137,9 @@ int cmd__parse_options(int argc, const char **argv) OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23), OPT_CMDMODE(0, "mode1", &integer, "set integer to 1 (cmdmode option)", 1), OPT_CMDMODE(0, "mode2", &integer, "set integer to 2 (cmdmode option)", 2), + OPT_CALLBACK_F(0, "mode34", &integer, "(3|4)", + "set integer to 3 or 4 (cmdmode option)", + PARSE_OPT_CMDMODE, mode34_callback), OPT_CALLBACK('L', "length", &integer, "str", "get length of <str>", length_callback), OPT_FILENAME('F', "file", &file, "set file to <file>"), @@ -133,6 +149,8 @@ int cmd__parse_options(int argc, const char **argv) OPT_STRING(0, "st", &string, "st", "get another string (pervert ordering)"), OPT_STRING('o', NULL, &string, "str", "get another string"), OPT_NOOP_NOARG(0, "obsolete"), + OPT_SET_INT_F(0, "longhelp", &integer, "help text of this entry\n" + "spans multiple lines", 0, PARSE_OPT_NONEG), OPT_STRING_LIST(0, "list", &list, "str", "add str to list"), OPT_GROUP("Magic arguments"), OPT_NUMBER_CALLBACK(&integer, "set integer to NUM", @@ -263,14 +281,14 @@ int cmd__parse_options_flags(int argc, const char **argv) return parse_options_flags__cmd(argc, argv, test_flags); } -static int subcmd_one(int argc, const char **argv, const char *prefix) +static int subcmd_one(int argc, const char **argv, const char *prefix UNUSED) { printf("fn: subcmd_one\n"); print_args(argc, argv); return 0; } -static int subcmd_two(int argc, const char **argv, const char *prefix) +static int subcmd_two(int argc, const char **argv, const char *prefix UNUSED) { printf("fn: subcmd_two\n"); print_args(argc, argv); diff --git a/t/helper/test-parse-pathspec-file.c b/t/helper/test-parse-pathspec-file.c index b3e08cef4b..89ecefd1cd 100644 --- a/t/helper/test-parse-pathspec-file.c +++ b/t/helper/test-parse-pathspec-file.c @@ -1,12 +1,11 @@ #include "test-tool.h" #include "parse-options.h" #include "pathspec.h" -#include "gettext.h" int cmd__parse_pathspec_file(int argc, const char **argv) { struct pathspec pathspec; - const char *pathspec_from_file = NULL; + char *pathspec_from_file = NULL; int pathspec_file_nul = 0, i; static const char *const usage[] = { @@ -29,5 +28,6 @@ int cmd__parse_pathspec_file(int argc, const char **argv) printf("%s\n", pathspec.items[i].original); clear_pathspec(&pathspec); + free(pathspec_from_file); return 0; } diff --git a/t/helper/test-partial-clone.c b/t/helper/test-partial-clone.c index 3f102cfddd..910a128614 100644 --- a/t/helper/test-partial-clone.c +++ b/t/helper/test-partial-clone.c @@ -1,7 +1,8 @@ -#include "cache.h" #include "test-tool.h" +#include "hex.h" #include "repository.h" -#include "object-store.h" +#include "object-store-ll.h" +#include "setup.h" /* * Prints the size of the object corresponding to the given hash in a specific diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c index f69709d674..70396fa384 100644 --- a/t/helper/test-path-utils.c +++ b/t/helper/test-path-utils.c @@ -1,6 +1,11 @@ #include "test-tool.h" -#include "cache.h" +#include "abspath.h" +#include "environment.h" +#include "path.h" +#include "read-cache-ll.h" +#include "setup.h" #include "string-list.h" +#include "trace.h" #include "utf8.h" /* diff --git a/t/helper/test-pcre2-config.c b/t/helper/test-pcre2-config.c index 5258fdddba..5d0b2a2e10 100644 --- a/t/helper/test-pcre2-config.c +++ b/t/helper/test-pcre2-config.c @@ -1,5 +1,4 @@ #include "test-tool.h" -#include "cache.h" #include "grep.h" int cmd__pcre2_config(int argc, const char **argv) diff --git a/t/helper/test-pkt-line.c b/t/helper/test-pkt-line.c index c5e052e537..f4d134a145 100644 --- a/t/helper/test-pkt-line.c +++ b/t/helper/test-pkt-line.c @@ -1,6 +1,7 @@ -#include "cache.h" +#include "git-compat-util.h" #include "test-tool.h" #include "pkt-line.h" +#include "write-or-die.h" static void pack_line(const char *line) { diff --git a/t/helper/test-prio-queue.c b/t/helper/test-prio-queue.c index 133b5e6f4a..f0bf255f5f 100644 --- a/t/helper/test-prio-queue.c +++ b/t/helper/test-prio-queue.c @@ -1,8 +1,7 @@ #include "test-tool.h" -#include "cache.h" #include "prio-queue.h" -static int intcmp(const void *va, const void *vb, void *data) +static int intcmp(const void *va, const void *vb, void *data UNUSED) { const int *a = va, *b = vb; return *a - *b; @@ -17,7 +16,7 @@ static void show(int *v) free(v); } -int cmd__prio_queue(int argc, const char **argv) +int cmd__prio_queue(int argc UNUSED, const char **argv) { struct prio_queue pq = { intcmp }; diff --git a/t/helper/test-proc-receive.c b/t/helper/test-proc-receive.c index a4b305f494..f30022d222 100644 --- a/t/helper/test-proc-receive.c +++ b/t/helper/test-proc-receive.c @@ -1,9 +1,10 @@ -#include "cache.h" +#include "test-tool.h" #include "connect.h" +#include "hex.h" #include "parse-options.h" #include "pkt-line.h" +#include "setup.h" #include "sigchain.h" -#include "test-tool.h" static const char *proc_receive_usage[] = { "test-tool proc-receive [<options>]", diff --git a/t/helper/test-progress.c b/t/helper/test-progress.c index 6cc9735b60..66acb6a06c 100644 --- a/t/helper/test-progress.c +++ b/t/helper/test-progress.c @@ -19,7 +19,6 @@ */ #define GIT_TEST_PROGRESS_ONLY #include "test-tool.h" -#include "gettext.h" #include "parse-options.h" #include "progress.h" #include "strbuf.h" diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c index 2f65c7f6a5..3e173399a0 100644 --- a/t/helper/test-reach.c +++ b/t/helper/test-reach.c @@ -1,10 +1,13 @@ #include "test-tool.h" -#include "cache.h" #include "commit.h" #include "commit-reach.h" #include "config.h" +#include "gettext.h" +#include "hex.h" +#include "object-name.h" #include "parse-options.h" #include "ref-filter.h" +#include "setup.h" #include "string-list.h" #include "tag.h" @@ -57,7 +60,7 @@ int cmd__reach(int ac, const char **av) if (buf.len < 3) continue; - if (get_oid_committish(buf.buf + 2, &oid)) + if (repo_get_oid_committish(the_repository, buf.buf + 2, &oid)) die("failed to resolve %s", buf.buf + 2); orig = parse_object(r, &oid); @@ -106,13 +109,17 @@ int cmd__reach(int ac, const char **av) if (!strcmp(av[1], "ref_newer")) printf("%s(A,B):%d\n", av[1], ref_newer(&oid_A, &oid_B)); else if (!strcmp(av[1], "in_merge_bases")) - printf("%s(A,B):%d\n", av[1], in_merge_bases(A, B)); + printf("%s(A,B):%d\n", av[1], + repo_in_merge_bases(the_repository, A, B)); else if (!strcmp(av[1], "in_merge_bases_many")) - printf("%s(A,X):%d\n", av[1], in_merge_bases_many(A, X_nr, X_array)); + printf("%s(A,X):%d\n", av[1], + repo_in_merge_bases_many(the_repository, A, X_nr, X_array)); else if (!strcmp(av[1], "is_descendant_of")) printf("%s(A,X):%d\n", av[1], repo_is_descendant_of(r, A, X)); else if (!strcmp(av[1], "get_merge_bases_many")) { - struct commit_list *list = get_merge_bases_many(A, X_nr, X_array); + struct commit_list *list = repo_get_merge_bases_many(the_repository, + A, X_nr, + X_array); printf("%s(A,X):\n", av[1]); print_sorted_commit_ids(list); } else if (!strcmp(av[1], "reduce_heads")) { @@ -131,7 +138,7 @@ int cmd__reach(int ac, const char **av) printf("%s(X,_,_,0,0):%d\n", av[1], can_all_from_reach_with_flag(&X_obj, 2, 4, 0, 0)); } else if (!strcmp(av[1], "commit_contains")) { - struct ref_filter filter; + struct ref_filter filter = REF_FILTER_INIT; struct contains_cache cache; init_contains_cache(&cache); diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c index 23e9e27109..1acd362346 100644 --- a/t/helper/test-read-cache.c +++ b/t/helper/test-read-cache.c @@ -1,7 +1,9 @@ #define USE_THE_INDEX_VARIABLE #include "test-tool.h" -#include "cache.h" #include "config.h" +#include "read-cache-ll.h" +#include "repository.h" +#include "setup.h" int cmd__read_cache(int argc, const char **argv) { diff --git a/t/helper/test-read-graph.c b/t/helper/test-read-graph.c index 98b73bb8f2..8c7a83f578 100644 --- a/t/helper/test-read-graph.c +++ b/t/helper/test-read-graph.c @@ -1,11 +1,11 @@ #include "test-tool.h" -#include "cache.h" #include "commit-graph.h" #include "repository.h" -#include "object-store.h" +#include "object-store-ll.h" #include "bloom.h" +#include "setup.h" -int cmd__read_graph(int argc, const char **argv) +int cmd__read_graph(int argc UNUSED, const char **argv UNUSED) { struct commit_graph *graph = NULL; struct object_directory *odb; diff --git a/t/helper/test-read-midx.c b/t/helper/test-read-midx.c index 27072ba94d..e9a444ddba 100644 --- a/t/helper/test-read-midx.c +++ b/t/helper/test-read-midx.c @@ -1,9 +1,11 @@ #include "test-tool.h" -#include "cache.h" +#include "hex.h" #include "midx.h" #include "repository.h" -#include "object-store.h" +#include "object-store-ll.h" #include "pack-bitmap.h" +#include "packfile.h" +#include "setup.h" static int read_midx_file(const char *object_dir, int show_objects) { diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index ae8a5648da..702ec1f128 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -1,9 +1,13 @@ #include "test-tool.h" -#include "cache.h" +#include "hex.h" #include "refs.h" +#include "setup.h" #include "worktree.h" -#include "object-store.h" +#include "object-store-ll.h" +#include "path.h" #include "repository.h" +#include "strbuf.h" +#include "revision.h" struct flag_definition { const char *name; @@ -115,8 +119,16 @@ static struct flag_definition pack_flags[] = { FLAG_DEF(PACK_REFS_PRUNE), static int cmd_pack_refs(struct ref_store *refs, const char **argv) { unsigned int flags = arg_flags(*argv++, "flags", pack_flags); + static struct ref_exclusions exclusions = REF_EXCLUSIONS_INIT; + static struct string_list included_refs = STRING_LIST_INIT_NODUP; + struct pack_refs_opts pack_opts = { .flags = flags, + .exclusions = &exclusions, + .includes = &included_refs }; - return refs_pack_refs(refs, flags); + if (pack_opts.flags & PACK_REFS_ALL) + string_list_append(pack_opts.includes, "*"); + + return refs_pack_refs(refs, &pack_opts); } static int cmd_create_symref(struct ref_store *refs, const char **argv) @@ -174,6 +186,15 @@ static int cmd_for_each_ref(struct ref_store *refs, const char **argv) return refs_for_each_ref_in(refs, prefix, each_ref, NULL); } +static int cmd_for_each_ref__exclude(struct ref_store *refs, const char **argv) +{ + const char *prefix = notnull(*argv++, "prefix"); + const char **exclude_patterns = argv; + + return refs_for_each_fullref_in(refs, prefix, exclude_patterns, each_ref, + NULL); +} + static int cmd_resolve_ref(struct ref_store *refs, const char **argv) { struct object_id oid = *null_oid(); @@ -200,7 +221,8 @@ static int cmd_verify_ref(struct ref_store *refs, const char **argv) return ret; } -static int cmd_for_each_reflog(struct ref_store *refs, const char **argv) +static int cmd_for_each_reflog(struct ref_store *refs, + const char **argv UNUSED) { return refs_for_each_reflog(refs, each_ref, NULL); } @@ -255,11 +277,6 @@ static int cmd_delete_reflog(struct ref_store *refs, const char **argv) return refs_delete_reflog(refs, refname); } -static int cmd_reflog_expire(struct ref_store *refs, const char **argv) -{ - die("not supported yet"); -} - static int cmd_delete_ref(struct ref_store *refs, const char **argv) { const char *msg = notnull(*argv++, "msg"); @@ -281,16 +298,19 @@ static int cmd_update_ref(struct ref_store *refs, const char **argv) const char *new_sha1_buf = notnull(*argv++, "new-sha1"); const char *old_sha1_buf = notnull(*argv++, "old-sha1"); unsigned int flags = arg_flags(*argv++, "flags", transaction_flags); - struct object_id old_oid; + struct object_id old_oid, *old_oid_ptr = NULL; struct object_id new_oid; - if (get_oid_hex(old_sha1_buf, &old_oid)) - die("cannot parse %s as %s", old_sha1_buf, the_hash_algo->name); + if (*old_sha1_buf) { + if (get_oid_hex(old_sha1_buf, &old_oid)) + die("cannot parse %s as %s", old_sha1_buf, the_hash_algo->name); + old_oid_ptr = &old_oid; + } if (get_oid_hex(new_sha1_buf, &new_oid)) die("cannot parse %s as %s", new_sha1_buf, the_hash_algo->name); return refs_update_ref(refs, msg, refname, - &new_oid, &old_oid, + &new_oid, old_oid_ptr, flags, UPDATE_REFS_DIE_ON_ERR); } @@ -305,6 +325,7 @@ static struct command commands[] = { { "delete-refs", cmd_delete_refs }, { "rename-ref", cmd_rename_ref }, { "for-each-ref", cmd_for_each_ref }, + { "for-each-ref--exclude", cmd_for_each_ref__exclude }, { "resolve-ref", cmd_resolve_ref }, { "verify-ref", cmd_verify_ref }, { "for-each-reflog", cmd_for_each_reflog }, @@ -313,7 +334,6 @@ static struct command commands[] = { { "reflog-exists", cmd_reflog_exists }, { "create-reflog", cmd_create_reflog }, { "delete-reflog", cmd_delete_reflog }, - { "reflog-expire", cmd_reflog_expire }, /* * backend transaction functions can't be tested separately */ @@ -322,7 +342,7 @@ static struct command commands[] = { { NULL, NULL } }; -int cmd__ref_store(int argc, const char **argv) +int cmd__ref_store(int argc UNUSED, const char **argv) { struct ref_store *refs; const char *func; diff --git a/t/helper/test-reftable.c b/t/helper/test-reftable.c index 1f0a28cbb6..00237ef0d9 100644 --- a/t/helper/test-reftable.c +++ b/t/helper/test-reftable.c @@ -1,3 +1,4 @@ +#include "reftable/system.h" #include "reftable/reftable-tests.h" #include "test-tool.h" diff --git a/t/helper/test-regex.c b/t/helper/test-regex.c index bd871a735b..80042eafc2 100644 --- a/t/helper/test-regex.c +++ b/t/helper/test-regex.c @@ -30,7 +30,7 @@ static int test_regex_bug(void) if (regexec(&r, str, 1, m, 0)) die("no match of pattern '%s' to string '%s'", pat, str); - /* http://sourceware.org/bugzilla/show_bug.cgi?id=3957 */ + /* https://sourceware.org/bugzilla/show_bug.cgi?id=3957 */ if (m[0].rm_so == 3) /* matches '\n' when it should not */ die("regex bug confirmed: re-build git with NO_REGEX=1"); diff --git a/t/helper/test-repository.c b/t/helper/test-repository.c index 56f0e3c1be..4cd8a952e5 100644 --- a/t/helper/test-repository.c +++ b/t/helper/test-repository.c @@ -1,11 +1,13 @@ #include "test-tool.h" -#include "cache.h" #include "commit-graph.h" #include "commit.h" #include "config.h" -#include "object-store.h" +#include "environment.h" +#include "hex.h" +#include "object-store-ll.h" #include "object.h" #include "repository.h" +#include "setup.h" #include "tree.h" static void test_parse_commit_in_graph(const char *gitdir, const char *worktree, diff --git a/t/helper/test-revision-walking.c b/t/helper/test-revision-walking.c index 4a45d5bac2..f346951bc2 100644 --- a/t/helper/test-revision-walking.c +++ b/t/helper/test-revision-walking.c @@ -9,17 +9,19 @@ */ #include "test-tool.h" -#include "cache.h" #include "commit.h" #include "diff.h" +#include "repository.h" #include "revision.h" +#include "setup.h" static void print_commit(struct commit *commit) { struct strbuf sb = STRBUF_INIT; struct pretty_print_context ctx = {0}; ctx.date_mode.type = DATE_NORMAL; - format_commit_message(commit, " %m %s", &sb, &ctx); + repo_format_commit_message(the_repository, commit, " %m %s", &sb, + &ctx); printf("%s\n", sb.buf); strbuf_release(&sb); } diff --git a/t/helper/test-run-command.c b/t/helper/test-run-command.c index 3ecb830f4a..c0ed8722c8 100644 --- a/t/helper/test-run-command.c +++ b/t/helper/test-run-command.c @@ -9,8 +9,6 @@ */ #include "test-tool.h" -#include "git-compat-util.h" -#include "cache.h" #include "run-command.h" #include "strvec.h" #include "strbuf.h" @@ -18,13 +16,12 @@ #include "string-list.h" #include "thread-utils.h" #include "wildmatch.h" -#include "gettext.h" static int number_callbacks; static int parallel_next(struct child_process *cp, struct strbuf *err, void *cb, - void **task_cb) + void **task_cb UNUSED) { struct child_process *d = cb; if (number_callbacks >= 4) @@ -40,10 +37,10 @@ static int parallel_next(struct child_process *cp, return 1; } -static int no_job(struct child_process *cp, +static int no_job(struct child_process *cp UNUSED, struct strbuf *err, - void *cb, - void **task_cb) + void *cb UNUSED, + void **task_cb UNUSED) { if (err) strbuf_addstr(err, "no further jobs available\n"); @@ -52,10 +49,10 @@ static int no_job(struct child_process *cp, return 0; } -static int task_finished(int result, +static int task_finished(int result UNUSED, struct strbuf *err, - void *pp_cb, - void *pp_task_cb) + void *pp_cb UNUSED, + void *pp_task_cb UNUSED) { if (err) strbuf_addstr(err, "asking for a quick stop\n"); diff --git a/t/helper/test-scrap-cache-tree.c b/t/helper/test-scrap-cache-tree.c index a26107ed70..0a816a96e2 100644 --- a/t/helper/test-scrap-cache-tree.c +++ b/t/helper/test-scrap-cache-tree.c @@ -1,11 +1,13 @@ #define USE_THE_INDEX_VARIABLE #include "test-tool.h" -#include "cache.h" #include "lockfile.h" +#include "read-cache-ll.h" +#include "repository.h" +#include "setup.h" #include "tree.h" #include "cache-tree.h" -int cmd__scrap_cache_tree(int ac, const char **av) +int cmd__scrap_cache_tree(int ac UNUSED, const char **av UNUSED) { struct lock_file index_lock = LOCK_INIT; diff --git a/t/helper/test-serve-v2.c b/t/helper/test-serve-v2.c index 824e5c0a95..054cbcf5d8 100644 --- a/t/helper/test-serve-v2.c +++ b/t/helper/test-serve-v2.c @@ -1,7 +1,8 @@ #include "test-tool.h" -#include "cache.h" +#include "gettext.h" #include "parse-options.h" #include "serve.h" +#include "setup.h" static char const * const serve_usage[] = { N_("test-tool serve-v2 [<options>]"), diff --git a/t/helper/test-sha1.c b/t/helper/test-sha1.c index 71fe5c6145..dcb7f6c003 100644 --- a/t/helper/test-sha1.c +++ b/t/helper/test-sha1.c @@ -1,5 +1,5 @@ #include "test-tool.h" -#include "cache.h" +#include "hash-ll.h" int cmd__sha1(int ac, const char **av) { diff --git a/t/helper/test-sha256.c b/t/helper/test-sha256.c index 0ac6a99d5f..08cf149001 100644 --- a/t/helper/test-sha256.c +++ b/t/helper/test-sha256.c @@ -1,5 +1,5 @@ #include "test-tool.h" -#include "cache.h" +#include "hash-ll.h" int cmd__sha256(int ac, const char **av) { diff --git a/t/helper/test-sigchain.c b/t/helper/test-sigchain.c index d013bccdda..2d5ecf7383 100644 --- a/t/helper/test-sigchain.c +++ b/t/helper/test-sigchain.c @@ -1,5 +1,4 @@ #include "test-tool.h" -#include "cache.h" #include "sigchain.h" #define X(f) \ @@ -14,7 +13,7 @@ X(two) X(three) #undef X -int cmd__sigchain(int argc, const char **argv) +int cmd__sigchain(int argc UNUSED, const char **argv UNUSED) { sigchain_push(SIGTERM, one); sigchain_push(SIGTERM, two); diff --git a/t/helper/test-simple-ipc.c b/t/helper/test-simple-ipc.c index 28365ff85b..941ae7e3bc 100644 --- a/t/helper/test-simple-ipc.c +++ b/t/helper/test-simple-ipc.c @@ -3,13 +3,14 @@ */ #include "test-tool.h" -#include "cache.h" +#include "gettext.h" #include "strbuf.h" #include "simple-ipc.h" #include "parse-options.h" #include "thread-utils.h" #include "strvec.h" #include "run-command.h" +#include "trace2.h" #ifndef SUPPORTS_SIMPLE_IPC int cmd__simple_ipc(int argc, const char **argv) @@ -277,7 +278,8 @@ static int daemon__run_server(void) static start_bg_wait_cb bg_wait_cb; -static int bg_wait_cb(const struct child_process *cp, void *cb_data) +static int bg_wait_cb(const struct child_process *cp UNUSED, + void *cb_data UNUSED) { int s = ipc_get_active_state(cl_args.path); diff --git a/t/helper/test-strcmp-offset.c b/t/helper/test-strcmp-offset.c index 44e4a6d143..d8473cf2fc 100644 --- a/t/helper/test-strcmp-offset.c +++ b/t/helper/test-strcmp-offset.c @@ -1,7 +1,7 @@ #include "test-tool.h" -#include "cache.h" +#include "read-cache-ll.h" -int cmd__strcmp_offset(int argc, const char **argv) +int cmd__strcmp_offset(int argc UNUSED, const char **argv) { int result; size_t offset; diff --git a/t/helper/test-string-list.c b/t/helper/test-string-list.c index 2123dda85b..e2aad611d1 100644 --- a/t/helper/test-string-list.c +++ b/t/helper/test-string-list.c @@ -1,5 +1,5 @@ #include "test-tool.h" -#include "cache.h" +#include "strbuf.h" #include "string-list.h" /* @@ -62,7 +62,7 @@ int cmd__string_list(int argc, const char **argv) struct string_list list = STRING_LIST_INIT_NODUP; int i; char *s = xstrdup(argv[2]); - int delim = *argv[3]; + const char *delim = argv[3]; int maxsplit = atoi(argv[4]); i = string_list_split_in_place(&list, s, delim, maxsplit); @@ -111,7 +111,7 @@ int cmd__string_list(int argc, const char **argv) */ if (sb.len && sb.buf[sb.len - 1] == '\n') strbuf_setlen(&sb, sb.len - 1); - string_list_split_in_place(&list, sb.buf, '\n', -1); + string_list_split_in_place(&list, sb.buf, "\n", -1); string_list_sort(&list); diff --git a/t/helper/test-submodule-config.c b/t/helper/test-submodule-config.c index 22a41c4092..9df2f03ac8 100644 --- a/t/helper/test-submodule-config.c +++ b/t/helper/test-submodule-config.c @@ -1,10 +1,13 @@ #include "test-tool.h" -#include "cache.h" #include "config.h" +#include "hash.h" +#include "object-name.h" +#include "repository.h" +#include "setup.h" #include "submodule-config.h" #include "submodule.h" -static void die_usage(int argc, const char **argv, const char *msg) +static void die_usage(int argc UNUSED, const char **argv, const char *msg) { fprintf(stderr, "%s\n", msg); fprintf(stderr, "Usage: %s [<commit> <submodulepath>] ...\n", argv[0]); @@ -42,7 +45,7 @@ int cmd__submodule_config(int argc, const char **argv) if (commit[0] == '\0') oidclr(&commit_oid); - else if (get_oid(commit, &commit_oid) < 0) + else if (repo_get_oid(the_repository, commit, &commit_oid) < 0) die_usage(argc, argv, "Commit not found."); if (lookup_name) { diff --git a/t/helper/test-submodule-nested-repo-config.c b/t/helper/test-submodule-nested-repo-config.c index dc1c14bde3..ecd40ded99 100644 --- a/t/helper/test-submodule-nested-repo-config.c +++ b/t/helper/test-submodule-nested-repo-config.c @@ -1,4 +1,6 @@ #include "test-tool.h" +#include "repository.h" +#include "setup.h" #include "submodule-config.h" static void die_usage(const char **argv, const char *msg) diff --git a/t/helper/test-submodule.c b/t/helper/test-submodule.c index e060cc6226..356e0a26c5 100644 --- a/t/helper/test-submodule.c +++ b/t/helper/test-submodule.c @@ -1,8 +1,9 @@ #include "test-tool.h" #include "test-tool-utils.h" -#include "cache.h" #include "parse-options.h" #include "remote.h" +#include "repository.h" +#include "setup.h" #include "submodule-config.h" #include "submodule.h" @@ -174,7 +175,7 @@ static int cmd__submodule_config_unset(int argc, const char **argv) usage_with_options(usage, options); } -static int cmd__submodule_config_writeable(int argc, const char **argv) +static int cmd__submodule_config_writeable(int argc, const char **argv UNUSED) { struct option options[] = { OPT_END() diff --git a/t/helper/test-subprocess.c b/t/helper/test-subprocess.c index ff22f2fa2c..c344f1694d 100644 --- a/t/helper/test-subprocess.c +++ b/t/helper/test-subprocess.c @@ -1,6 +1,6 @@ #include "test-tool.h" -#include "cache.h" #include "run-command.h" +#include "setup.h" int cmd__subprocess(int argc, const char **argv) { diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c index abe8a785eb..37ba996539 100644 --- a/t/helper/test-tool.c +++ b/t/helper/test-tool.c @@ -30,7 +30,7 @@ static struct test_cmd cmds[] = { { "dump-untracked-cache", cmd__dump_untracked_cache }, { "env-helper", cmd__env_helper }, { "example-decorate", cmd__example_decorate }, - { "fast-rebase", cmd__fast_rebase }, + { "find-pack", cmd__find_pack }, { "fsmonitor-client", cmd__fsmonitor_client }, { "genrandom", cmd__genrandom }, { "genzeros", cmd__genzeros }, @@ -38,7 +38,6 @@ static struct test_cmd cmds[] = { { "hashmap", cmd__hashmap }, { "hash-speed", cmd__hash_speed }, { "hexdump", cmd__hexdump }, - { "index-version", cmd__index_version }, { "json-writer", cmd__json_writer }, { "lazy-init-name-hash", cmd__lazy_init_name_hash }, { "match-trees", cmd__match_trees }, @@ -86,6 +85,7 @@ static struct test_cmd cmds[] = { { "submodule-nested-repo-config", cmd__submodule_nested_repo_config }, { "subprocess", cmd__subprocess }, { "trace2", cmd__trace2 }, + { "truncate", cmd__truncate }, { "userdiff", cmd__userdiff }, { "urlmatch-normalization", cmd__urlmatch_normalization }, { "xml-encode", cmd__xml_encode }, diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h index ea2672436c..8a1a7c63da 100644 --- a/t/helper/test-tool.h +++ b/t/helper/test-tool.h @@ -24,7 +24,7 @@ int cmd__dump_untracked_cache(int argc, const char **argv); int cmd__dump_reftable(int argc, const char **argv); int cmd__env_helper(int argc, const char **argv); int cmd__example_decorate(int argc, const char **argv); -int cmd__fast_rebase(int argc, const char **argv); +int cmd__find_pack(int argc, const char **argv); int cmd__fsmonitor_client(int argc, const char **argv); int cmd__genrandom(int argc, const char **argv); int cmd__genzeros(int argc, const char **argv); @@ -32,7 +32,6 @@ int cmd__getcwd(int argc, const char **argv); int cmd__hashmap(int argc, const char **argv); int cmd__hash_speed(int argc, const char **argv); int cmd__hexdump(int argc, const char **argv); -int cmd__index_version(int argc, const char **argv); int cmd__json_writer(int argc, const char **argv); int cmd__lazy_init_name_hash(int argc, const char **argv); int cmd__match_trees(int argc, const char **argv); @@ -79,6 +78,7 @@ int cmd__submodule_config(int argc, const char **argv); int cmd__submodule_nested_repo_config(int argc, const char **argv); int cmd__subprocess(int argc, const char **argv); int cmd__trace2(int argc, const char **argv); +int cmd__truncate(int argc, const char **argv); int cmd__userdiff(int argc, const char **argv); int cmd__urlmatch_normalization(int argc, const char **argv); int cmd__xml_encode(int argc, const char **argv); diff --git a/t/helper/test-trace2.c b/t/helper/test-trace2.c index f374c21ec3..1adac29a57 100644 --- a/t/helper/test-trace2.c +++ b/t/helper/test-trace2.c @@ -1,9 +1,10 @@ #include "test-tool.h" -#include "cache.h" #include "strvec.h" #include "run-command.h" #include "exec-cmd.h" #include "config.h" +#include "repository.h" +#include "trace2.h" typedef int(fn_unit_test)(int argc, const char **argv); @@ -44,7 +45,7 @@ static int get_i(int *p_value, const char *data) * [] "def_param" events for all of the "interesting" pre-defined * config settings. */ -static int ut_001return(int argc, const char **argv) +static int ut_001return(int argc UNUSED, const char **argv) { int rc; @@ -64,7 +65,7 @@ static int ut_001return(int argc, const char **argv) * [] "def_param" events for all of the "interesting" pre-defined * config settings. */ -static int ut_002exit(int argc, const char **argv) +static int ut_002exit(int argc UNUSED, const char **argv) { int rc; @@ -200,7 +201,7 @@ static int ut_006data(int argc, const char **argv) return 0; } -static int ut_007BUG(int argc, const char **argv) +static int ut_007BUG(int argc UNUSED, const char **argv UNUSED) { /* * Exercise BUG() to ensure that the message is printed to trace2. @@ -208,7 +209,7 @@ static int ut_007BUG(int argc, const char **argv) BUG("the bug message"); } -static int ut_008bug(int argc, const char **argv) +static int ut_008bug(int argc UNUSED, const char **argv UNUSED) { bug("a bug message"); bug("another bug message"); @@ -216,7 +217,7 @@ static int ut_008bug(int argc, const char **argv) return 0; } -static int ut_009bug_BUG(int argc, const char **argv) +static int ut_009bug_BUG(int argc UNUSED, const char **argv UNUSED) { bug("a bug message"); bug("another bug message"); @@ -224,7 +225,7 @@ static int ut_009bug_BUG(int argc, const char **argv) return 0; } -static int ut_010bug_BUG(int argc, const char **argv) +static int ut_010bug_BUG(int argc UNUSED, const char **argv UNUSED) { bug("a %s message", "bug"); BUG("a %s message", "BUG"); @@ -411,6 +412,56 @@ static int ut_201counter(int argc, const char **argv) return 0; } +static int ut_300redact_start(int argc, const char **argv) +{ + if (!argc) + die("expect <argv...>"); + + trace2_cmd_start(argv); + + return 0; +} + +static int ut_301redact_child_start(int argc, const char **argv) +{ + struct child_process cmd = CHILD_PROCESS_INIT; + int k; + + if (!argc) + die("expect <argv...>"); + + for (k = 0; argv[k]; k++) + strvec_push(&cmd.args, argv[k]); + + trace2_child_start(&cmd); + + strvec_clear(&cmd.args); + + return 0; +} + +static int ut_302redact_exec(int argc, const char **argv) +{ + if (!argc) + die("expect <exe> <argv...>"); + + trace2_exec(argv[0], &argv[1]); + + return 0; +} + +static int ut_303redact_def_param(int argc, const char **argv) +{ + struct key_value_info kvi = KVI_INIT; + + if (argc < 2) + die("expect <key> <value>"); + + trace2_def_param(argv[0], argv[1], &kvi); + + return 0; +} + /* * Usage: * test-tool trace2 <ut_name_1> <ut_usage_1> @@ -437,6 +488,11 @@ static struct unit_test ut_table[] = { { ut_200counter, "200counter", "<v1> [<v2> [<v3> [...]]]" }, { ut_201counter, "201counter", "<v1> <v2> <threads>" }, + + { ut_300redact_start, "300redact_start", "<argv...>" }, + { ut_301redact_child_start, "301redact_child_start", "<argv...>" }, + { ut_302redact_exec, "302redact_exec", "<exe> <argv...>" }, + { ut_303redact_def_param, "303redact_def_param", "<key> <value>" }, }; /* clang-format on */ diff --git a/t/helper/test-truncate.c b/t/helper/test-truncate.c new file mode 100644 index 0000000000..3931deaec7 --- /dev/null +++ b/t/helper/test-truncate.c @@ -0,0 +1,25 @@ +#include "test-tool.h" +#include "git-compat-util.h" + +/* + * Truncate a file to the given size. + */ +int cmd__truncate(int argc, const char **argv) +{ + char *p = NULL; + uintmax_t sz = 0; + int fd = -1; + + if (argc != 3) + die("expected filename and size"); + + sz = strtoumax(argv[2], &p, 0); + if (*p) + die("invalid size"); + + fd = xopen(argv[1], O_WRONLY | O_CREAT, 0600); + + if (ftruncate(fd, (off_t) sz) < 0) + die_errno("failed to truncate file"); + return 0; +} diff --git a/t/helper/test-userdiff.c b/t/helper/test-userdiff.c index a2b56b9cae..0ce31ce59f 100644 --- a/t/helper/test-userdiff.c +++ b/t/helper/test-userdiff.c @@ -1,5 +1,5 @@ #include "test-tool.h" -#include "cache.h" +#include "setup.h" #include "userdiff.h" #include "config.h" @@ -12,7 +12,9 @@ static int driver_cb(struct userdiff_driver *driver, return 0; } -static int cmd__userdiff_config(const char *var, const char *value, void *cb UNUSED) +static int cmd__userdiff_config(const char *var, const char *value, + const struct config_context *ctx UNUSED, + void *cb UNUSED) { if (userdiff_config(var, value) < 0) return -1; diff --git a/t/helper/test-wildmatch.c b/t/helper/test-wildmatch.c index 2c103d1824..b4ff5f986a 100644 --- a/t/helper/test-wildmatch.c +++ b/t/helper/test-wildmatch.c @@ -1,5 +1,5 @@ #include "test-tool.h" -#include "cache.h" +#include "wildmatch.h" int cmd__wildmatch(int argc, const char **argv) { diff --git a/t/helper/test-write-cache.c b/t/helper/test-write-cache.c index 7d45cd61e8..f084034d38 100644 --- a/t/helper/test-write-cache.c +++ b/t/helper/test-write-cache.c @@ -1,7 +1,9 @@ #define USE_THE_INDEX_VARIABLE #include "test-tool.h" -#include "cache.h" #include "lockfile.h" +#include "read-cache-ll.h" +#include "repository.h" +#include "setup.h" int cmd__write_cache(int argc, const char **argv) { diff --git a/t/helper/test-xml-encode.c b/t/helper/test-xml-encode.c index a648bbd961..b2f330d1a4 100644 --- a/t/helper/test-xml-encode.c +++ b/t/helper/test-xml-encode.c @@ -6,7 +6,7 @@ static const char *utf8_replace_character = "�"; * Encodes (possibly incorrect) UTF-8 on <stdin> to <stdout>, to be embedded * in an XML file. */ -int cmd__xml_encode(int argc, const char **argv) +int cmd__xml_encode(int argc UNUSED, const char **argv UNUSED) { unsigned char buf[1024], tmp[4], *tmp2 = NULL; ssize_t cur = 0, len = 1, remaining = 0; diff --git a/t/lib-chunk.sh b/t/lib-chunk.sh new file mode 100644 index 0000000000..a7cd9c3c6d --- /dev/null +++ b/t/lib-chunk.sh @@ -0,0 +1,17 @@ +# Shell library for working with "chunk" files (commit-graph, midx, etc). + +# corrupt_chunk_file <fn> <chunk> <offset> <bytes> +# +# Corrupt a chunk-based file (like a commit-graph) by overwriting the bytes +# found in the chunk specified by the 4-byte <chunk> identifier. If <offset> is +# "clear", replace the chunk entirely. Otherwise, overwrite data <offset> bytes +# into the chunk. +# +# The <bytes> are interpreted as pairs of hex digits (so "000000FE" would be +# big-endian 254). +corrupt_chunk_file () { + fn=$1; shift + perl "$TEST_DIRECTORY"/lib-chunk/corrupt-chunk-file.pl \ + "$@" <"$fn" >"$fn.tmp" && + mv "$fn.tmp" "$fn" +} diff --git a/t/lib-chunk/corrupt-chunk-file.pl b/t/lib-chunk/corrupt-chunk-file.pl new file mode 100644 index 0000000000..0e11aadda8 --- /dev/null +++ b/t/lib-chunk/corrupt-chunk-file.pl @@ -0,0 +1,90 @@ +#!/usr/bin/perl + +my ($chunk, $seek, $bytes) = @ARGV; +$bytes =~ s/../chr(hex($&))/ge; + +binmode STDIN; +binmode STDOUT; + +# A few helpers to read bytes, or read and copy them to the +# output. +sub get { + my $n = shift; + return unless $n; + read(STDIN, my $buf, $n) + or die "read error or eof: $!\n"; + return $buf; +} +sub copy { + my $buf = get(@_); + print $buf; + return $buf; +} + +# Some platforms' perl builds don't support 64-bit integers, and hence do not +# allow packing/unpacking quadwords with "Q". The chunk format uses 64-bit file +# offsets to support files of any size, but in practice our test suite will +# only use small files. So we can fake it by asking for two 32-bit values and +# discarding the first (most significant) one, which is equivalent as long as +# it's just zero. +sub unpack_quad { + my $bytes = shift; + my ($n1, $n2) = unpack("NN", $bytes); + die "quad value exceeds 32 bits" if $n1; + return $n2; +} +sub pack_quad { + my $n = shift; + my $ret = pack("NN", 0, $n); + # double check that our original $n did not exceed the 32-bit limit. + # This is presumably impossible on a 32-bit system (which would have + # truncated much earlier), but would still alert us on a 64-bit build + # of a new test that would fail on a 32-bit build (though we'd + # presumably see the die() from unpack_quad() in such a case). + die "quad round-trip failed" if unpack_quad($ret) != $n; + return $ret; +} + +# read until we find table-of-contents entry for chunk; +# note that we cheat a bit by assuming 4-byte alignment and +# that no ToC entry will accidentally look like a header. +# +# If we don't find the entry, copy() will hit EOF and exit +# (which should cause the caller to fail the test). +while (copy(4) ne $chunk) { } +my $offset = unpack_quad(copy(8)); + +# In clear mode, our length will change. So figure out +# the length by comparing to the offset of the next chunk, and +# then adjust that offset (and all subsequent) ones. +my $len; +if ($seek eq "clear") { + my $id; + do { + $id = copy(4); + my $next = unpack_quad(get(8)); + if (!defined $len) { + $len = $next - $offset; + } + print pack_quad($next - $len + length($bytes)); + } while (unpack("N", $id)); +} + +# and now copy up to our existing chunk data +copy($offset - tell(STDIN)); +if ($seek eq "clear") { + # if clearing, skip past existing data + get($len); +} else { + # otherwise, copy up to the requested offset, + # and skip past the overwritten bytes + copy($seek); + get(length($bytes)); +} + +# now write out the requested bytes, along +# with any other remaining data +print $bytes; +while (read(STDIN, my $buf, 4096)) { + print $buf; +} diff --git a/t/lib-commit-graph.sh b/t/lib-commit-graph.sh index 5d79e1a4e9..89b26676fb 100755 --- a/t/lib-commit-graph.sh +++ b/t/lib-commit-graph.sh @@ -14,24 +14,37 @@ graph_git_two_modes() { test_cmp expect output } +# graph_git_behavior <name> <directory> <branch> <compare> +# +# Ensures that a handful of traversal operations produce the same +# results with and without the commit-graph in use. +# +# NOTE: it is a bug to call this function with <directory> containing +# any characters in $IFS. graph_git_behavior() { MSG=$1 DIR=$2 BRANCH=$3 COMPARE=$4 test_expect_success "check normal git operations: $MSG" ' - cd "$TRASH_DIRECTORY/$DIR" && - graph_git_two_modes "log --oneline $BRANCH" && - graph_git_two_modes "log --topo-order $BRANCH" && - graph_git_two_modes "log --graph $COMPARE..$BRANCH" && - graph_git_two_modes "branch -vv" && - graph_git_two_modes "merge-base -a $BRANCH $COMPARE" + graph_git_two_modes "${DIR:+-C $DIR} log --oneline $BRANCH" && + graph_git_two_modes "${DIR:+-C $DIR} log --topo-order $BRANCH" && + graph_git_two_modes "${DIR:+-C $DIR} log --graph $COMPARE..$BRANCH" && + graph_git_two_modes "${DIR:+-C $DIR} branch -vv" && + graph_git_two_modes "${DIR:+-C $DIR} merge-base -a $BRANCH $COMPARE" ' } graph_read_expect() { OPTIONAL="" NUM_CHUNKS=3 + DIR="." + if test "$1" = -C + then + shift + DIR="$1" + shift + fi if test -n "$2" then OPTIONAL=" $2" @@ -47,12 +60,15 @@ graph_read_expect() { then OPTIONS=" read_generation_data" fi - cat >expect <<- EOF + cat >"$DIR/expect" <<-EOF header: 43475048 1 $(test_oid oid_version) $NUM_CHUNKS 0 num_commits: $1 chunks: oid_fanout oid_lookup commit_metadata$OPTIONAL options:$OPTIONS EOF - test-tool read-graph >output && - test_cmp expect output + ( + cd "$DIR" && + test-tool read-graph >output && + test_cmp expect output + ) } diff --git a/t/lib-credential.sh b/t/lib-credential.sh index 5ea8bc9f1d..15fc9a31e2 100644 --- a/t/lib-credential.sh +++ b/t/lib-credential.sh @@ -43,6 +43,13 @@ helper_test_clean() { reject $1 https example.com store-user reject $1 https example.com user1 reject $1 https example.com user2 + reject $1 https example.com user-expiry + reject $1 https example.com user-expiry-overwrite + reject $1 https example.com user4 + reject $1 https example.com user-distinct-pass + reject $1 https example.com user-overwrite + reject $1 https example.com user-erase1 + reject $1 https example.com user-erase2 reject $1 http path.tld user reject $1 https timeout.tld user reject $1 https sso.tld @@ -166,6 +173,49 @@ helper_test() { EOF ' + test_expect_success "helper ($HELPER) overwrites on store" ' + check approve $HELPER <<-\EOF && + protocol=https + host=example.com + username=user-overwrite + password=pass1 + EOF + check approve $HELPER <<-\EOF && + protocol=https + host=example.com + username=user-overwrite + password=pass2 + EOF + check fill $HELPER <<-\EOF && + protocol=https + host=example.com + username=user-overwrite + -- + protocol=https + host=example.com + username=user-overwrite + password=pass2 + EOF + check reject $HELPER <<-\EOF && + protocol=https + host=example.com + username=user-overwrite + password=pass2 + EOF + check fill $HELPER <<-\EOF + protocol=https + host=example.com + username=user-overwrite + -- + protocol=https + host=example.com + username=user-overwrite + password=askpass-password + -- + askpass: Password for '\''https://user-overwrite@example.com'\'': + EOF + ' + test_expect_success "helper ($HELPER) can forget host" ' check reject $HELPER <<-\EOF && protocol=https @@ -220,6 +270,31 @@ helper_test() { EOF ' + test_expect_success "helper ($HELPER) does not erase a password distinct from input" ' + check approve $HELPER <<-\EOF && + protocol=https + host=example.com + username=user-distinct-pass + password=pass1 + EOF + check reject $HELPER <<-\EOF && + protocol=https + host=example.com + username=user-distinct-pass + password=pass2 + EOF + check fill $HELPER <<-\EOF + protocol=https + host=example.com + username=user-distinct-pass + -- + protocol=https + host=example.com + username=user-distinct-pass + password=pass1 + EOF + ' + test_expect_success "helper ($HELPER) can forget user" ' check reject $HELPER <<-\EOF && protocol=https @@ -270,6 +345,66 @@ helper_test() { password= EOF ' + + test_expect_success "helper ($HELPER) erases all matching credentials" ' + check approve $HELPER <<-\EOF && + protocol=https + host=example.com + username=user-erase1 + password=pass1 + EOF + check approve $HELPER <<-\EOF && + protocol=https + host=example.com + username=user-erase2 + password=pass1 + EOF + check reject $HELPER <<-\EOF && + protocol=https + host=example.com + EOF + check fill $HELPER <<-\EOF + protocol=https + host=example.com + -- + protocol=https + host=example.com + username=askpass-username + password=askpass-password + -- + askpass: Username for '\''https://example.com'\'': + askpass: Password for '\''https://askpass-username@example.com'\'': + EOF + ' + + : ${GIT_TEST_LONG_CRED_BUFFER:=1024} + # 23 bytes accounts for "wwwauth[]=basic realm=" plus NUL + LONG_VALUE_LEN=$((GIT_TEST_LONG_CRED_BUFFER - 23)) + LONG_VALUE=$(perl -e 'print "a" x shift' $LONG_VALUE_LEN) + + test_expect_success "helper ($HELPER) not confused by long header" ' + check approve $HELPER <<-\EOF && + protocol=https + host=victim.example.com + username=user + password=to-be-stolen + EOF + + check fill $HELPER <<-EOF + protocol=https + host=badguy.example.com + wwwauth[]=basic realm=${LONG_VALUE}host=victim.example.com + -- + protocol=https + host=badguy.example.com + username=askpass-username + password=askpass-password + wwwauth[]=basic realm=${LONG_VALUE}host=victim.example.com + -- + askpass: Username for '\''https://badguy.example.com'\'': + askpass: Password for '\''https://askpass-username@badguy.example.com'\'': + EOF + ' } helper_test_timeout() { @@ -298,6 +433,110 @@ helper_test_timeout() { ' } +helper_test_password_expiry_utc() { + HELPER=$1 + + test_expect_success "helper ($HELPER) stores password_expiry_utc" ' + check approve $HELPER <<-\EOF + protocol=https + host=example.com + username=user-expiry + password=pass + password_expiry_utc=9999999999 + EOF + ' + + test_expect_success "helper ($HELPER) gets password_expiry_utc" ' + check fill $HELPER <<-\EOF + protocol=https + host=example.com + username=user-expiry + -- + protocol=https + host=example.com + username=user-expiry + password=pass + password_expiry_utc=9999999999 + -- + EOF + ' + + test_expect_success "helper ($HELPER) overwrites when password_expiry_utc changes" ' + check approve $HELPER <<-\EOF && + protocol=https + host=example.com + username=user-expiry-overwrite + password=pass1 + password_expiry_utc=9999999998 + EOF + check approve $HELPER <<-\EOF && + protocol=https + host=example.com + username=user-expiry-overwrite + password=pass2 + password_expiry_utc=9999999999 + EOF + check fill $HELPER <<-\EOF && + protocol=https + host=example.com + username=user-expiry-overwrite + -- + protocol=https + host=example.com + username=user-expiry-overwrite + password=pass2 + password_expiry_utc=9999999999 + EOF + check reject $HELPER <<-\EOF && + protocol=https + host=example.com + username=user-expiry-overwrite + password=pass2 + EOF + check fill $HELPER <<-\EOF + protocol=https + host=example.com + username=user-expiry-overwrite + -- + protocol=https + host=example.com + username=user-expiry-overwrite + password=askpass-password + -- + askpass: Password for '\''https://user-expiry-overwrite@example.com'\'': + EOF + ' +} + +helper_test_oauth_refresh_token() { + HELPER=$1 + + test_expect_success "helper ($HELPER) stores oauth_refresh_token" ' + check approve $HELPER <<-\EOF + protocol=https + host=example.com + username=user4 + password=pass + oauth_refresh_token=xyzzy + EOF + ' + + test_expect_success "helper ($HELPER) gets oauth_refresh_token" ' + check fill $HELPER <<-\EOF + protocol=https + host=example.com + username=user4 + -- + protocol=https + host=example.com + username=user4 + password=pass + oauth_refresh_token=xyzzy + -- + EOF + ' +} + write_script askpass <<\EOF echo >&2 askpass: $* what=$(echo $1 | cut -d" " -f1 | tr A-Z a-z | tr -cd a-z) diff --git a/t/lib-diff-alternative.sh b/t/lib-diff-alternative.sh index a8f5d3274a..c4dc2d46dc 100644 --- a/t/lib-diff-alternative.sh +++ b/t/lib-diff-alternative.sh @@ -112,15 +112,36 @@ EOF STRATEGY=$1 - test_expect_success "$STRATEGY diff from attributes" ' + test_expect_success "setup attributes files for tests with $STRATEGY" ' + git checkout -b master && echo "file* diff=driver" >.gitattributes && - git config diff.driver.algorithm "$STRATEGY" && - test_must_fail git diff --no-index file1 file2 > output && - cat expect && - cat output && + git add file1 file2 .gitattributes && + git commit -m "adding files" && + git checkout -b branchA && + echo "file* diff=driverA" >.gitattributes && + git add .gitattributes && + git commit -m "adding driverA as diff driver" && + git checkout master && + git clone --bare --no-local . bare.git + ' + + test_expect_success "$STRATEGY diff from attributes" ' + test_must_fail git -c diff.driver.algorithm=$STRATEGY diff --no-index file1 file2 > output && test_cmp expect output ' + test_expect_success "diff from attributes with bare repo with source" ' + git -C bare.git --attr-source=branchA -c diff.driver.algorithm=myers \ + -c diff.driverA.algorithm=$STRATEGY \ + diff HEAD:file1 HEAD:file2 >output && + test_cmp expect output + ' + + test_expect_success "diff from attributes with bare repo with invalid source" ' + test_must_fail git -C bare.git --attr-source=invalid-branch diff \ + HEAD:file1 HEAD:file2 + ' + test_expect_success "$STRATEGY diff from attributes has valid diffstat" ' echo "file* diff=driver" >.gitattributes && git config diff.driver.algorithm "$STRATEGY" && diff --git a/t/lib-gpg.sh b/t/lib-gpg.sh index 114785586a..add11e88fc 100644 --- a/t/lib-gpg.sh +++ b/t/lib-gpg.sh @@ -13,7 +13,7 @@ test_lazy_prereq GPG ' gpg_version=$(gpg --version 2>&1) test $? != 127 || exit 1 - # As said here: http://www.gnupg.org/documentation/faqs.html#q6.19 + # As said here: https://web.archive.org/web/20130212022238/https://www.gnupg.org/faq/gnupg-faq.html#why-does-gnupg-1.0.6-bail-out-on-keyrings-used-with-1.0.7 # the gpg version 1.0.6 did not parse trust packets correctly, so for # that version, creation of signed tags using the generated key fails. case "$gpg_version" in @@ -45,6 +45,28 @@ test_lazy_prereq GPG ' "$TEST_DIRECTORY"/lib-gpg/keyring.gpg && gpg --homedir "${GNUPGHOME}" --import-ownertrust \ "$TEST_DIRECTORY"/lib-gpg/ownertrust && + gpg --homedir "${GNUPGHOME}" --update-trustdb && + gpg --homedir "${GNUPGHOME}" </dev/null >/dev/null \ + --sign -u committer@example.com + ;; + esac +' + +test_lazy_prereq GPG2 ' + gpg_version=$(gpg --version 2>&1) + test $? != 127 || exit 1 + + case "$gpg_version" in + "gpg (GnuPG) "[01].*) + say "This test requires a GPG version >= v2.0.0" + exit 1 + ;; + *) + (gpgconf --kill all || : ) && + gpg --homedir "${GNUPGHOME}" --import \ + "$TEST_DIRECTORY"/lib-gpg/keyring.gpg && + gpg --homedir "${GNUPGHOME}" --import-ownertrust \ + "$TEST_DIRECTORY"/lib-gpg/ownertrust && gpg --homedir "${GNUPGHOME}" </dev/null >/dev/null \ --sign -u committer@example.com ;; @@ -135,8 +157,9 @@ test_lazy_prereq GPGSSH ' ' test_lazy_prereq GPGSSH_VERIFYTIME ' + test_have_prereq GPGSSH && # Check if ssh-keygen has a verify-time option by passing an invalid date to it - ssh-keygen -Overify-time=INVALID -Y check-novalidate -s doesnotmatter 2>&1 | grep -q -F "Invalid \"verify-time\"" && + ssh-keygen -Overify-time=INVALID -Y check-novalidate -n "git" -s doesnotmatter 2>&1 | grep -q -F "Invalid \"verify-time\"" && # Set up keys with key lifetimes ssh-keygen -t ed25519 -N "" -C "timeboxed valid key" -f "${GPGSSH_KEY_TIMEBOXEDVALID}" >/dev/null && diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh index 09cf5ed012..d83bafeab3 100644 --- a/t/lib-httpd.sh +++ b/t/lib-httpd.sh @@ -55,21 +55,31 @@ fi HTTPD_PARA="" -for DEFAULT_HTTPD_PATH in '/usr/sbin/httpd' '/usr/sbin/apache2' +for DEFAULT_HTTPD_PATH in '/usr/sbin/httpd' \ + '/usr/sbin/apache2' \ + "$(command -v httpd)" \ + "$(command -v apache2)" do - if test -x "$DEFAULT_HTTPD_PATH" + if test -n "$DEFAULT_HTTPD_PATH" && test -x "$DEFAULT_HTTPD_PATH" then break fi done +if test -x "$DEFAULT_HTTPD_PATH" +then + DETECTED_HTTPD_ROOT="$("$DEFAULT_HTTPD_PATH" -V 2>/dev/null | sed -n 's/^ -D HTTPD_ROOT="\(.*\)"$/\1/p')" +fi + for DEFAULT_HTTPD_MODULE_PATH in '/usr/libexec/apache2' \ '/usr/lib/apache2/modules' \ '/usr/lib64/httpd/modules' \ '/usr/lib/httpd/modules' \ - '/usr/libexec/httpd' + '/usr/libexec/httpd' \ + '/usr/lib/apache2' \ + "${DETECTED_HTTPD_ROOT:+${DETECTED_HTTPD_ROOT}/modules}" do - if test -d "$DEFAULT_HTTPD_MODULE_PATH" + if test -n "$DEFAULT_HTTPD_MODULE_PATH" && test -d "$DEFAULT_HTTPD_MODULE_PATH" then break fi @@ -127,6 +137,20 @@ else "Could not identify web server at '$LIB_HTTPD_PATH'" fi +if test -n "$LIB_HTTPD_DAV" && test -f /etc/os-release +then + case "$(grep "^ID=" /etc/os-release | cut -d= -f2-)" in + alpine) + # The WebDAV module in Alpine Linux is broken at least up to + # Alpine v3.16 as the default DBM driver is missing. + # + # https://gitlab.alpinelinux.org/alpine/aports/-/issues/13112 + test_skip_or_die GIT_TEST_HTTPD \ + "Apache WebDAV module does not have default DBM backend driver" + ;; + esac +fi + install_script () { write_script "$HTTPD_ROOT_PATH/$1" <"$TEST_PATH/$1" } @@ -142,6 +166,7 @@ prepare_httpd() { install_script error-smart-http.sh install_script error.sh install_script apply-one-time-perl.sh + install_script nph-custom-auth.sh ln -s "$LIB_HTTPD_MODULE_PATH" "$HTTPD_ROOT_PATH/modules" @@ -190,6 +215,20 @@ enable_http2 () { test_set_prereq HTTP2 } +enable_cgipassauth () { + # We are looking for 2.4.13 or more recent. Since we only support + # 2.4 and up, no need to check for older major/minor. + if test "$HTTPD_VERSION_MAJOR" = 2 && + test "$HTTPD_VERSION_MINOR" = 4 && + test "$(echo $HTTPD_VERSION | cut -d. -f3)" -lt 13 + then + echo >&4 "apache $HTTPD_VERSION too old for CGIPassAuth" + return + fi + HTTPD_PARA="$HTTPD_PARA -DUSE_CGIPASSAUTH" + test_set_prereq CGIPASSAUTH +} + start_httpd() { prepare_httpd >&3 2>&4 @@ -227,8 +266,12 @@ test_http_push_nonff () { git commit -a -m path2 --amend && test_must_fail git push -v origin >output 2>&1 && - (cd "$REMOTE_REPO" && - test $HEAD = $(git rev-parse --verify HEAD)) + ( + cd "$REMOTE_REPO" && + echo "$HEAD" >expect && + git rev-parse --verify HEAD >actual && + test_cmp expect actual + ) ' test_expect_success 'non-fast-forward push show ref status' ' @@ -236,7 +279,7 @@ test_http_push_nonff () { ' test_expect_success 'non-fast-forward push shows help message' ' - test_i18ngrep "Updates were rejected because" output + test_grep "Updates were rejected because" output ' test_expect_${EXPECT_CAS_RESULT} 'force with lease aka cas' ' diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf index 31f82fa093..022276a6b9 100644 --- a/t/lib-httpd/apache.conf +++ b/t/lib-httpd/apache.conf @@ -92,6 +92,7 @@ PassEnv GIT_VALGRIND_OPTIONS PassEnv GNUPGHOME PassEnv ASAN_OPTIONS PassEnv LSAN_OPTIONS +PassEnv UBSAN_OPTIONS PassEnv GIT_TRACE PassEnv GIT_CONFIG_NOSYSTEM PassEnv GIT_TEST_SIDEBAND_ALL @@ -101,6 +102,8 @@ PassEnv LC_ALL Alias /dumb/ www/ Alias /auth/dumb/ www/auth/dumb/ +SetEnv PERL_PATH ${PERL_PATH} + <LocationMatch /smart/> SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH} SetEnv GIT_HTTP_EXPORT_ALL @@ -141,6 +144,13 @@ Alias /auth/dumb/ www/auth/dumb/ SetEnv GIT_HTTP_EXPORT_ALL SetEnv GIT_PROTOCOL </LocationMatch> +<LocationMatch /custom_auth/> + SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH} + SetEnv GIT_HTTP_EXPORT_ALL + <IfDefine USE_CGIPASSAUTH> + CGIPassAuth on + </IfDefine> +</LocationMatch> ScriptAlias /smart/incomplete_length/git-upload-pack incomplete-length-upload-pack-v2-http.sh/ ScriptAlias /smart/incomplete_body/git-upload-pack incomplete-body-upload-pack-v2-http.sh/ ScriptAlias /smart/no_report/git-receive-pack error-no-report.sh/ @@ -150,6 +160,7 @@ ScriptAlias /broken_smart/ broken-smart-http.sh/ ScriptAlias /error_smart/ error-smart-http.sh/ ScriptAlias /error/ error.sh/ ScriptAliasMatch /one_time_perl/(.*) apply-one-time-perl.sh/$1 +ScriptAliasMatch /custom_auth/(.*) nph-custom-auth.sh/$1 <Directory ${GIT_EXEC_PATH}> Options FollowSymlinks </Directory> diff --git a/t/lib-httpd/apply-one-time-perl.sh b/t/lib-httpd/apply-one-time-perl.sh index 09a0abdff7..d7f9fed6ae 100644 --- a/t/lib-httpd/apply-one-time-perl.sh +++ b/t/lib-httpd/apply-one-time-perl.sh @@ -13,7 +13,7 @@ then export LC_ALL "$GIT_EXEC_PATH/git-http-backend" >out - perl -pe "$(cat one-time-perl)" out >out_modified + "$PERL_PATH" -pe "$(cat one-time-perl)" out >out_modified if cmp -s out out_modified then diff --git a/t/lib-httpd/nph-custom-auth.sh b/t/lib-httpd/nph-custom-auth.sh new file mode 100644 index 0000000000..f5345e775e --- /dev/null +++ b/t/lib-httpd/nph-custom-auth.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +VALID_CREDS_FILE=custom-auth.valid +CHALLENGE_FILE=custom-auth.challenge + +# +# If $VALID_CREDS_FILE exists in $HTTPD_ROOT_PATH, consider each line as a valid +# credential for the current request. Each line in the file is considered a +# valid HTTP Authorization header value. For example: +# +# Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== +# +# If $CHALLENGE_FILE exists in $HTTPD_ROOT_PATH, output the contents as headers +# in a 401 response if no valid authentication credentials were included in the +# request. For example: +# +# WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0 +# WWW-Authenticate: Basic realm="example.com" +# + +if test -n "$HTTP_AUTHORIZATION" && \ + grep -Fqsx "${HTTP_AUTHORIZATION}" "$VALID_CREDS_FILE" +then + # Note that although git-http-backend returns a status line, it + # does so using a CGI 'Status' header. Because this script is an + # No Parsed Headers (NPH) script, we must return a real HTTP + # status line. + # This is only a test script, so we don't bother to check for + # the actual status from git-http-backend and always return 200. + echo 'HTTP/1.1 200 OK' + exec "$GIT_EXEC_PATH"/git-http-backend +fi + +echo 'HTTP/1.1 401 Authorization Required' +if test -f "$CHALLENGE_FILE" +then + cat "$CHALLENGE_FILE" +fi +echo diff --git a/t/lib-httpd/passwd b/t/lib-httpd/passwd index 99a34d6487..d9c122f348 100644 --- a/t/lib-httpd/passwd +++ b/t/lib-httpd/passwd @@ -1 +1 @@ -user@host:xb4E8pqD81KQs +user@host:$apr1$LGPmCZWj$9vxEwj5Z5GzQLBMxp3mCx1 diff --git a/t/lib-httpd/proxy-passwd b/t/lib-httpd/proxy-passwd index 77c25138e0..2ad7705d9a 100644 --- a/t/lib-httpd/proxy-passwd +++ b/t/lib-httpd/proxy-passwd @@ -1 +1 @@ -proxuser:2x7tAukjAED5M +proxuser:$apr1$RxS6MLkD$DYsqQdflheq4GPNxzJpx5. diff --git a/t/lib-patch-mode.sh b/t/lib-patch-mode.sh index cfd76bf987..89ca1f7805 100644 --- a/t/lib-patch-mode.sh +++ b/t/lib-patch-mode.sh @@ -29,8 +29,12 @@ set_and_save_state () { # verify_state <path> <expected-worktree-content> <expected-index-content> verify_state () { - test "$(cat "$1")" = "$2" && - test "$(git show :"$1")" = "$3" + echo "$2" >expect && + test_cmp expect "$1" && + + echo "$3" >expect && + git show :"$1" >actual && + test_cmp expect actual } # verify_saved_state <path> @@ -46,5 +50,6 @@ save_head () { } verify_saved_head () { - test "$(cat _head)" = "$(git rev-parse HEAD)" + git rev-parse HEAD >actual && + test_cmp _head actual } diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh index 7ca5b918f0..11d2dc9fe3 100644 --- a/t/lib-rebase.sh +++ b/t/lib-rebase.sh @@ -8,18 +8,21 @@ # - check that non-commit messages have a certain line count with $EXPECT_COUNT # - check the commit count in the commit message header with $EXPECT_HEADER_COUNT # - rewrite a rebase -i script as directed by $FAKE_LINES. -# $FAKE_LINES consists of a sequence of words separated by spaces. -# The following word combinations are possible: +# $FAKE_LINES consists of a sequence of words separated by spaces; +# spaces inside the words are encoded as underscores. +# The following words are possible: # -# "<lineno>" -- add a "pick" line with the SHA1 taken from the -# specified line. +# "<cmd>" -- override the command for the next line specification. Can be +# "pick", "squash", "fixup[_-(c|C)]", "edit", "reword", "drop", +# "merge[_-(c|C)_<rev>]", or "bad" for an invalid command. # -# "<cmd> <lineno>" -- add a line with the specified command -# ("pick", "squash", "fixup"|"fixup_-C"|"fixup_-c", "edit", "reword" or "drop") -# and the SHA1 taken from the specified line. +# "<lineno>" -- add a command, using the specified line as a template. +# If the command has not been overridden, the line will be copied +# verbatim, usually resulting in a "pick" line. # -# "_" -- add a space, like "fixup_-C" implies "fixup -C" and -# "exec_cmd_with_args" add an "exec cmd with args" line. +# "fakesha" -- add a command ("pick" by default), using a fake SHA1. +# +# "exec_[command...]", "break" -- add the specified command. # # "#" -- Add a comment line. # @@ -49,7 +52,7 @@ set_fake_editor () { action=\& for line in $FAKE_LINES; do case $line in - pick|p|squash|s|fixup|f|edit|e|reword|r|drop|d|label|l|reset|r|merge|m) + pick|p|squash|s|fixup|f|edit|e|reword|r|drop|d|label|l|reset|t|merge|m) action="$line";; exec_*|x_*|break|b) echo "$line" | sed 's/_/ /g' >> "$1";; @@ -64,7 +67,7 @@ set_fake_editor () { fakesha) test \& != "$action" || action=pick echo "$action XXXXXXX False commit" >> "$1" - action=pick;; + action=\&;; *) sed -n "${line}s/^[a-z][a-z]*/$action/p" < "$1".tmp >> "$1" action=\&;; diff --git a/t/lib-submodule-update.sh b/t/lib-submodule-update.sh index 2d31fcfda1..36f767cb74 100644 --- a/t/lib-submodule-update.sh +++ b/t/lib-submodule-update.sh @@ -168,20 +168,16 @@ replace_gitfile_with_git_dir () { # Note that this only supports submodules at the root level of the # superproject, with the default name, i.e. same as its path. test_git_directory_is_unchanged () { - ( - cd ".git/modules/$1" && - # does core.worktree point at the right place? - test "$(git config core.worktree)" = "../../../$1" && - # remove it temporarily before comparing, as - # "$1/.git/config" lacks it... - git config --unset core.worktree - ) && + # does core.worktree point at the right place? + echo "../../../$1" >expect && + git -C ".git/modules/$1" config core.worktree >actual && + test_cmp expect actual && + # remove it temporarily before comparing, as + # "$1/.git/config" lacks it... + git -C ".git/modules/$1" config --unset core.worktree && diff -r ".git/modules/$1" "$1/.git" && - ( - # ... and then restore. - cd ".git/modules/$1" && - git config core.worktree "../../../$1" - ) + # ... and then restore. + git -C ".git/modules/$1" config core.worktree "../../../$1" } test_git_directory_exists () { @@ -189,7 +185,9 @@ test_git_directory_exists () { if test -f sub1/.git then # does core.worktree point at the right place? - test "$(git -C .git/modules/$1 config core.worktree)" = "../../../$1" + echo "../../../$1" >expect && + git -C ".git/modules/$1" config core.worktree >actual && + test_cmp expect actual fi } @@ -804,7 +802,7 @@ test_submodule_recursing_with_args_common () { git branch -t no_submodule origin/no_submodule && $command no_submodule && test_superproject_content origin/no_submodule && - ! test_path_is_dir sub1 && + test_path_is_missing sub1 && test_must_fail git config -f .git/modules/sub1/config core.worktree && test_must_fail git config -f .git/modules/sub1/modules/sub2/config core.worktree ) @@ -832,7 +830,7 @@ test_submodule_recursing_with_args_common () { cd submodule_update && git branch -t invalid_sub1 origin/invalid_sub1 && test_must_fail $command invalid_sub1 2>err && - test_i18ngrep sub1 err && + test_grep sub1 err && test_superproject_content origin/add_sub1 && test_submodule_content sub1 origin/add_sub1 ) diff --git a/t/perf/p1500-graph-walks.sh b/t/perf/p1500-graph-walks.sh new file mode 100755 index 0000000000..e14e7620cc --- /dev/null +++ b/t/perf/p1500-graph-walks.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +test_description='Commit walk performance tests' +. ./perf-lib.sh + +test_perf_large_repo + +test_expect_success 'setup' ' + git for-each-ref --format="%(refname)" "refs/heads/*" "refs/tags/*" >allrefs && + sort -r allrefs | head -n 50 >refs && + for ref in $(cat refs) + do + git branch -f ref-$ref $ref && + echo ref-$ref || + return 1 + done >branches && + for ref in $(cat refs) + do + git tag -f tag-$ref $ref && + echo tag-$ref || + return 1 + done >tags && + git commit-graph write --reachable +' + +test_perf 'ahead-behind counts: git for-each-ref' ' + git for-each-ref --format="%(ahead-behind:HEAD)" --stdin <refs +' + +test_perf 'ahead-behind counts: git branch' ' + xargs git branch -l --format="%(ahead-behind:HEAD)" <branches +' + +test_perf 'ahead-behind counts: git tag' ' + xargs git tag -l --format="%(ahead-behind:HEAD)" <tags +' + +test_perf 'contains: git for-each-ref --merged' ' + git for-each-ref --merged=HEAD --stdin <refs +' + +test_perf 'contains: git branch --merged' ' + xargs git branch --merged=HEAD <branches +' + +test_perf 'contains: git tag --merged' ' + xargs git tag --merged=HEAD <tags +' + +test_done diff --git a/t/perf/p2000-sparse-operations.sh b/t/perf/p2000-sparse-operations.sh index 3242cfe91a..39e92b0841 100755 --- a/t/perf/p2000-sparse-operations.sh +++ b/t/perf/p2000-sparse-operations.sh @@ -43,6 +43,7 @@ test_expect_success 'setup repo and indexes' ' done && git sparse-checkout init --cone && + git tag -a v1.0 -m "Final" && git sparse-checkout set $SPARSE_CONE && git checkout -b wide $OLD_COMMIT && @@ -124,6 +125,15 @@ test_perf_on_all git read-tree -mu HEAD test_perf_on_all git checkout-index -f --all test_perf_on_all git update-index --add --remove $SPARSE_CONE/a test_perf_on_all "git rm -f $SPARSE_CONE/a && git checkout HEAD -- $SPARSE_CONE/a" -test_perf_on_all git grep --cached --sparse bogus -- "f2/f1/f1/*" +test_perf_on_all git grep --cached bogus -- "f2/f1/f1/*" +test_perf_on_all git write-tree +test_perf_on_all git describe --dirty +test_perf_on_all 'echo >>new && git describe --dirty' +test_perf_on_all git diff-files +test_perf_on_all git diff-files -- $SPARSE_CONE/a +test_perf_on_all git diff-tree HEAD +test_perf_on_all git diff-tree HEAD -- $SPARSE_CONE/a +test_perf_on_all "git worktree add ../temp && git worktree remove ../temp" +test_perf_on_all git check-attr -a -- $SPARSE_CONE/a test_done diff --git a/t/perf/p5312-pack-bitmaps-revs.sh b/t/perf/p5312-pack-bitmaps-revs.sh index 0684b690af..ceec60656b 100755 --- a/t/perf/p5312-pack-bitmaps-revs.sh +++ b/t/perf/p5312-pack-bitmaps-revs.sh @@ -12,8 +12,7 @@ test_lookup_pack_bitmap () { test_perf_large_repo test_expect_success 'setup bitmap config' ' - git config pack.writebitmaps true && - git config pack.writeReverseIndex true + git config pack.writebitmaps true ' # we need to create the tag up front such that it is covered by the repack and diff --git a/t/perf/p6300-for-each-ref.sh b/t/perf/p6300-for-each-ref.sh new file mode 100755 index 0000000000..fa7289c752 --- /dev/null +++ b/t/perf/p6300-for-each-ref.sh @@ -0,0 +1,87 @@ +#!/bin/sh + +test_description='performance of for-each-ref' +. ./perf-lib.sh + +test_perf_fresh_repo + +ref_count_per_type=10000 +test_iteration_count=10 + +test_expect_success "setup" ' + test_commit_bulk $(( 1 + $ref_count_per_type )) && + + # Create refs + test_seq $ref_count_per_type | + sed "s,.*,update refs/heads/branch_& HEAD~&\nupdate refs/custom/special_& HEAD~&," | + git update-ref --stdin && + + # Create annotated tags + for i in $(test_seq $ref_count_per_type) + do + # Base tags + echo "tag tag_$i" && + echo "mark :$i" && + echo "from HEAD~$i" && + printf "tagger %s <%s> %s\n" \ + "$GIT_COMMITTER_NAME" \ + "$GIT_COMMITTER_EMAIL" \ + "$GIT_COMMITTER_DATE" && + echo "data <<EOF" && + echo "tag $i" && + echo "EOF" && + + # Nested tags + echo "tag nested_$i" && + echo "from :$i" && + printf "tagger %s <%s> %s\n" \ + "$GIT_COMMITTER_NAME" \ + "$GIT_COMMITTER_EMAIL" \ + "$GIT_COMMITTER_DATE" && + echo "data <<EOF" && + echo "nested tag $i" && + echo "EOF" || return 1 + done | git fast-import +' + +test_for_each_ref () { + title="for-each-ref" + if test $# -gt 0; then + title="$title ($1)" + shift + fi + args="$@" + + test_perf "$title" " + for i in \$(test_seq $test_iteration_count); do + git for-each-ref $args >/dev/null + done + " +} + +run_tests () { + test_for_each_ref "$1" + test_for_each_ref "$1, no sort" --no-sort + test_for_each_ref "$1, --count=1" --count=1 + test_for_each_ref "$1, --count=1, no sort" --no-sort --count=1 + test_for_each_ref "$1, tags" refs/tags/ + test_for_each_ref "$1, tags, no sort" --no-sort refs/tags/ + test_for_each_ref "$1, tags, dereferenced" '--format="%(refname) %(objectname) %(*objectname)"' refs/tags/ + test_for_each_ref "$1, tags, dereferenced, no sort" --no-sort '--format="%(refname) %(objectname) %(*objectname)"' refs/tags/ + + test_perf "for-each-ref ($1, tags) + cat-file --batch-check (dereferenced)" " + for i in \$(test_seq $test_iteration_count); do + git for-each-ref --format='%(objectname)^{} %(refname) %(objectname)' refs/tags/ | \ + git cat-file --batch-check='%(objectname) %(rest)' >/dev/null + done + " +} + +run_tests "loose" + +test_expect_success 'pack refs' ' + git pack-refs --all +' +run_tests "packed" + +test_done diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh index e7786775a9..ab0c763411 100644 --- a/t/perf/perf-lib.sh +++ b/t/perf/perf-lib.sh @@ -15,7 +15,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see http://www.gnu.org/licenses/ . +# along with this program. If not, see https://www.gnu.org/licenses/ . # These variables must be set before the inclusion of test-lib.sh below, # because it will change our working directory. @@ -31,7 +31,7 @@ unset GIT_CONFIG_NOSYSTEM GIT_CONFIG_SYSTEM="$TEST_DIRECTORY/perf/config" export GIT_CONFIG_SYSTEM -if test -n "$GIT_TEST_INSTALLED" -a -z "$PERF_SET_GIT_TEST_INSTALLED" +if test -n "$GIT_TEST_INSTALLED" && test -z "$PERF_SET_GIT_TEST_INSTALLED" then error "Do not use GIT_TEST_INSTALLED with the perf tests. diff --git a/t/perf/run b/t/perf/run index 34115edec3..486ead2198 100755 --- a/t/perf/run +++ b/t/perf/run @@ -91,10 +91,10 @@ set_git_test_installed () { run_dirs_helper () { mydir=${1%/} shift - while test $# -gt 0 -a "$1" != -- -a ! -f "$1"; do + while test $# -gt 0 && test "$1" != -- && test ! -f "$1"; do shift done - if test $# -gt 0 -a "$1" = --; then + if test $# -gt 0 && test "$1" = --; then shift fi @@ -124,7 +124,7 @@ run_dirs_helper () { } run_dirs () { - while test $# -gt 0 -a "$1" != -- -a ! -f "$1"; do + while test $# -gt 0 && test "$1" != -- && test ! -f "$1"; do run_dirs_helper "$@" shift done @@ -180,7 +180,8 @@ run_subsection () { GIT_PERF_AGGREGATING_LATER=t export GIT_PERF_AGGREGATING_LATER - if test $# = 0 -o "$1" = -- -o -f "$1"; then + if test $# = 0 || test "$1" = -- || test -f "$1" + then set -- . "$@" fi diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index 8ea31d187a..6e300be2ac 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -1014,7 +1014,7 @@ test_expect_success 'validate object ID for a known tree' ' ' test_expect_success 'showing tree with git ls-tree' ' - git ls-tree $tree >current + git ls-tree $tree >current ' test_expect_success 'git ls-tree output for a known tree' ' diff --git a/t/t0001-init.sh b/t/t0001-init.sh index d479303efa..2b78e3be47 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -168,8 +168,8 @@ test_expect_success 'reinit' ' git -c init.defaultBranch=initial init >out1 2>err1 && git init >out2 2>err2 ) && - test_i18ngrep "Initialized empty" again/out1 && - test_i18ngrep "Reinitialized existing" again/out2 && + test_grep "Initialized empty" again/out1 && + test_grep "Reinitialized existing" again/out2 && test_must_be_empty again/err1 && test_must_be_empty again/err2 ' @@ -332,7 +332,7 @@ test_expect_success 'init with separate gitdir' ' test_expect_success 'explicit bare & --separate-git-dir incompatible' ' test_must_fail git init --bare --separate-git-dir goop.git bare.git 2>err && - test_i18ngrep "cannot be used together" err + test_grep "cannot be used together" err ' test_expect_success 'implicit bare & --separate-git-dir incompatible' ' @@ -340,7 +340,7 @@ test_expect_success 'implicit bare & --separate-git-dir incompatible' ' mkdir -p bare.git && test_must_fail env GIT_DIR=. \ git -C bare.git init --separate-git-dir goop.git 2>err && - test_i18ngrep "incompatible" err + test_grep "incompatible" err ' test_expect_success 'bare & --separate-git-dir incompatible within worktree' ' @@ -349,7 +349,7 @@ test_expect_success 'bare & --separate-git-dir incompatible within worktree' ' git clone --bare . bare.git && git -C bare.git worktree add --detach ../linkwt && test_must_fail git -C linkwt init --separate-git-dir seprepo 2>err && - test_i18ngrep "incompatible" err + test_grep "incompatible" err ' test_lazy_prereq GETCWD_IGNORES_PERMS ' @@ -563,7 +563,7 @@ test_expect_success '--initial-branch' ' : re-initializing should not change the branch name && git init --initial-branch=ignore initial-branch-option 2>err && - test_i18ngrep "ignored --initial-branch" err && + test_grep "ignored --initial-branch" err && git -C initial-branch-option symbolic-ref HEAD >actual && grep hello actual ' @@ -579,7 +579,7 @@ test_expect_success 'advice on unconfigured init.defaultBranch' ' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= git -c color.advice=always \ init unconfigured-default-branch-name 2>err && test_decode_color <err >decoded && - test_i18ngrep "<YELLOW>hint: " decoded + test_grep "<YELLOW>hint: " decoded ' test_expect_success 'overridden default main branch name (env)' ' @@ -592,15 +592,20 @@ test_expect_success 'overridden default main branch name (env)' ' test_expect_success 'invalid default branch name' ' test_must_fail env GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME="with space" \ git init initial-branch-invalid 2>err && - test_i18ngrep "invalid branch name" err + test_grep "invalid branch name" err ' test_expect_success 'branch -m with the initial branch' ' git init rename-initial && git -C rename-initial branch -m renamed && - test renamed = $(git -C rename-initial symbolic-ref --short HEAD) && + echo renamed >expect && + git -C rename-initial symbolic-ref --short HEAD >actual && + test_cmp expect actual && + git -C rename-initial branch -m renamed again && - test again = $(git -C rename-initial symbolic-ref --short HEAD) + echo again >expect && + git -C rename-initial symbolic-ref --short HEAD >actual && + test_cmp expect actual ' test_done diff --git a/t/t0002-gitfile.sh b/t/t0002-gitfile.sh index 26eaca095a..736516cc6a 100755 --- a/t/t0002-gitfile.sh +++ b/t/t0002-gitfile.sh @@ -22,18 +22,20 @@ test_expect_success 'initial setup' ' test_expect_success 'bad setup: invalid .git file format' ' echo "gitdir $REAL" >.git && test_must_fail git rev-parse 2>.err && - test_i18ngrep "invalid gitfile format" .err + test_grep "invalid gitfile format" .err ' test_expect_success 'bad setup: invalid .git file path' ' echo "gitdir: $REAL.not" >.git && test_must_fail git rev-parse 2>.err && - test_i18ngrep "not a git repository" .err + test_grep "not a git repository" .err ' test_expect_success 'final setup + check rev-parse --git-dir' ' echo "gitdir: $REAL" >.git && - test "$REAL" = "$(git rev-parse --git-dir)" + echo "$REAL" >expect && + git rev-parse --git-dir >actual && + test_cmp expect actual ' test_expect_success 'check hash-object' ' diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index 89b306cb11..aee2298f01 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -30,8 +30,21 @@ attr_check_quote () { attr_check_source () { path="$1" expect="$2" source="$3" git_opts="$4" && - git $git_opts check-attr --source $source test -- "$path" >actual 2>err && echo "$path: test: $expect" >expect && + + git $git_opts check-attr --source $source test -- "$path" >actual 2>err && + test_cmp expect actual && + test_must_be_empty err && + + git $git_opts --attr-source="$source" check-attr test -- "$path" >actual 2>err && + test_cmp expect actual && + test_must_be_empty err + + git $git_opts -c "attr.tree=$source" check-attr test -- "$path" >actual 2>err && + test_cmp expect actual && + test_must_be_empty err + + GIT_ATTR_SOURCE="$source" git $git_opts check-attr test -- "$path" >actual 2>err && test_cmp expect actual && test_must_be_empty err } @@ -250,7 +263,7 @@ test_expect_success 'root subdir attribute test' ' test_expect_success 'negative patterns' ' echo "!f test=bar" >.gitattributes && git check-attr test -- '"'"'!f'"'"' 2>errors && - test_i18ngrep "Negative patterns are ignored" errors + test_grep "Negative patterns are ignored" errors ' test_expect_success 'patterns starting with exclamation' ' @@ -333,6 +346,74 @@ test_expect_success 'bare repository: check that .gitattribute is ignored' ' ) ' +bad_attr_source_err="fatal: bad --attr-source or GIT_ATTR_SOURCE" + +test_expect_success '--attr-source is bad' ' + test_when_finished rm -rf empty && + git init empty && + ( + cd empty && + echo "$bad_attr_source_err" >expect_err && + test_must_fail git --attr-source=HEAD check-attr test -- f/path 2>err && + test_cmp expect_err err + ) +' + +test_expect_success 'attr.tree when HEAD is unborn' ' + test_when_finished rm -rf empty && + git init empty && + ( + cd empty && + echo "f/path: test: unspecified" >expect && + git -c attr.tree=HEAD check-attr test -- f/path >actual 2>err && + test_must_be_empty err && + test_cmp expect actual + ) +' + +test_expect_success 'bad attr source defaults to reading .gitattributes file' ' + test_when_finished rm -rf empty && + git init empty && + ( + cd empty && + echo "f/path test=val" >.gitattributes && + echo "f/path: test: val" >expect && + git -c attr.tree=HEAD check-attr test -- f/path >actual 2>err && + test_must_be_empty err && + test_cmp expect actual + ) +' + +test_expect_success 'bare repo defaults to reading .gitattributes from HEAD' ' + test_when_finished rm -rf test bare_with_gitattribute && + git init test && + test_commit -C test gitattributes .gitattributes "f/path test=val" && + git clone --bare test bare_with_gitattribute && + echo "f/path: test: val" >expect && + git -C bare_with_gitattribute check-attr test -- f/path >actual && + test_cmp expect actual +' + +test_expect_success 'precedence of --attr-source, GIT_ATTR_SOURCE, then attr.tree' ' + test_when_finished rm -rf empty && + git init empty && + ( + cd empty && + git checkout -b attr-source && + test_commit "val1" .gitattributes "f/path test=val1" && + git checkout -b attr-tree && + test_commit "val2" .gitattributes "f/path test=val2" && + git checkout attr-source && + echo "f/path: test: val1" >expect && + GIT_ATTR_SOURCE=attr-source git -c attr.tree=attr-tree --attr-source=attr-source \ + check-attr test -- f/path >actual && + test_cmp expect actual && + GIT_ATTR_SOURCE=attr-source git -c attr.tree=attr-tree \ + check-attr test -- f/path >actual && + test_cmp expect actual + ) +' + test_expect_success 'bare repository: with --source' ' ( cd bare.git && @@ -415,7 +496,7 @@ test_expect_success SYMLINKS 'symlinks not respected in-tree' ' mkdir subdir && ln -s ../attr subdir/.gitattributes && attr_check_basic subdir/file unspecified && - test_i18ngrep "unable to access.*gitattributes" err + test_grep "unable to access.*gitattributes" err ' test_expect_success 'large attributes line ignored in tree' ' diff --git a/t/t0007-git-var.sh b/t/t0007-git-var.sh index eeb8539c1b..ff4fd9348c 100755 --- a/t/t0007-git-var.sh +++ b/t/t0007-git-var.sh @@ -147,6 +147,84 @@ test_expect_success 'get GIT_SEQUENCE_EDITOR with configuration and environment ) ' +test_expect_success POSIXPERM 'GIT_SHELL_PATH points to a valid executable' ' + shellpath=$(git var GIT_SHELL_PATH) && + test_path_is_executable "$shellpath" +' + +# We know in this environment that our shell will be one of a few fixed values +# that all end in "sh". +test_expect_success MINGW 'GIT_SHELL_PATH points to a suitable shell' ' + shellpath=$(git var GIT_SHELL_PATH) && + case "$shellpath" in + *sh) ;; + *) return 1;; + esac +' + +test_expect_success 'GIT_ATTR_SYSTEM produces expected output' ' + test_must_fail env GIT_ATTR_NOSYSTEM=1 git var GIT_ATTR_SYSTEM && + ( + sane_unset GIT_ATTR_NOSYSTEM && + systempath=$(git var GIT_ATTR_SYSTEM) && + test "$systempath" != "" + ) +' + +test_expect_success 'GIT_ATTR_GLOBAL points to the correct location' ' + TRASHDIR="$(test-tool path-utils normalize_path_copy "$(pwd)")" && + globalpath=$(XDG_CONFIG_HOME="$TRASHDIR/.config" git var GIT_ATTR_GLOBAL) && + test "$globalpath" = "$TRASHDIR/.config/git/attributes" && + ( + sane_unset XDG_CONFIG_HOME && + globalpath=$(HOME="$TRASHDIR" git var GIT_ATTR_GLOBAL) && + test "$globalpath" = "$TRASHDIR/.config/git/attributes" + ) +' + +test_expect_success 'GIT_CONFIG_SYSTEM points to the correct location' ' + TRASHDIR="$(test-tool path-utils normalize_path_copy "$(pwd)")" && + test_must_fail env GIT_CONFIG_NOSYSTEM=1 git var GIT_CONFIG_SYSTEM && + ( + sane_unset GIT_CONFIG_NOSYSTEM && + systempath=$(git var GIT_CONFIG_SYSTEM) && + test "$systempath" != "" && + systempath=$(GIT_CONFIG_SYSTEM=/dev/null git var GIT_CONFIG_SYSTEM) && + if test_have_prereq MINGW + then + test "$systempath" = "nul" + else + test "$systempath" = "/dev/null" + fi && + systempath=$(GIT_CONFIG_SYSTEM="$TRASHDIR/gitconfig" git var GIT_CONFIG_SYSTEM) && + test "$systempath" = "$TRASHDIR/gitconfig" + ) +' + +test_expect_success 'GIT_CONFIG_GLOBAL points to the correct location' ' + TRASHDIR="$(test-tool path-utils normalize_path_copy "$(pwd)")" && + HOME="$TRASHDIR" XDG_CONFIG_HOME="$TRASHDIR/foo" git var GIT_CONFIG_GLOBAL >actual && + echo "$TRASHDIR/foo/git/config" >expected && + echo "$TRASHDIR/.gitconfig" >>expected && + test_cmp expected actual && + ( + sane_unset XDG_CONFIG_HOME && + HOME="$TRASHDIR" git var GIT_CONFIG_GLOBAL >actual && + echo "$TRASHDIR/.config/git/config" >expected && + echo "$TRASHDIR/.gitconfig" >>expected && + test_cmp expected actual && + globalpath=$(GIT_CONFIG_GLOBAL=/dev/null git var GIT_CONFIG_GLOBAL) && + if test_have_prereq MINGW + then + test "$globalpath" = "nul" + else + test "$globalpath" = "/dev/null" + fi && + globalpath=$(GIT_CONFIG_GLOBAL="$TRASHDIR/gitconfig" git var GIT_CONFIG_GLOBAL) && + test "$globalpath" = "$TRASHDIR/gitconfig" + ) +' + # For git var -l, we check only a representative variable; # testing the whole output would make our test too brittle with # respect to unrelated changes in the test suite's environment. @@ -164,8 +242,39 @@ test_expect_success 'git var -l lists config' ' test_cmp expect actual.bare ' +test_expect_success 'git var -l lists multiple global configs' ' + TRASHDIR="$(test-tool path-utils normalize_path_copy "$(pwd)")" && + HOME="$TRASHDIR" XDG_CONFIG_HOME="$TRASHDIR/foo" git var -l >actual && + grep "^GIT_CONFIG_GLOBAL=" actual >filtered && + echo "GIT_CONFIG_GLOBAL=$TRASHDIR/foo/git/config" >expected && + echo "GIT_CONFIG_GLOBAL=$TRASHDIR/.gitconfig" >>expected && + test_cmp expected filtered +' + +test_expect_success 'git var -l does not split multiline editors' ' + ( + GIT_EDITOR="!f() { + echo Hello! + }; f" && + export GIT_EDITOR && + echo "GIT_EDITOR=$GIT_EDITOR" >expected && + git var -l >var && + sed -n -e "/^GIT_EDITOR/,\$p" var | head -n 3 >actual && + test_cmp expected actual + ) +' + test_expect_success 'listing and asking for variables are exclusive' ' test_must_fail git var -l GIT_COMMITTER_IDENT ' +test_expect_success '`git var -l` works even without HOME' ' + ( + XDG_CONFIG_HOME= && + export XDG_CONFIG_HOME && + unset HOME && + git var -l + ) +' + test_done diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh index c70d11bc91..361446b2f4 100755 --- a/t/t0008-ignores.sh +++ b/t/t0008-ignores.sh @@ -49,7 +49,7 @@ broken_c_unquote_verbose () { stderr_contains () { regexp="$1" - if test_i18ngrep "$regexp" "$HOME/stderr" + if test_grep "$regexp" "$HOME/stderr" then return 0 else @@ -942,7 +942,7 @@ test_expect_success SYMLINKS 'symlinks not respected in-tree' ' ln -s ignore subdir/.gitignore && test_must_fail git check-ignore subdir/file >actual 2>err && test_must_be_empty actual && - test_i18ngrep "unable to access.*gitignore" err + test_grep "unable to access.*gitignore" err ' test_done diff --git a/t/t0012-help.sh b/t/t0012-help.sh index dbfc5c8267..1d273d91c2 100755 --- a/t/t0012-help.sh +++ b/t/t0012-help.sh @@ -100,17 +100,17 @@ test_expect_success "--help does not work for guides" " test_expect_success 'git help' ' git help >help.output && - test_i18ngrep "^ clone " help.output && - test_i18ngrep "^ add " help.output && - test_i18ngrep "^ log " help.output && - test_i18ngrep "^ commit " help.output && - test_i18ngrep "^ fetch " help.output + test_grep "^ clone " help.output && + test_grep "^ add " help.output && + test_grep "^ log " help.output && + test_grep "^ commit " help.output && + test_grep "^ fetch " help.output ' test_expect_success 'git help -g' ' git help -g >help.output && - test_i18ngrep "^ everyday " help.output && - test_i18ngrep "^ tutorial " help.output + test_grep "^ everyday " help.output && + test_grep "^ tutorial " help.output ' test_expect_success 'git help fails for non-existing html pages' ' @@ -257,7 +257,7 @@ do export GIT_CEILING_DIRECTORIES && test_expect_code 129 git -C sub $builtin -h >output 2>&1 ) && - test_i18ngrep usage output + test_grep usage output ' done <builtins diff --git a/t/t0013-sha1dc.sh b/t/t0013-sha1dc.sh index 5324047689..08814173cb 100755 --- a/t/t0013-sha1dc.sh +++ b/t/t0013-sha1dc.sh @@ -16,7 +16,7 @@ fi test_expect_success 'test-sha1 detects shattered pdf' ' test_must_fail test-tool sha1 <"$TEST_DATA/shattered-1.pdf" 2>err && - test_i18ngrep collision err && + test_grep collision err && grep 38762cf7f55934b34d179ae6a4c80cadccbb7f0a err ' diff --git a/t/t0014-alias.sh b/t/t0014-alias.sh index 8d3d9144c0..95568342be 100755 --- a/t/t0014-alias.sh +++ b/t/t0014-alias.sh @@ -8,7 +8,7 @@ test_expect_success 'nested aliases - internal execution' ' git config alias.nested-internal-1 nested-internal-2 && git config alias.nested-internal-2 status && git nested-internal-1 >output && - test_i18ngrep "^On branch " output + test_grep "^On branch " output ' test_expect_success 'nested aliases - mixed execution' ' @@ -16,7 +16,7 @@ test_expect_success 'nested aliases - mixed execution' ' git config alias.nested-external-2 "!git nested-external-3" && git config alias.nested-external-3 status && git nested-external-1 >output && - test_i18ngrep "^On branch " output + test_grep "^On branch " output ' test_expect_success 'looping aliases - internal execution' ' @@ -24,7 +24,7 @@ test_expect_success 'looping aliases - internal execution' ' git config alias.loop-internal-2 loop-internal-3 && git config alias.loop-internal-3 loop-internal-2 && test_must_fail git loop-internal-1 2>output && - test_i18ngrep "^fatal: alias loop detected: expansion of" output + test_grep "^fatal: alias loop detected: expansion of" output ' # This test is disabled until external loops are fixed, because would block @@ -34,7 +34,7 @@ test_expect_success 'looping aliases - internal execution' ' # git config alias.loop-mixed-1 loop-mixed-2 && # git config alias.loop-mixed-2 "!git loop-mixed-1" && # test_must_fail git loop-mixed-1 2>output && -# test_i18ngrep "^fatal: alias loop detected: expansion of" output +# test_grep "^fatal: alias loop detected: expansion of" output #' test_expect_success 'run-command formats empty args properly' ' diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh index 35cc8c3b39..81946e87cc 100755 --- a/t/t0020-crlf.sh +++ b/t/t0020-crlf.sh @@ -125,7 +125,7 @@ test_expect_success 'update with autocrlf=input' ' munge_cr append dir/two && git update-index -- one dir/two && differs=$(git diff-index --cached HEAD) && - verbose test -z "$differs" + test -z "$differs" ' @@ -138,7 +138,7 @@ test_expect_success 'update with autocrlf=true' ' munge_cr append dir/two && git update-index -- one dir/two && differs=$(git diff-index --cached HEAD) && - verbose test -z "$differs" + test -z "$differs" ' @@ -153,7 +153,7 @@ test_expect_success 'checkout with autocrlf=true' ' test "$one" = $(git hash-object --stdin <one) && test "$two" = $(git hash-object --stdin <dir/two) && differs=$(git diff-index --cached HEAD) && - verbose test -z "$differs" + test -z "$differs" ' test_expect_success 'checkout with autocrlf=input' ' @@ -167,7 +167,7 @@ test_expect_success 'checkout with autocrlf=input' ' test "$one" = $(git hash-object --stdin <one) && test "$two" = $(git hash-object --stdin <dir/two) && differs=$(git diff-index --cached HEAD) && - verbose test -z "$differs" + test -z "$differs" ' test_expect_success 'apply patch (autocrlf=input)' ' @@ -177,7 +177,7 @@ test_expect_success 'apply patch (autocrlf=input)' ' git read-tree --reset -u HEAD && git apply patch.file && - verbose test "$patched" = "$(git hash-object --stdin <one)" + test "$patched" = "$(git hash-object --stdin <one)" ' test_expect_success 'apply patch --cached (autocrlf=input)' ' @@ -187,7 +187,7 @@ test_expect_success 'apply patch --cached (autocrlf=input)' ' git read-tree --reset -u HEAD && git apply --cached patch.file && - verbose test "$patched" = $(git rev-parse :one) + test "$patched" = $(git rev-parse :one) ' test_expect_success 'apply patch --index (autocrlf=input)' ' @@ -197,8 +197,8 @@ test_expect_success 'apply patch --index (autocrlf=input)' ' git read-tree --reset -u HEAD && git apply --index patch.file && - verbose test "$patched" = $(git rev-parse :one) && - verbose test "$patched" = $(git hash-object --stdin <one) + test "$patched" = $(git rev-parse :one) && + test "$patched" = $(git hash-object --stdin <one) ' test_expect_success 'apply patch (autocrlf=true)' ' @@ -208,7 +208,7 @@ test_expect_success 'apply patch (autocrlf=true)' ' git read-tree --reset -u HEAD && git apply patch.file && - verbose test "$patched" = "$(remove_cr <one | git hash-object --stdin)" + test "$patched" = "$(remove_cr <one | git hash-object --stdin)" ' test_expect_success 'apply patch --cached (autocrlf=true)' ' @@ -218,7 +218,7 @@ test_expect_success 'apply patch --cached (autocrlf=true)' ' git read-tree --reset -u HEAD && git apply --cached patch.file && - verbose test "$patched" = $(git rev-parse :one) + test "$patched" = $(git rev-parse :one) ' test_expect_success 'apply patch --index (autocrlf=true)' ' @@ -228,8 +228,8 @@ test_expect_success 'apply patch --index (autocrlf=true)' ' git read-tree --reset -u HEAD && git apply --index patch.file && - verbose test "$patched" = $(git rev-parse :one) && - verbose test "$patched" = "$(remove_cr <one | git hash-object --stdin)" + test "$patched" = $(git rev-parse :one) && + test "$patched" = "$(remove_cr <one | git hash-object --stdin)" ' test_expect_success '.gitattributes says two is binary' ' @@ -240,7 +240,7 @@ test_expect_success '.gitattributes says two is binary' ' git read-tree --reset -u HEAD && ! has_cr dir/two && - verbose has_cr one && + has_cr one && ! has_cr three ' @@ -259,8 +259,8 @@ test_expect_success '.gitattributes says two and three are text' ' echo "t* crlf" >.gitattributes && git read-tree --reset -u HEAD && - verbose has_cr dir/two && - verbose has_cr three + has_cr dir/two && + has_cr three ' test_expect_success 'in-tree .gitattributes (1)' ' @@ -273,7 +273,7 @@ test_expect_success 'in-tree .gitattributes (1)' ' git read-tree --reset -u HEAD && ! has_cr one && - verbose has_cr three + has_cr three ' test_expect_success 'in-tree .gitattributes (2)' ' @@ -283,7 +283,7 @@ test_expect_success 'in-tree .gitattributes (2)' ' git checkout-index -f -q -u -a && ! has_cr one && - verbose has_cr three + has_cr three ' test_expect_success 'in-tree .gitattributes (3)' ' @@ -294,7 +294,7 @@ test_expect_success 'in-tree .gitattributes (3)' ' git checkout-index -u one dir/two three && ! has_cr one && - verbose has_cr three + has_cr three ' test_expect_success 'in-tree .gitattributes (4)' ' @@ -305,7 +305,7 @@ test_expect_success 'in-tree .gitattributes (4)' ' git checkout-index -u .gitattributes && ! has_cr one && - verbose has_cr three + has_cr three ' test_expect_success 'checkout with existing .gitattributes' ' diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh index 46abbeed68..0b4997022b 100755 --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@ -263,7 +263,7 @@ test_expect_success 'required filter with absent clean field' ' echo test >test.ac && test_must_fail git add test.ac 2>stderr && - test_i18ngrep "fatal: test.ac: clean filter .absentclean. failed" stderr + test_grep "fatal: test.ac: clean filter .absentclean. failed" stderr ' test_expect_success 'required filter with absent smudge field' ' @@ -276,7 +276,7 @@ test_expect_success 'required filter with absent smudge field' ' git add test.as && rm -f test.as && test_must_fail git checkout -- test.as 2>stderr && - test_i18ngrep "fatal: test.as: smudge filter absentsmudge failed" stderr + test_grep "fatal: test.as: smudge filter absentsmudge failed" stderr ' test_expect_success 'filtering large input to small output should use little memory' ' @@ -733,7 +733,7 @@ test_expect_success 'process filter should restart after unexpected write failur git checkout --quiet --no-progress . 2>git-stderr.log && grep "smudge write error" git-stderr.log && - test_i18ngrep "error: external filter" git-stderr.log && + test_grep "error: external filter" git-stderr.log && cat >expected.log <<-EOF && START diff --git a/t/t0027-auto-crlf.sh b/t/t0027-auto-crlf.sh index a94ac1eae3..2f57c8669c 100755 --- a/t/t0027-auto-crlf.sh +++ b/t/t0027-auto-crlf.sh @@ -70,7 +70,8 @@ create_NNO_MIX_files () { cp CRLF ${pfx}_CRLF.txt && cp CRLF_mix_LF ${pfx}_CRLF_mix_LF.txt && cp LF_mix_CR ${pfx}_LF_mix_CR.txt && - cp CRLF_nul ${pfx}_CRLF_nul.txt + cp CRLF_nul ${pfx}_CRLF_nul.txt || + return 1 done done done @@ -101,7 +102,8 @@ commit_check_warn () { do fname=${pfx}_$f.txt && cp $f $fname && - git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err" + git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err" || + return 1 done && git commit -m "core.autocrlf $crlf" && check_warning "$lfname" ${pfx}_LF.err && @@ -121,15 +123,19 @@ commit_chk_wrnNNO () { lfmixcr=$1 ; shift crlfnul=$1 ; shift pfx=NNO_attr_${attr}_aeol_${aeol}_${crlf} - #Commit files on top of existing file - create_gitattributes "$attr" $aeol && - for f in LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul - do - fname=${pfx}_$f.txt && - cp $f $fname && - printf Z >>"$fname" && - git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err" - done + + test_expect_success 'setup commit NNO files' ' + #Commit files on top of existing file + create_gitattributes "$attr" $aeol && + for f in LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul + do + fname=${pfx}_$f.txt && + cp $f $fname && + printf Z >>"$fname" && + git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err" || + return 1 + done + ' test_expect_success "commit NNO files crlf=$crlf attr=$attr LF" ' check_warning "$lfwarn" ${pfx}_LF.err @@ -163,15 +169,19 @@ commit_MIX_chkwrn () { lfmixcr=$1 ; shift crlfnul=$1 ; shift pfx=MIX_attr_${attr}_aeol_${aeol}_${crlf} - #Commit file with CLRF_mix_LF on top of existing file - create_gitattributes "$attr" $aeol && - for f in LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul - do - fname=${pfx}_$f.txt && - cp CRLF_mix_LF $fname && - printf Z >>"$fname" && - git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err" - done + + test_expect_success 'setup commit file with mixed EOL' ' + #Commit file with CLRF_mix_LF on top of existing file + create_gitattributes "$attr" $aeol && + for f in LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul + do + fname=${pfx}_$f.txt && + cp CRLF_mix_LF $fname && + printf Z >>"$fname" && + git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err" || + return 1 + done + ' test_expect_success "commit file with mixed EOL onto LF crlf=$crlf attr=$attr" ' check_warning "$lfwarn" ${pfx}_LF.err @@ -289,17 +299,17 @@ checkout_files () { lfmixcrlf=$1 ; shift lfmixcr=$1 ; shift crlfnul=$1 ; shift - create_gitattributes "$attr" $ident $aeol && - git config core.autocrlf $crlf && + test_expect_success "setup config for checkout attr=$attr ident=$ident aeol=$aeol core.autocrlf=$crlf" ' + create_gitattributes "$attr" $ident $aeol && + git config core.autocrlf $crlf + ' pfx=eol_${ceol}_crlf_${crlf}_attr_${attr}_ && for f in LF CRLF LF_mix_CR CRLF_mix_LF LF_nul do - rm crlf_false_attr__$f.txt && - if test -z "$ceol"; then - git checkout -- crlf_false_attr__$f.txt - else - git -c core.eol=$ceol checkout -- crlf_false_attr__$f.txt - fi + test_expect_success "setup $f checkout ${ceol:+ with -c core.eol=$ceol}" ' + rm -f crlf_false_attr__$f.txt && + git ${ceol:+-c core.eol=$ceol} checkout -- crlf_false_attr__$f.txt + ' done test_expect_success "ls-files --eol attr=$attr $ident aeol=$aeol core.autocrlf=$crlf core.eol=$ceol" ' diff --git a/t/t0028-working-tree-encoding.sh b/t/t0028-working-tree-encoding.sh index c196fdb0ee..1b55f59c23 100755 --- a/t/t0028-working-tree-encoding.sh +++ b/t/t0028-working-tree-encoding.sh @@ -92,23 +92,23 @@ do # In these cases the BOM is prohibited. cp bebom.utf${i}be.raw bebom.utf${i}be && test_must_fail git add bebom.utf${i}be 2>err.out && - test_i18ngrep "fatal: BOM is prohibited .* utf-${i}be" err.out && - test_i18ngrep "use UTF-${i} as working-tree-encoding" err.out && + test_grep "fatal: BOM is prohibited .* utf-${i}be" err.out && + test_grep "use UTF-${i} as working-tree-encoding" err.out && cp lebom.utf${i}le.raw lebom.utf${i}be && test_must_fail git add lebom.utf${i}be 2>err.out && - test_i18ngrep "fatal: BOM is prohibited .* utf-${i}be" err.out && - test_i18ngrep "use UTF-${i} as working-tree-encoding" err.out && + test_grep "fatal: BOM is prohibited .* utf-${i}be" err.out && + test_grep "use UTF-${i} as working-tree-encoding" err.out && cp bebom.utf${i}be.raw bebom.utf${i}le && test_must_fail git add bebom.utf${i}le 2>err.out && - test_i18ngrep "fatal: BOM is prohibited .* utf-${i}LE" err.out && - test_i18ngrep "use UTF-${i} as working-tree-encoding" err.out && + test_grep "fatal: BOM is prohibited .* utf-${i}LE" err.out && + test_grep "use UTF-${i} as working-tree-encoding" err.out && cp lebom.utf${i}le.raw lebom.utf${i}le && test_must_fail git add lebom.utf${i}le 2>err.out && - test_i18ngrep "fatal: BOM is prohibited .* utf-${i}LE" err.out && - test_i18ngrep "use UTF-${i} as working-tree-encoding" err.out + test_grep "fatal: BOM is prohibited .* utf-${i}LE" err.out && + test_grep "use UTF-${i} as working-tree-encoding" err.out ' test_expect_success "check required UTF-${i} BOM" ' @@ -118,13 +118,13 @@ do cp nobom.utf${i}be.raw nobom.utf${i} && test_must_fail git add nobom.utf${i} 2>err.out && - test_i18ngrep "fatal: BOM is required .* utf-${i}" err.out && - test_i18ngrep "use UTF-${i}BE or UTF-${i}LE" err.out && + test_grep "fatal: BOM is required .* utf-${i}" err.out && + test_grep "use UTF-${i}BE or UTF-${i}LE" err.out && cp nobom.utf${i}le.raw nobom.utf${i} && test_must_fail git add nobom.utf${i} 2>err.out && - test_i18ngrep "fatal: BOM is required .* utf-${i}" err.out && - test_i18ngrep "use UTF-${i}BE or UTF-${i}LE" err.out + test_grep "fatal: BOM is required .* utf-${i}" err.out && + test_grep "use UTF-${i}BE or UTF-${i}LE" err.out ' test_expect_success "eol conversion for UTF-${i} encoded files on checkout" ' @@ -169,7 +169,7 @@ test_expect_success 'check unsupported encodings' ' echo "*.set text working-tree-encoding" >.gitattributes && printf "set" >t.set && test_must_fail git add t.set 2>err.out && - test_i18ngrep "true/false are no valid working-tree-encodings" err.out && + test_grep "true/false are no valid working-tree-encodings" err.out && echo "*.unset text -working-tree-encoding" >.gitattributes && printf "unset" >t.unset && @@ -182,7 +182,7 @@ test_expect_success 'check unsupported encodings' ' echo "*.garbage text working-tree-encoding=garbage" >.gitattributes && printf "garbage" >t.garbage && test_must_fail git add t.garbage 2>err.out && - test_i18ngrep "failed to encode" err.out + test_grep "failed to encode" err.out ' test_expect_success 'error if encoding round trip is not the same during refresh' ' @@ -201,7 +201,7 @@ test_expect_success 'error if encoding round trip is not the same during refresh git update-ref refs/heads/main $COMMIT && test_must_fail git checkout HEAD^ 2>err.out && - test_i18ngrep "error: .* overwritten by checkout:" err.out + test_grep "error: .* overwritten by checkout:" err.out ' test_expect_success 'error if encoding garbage is already in Git' ' @@ -217,7 +217,7 @@ test_expect_success 'error if encoding garbage is already in Git' ' git update-ref refs/heads/main $COMMIT && git diff 2>err.out && - test_i18ngrep "error: BOM is required" err.out + test_grep "error: BOM is required" err.out ' test_lazy_prereq ICONV_SHIFT_JIS ' diff --git a/t/t0030-stripspace.sh b/t/t0030-stripspace.sh index 0a5713c524..d1b3be8725 100755 --- a/t/t0030-stripspace.sh +++ b/t/t0030-stripspace.sh @@ -17,396 +17,378 @@ printf_git_stripspace () { printf "$1" | git stripspace } -test_expect_success \ - 'long lines without spaces should be unchanged' ' - echo "$ttt" >expect && - git stripspace <expect >actual && - test_cmp expect actual && - - echo "$ttt$ttt" >expect && - git stripspace <expect >actual && - test_cmp expect actual && - - echo "$ttt$ttt$ttt" >expect && - git stripspace <expect >actual && - test_cmp expect actual && - - echo "$ttt$ttt$ttt$ttt" >expect && - git stripspace <expect >actual && - test_cmp expect actual +test_expect_success 'long lines without spaces should be unchanged' ' + echo "$ttt" >expect && + git stripspace <expect >actual && + test_cmp expect actual && + + echo "$ttt$ttt" >expect && + git stripspace <expect >actual && + test_cmp expect actual && + + echo "$ttt$ttt$ttt" >expect && + git stripspace <expect >actual && + test_cmp expect actual && + + echo "$ttt$ttt$ttt$ttt" >expect && + git stripspace <expect >actual && + test_cmp expect actual ' -test_expect_success \ - 'lines with spaces at the beginning should be unchanged' ' - echo "$sss$ttt" >expect && - git stripspace <expect >actual && - test_cmp expect actual && +test_expect_success 'lines with spaces at the beginning should be unchanged' ' + echo "$sss$ttt" >expect && + git stripspace <expect >actual && + test_cmp expect actual && - echo "$sss$sss$ttt" >expect && - git stripspace <expect >actual && - test_cmp expect actual && + echo "$sss$sss$ttt" >expect && + git stripspace <expect >actual && + test_cmp expect actual && - echo "$sss$sss$sss$ttt" >expect && - git stripspace <expect >actual && - test_cmp expect actual + echo "$sss$sss$sss$ttt" >expect && + git stripspace <expect >actual && + test_cmp expect actual ' -test_expect_success \ - 'lines with intermediate spaces should be unchanged' ' - echo "$ttt$sss$ttt" >expect && - git stripspace <expect >actual && - test_cmp expect actual && +test_expect_success 'lines with intermediate spaces should be unchanged' ' + echo "$ttt$sss$ttt" >expect && + git stripspace <expect >actual && + test_cmp expect actual && - echo "$ttt$sss$sss$ttt" >expect && - git stripspace <expect >actual && - test_cmp expect actual + echo "$ttt$sss$sss$ttt" >expect && + git stripspace <expect >actual && + test_cmp expect actual ' -test_expect_success \ - 'consecutive blank lines should be unified' ' - printf "$ttt\n\n$ttt\n" > expect && - printf "$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual && - test_cmp expect actual && +test_expect_success 'consecutive blank lines should be unified' ' + printf "$ttt\n\n$ttt\n" > expect && + printf "$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt$ttt\n\n$ttt\n" > expect && - printf "$ttt$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt$ttt\n\n$ttt\n" > expect && + printf "$ttt$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt$ttt$ttt\n\n$ttt\n" > expect && - printf "$ttt$ttt$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt$ttt$ttt\n\n$ttt\n" > expect && + printf "$ttt$ttt$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n\n$ttt\n" > expect && - printf "$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt\n\n$ttt\n" > expect && + printf "$ttt\n\n\n\n\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n\n$ttt$ttt\n" > expect && - printf "$ttt\n\n\n\n\n$ttt$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt\n\n$ttt$ttt\n" > expect && + printf "$ttt\n\n\n\n\n$ttt$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n\n$ttt$ttt$ttt\n" > expect && - printf "$ttt\n\n\n\n\n$ttt$ttt$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt\n\n$ttt$ttt$ttt\n" > expect && + printf "$ttt\n\n\n\n\n$ttt$ttt$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n\n$ttt\n" > expect && - printf "$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt\n\n$ttt\n" > expect && + printf "$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt$ttt\n\n$ttt\n" > expect && - printf "$ttt$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt$ttt\n\n$ttt\n" > expect && + printf "$ttt$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt$ttt$ttt\n\n$ttt\n" > expect && - printf "$ttt$ttt$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt$ttt$ttt\n\n$ttt\n" > expect && + printf "$ttt$ttt$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n\n$ttt\n" > expect && - printf "$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt\n\n$ttt\n" > expect && + printf "$ttt\n\t\n \n\n \t\t\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n\n$ttt$ttt\n" > expect && - printf "$ttt\n\t\n \n\n \t\t\n$ttt$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt\n\n$ttt$ttt\n" > expect && + printf "$ttt\n\t\n \n\n \t\t\n$ttt$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n\n$ttt$ttt$ttt\n" > expect && - printf "$ttt\n\t\n \n\n \t\t\n$ttt$ttt$ttt\n" | git stripspace >actual && - test_cmp expect actual + printf "$ttt\n\n$ttt$ttt$ttt\n" > expect && + printf "$ttt\n\t\n \n\n \t\t\n$ttt$ttt$ttt\n" | git stripspace >actual && + test_cmp expect actual ' -test_expect_success \ - 'only consecutive blank lines should be completely removed' ' +test_expect_success 'only consecutive blank lines should be completely removed' ' + printf "\n" | git stripspace >actual && + test_must_be_empty actual && - printf "\n" | git stripspace >actual && - test_must_be_empty actual && + printf "\n\n\n" | git stripspace >actual && + test_must_be_empty actual && - printf "\n\n\n" | git stripspace >actual && - test_must_be_empty actual && + printf "$sss\n$sss\n$sss\n" | git stripspace >actual && + test_must_be_empty actual && - printf "$sss\n$sss\n$sss\n" | git stripspace >actual && - test_must_be_empty actual && + printf "$sss$sss\n$sss\n\n" | git stripspace >actual && + test_must_be_empty actual && - printf "$sss$sss\n$sss\n\n" | git stripspace >actual && - test_must_be_empty actual && + printf "\n$sss\n$sss$sss\n" | git stripspace >actual && + test_must_be_empty actual && - printf "\n$sss\n$sss$sss\n" | git stripspace >actual && - test_must_be_empty actual && + printf "$sss$sss$sss$sss\n\n\n" | git stripspace >actual && + test_must_be_empty actual && - printf "$sss$sss$sss$sss\n\n\n" | git stripspace >actual && - test_must_be_empty actual && + printf "\n$sss$sss$sss$sss\n\n" | git stripspace >actual && + test_must_be_empty actual && - printf "\n$sss$sss$sss$sss\n\n" | git stripspace >actual && - test_must_be_empty actual && - - printf "\n\n$sss$sss$sss$sss\n" | git stripspace >actual && - test_must_be_empty actual + printf "\n\n$sss$sss$sss$sss\n" | git stripspace >actual && + test_must_be_empty actual ' -test_expect_success \ - 'consecutive blank lines at the beginning should be removed' ' - printf "$ttt\n" > expect && - printf "\n$ttt\n" | git stripspace >actual && - test_cmp expect actual && +test_expect_success 'consecutive blank lines at the beginning should be removed' ' + printf "$ttt\n" > expect && + printf "\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n" > expect && - printf "\n\n\n$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt\n" > expect && + printf "\n\n\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt$ttt\n" > expect && - printf "\n\n\n$ttt$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt$ttt\n" > expect && + printf "\n\n\n$ttt$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt$ttt$ttt\n" > expect && - printf "\n\n\n$ttt$ttt$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt$ttt$ttt\n" > expect && + printf "\n\n\n$ttt$ttt$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt$ttt$ttt$ttt\n" > expect && - printf "\n\n\n$ttt$ttt$ttt$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt$ttt$ttt$ttt\n" > expect && + printf "\n\n\n$ttt$ttt$ttt$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n" > expect && + printf "$ttt\n" > expect && - printf "$sss\n$sss\n$sss\n$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$sss\n$sss\n$sss\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "\n$sss\n$sss$sss\n$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "\n$sss\n$sss$sss\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$sss$sss\n$sss\n\n$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$sss$sss\n$sss\n\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$sss$sss$sss\n\n\n$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$sss$sss$sss\n\n\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "\n$sss$sss$sss\n\n$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "\n$sss$sss$sss\n\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "\n\n$sss$sss$sss\n$ttt\n" | git stripspace >actual && - test_cmp expect actual + printf "\n\n$sss$sss$sss\n$ttt\n" | git stripspace >actual && + test_cmp expect actual ' -test_expect_success \ - 'consecutive blank lines at the end should be removed' ' - printf "$ttt\n" > expect && - printf "$ttt\n\n" | git stripspace >actual && - test_cmp expect actual && +test_expect_success 'consecutive blank lines at the end should be removed' ' + printf "$ttt\n" > expect && + printf "$ttt\n\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n" > expect && - printf "$ttt\n\n\n\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt\n" > expect && + printf "$ttt\n\n\n\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt$ttt\n" > expect && - printf "$ttt$ttt\n\n\n\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt$ttt\n" > expect && + printf "$ttt$ttt\n\n\n\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt$ttt$ttt\n" > expect && - printf "$ttt$ttt$ttt\n\n\n\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt$ttt$ttt\n" > expect && + printf "$ttt$ttt$ttt\n\n\n\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt$ttt$ttt$ttt\n" > expect && - printf "$ttt$ttt$ttt$ttt\n\n\n\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt$ttt$ttt$ttt\n" > expect && + printf "$ttt$ttt$ttt$ttt\n\n\n\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n" > expect && + printf "$ttt\n" > expect && - printf "$ttt\n$sss\n$sss\n$sss\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt\n$sss\n$sss\n$sss\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n\n$sss\n$sss$sss\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt\n\n$sss\n$sss$sss\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n$sss$sss\n$sss\n\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt\n$sss$sss\n$sss\n\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n$sss$sss$sss\n\n\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt\n$sss$sss$sss\n\n\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n\n$sss$sss$sss\n\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt\n\n$sss$sss$sss\n\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n\n\n$sss$sss$sss\n" | git stripspace >actual && - test_cmp expect actual + printf "$ttt\n\n\n$sss$sss$sss\n" | git stripspace >actual && + test_cmp expect actual ' -test_expect_success \ - 'text without newline at end should end with newline' ' - test_stdout_line_count -gt 0 printf_git_stripspace "$ttt" && - test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt" && - test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$ttt" && - test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$ttt$ttt" +test_expect_success 'text without newline at end should end with newline' ' + test_stdout_line_count -gt 0 printf_git_stripspace "$ttt" && + test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt" && + test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$ttt" && + test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$ttt$ttt" ' # text plus spaces at the end: -test_expect_success \ - 'text plus spaces without newline at end should end with newline' ' - test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$sss" && - test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$sss" && - test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$ttt$sss" && - test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$sss$sss" && - test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$sss$sss" && - test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$sss$sss$sss" +test_expect_success 'text plus spaces without newline at end should end with newline' ' + test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$sss" && + test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$sss" && + test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$ttt$sss" && + test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$sss$sss" && + test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$ttt$sss$sss" && + test_stdout_line_count -gt 0 printf_git_stripspace "$ttt$sss$sss$sss" ' -test_expect_success \ - 'text plus spaces without newline at end should not show spaces' ' - printf "$ttt$sss" | git stripspace >tmp && - ! grep " " tmp >/dev/null && - printf "$ttt$ttt$sss" | git stripspace >tmp && - ! grep " " tmp >/dev/null && - printf "$ttt$ttt$ttt$sss" | git stripspace >tmp && - ! grep " " tmp >/dev/null && - printf "$ttt$sss$sss" | git stripspace >tmp && - ! grep " " tmp >/dev/null && - printf "$ttt$ttt$sss$sss" | git stripspace >tmp && - ! grep " " tmp >/dev/null && - printf "$ttt$sss$sss$sss" | git stripspace >tmp && - ! grep " " tmp >/dev/null +test_expect_success 'text plus spaces without newline at end should not show spaces' ' + printf "$ttt$sss" | git stripspace >tmp && + ! grep " " tmp >/dev/null && + printf "$ttt$ttt$sss" | git stripspace >tmp && + ! grep " " tmp >/dev/null && + printf "$ttt$ttt$ttt$sss" | git stripspace >tmp && + ! grep " " tmp >/dev/null && + printf "$ttt$sss$sss" | git stripspace >tmp && + ! grep " " tmp >/dev/null && + printf "$ttt$ttt$sss$sss" | git stripspace >tmp && + ! grep " " tmp >/dev/null && + printf "$ttt$sss$sss$sss" | git stripspace >tmp && + ! grep " " tmp >/dev/null ' -test_expect_success \ - 'text plus spaces without newline should show the correct lines' ' - printf "$ttt\n" >expect && - printf "$ttt$sss" | git stripspace >actual && - test_cmp expect actual && +test_expect_success 'text plus spaces without newline should show the correct lines' ' + printf "$ttt\n" >expect && + printf "$ttt$sss" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n" >expect && - printf "$ttt$sss$sss" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt\n" >expect && + printf "$ttt$sss$sss" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n" >expect && - printf "$ttt$sss$sss$sss" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt\n" >expect && + printf "$ttt$sss$sss$sss" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt$ttt\n" >expect && - printf "$ttt$ttt$sss" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt$ttt\n" >expect && + printf "$ttt$ttt$sss" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt$ttt\n" >expect && - printf "$ttt$ttt$sss$sss" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt$ttt\n" >expect && + printf "$ttt$ttt$sss$sss" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt$ttt$ttt\n" >expect && - printf "$ttt$ttt$ttt$sss" | git stripspace >actual && - test_cmp expect actual + printf "$ttt$ttt$ttt\n" >expect && + printf "$ttt$ttt$ttt$sss" | git stripspace >actual && + test_cmp expect actual ' -test_expect_success \ - 'text plus spaces at end should not show spaces' ' - echo "$ttt$sss" | git stripspace >tmp && - ! grep " " tmp >/dev/null && - echo "$ttt$ttt$sss" | git stripspace >tmp && - ! grep " " tmp >/dev/null && - echo "$ttt$ttt$ttt$sss" | git stripspace >tmp && - ! grep " " tmp >/dev/null && - echo "$ttt$sss$sss" | git stripspace >tmp && - ! grep " " tmp >/dev/null && - echo "$ttt$ttt$sss$sss" | git stripspace >tmp && - ! grep " " tmp >/dev/null && - echo "$ttt$sss$sss$sss" | git stripspace >tmp && - ! grep " " tmp >/dev/null +test_expect_success 'text plus spaces at end should not show spaces' ' + echo "$ttt$sss" | git stripspace >tmp && + ! grep " " tmp >/dev/null && + echo "$ttt$ttt$sss" | git stripspace >tmp && + ! grep " " tmp >/dev/null && + echo "$ttt$ttt$ttt$sss" | git stripspace >tmp && + ! grep " " tmp >/dev/null && + echo "$ttt$sss$sss" | git stripspace >tmp && + ! grep " " tmp >/dev/null && + echo "$ttt$ttt$sss$sss" | git stripspace >tmp && + ! grep " " tmp >/dev/null && + echo "$ttt$sss$sss$sss" | git stripspace >tmp && + ! grep " " tmp >/dev/null ' -test_expect_success \ - 'text plus spaces at end should be cleaned and newline must remain' ' - echo "$ttt" >expect && - echo "$ttt$sss" | git stripspace >actual && - test_cmp expect actual && +test_expect_success 'text plus spaces at end should be cleaned and newline must remain' ' + echo "$ttt" >expect && + echo "$ttt$sss" | git stripspace >actual && + test_cmp expect actual && - echo "$ttt" >expect && - echo "$ttt$sss$sss" | git stripspace >actual && - test_cmp expect actual && + echo "$ttt" >expect && + echo "$ttt$sss$sss" | git stripspace >actual && + test_cmp expect actual && - echo "$ttt" >expect && - echo "$ttt$sss$sss$sss" | git stripspace >actual && - test_cmp expect actual && + echo "$ttt" >expect && + echo "$ttt$sss$sss$sss" | git stripspace >actual && + test_cmp expect actual && - echo "$ttt$ttt" >expect && - echo "$ttt$ttt$sss" | git stripspace >actual && - test_cmp expect actual && + echo "$ttt$ttt" >expect && + echo "$ttt$ttt$sss" | git stripspace >actual && + test_cmp expect actual && - echo "$ttt$ttt" >expect && - echo "$ttt$ttt$sss$sss" | git stripspace >actual && - test_cmp expect actual && + echo "$ttt$ttt" >expect && + echo "$ttt$ttt$sss$sss" | git stripspace >actual && + test_cmp expect actual && - echo "$ttt$ttt$ttt" >expect && - echo "$ttt$ttt$ttt$sss" | git stripspace >actual && - test_cmp expect actual + echo "$ttt$ttt$ttt" >expect && + echo "$ttt$ttt$ttt$sss" | git stripspace >actual && + test_cmp expect actual ' # spaces only: -test_expect_success \ - 'spaces with newline at end should be replaced with empty string' ' - echo | git stripspace >actual && - test_must_be_empty actual && +test_expect_success 'spaces with newline at end should be replaced with empty string' ' + echo | git stripspace >actual && + test_must_be_empty actual && - echo "$sss" | git stripspace >actual && - test_must_be_empty actual && + echo "$sss" | git stripspace >actual && + test_must_be_empty actual && - echo "$sss$sss" | git stripspace >actual && - test_must_be_empty actual && + echo "$sss$sss" | git stripspace >actual && + test_must_be_empty actual && - echo "$sss$sss$sss" | git stripspace >actual && - test_must_be_empty actual && + echo "$sss$sss$sss" | git stripspace >actual && + test_must_be_empty actual && - echo "$sss$sss$sss$sss" | git stripspace >actual && - test_must_be_empty actual + echo "$sss$sss$sss$sss" | git stripspace >actual && + test_must_be_empty actual ' -test_expect_success \ - 'spaces without newline at end should not show spaces' ' - printf "" | git stripspace >tmp && - ! grep " " tmp >/dev/null && - printf "$sss" | git stripspace >tmp && - ! grep " " tmp >/dev/null && - printf "$sss$sss" | git stripspace >tmp && - ! grep " " tmp >/dev/null && - printf "$sss$sss$sss" | git stripspace >tmp && - ! grep " " tmp >/dev/null && - printf "$sss$sss$sss$sss" | git stripspace >tmp && - ! grep " " tmp >/dev/null +test_expect_success 'spaces without newline at end should not show spaces' ' + printf "" | git stripspace >tmp && + ! grep " " tmp >/dev/null && + printf "$sss" | git stripspace >tmp && + ! grep " " tmp >/dev/null && + printf "$sss$sss" | git stripspace >tmp && + ! grep " " tmp >/dev/null && + printf "$sss$sss$sss" | git stripspace >tmp && + ! grep " " tmp >/dev/null && + printf "$sss$sss$sss$sss" | git stripspace >tmp && + ! grep " " tmp >/dev/null ' -test_expect_success \ - 'spaces without newline at end should be replaced with empty string' ' - printf "" | git stripspace >actual && - test_must_be_empty actual && +test_expect_success 'spaces without newline at end should be replaced with empty string' ' + printf "" | git stripspace >actual && + test_must_be_empty actual && - printf "$sss$sss" | git stripspace >actual && - test_must_be_empty actual && + printf "$sss$sss" | git stripspace >actual && + test_must_be_empty actual && - printf "$sss$sss$sss" | git stripspace >actual && - test_must_be_empty actual && + printf "$sss$sss$sss" | git stripspace >actual && + test_must_be_empty actual && - printf "$sss$sss$sss$sss" | git stripspace >actual && - test_must_be_empty actual + printf "$sss$sss$sss$sss" | git stripspace >actual && + test_must_be_empty actual ' -test_expect_success \ - 'consecutive text lines should be unchanged' ' - printf "$ttt$ttt\n$ttt\n" >expect && - printf "$ttt$ttt\n$ttt\n" | git stripspace >actual && - test_cmp expect actual && +test_expect_success 'consecutive text lines should be unchanged' ' + printf "$ttt$ttt\n$ttt\n" >expect && + printf "$ttt$ttt\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n$ttt$ttt\n$ttt\n" >expect && - printf "$ttt\n$ttt$ttt\n$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt\n$ttt$ttt\n$ttt\n" >expect && + printf "$ttt\n$ttt$ttt\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n$ttt\n$ttt\n$ttt$ttt\n" >expect && - printf "$ttt\n$ttt\n$ttt\n$ttt$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt\n$ttt\n$ttt\n$ttt$ttt\n" >expect && + printf "$ttt\n$ttt\n$ttt\n$ttt$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n$ttt\n\n$ttt$ttt\n$ttt\n" >expect && - printf "$ttt\n$ttt\n\n$ttt$ttt\n$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt\n$ttt\n\n$ttt$ttt\n$ttt\n" >expect && + printf "$ttt\n$ttt\n\n$ttt$ttt\n$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt$ttt\n\n$ttt\n$ttt$ttt\n" >expect && - printf "$ttt$ttt\n\n$ttt\n$ttt$ttt\n" | git stripspace >actual && - test_cmp expect actual && + printf "$ttt$ttt\n\n$ttt\n$ttt$ttt\n" >expect && + printf "$ttt$ttt\n\n$ttt\n$ttt$ttt\n" | git stripspace >actual && + test_cmp expect actual && - printf "$ttt\n$ttt$ttt\n\n$ttt\n" >expect && - printf "$ttt\n$ttt$ttt\n\n$ttt\n" | git stripspace >actual && - test_cmp expect actual + printf "$ttt\n$ttt$ttt\n\n$ttt\n" >expect && + printf "$ttt\n$ttt$ttt\n\n$ttt\n" | git stripspace >actual && + test_cmp expect actual ' test_expect_success 'strip comments, too' ' diff --git a/t/t0035-safe-bare-repository.sh b/t/t0035-safe-bare-repository.sh index 11c15a48aa..038b8b788d 100755 --- a/t/t0035-safe-bare-repository.sh +++ b/t/t0035-safe-bare-repository.sh @@ -7,13 +7,26 @@ TEST_PASSES_SANITIZE_LEAK=true pwd="$(pwd)" -expect_accepted () { - git "$@" rev-parse --git-dir +expect_accepted_implicit () { + test_when_finished 'rm "$pwd/trace.perf"' && + GIT_TRACE2_PERF="$pwd/trace.perf" git "$@" rev-parse --git-dir && + # Note: we're intentionally only checking that the bare repo has a + # directory *prefix* of $pwd + grep -F "implicit-bare-repository:$pwd" "$pwd/trace.perf" +} + +expect_accepted_explicit () { + test_when_finished 'rm "$pwd/trace.perf"' && + GIT_DIR="$1" GIT_TRACE2_PERF="$pwd/trace.perf" git rev-parse --git-dir && + ! grep -F "implicit-bare-repository:$pwd" "$pwd/trace.perf" } expect_rejected () { - test_must_fail git "$@" rev-parse --git-dir 2>err && - grep -F "cannot use bare repository" err + test_when_finished 'rm "$pwd/trace.perf"' && + test_env GIT_TRACE2_PERF="$pwd/trace.perf" \ + test_must_fail git "$@" rev-parse --git-dir 2>err && + grep -F "cannot use bare repository" err && + grep -F "implicit-bare-repository:$pwd" "$pwd/trace.perf" } test_expect_success 'setup bare repo in worktree' ' @@ -22,12 +35,13 @@ test_expect_success 'setup bare repo in worktree' ' ' test_expect_success 'safe.bareRepository unset' ' - expect_accepted -C outer-repo/bare-repo + test_unconfig --global safe.bareRepository && + expect_accepted_implicit -C outer-repo/bare-repo ' test_expect_success 'safe.bareRepository=all' ' test_config_global safe.bareRepository all && - expect_accepted -C outer-repo/bare-repo + expect_accepted_implicit -C outer-repo/bare-repo ' test_expect_success 'safe.bareRepository=explicit' ' @@ -47,7 +61,7 @@ test_expect_success 'safe.bareRepository in the repository' ' test_expect_success 'safe.bareRepository on the command line' ' test_config_global safe.bareRepository explicit && - expect_accepted -C outer-repo/bare-repo \ + expect_accepted_implicit -C outer-repo/bare-repo \ -c safe.bareRepository=all ' @@ -60,4 +74,8 @@ test_expect_success 'safe.bareRepository in included file' ' expect_rejected -C outer-repo/bare-repo ' +test_expect_success 'no trace when GIT_DIR is explicitly provided' ' + expect_accepted_explicit "$pwd/outer-repo/bare-repo" +' + test_done diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index 7d7ecfd571..ec974867e4 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -13,29 +13,36 @@ usage: test-tool parse-options <options> A helper function for the parse-options API. - --yes get a boolean + --[no-]yes get a boolean -D, --no-doubt begins with 'no-' + --doubt opposite of --no-doubt -B, --no-fear be brave - -b, --boolean increment by one - -4, --or4 bitwise-or boolean with ...0100 - --neg-or4 same as --no-or4 + -b, --[no-]boolean increment by one + -4, --[no-]or4 bitwise-or boolean with ...0100 + --[no-]neg-or4 same as --no-or4 - -i, --integer <n> get a integer + -i, --[no-]integer <n> + get a integer -j <n> get a integer, too -m, --magnitude <n> get a magnitude - --set23 set integer to 23 + --[no-]set23 set integer to 23 --mode1 set integer to 1 (cmdmode option) --mode2 set integer to 2 (cmdmode option) - -L, --length <str> get length of <str> - -F, --file <file> set file to <file> + --[no-]mode34 (3|4) set integer to 3 or 4 (cmdmode option) + -L, --[no-]length <str> + get length of <str> + -F, --[no-]file <file> + set file to <file> String options - -s, --string <string> + -s, --[no-]string <string> get a string - --string2 <str> get another string - --st <st> get another string (pervert ordering) + --[no-]string2 <str> get another string + --[no-]st <st> get another string (pervert ordering) -o <str> get another string - --list <str> add str to list + --longhelp help text of this entry + spans multiple lines + --[no-]list <str> add str to list Magic arguments -NUM set integer to NUM @@ -44,16 +51,17 @@ Magic arguments --no-ambiguous negative ambiguity Standard options - --abbrev[=<n>] use <n> digits to display object names - -v, --verbose be verbose - -n, --dry-run dry run - -q, --quiet be quiet - --expect <string> expected output in the variable dump + --[no-]abbrev[=<n>] use <n> digits to display object names + -v, --[no-]verbose be verbose + -n, --[no-]dry-run dry run + -q, --[no-]quiet be quiet + --[no-]expect <string> + expected output in the variable dump Alias - -A, --alias-source <string> + -A, --[no-]alias-source <string> get a string - -Z, --alias-target <string> + -Z, --[no-]alias-target <string> alias of --alias-source EOF @@ -359,19 +367,41 @@ test_expect_success 'OPT_NEGBIT() works' ' ' test_expect_success 'OPT_CMDMODE() works' ' - test-tool parse-options --expect="integer: 1" --mode1 + test-tool parse-options --expect="integer: 1" --mode1 && + test-tool parse-options --expect="integer: 3" --mode34=3 ' -test_expect_success 'OPT_CMDMODE() detects incompatibility' ' +test_expect_success 'OPT_CMDMODE() detects incompatibility (1)' ' test_must_fail test-tool parse-options --mode1 --mode2 >output 2>output.err && test_must_be_empty output && - test_i18ngrep "incompatible with --mode" output.err + test_grep "mode1" output.err && + test_grep "mode2" output.err && + test_grep "cannot be used together" output.err ' -test_expect_success 'OPT_CMDMODE() detects incompatibility with something else' ' +test_expect_success 'OPT_CMDMODE() detects incompatibility (2)' ' test_must_fail test-tool parse-options --set23 --mode2 >output 2>output.err && test_must_be_empty output && - test_i18ngrep "incompatible with something else" output.err + test_grep "mode2" output.err && + test_grep "set23" output.err && + test_grep "cannot be used together" output.err +' + +test_expect_success 'OPT_CMDMODE() detects incompatibility (3)' ' + test_must_fail test-tool parse-options --mode2 --set23 >output 2>output.err && + test_must_be_empty output && + test_grep "mode2" output.err && + test_grep "set23" output.err && + test_grep "cannot be used together" output.err +' + +test_expect_success 'OPT_CMDMODE() detects incompatibility (4)' ' + test_must_fail test-tool parse-options --mode2 --mode34=3 \ + >output 2>output.err && + test_must_be_empty output && + test_grep "mode2" output.err && + test_grep "mode34.3" output.err && + test_grep "cannot be used together" output.err ' test_expect_success 'OPT_COUNTUP() with PARSE_OPT_NODASH works' ' diff --git a/t/t0041-usage.sh b/t/t0041-usage.sh index c4fc34eb18..1464294bd1 100755 --- a/t/t0041-usage.sh +++ b/t/t0041-usage.sh @@ -5,6 +5,7 @@ test_description='Test commands behavior when given invalid argument value' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup ' ' @@ -20,8 +21,8 @@ test_expect_success 'tag --contains <existent_tag>' ' test_expect_success 'tag --contains <inexistent_tag>' ' test_must_fail git tag --contains "notag" >actual 2>actual.err && test_line_count = 0 actual && - test_i18ngrep "error" actual.err && - test_i18ngrep ! "usage" actual.err + test_grep "error" actual.err && + test_grep ! "usage" actual.err ' test_expect_success 'tag --no-contains <existent_tag>' ' @@ -33,27 +34,27 @@ test_expect_success 'tag --no-contains <existent_tag>' ' test_expect_success 'tag --no-contains <inexistent_tag>' ' test_must_fail git tag --no-contains "notag" >actual 2>actual.err && test_line_count = 0 actual && - test_i18ngrep "error" actual.err && - test_i18ngrep ! "usage" actual.err + test_grep "error" actual.err && + test_grep ! "usage" actual.err ' test_expect_success 'tag usage error' ' test_must_fail git tag --noopt >actual 2>actual.err && test_line_count = 0 actual && - test_i18ngrep "usage" actual.err + test_grep "usage" actual.err ' test_expect_success 'branch --contains <existent_commit>' ' git branch --contains "main" >actual 2>actual.err && - test_i18ngrep "main" actual && + test_grep "main" actual && test_line_count = 0 actual.err ' test_expect_success 'branch --contains <inexistent_commit>' ' test_must_fail git branch --no-contains "nocommit" >actual 2>actual.err && test_line_count = 0 actual && - test_i18ngrep "error" actual.err && - test_i18ngrep ! "usage" actual.err + test_grep "error" actual.err && + test_grep ! "usage" actual.err ' test_expect_success 'branch --no-contains <existent_commit>' ' @@ -65,14 +66,14 @@ test_expect_success 'branch --no-contains <existent_commit>' ' test_expect_success 'branch --no-contains <inexistent_commit>' ' test_must_fail git branch --no-contains "nocommit" >actual 2>actual.err && test_line_count = 0 actual && - test_i18ngrep "error" actual.err && - test_i18ngrep ! "usage" actual.err + test_grep "error" actual.err && + test_grep ! "usage" actual.err ' test_expect_success 'branch usage error' ' test_must_fail git branch --noopt >actual 2>actual.err && test_line_count = 0 actual && - test_i18ngrep "usage" actual.err + test_grep "usage" actual.err ' test_expect_success 'for-each-ref --contains <existent_object>' ' @@ -84,8 +85,8 @@ test_expect_success 'for-each-ref --contains <existent_object>' ' test_expect_success 'for-each-ref --contains <inexistent_object>' ' test_must_fail git for-each-ref --no-contains "noobject" >actual 2>actual.err && test_line_count = 0 actual && - test_i18ngrep "error" actual.err && - test_i18ngrep ! "usage" actual.err + test_grep "error" actual.err && + test_grep ! "usage" actual.err ' test_expect_success 'for-each-ref --no-contains <existent_object>' ' @@ -97,14 +98,14 @@ test_expect_success 'for-each-ref --no-contains <existent_object>' ' test_expect_success 'for-each-ref --no-contains <inexistent_object>' ' test_must_fail git for-each-ref --no-contains "noobject" >actual 2>actual.err && test_line_count = 0 actual && - test_i18ngrep "error" actual.err && - test_i18ngrep ! "usage" actual.err + test_grep "error" actual.err && + test_grep ! "usage" actual.err ' test_expect_success 'for-each-ref usage error' ' test_must_fail git for-each-ref --noopt >actual 2>actual.err && test_line_count = 0 actual && - test_i18ngrep "usage" actual.err + test_grep "usage" actual.err ' test_done diff --git a/t/t0055-beyond-symlinks.sh b/t/t0055-beyond-symlinks.sh index 6bada37022..c3eb1158ef 100755 --- a/t/t0055-beyond-symlinks.sh +++ b/t/t0055-beyond-symlinks.sh @@ -15,12 +15,22 @@ test_expect_success SYMLINKS setup ' test_expect_success SYMLINKS 'update-index --add beyond symlinks' ' test_must_fail git update-index --add c/d && - ! ( git ls-files | grep c/d ) + cat >expect <<-\EOF && + a + b/d + EOF + git ls-files >actual && + test_cmp expect actual ' test_expect_success SYMLINKS 'add beyond symlinks' ' test_must_fail git add c/d && - ! ( git ls-files | grep c/d ) + cat >expect <<-\EOF && + a + b/d + EOF + git ls-files >actual && + test_cmp expect actual ' test_done diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh index 68e29c904a..0afa3d0d31 100755 --- a/t/t0060-path-utils.sh +++ b/t/t0060-path-utils.sh @@ -10,20 +10,27 @@ TEST_PASSES_SANITIZE_LEAK=true norm_path() { expected=$(test-tool path-utils print_path "$2") - test_expect_success $3 "normalize path: $1 => $2" \ - "test \"\$(test-tool path-utils normalize_path_copy '$1')\" = '$expected'" + test_expect_success $3 "normalize path: $1 => $2" " + echo '$expected' >expect && + test-tool path-utils normalize_path_copy '$1' >actual && + test_cmp expect actual + " } relative_path() { expected=$(test-tool path-utils print_path "$3") - test_expect_success $4 "relative path: $1 $2 => $3" \ - "test \"\$(test-tool path-utils relative_path '$1' '$2')\" = '$expected'" + test_expect_success $4 "relative path: $1 $2 => $3" " + echo '$expected' >expect && + test-tool path-utils relative_path '$1' '$2' >actual && + test_cmp expect actual + " } test_submodule_relative_url() { test_expect_success "test_submodule_relative_url: $1 $2 $3 => $4" " - actual=\$(test-tool submodule resolve-relative-url '$1' '$2' '$3') && - test \"\$actual\" = '$4' + echo '$4' >expect && + test-tool submodule resolve-relative-url '$1' '$2' '$3' >actual && + test_cmp expect actual " } @@ -64,9 +71,11 @@ ancestor() { expected=$(($expected-$rootslash+$rootoff)) ;; esac - test_expect_success $4 "longest ancestor: $1 $2 => $expected" \ - "actual=\$(test-tool path-utils longest_ancestor_length '$1' '$2') && - test \"\$actual\" = '$expected'" + test_expect_success $4 "longest ancestor: $1 $2 => $expected" " + echo '$expected' >expect && + test-tool path-utils longest_ancestor_length '$1' '$2' >actual && + test_cmp expect actual + " } # Some absolute path tests should be skipped on Windows due to path mangling @@ -166,8 +175,10 @@ ancestor D:/Users/me C:/ -1 MINGW ancestor //server/share/my-directory //server/share/ 14 MINGW test_expect_success 'strip_path_suffix' ' - test c:/msysgit = $(test-tool path-utils strip_path_suffix \ - c:/msysgit/libexec//git-core libexec/git-core) + echo c:/msysgit >expect && + test-tool path-utils strip_path_suffix \ + c:/msysgit/libexec//git-core libexec/git-core >actual && + test_cmp expect actual ' test_expect_success 'absolute path rejects the empty string' ' @@ -188,35 +199,61 @@ test_expect_success 'real path rejects the empty string' ' ' test_expect_success POSIX 'real path works on absolute paths 1' ' + echo / >expect && + test-tool path-utils real_path "/" >actual && + test_cmp expect actual && + nopath="hopefully-absent-path" && - test "/" = "$(test-tool path-utils real_path "/")" && - test "/$nopath" = "$(test-tool path-utils real_path "/$nopath")" + echo "/$nopath" >expect && + test-tool path-utils real_path "/$nopath" >actual && + test_cmp expect actual ' test_expect_success 'real path works on absolute paths 2' ' - nopath="hopefully-absent-path" && # Find an existing top-level directory for the remaining tests: d=$(pwd -P | sed -e "s|^\([^/]*/[^/]*\)/.*|\1|") && - test "$d" = "$(test-tool path-utils real_path "$d")" && - test "$d/$nopath" = "$(test-tool path-utils real_path "$d/$nopath")" + echo "$d" >expect && + test-tool path-utils real_path "$d" >actual && + test_cmp expect actual && + + nopath="hopefully-absent-path" && + echo "$d/$nopath" >expect && + test-tool path-utils real_path "$d/$nopath" >actual && + test_cmp expect actual ' test_expect_success POSIX 'real path removes extra leading slashes' ' + echo "/" >expect && + test-tool path-utils real_path "///" >actual && + test_cmp expect actual && + nopath="hopefully-absent-path" && - test "/" = "$(test-tool path-utils real_path "///")" && - test "/$nopath" = "$(test-tool path-utils real_path "///$nopath")" && + echo "/$nopath" >expect && + test-tool path-utils real_path "///$nopath" >actual && + test_cmp expect actual && + # Find an existing top-level directory for the remaining tests: d=$(pwd -P | sed -e "s|^\([^/]*/[^/]*\)/.*|\1|") && - test "$d" = "$(test-tool path-utils real_path "//$d")" && - test "$d/$nopath" = "$(test-tool path-utils real_path "//$d/$nopath")" + echo "$d" >expect && + test-tool path-utils real_path "//$d" >actual && + test_cmp expect actual && + + echo "$d/$nopath" >expect && + test-tool path-utils real_path "//$d/$nopath" >actual && + test_cmp expect actual ' test_expect_success 'real path removes other extra slashes' ' - nopath="hopefully-absent-path" && # Find an existing top-level directory for the remaining tests: d=$(pwd -P | sed -e "s|^\([^/]*/[^/]*\)/.*|\1|") && - test "$d" = "$(test-tool path-utils real_path "$d///")" && - test "$d/$nopath" = "$(test-tool path-utils real_path "$d///$nopath")" + echo "$d" >expect && + test-tool path-utils real_path "$d///" >actual && + test_cmp expect actual && + + nopath="hopefully-absent-path" && + echo "$d/$nopath" >expect && + test-tool path-utils real_path "$d///$nopath" >actual && + test_cmp expect actual ' test_expect_success SYMLINKS 'real path works on symlinks' ' @@ -227,19 +264,29 @@ test_expect_success SYMLINKS 'real path works on symlinks' ' mkdir third && dir="$(cd .git && pwd -P)" && dir2=third/../second/other/.git && - test "$dir" = "$(test-tool path-utils real_path $dir2)" && + echo "$dir" >expect && + test-tool path-utils real_path $dir2 >actual && + test_cmp expect actual && file="$dir"/index && - test "$file" = "$(test-tool path-utils real_path $dir2/index)" && + echo "$file" >expect && + test-tool path-utils real_path $dir2/index >actual && + test_cmp expect actual && basename=blub && - test "$dir/$basename" = "$(cd .git && test-tool path-utils real_path "$basename")" && + echo "$dir/$basename" >expect && + test-tool -C .git path-utils real_path "$basename" >actual && + test_cmp expect actual && ln -s ../first/file .git/syml && sym="$(cd first && pwd -P)"/file && - test "$sym" = "$(test-tool path-utils real_path "$dir2/syml")" + echo "$sym" >expect && + test-tool path-utils real_path "$dir2/syml" >actual && + test_cmp expect actual ' test_expect_success SYMLINKS 'prefix_path works with absolute paths to work tree symlinks' ' ln -s target symlink && - test "$(test-tool path-utils prefix_path prefix "$(pwd)/symlink")" = "symlink" + echo "symlink" >expect && + test-tool path-utils prefix_path prefix "$(pwd)/symlink" >actual && + test_cmp expect actual ' test_expect_success 'prefix_path works with only absolute path to work tree' ' @@ -255,7 +302,10 @@ test_expect_success 'prefix_path rejects absolute path to dir with same beginnin test_expect_success SYMLINKS 'prefix_path works with absolute path to a symlink to work tree having same beginning as work tree' ' git init repo && ln -s repo repolink && - test "a" = "$(cd repo && test-tool path-utils prefix_path prefix "$(pwd)/../repolink/a")" + echo "a" >expect && + repo_path="$(cd repo && pwd)" && + test-tool -C repo path-utils prefix_path prefix "$repo_path/../repolink/a" >actual && + test_cmp expect actual ' relative_path /foo/a/b/c/ /foo/a/b/ c/ diff --git a/t/t0061-run-command.sh b/t/t0061-run-command.sh index e2411f6a9b..20986b693c 100755 --- a/t/t0061-run-command.sh +++ b/t/t0061-run-command.sh @@ -19,12 +19,12 @@ test_expect_success MINGW 'subprocess inherits only std handles' ' test_expect_success 'start_command reports ENOENT (slash)' ' test-tool run-command start-command-ENOENT ./does-not-exist 2>err && - test_i18ngrep "\./does-not-exist" err + test_grep "\./does-not-exist" err ' test_expect_success 'start_command reports ENOENT (no slash)' ' test-tool run-command start-command-ENOENT does-not-exist 2>err && - test_i18ngrep "does-not-exist" err + test_grep "does-not-exist" err ' test_expect_success 'run_command can run a command' ' @@ -49,7 +49,7 @@ test_expect_success !RUNS_COMMANDS_FROM_PWD 'run_command is restricted to PATH' echo yikes EOF test_must_fail test-tool run-command run-command should-not-run 2>err && - test_i18ngrep "should-not-run" err + test_grep "should-not-run" err ' test_expect_success !MINGW 'run_command can run a script without a #! line' ' diff --git a/t/t0063-string-list.sh b/t/t0063-string-list.sh index 46d4839194..1fee6d9010 100755 --- a/t/t0063-string-list.sh +++ b/t/t0063-string-list.sh @@ -18,6 +18,14 @@ test_split () { " } +test_split_in_place() { + cat >expected && + test_expect_success "split (in place) $1 at $2, max $3" " + test-tool string-list split_in_place '$1' '$2' '$3' >actual && + test_cmp expected actual + " +} + test_split "foo:bar:baz" ":" "-1" <<EOF 3 [0]: "foo" @@ -61,6 +69,49 @@ test_split ":" ":" "-1" <<EOF [1]: "" EOF +test_split_in_place "foo:;:bar:;:baz:;:" ":;" "-1" <<EOF +10 +[0]: "foo" +[1]: "" +[2]: "" +[3]: "bar" +[4]: "" +[5]: "" +[6]: "baz" +[7]: "" +[8]: "" +[9]: "" +EOF + +test_split_in_place "foo:;:bar:;:baz" ":;" "0" <<EOF +1 +[0]: "foo:;:bar:;:baz" +EOF + +test_split_in_place "foo:;:bar:;:baz" ":;" "1" <<EOF +2 +[0]: "foo" +[1]: ";:bar:;:baz" +EOF + +test_split_in_place "foo:;:bar:;:baz" ":;" "2" <<EOF +3 +[0]: "foo" +[1]: "" +[2]: ":bar:;:baz" +EOF + +test_split_in_place "foo:;:bar:;:" ":;" "-1" <<EOF +7 +[0]: "foo" +[1]: "" +[2]: "" +[3]: "bar" +[4]: "" +[5]: "" +[6]: "" +EOF + test_expect_success "test filter_string_list" ' test "x-" = "x$(test-tool string-list filter - y)" && test "x-" = "x$(test-tool string-list filter no y)" && diff --git a/t/t0068-for-each-repo.sh b/t/t0068-for-each-repo.sh index 3648d439a8..4b90b74d5d 100755 --- a/t/t0068-for-each-repo.sh +++ b/t/t0068-for-each-repo.sh @@ -40,4 +40,23 @@ test_expect_success 'do nothing on empty config' ' git for-each-repo --config=bogus.config -- help --no-such-option ' +test_expect_success 'error on bad config keys' ' + test_expect_code 129 git for-each-repo --config=a && + test_expect_code 129 git for-each-repo --config=a.b. && + test_expect_code 129 git for-each-repo --config="'\''.b" +' + +test_expect_success 'error on NULL value for config keys' ' + cat >>.git/config <<-\EOF && + [empty] + key + EOF + cat >expect <<-\EOF && + error: missing value for '\''empty.key'\'' + EOF + test_expect_code 129 git for-each-repo --config=empty.key 2>actual.raw && + grep ^error actual.raw >actual && + test_cmp expect actual +' + test_done diff --git a/t/t0070-fundamental.sh b/t/t0070-fundamental.sh index 574de34198..487bc8d905 100755 --- a/t/t0070-fundamental.sh +++ b/t/t0070-fundamental.sh @@ -44,13 +44,13 @@ test_expect_success 'incomplete sideband messages are reassembled' ' test_expect_success 'eof on sideband message is reported' ' printf 1234 >input && test-tool pkt-line receive-sideband <input 2>err && - test_i18ngrep "unexpected disconnect" err + test_grep "unexpected disconnect" err ' test_expect_success 'missing sideband designator is reported' ' printf 0004 >input && test-tool pkt-line receive-sideband <input 2>err && - test_i18ngrep "missing sideband" err + test_grep "missing sideband" err ' test_done diff --git a/t/t0080-unit-test-output.sh b/t/t0080-unit-test-output.sh new file mode 100755 index 0000000000..961b54b06c --- /dev/null +++ b/t/t0080-unit-test-output.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +test_description='Test the output of the unit test framework' + +. ./test-lib.sh + +test_expect_success 'TAP output from unit tests' ' + cat >expect <<-EOF && + ok 1 - passing test + ok 2 - passing test and assertion return 1 + # check "1 == 2" failed at t/unit-tests/t-basic.c:76 + # left: 1 + # right: 2 + not ok 3 - failing test + ok 4 - failing test and assertion return 0 + not ok 5 - passing TEST_TODO() # TODO + ok 6 - passing TEST_TODO() returns 1 + # todo check ${SQ}check(x)${SQ} succeeded at t/unit-tests/t-basic.c:25 + not ok 7 - failing TEST_TODO() + ok 8 - failing TEST_TODO() returns 0 + # check "0" failed at t/unit-tests/t-basic.c:30 + # skipping test - missing prerequisite + # skipping check ${SQ}1${SQ} at t/unit-tests/t-basic.c:32 + ok 9 - test_skip() # SKIP + ok 10 - skipped test returns 1 + # skipping test - missing prerequisite + ok 11 - test_skip() inside TEST_TODO() # SKIP + ok 12 - test_skip() inside TEST_TODO() returns 1 + # check "0" failed at t/unit-tests/t-basic.c:48 + not ok 13 - TEST_TODO() after failing check + ok 14 - TEST_TODO() after failing check returns 0 + # check "0" failed at t/unit-tests/t-basic.c:56 + not ok 15 - failing check after TEST_TODO() + ok 16 - failing check after TEST_TODO() returns 0 + # check "!strcmp("\thello\\\\", "there\"\n")" failed at t/unit-tests/t-basic.c:61 + # left: "\011hello\\\\" + # right: "there\"\012" + # check "!strcmp("NULL", NULL)" failed at t/unit-tests/t-basic.c:62 + # left: "NULL" + # right: NULL + # check "${SQ}a${SQ} == ${SQ}\n${SQ}" failed at t/unit-tests/t-basic.c:63 + # left: ${SQ}a${SQ} + # right: ${SQ}\012${SQ} + # check "${SQ}\\\\${SQ} == ${SQ}\\${SQ}${SQ}" failed at t/unit-tests/t-basic.c:64 + # left: ${SQ}\\\\${SQ} + # right: ${SQ}\\${SQ}${SQ} + not ok 17 - messages from failing string and char comparison + # BUG: test has no checks at t/unit-tests/t-basic.c:91 + not ok 18 - test with no checks + ok 19 - test with no checks returns 0 + 1..19 + EOF + + ! "$GIT_BUILD_DIR"/t/unit-tests/bin/t-basic >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t0081-find-pack.sh b/t/t0081-find-pack.sh new file mode 100755 index 0000000000..67b11216a3 --- /dev/null +++ b/t/t0081-find-pack.sh @@ -0,0 +1,82 @@ +#!/bin/sh + +test_description='test `test-tool find-pack`' + +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit one && + test_commit two && + test_commit three && + test_commit four && + test_commit five +' + +test_expect_success 'repack everything into a single packfile' ' + git repack -a -d --no-write-bitmap-index && + + head_commit_pack=$(test-tool find-pack HEAD) && + head_tree_pack=$(test-tool find-pack HEAD^{tree}) && + one_pack=$(test-tool find-pack HEAD:one.t) && + three_pack=$(test-tool find-pack HEAD:three.t) && + old_commit_pack=$(test-tool find-pack HEAD~4) && + + test-tool find-pack --check-count 1 HEAD && + test-tool find-pack --check-count=1 HEAD^{tree} && + ! test-tool find-pack --check-count=0 HEAD:one.t && + ! test-tool find-pack -c 2 HEAD:one.t && + test-tool find-pack -c 1 HEAD:three.t && + + # Packfile exists at the right path + case "$head_commit_pack" in + ".git/objects/pack/pack-"*".pack") true ;; + *) false ;; + esac && + test -f "$head_commit_pack" && + + # Everything is in the same pack + test "$head_commit_pack" = "$head_tree_pack" && + test "$head_commit_pack" = "$one_pack" && + test "$head_commit_pack" = "$three_pack" && + test "$head_commit_pack" = "$old_commit_pack" +' + +test_expect_success 'add more packfiles' ' + git rev-parse HEAD^{tree} HEAD:two.t HEAD:four.t >objects && + git pack-objects .git/objects/pack/mypackname1 >packhash1 <objects && + + git rev-parse HEAD~ HEAD~^{tree} HEAD:five.t >objects && + git pack-objects .git/objects/pack/mypackname2 >packhash2 <objects && + + head_commit_pack=$(test-tool find-pack HEAD) && + + # HEAD^{tree} is in 2 packfiles + test-tool find-pack HEAD^{tree} >head_tree_packs && + grep "$head_commit_pack" head_tree_packs && + grep mypackname1 head_tree_packs && + ! grep mypackname2 head_tree_packs && + test-tool find-pack --check-count 2 HEAD^{tree} && + ! test-tool find-pack --check-count 1 HEAD^{tree} && + + # HEAD:five.t is also in 2 packfiles + test-tool find-pack HEAD:five.t >five_packs && + grep "$head_commit_pack" five_packs && + ! grep mypackname1 five_packs && + grep mypackname2 five_packs && + test-tool find-pack -c 2 HEAD:five.t && + ! test-tool find-pack --check-count=0 HEAD:five.t +' + +test_expect_success 'add more commits (as loose objects)' ' + test_commit six && + test_commit seven && + + test -z "$(test-tool find-pack HEAD)" && + test -z "$(test-tool find-pack HEAD:six.t)" && + test-tool find-pack --check-count 0 HEAD && + test-tool find-pack -c 0 HEAD:six.t && + ! test-tool find-pack -c 1 HEAD:seven.t +' + +test_done diff --git a/t/t0091-bugreport.sh b/t/t0091-bugreport.sh index b6d2f591ac..8798feefe3 100755 --- a/t/t0091-bugreport.sh +++ b/t/t0091-bugreport.sh @@ -5,29 +5,50 @@ test_description='git bugreport' TEST_PASSES_SANITIZE_LEAK=true . ./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 'create a report' ' + git bugreport -s format && + test_file_not_empty git-bugreport-format.txt +' + +test_expect_success 'report contains wanted template (before first section)' ' + sed -ne "/^\[/q;p" git-bugreport-format.txt >actual && + cat >expect <<-\EOF && + Thank you for filling out a Git bug report! + Please answer the following questions to help us understand your issue. + + What did you do before the bug happened? (Steps to reproduce your issue) + + What did you expect to happen? (Expected behavior) + + What happened instead? (Actual behavior) + + What'\''s different between what you expected and what actually happened? + + Anything else you want to add: + + Please review the rest of the bug report below. + You can delete any lines you don'\''t wish to share. + + + EOF + test_cmp expect actual +' + +test_expect_success 'sanity check "System Info" section' ' + test_when_finished rm -f git-bugreport-format.txt && + + sed -ne "/^\[System Info\]$/,/^$/p" <git-bugreport-format.txt >system && + + # The beginning should match "git version --build-info" verbatim, + # but rather than checking bit-for-bit equality, just test some basics. + grep "git version [0-9]." system && + grep "shell-path: ." system && + + # After the version, there should be some more info. + # This is bound to differ from environment to environment, + # so we just do some rather high-level checks. + grep "uname: ." system && + grep "compiler info: ." system ' test_expect_success 'dies if file with same name as report already exists' ' @@ -44,7 +65,14 @@ test_expect_success '--output-directory puts the report in the provided dir' ' test_expect_success 'incorrect arguments abort with usage' ' test_must_fail git bugreport --false 2>output && - test_i18ngrep usage output && + test_grep usage output && + test_path_is_missing git-bugreport-* +' + +test_expect_success 'incorrect positional arguments abort with usage and hint' ' + test_must_fail git bugreport false 2>output && + test_grep usage output && + test_grep false output && test_path_is_missing git-bugreport-* ' diff --git a/t/t0100-previous.sh b/t/t0100-previous.sh index a16cc3d298..70a3223f21 100755 --- a/t/t0100-previous.sh +++ b/t/t0100-previous.sh @@ -12,7 +12,9 @@ test_expect_success 'branch -d @{-1}' ' test_commit A && git checkout -b junk && git checkout - && - test "$(git symbolic-ref HEAD)" = refs/heads/main && + echo refs/heads/main >expect && + git symbolic-ref HEAD >actual && + test_cmp expect actual && git branch -d @{-1} && test_must_fail git rev-parse --verify refs/heads/junk ' @@ -21,7 +23,9 @@ test_expect_success 'branch -d @{-12} when there is not enough switches yet' ' git reflog expire --expire=now && git checkout -b junk2 && git checkout - && - test "$(git symbolic-ref HEAD)" = refs/heads/main && + echo refs/heads/main >expect && + git symbolic-ref HEAD >actual && + test_cmp expect actual && test_must_fail git branch -d @{-12} && git rev-parse --verify refs/heads/main ' diff --git a/t/t0202/test.pl b/t/t0202/test.pl index 2cbf7b9590..47d96a2a13 100755 --- a/t/t0202/test.pl +++ b/t/t0202/test.pl @@ -1,5 +1,5 @@ #!/usr/bin/perl -use 5.008; +use 5.008001; use lib (split(/:/, $ENV{GITPERLLIB})); use strict; use warnings; diff --git a/t/t0210-trace2-normal.sh b/t/t0210-trace2-normal.sh index 80e76a4695..c312657a12 100755 --- a/t/t0210-trace2-normal.sh +++ b/t/t0210-trace2-normal.sh @@ -2,7 +2,7 @@ test_description='test trace2 facility (normal target)' -TEST_PASSES_SANITIZE_LEAK=true +TEST_PASSES_SANITIZE_LEAK=false . ./test-lib.sh # Turn off any inherited trace2 settings for this test. @@ -283,4 +283,22 @@ test_expect_success 'using global config with include' ' test_cmp expect actual ' +test_expect_success 'unsafe URLs are redacted by default' ' + test_when_finished \ + "rm -r trace.normal unredacted.normal clone clone2" && + + test_config_global \ + "url.$(pwd).insteadOf" https://user:pwd@example.com/ && + test_config_global trace2.configParams "core.*,remote.*.url" && + + GIT_TRACE2="$(pwd)/trace.normal" \ + git clone https://user:pwd@example.com/ clone && + ! grep user:pwd trace.normal && + + GIT_TRACE2_REDACT=0 GIT_TRACE2="$(pwd)/unredacted.normal" \ + git clone https://user:pwd@example.com/ clone2 && + grep "start .* clone https://user:pwd@example.com" unredacted.normal && + grep "remote.origin.url=https://user:pwd@example.com" unredacted.normal +' + test_done diff --git a/t/t0211-trace2-perf.sh b/t/t0211-trace2-perf.sh index b4e9135118..290b6eaaab 100755 --- a/t/t0211-trace2-perf.sh +++ b/t/t0211-trace2-perf.sh @@ -2,7 +2,7 @@ test_description='test trace2 facility (perf target)' -TEST_PASSES_SANITIZE_LEAK=true +TEST_PASSES_SANITIZE_LEAK=false . ./test-lib.sh # Turn off any inherited trace2 settings for this test. @@ -203,7 +203,7 @@ test_expect_success 'stopwatch timer test/test1' ' have_timer_event "main" "timer" "test" "test1" 5 actual ' -test_expect_success PTHREAD 'stopwatch timer test/test2' ' +test_expect_success PTHREADS 'stopwatch timer test/test2' ' test_when_finished "rm trace.perf actual" && test_config_global trace2.perfBrief 1 && test_config_global trace2.perfTarget "$(pwd)/trace.perf" && @@ -249,7 +249,7 @@ test_expect_success 'global counter test/test1' ' have_counter_event "main" "counter" "test" "test1" 15 actual ' -test_expect_success PTHREAD 'global counter test/test2' ' +test_expect_success PTHREADS 'global counter test/test2' ' test_when_finished "rm trace.perf actual" && test_config_global trace2.perfBrief 1 && test_config_global trace2.perfTarget "$(pwd)/trace.perf" && @@ -268,4 +268,23 @@ test_expect_success PTHREAD 'global counter test/test2' ' have_counter_event "main" "counter" "test" "test2" 60 actual ' +test_expect_success 'unsafe URLs are redacted by default' ' + test_when_finished \ + "rm -r actual trace.perf unredacted.perf clone clone2" && + + test_config_global \ + "url.$(pwd).insteadOf" https://user:pwd@example.com/ && + test_config_global trace2.configParams "core.*,remote.*.url" && + + GIT_TRACE2_PERF="$(pwd)/trace.perf" \ + git clone https://user:pwd@example.com/ clone && + ! grep user:pwd trace.perf && + + GIT_TRACE2_REDACT=0 GIT_TRACE2_PERF="$(pwd)/unredacted.perf" \ + git clone https://user:pwd@example.com/ clone2 && + perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <unredacted.perf >actual && + grep "d0|main|start|.* clone https://user:pwd@example.com" actual && + grep "d0|main|def_param|.*|remote.origin.url:https://user:pwd@example.com" actual +' + test_done diff --git a/t/t0212-trace2-event.sh b/t/t0212-trace2-event.sh index 6d3374ff77..147643d582 100755 --- a/t/t0212-trace2-event.sh +++ b/t/t0212-trace2-event.sh @@ -323,4 +323,44 @@ test_expect_success 'discard traces when there are too many files' ' head -n2 trace_target_dir/git-trace2-discard | tail -n1 | grep \"event\":\"too_many_files\" ' +# In the following "...redact..." tests, skip testing the GIT_TRACE2_REDACT=0 +# case because we would need to exactly model the full JSON event stream like +# we did in the basic tests above and I do not think it is worth it. + +test_expect_success 'unsafe URLs are redacted by default in cmd_start events' ' + test_when_finished \ + "rm -r trace.event" && + + GIT_TRACE2_EVENT="$(pwd)/trace.event" \ + test-tool trace2 300redact_start git clone https://user:pwd@example.com/ clone2 && + ! grep user:pwd trace.event +' + +test_expect_success 'unsafe URLs are redacted by default in child_start events' ' + test_when_finished \ + "rm -r trace.event" && + + GIT_TRACE2_EVENT="$(pwd)/trace.event" \ + test-tool trace2 301redact_child_start git clone https://user:pwd@example.com/ clone2 && + ! grep user:pwd trace.event +' + +test_expect_success 'unsafe URLs are redacted by default in exec events' ' + test_when_finished \ + "rm -r trace.event" && + + GIT_TRACE2_EVENT="$(pwd)/trace.event" \ + test-tool trace2 302redact_exec git clone https://user:pwd@example.com/ clone2 && + ! grep user:pwd trace.event +' + +test_expect_success 'unsafe URLs are redacted by default in def_param events' ' + test_when_finished \ + "rm -r trace.event" && + + GIT_TRACE2_EVENT="$(pwd)/trace.event" \ + test-tool trace2 303redact_def_param url https://user:pwd@example.com/ && + ! grep user:pwd trace.event +' + test_done diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh index c66d91e82d..400f6bdbca 100755 --- a/t/t0300-credentials.sh +++ b/t/t0300-credentials.sh @@ -214,6 +214,24 @@ test_expect_success 'credential_approve stores password expiry' ' EOF ' +test_expect_success 'credential_approve stores oauth refresh token' ' + check approve useless <<-\EOF + protocol=http + host=example.com + username=foo + password=bar + oauth_refresh_token=xyzzy + -- + -- + useless: store + useless: protocol=http + useless: host=example.com + useless: username=foo + useless: password=bar + useless: oauth_refresh_token=xyzzy + EOF +' + test_expect_success 'do not bother storing password-less credential' ' check approve useless <<-\EOF protocol=http @@ -808,8 +826,8 @@ test_expect_success 'credential config with partial URLs' ' git -c credential.$partial.helper=yep \ -c credential.with%0anewline.username=uh-oh \ - credential fill <stdin >stdout 2>stderr && - test_i18ngrep "skipping credential lookup for key" stderr + credential fill <stdin 2>stderr && + test_grep "skipping credential lookup for key" stderr ' test_done diff --git a/t/t0301-credential-cache.sh b/t/t0301-credential-cache.sh index 698b7159f0..8300faadea 100755 --- a/t/t0301-credential-cache.sh +++ b/t/t0301-credential-cache.sh @@ -29,6 +29,8 @@ test_atexit 'git credential-cache exit' # test that the daemon works with no special setup helper_test cache +helper_test_password_expiry_utc cache +helper_test_oauth_refresh_token cache test_expect_success 'socket defaults to ~/.cache/git/credential/socket' ' test_when_finished " diff --git a/t/t0303-credential-external.sh b/t/t0303-credential-external.sh index f028fd1418..095574bfc6 100755 --- a/t/t0303-credential-external.sh +++ b/t/t0303-credential-external.sh @@ -45,6 +45,8 @@ test -z "$GIT_TEST_CREDENTIAL_HELPER_SETUP" || helper_test_clean "$GIT_TEST_CREDENTIAL_HELPER" helper_test "$GIT_TEST_CREDENTIAL_HELPER" +helper_test_password_expiry_utc "$GIT_TEST_CREDENTIAL_HELPER" +helper_test_oauth_refresh_token "$GIT_TEST_CREDENTIAL_HELPER" if test -z "$GIT_TEST_CREDENTIAL_HELPER_TIMEOUT"; then say "# skipping timeout tests (GIT_TEST_CREDENTIAL_HELPER_TIMEOUT not set)" diff --git a/t/t0410-partial-clone.sh b/t/t0410-partial-clone.sh index 5b7bee888d..6b6424b3df 100755 --- a/t/t0410-partial-clone.sh +++ b/t/t0410-partial-clone.sh @@ -49,7 +49,7 @@ test_expect_success 'convert shallow clone to partial clone' ' test_cmp_config -C client 1 core.repositoryformatversion ' -test_expect_success SHA1 'convert to partial clone with noop extension' ' +test_expect_success SHA1,REFFILES 'convert to partial clone with noop extension' ' rm -fr server client && test_create_repo server && test_commit -C server my_commit 1 && @@ -60,7 +60,7 @@ test_expect_success SHA1 'convert to partial clone with noop extension' ' git -C client fetch --unshallow --filter="blob:none" ' -test_expect_success SHA1 'converting to partial clone fails with unrecognized extension' ' +test_expect_success SHA1,REFFILES 'converting to partial clone fails with unrecognized extension' ' rm -fr server client && test_create_repo server && test_commit -C server my_commit 1 && diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh index 3fb1b0c162..88c524f655 100755 --- a/t/t1001-read-tree-m-2way.sh +++ b/t/t1001-read-tree-m-2way.sh @@ -26,7 +26,7 @@ TEST_PASSES_SANITIZE_LEAK=true . "$TEST_DIRECTORY"/lib-read-tree.sh read_tree_twoway () { - git read-tree -m "$1" "$2" && git ls-files --stage + git read-tree -m "$1" "$2" && git ls-files --stage } compare_change () { diff --git a/t/t1002-read-tree-m-u-2way.sh b/t/t1002-read-tree-m-u-2way.sh index cdc077ce12..a7c2ed0d7c 100755 --- a/t/t1002-read-tree-m-u-2way.sh +++ b/t/t1002-read-tree-m-u-2way.sh @@ -37,315 +37,312 @@ check_cache_at () { esac } -test_expect_success \ - setup \ - 'echo frotz >frotz && - echo nitfol >nitfol && - echo bozbar >bozbar && - echo rezrov >rezrov && - git update-index --add nitfol bozbar rezrov && - treeH=$(git write-tree) && - echo treeH $treeH && - git ls-tree $treeH && - - echo gnusto >bozbar && - git update-index --add frotz bozbar --force-remove rezrov && - git ls-files --stage >M.out && - treeM=$(git write-tree) && - echo treeM $treeM && - git ls-tree $treeM && - cp bozbar bozbar.M && - cp frotz frotz.M && - cp nitfol nitfol.M && - git diff-tree $treeH $treeM' - -test_expect_success \ - '1, 2, 3 - no carry forward' \ - 'rm -f .git/index nitfol bozbar rezrov frotz && - read_tree_u_must_succeed --reset -u $treeH && - read_tree_u_must_succeed -m -u $treeH $treeM && - git ls-files --stage >1-3.out && - cmp M.out 1-3.out && - test_cmp bozbar.M bozbar && - test_cmp frotz.M frotz && - test_cmp nitfol.M nitfol && - check_cache_at bozbar clean && - check_cache_at frotz clean && - check_cache_at nitfol clean' - -test_expect_success \ - '4 - carry forward local addition.' \ - 'rm -f .git/index nitfol bozbar rezrov frotz && - read_tree_u_must_succeed --reset -u $treeH && - echo "+100644 X 0 yomin" >expected && - echo yomin >yomin && - git update-index --add yomin && - read_tree_u_must_succeed -m -u $treeH $treeM && - git ls-files --stage >4.out && - test_might_fail git diff -U0 --no-index M.out 4.out >4diff.out && - compare_change 4diff.out expected && - check_cache_at yomin clean && - test_cmp bozbar.M bozbar && - test_cmp frotz.M frotz && - test_cmp nitfol.M nitfol && - echo yomin >yomin1 && - diff yomin yomin1 && - rm -f yomin1' - -test_expect_success \ - '5 - carry forward local addition.' \ - 'rm -f .git/index nitfol bozbar rezrov frotz && - read_tree_u_must_succeed --reset -u $treeH && - read_tree_u_must_succeed -m -u $treeH && - echo yomin >yomin && - git update-index --add yomin && - echo yomin yomin >yomin && - read_tree_u_must_succeed -m -u $treeH $treeM && - git ls-files --stage >5.out && - test_might_fail git diff -U0 --no-index M.out 5.out >5diff.out && - compare_change 5diff.out expected && - check_cache_at yomin dirty && - test_cmp bozbar.M bozbar && - test_cmp frotz.M frotz && - test_cmp nitfol.M nitfol && - : dirty index should have prevented -u from checking it out. && - echo yomin yomin >yomin1 && - diff yomin yomin1 && - rm -f yomin1' - -test_expect_success \ - '6 - local addition already has the same.' \ - 'rm -f .git/index nitfol bozbar rezrov frotz && - read_tree_u_must_succeed --reset -u $treeH && - echo frotz >frotz && - git update-index --add frotz && - read_tree_u_must_succeed -m -u $treeH $treeM && - git ls-files --stage >6.out && - test_cmp M.out 6.out && - check_cache_at frotz clean && - test_cmp bozbar.M bozbar && - test_cmp frotz.M frotz && - test_cmp nitfol.M nitfol && - echo frotz >frotz1 && - diff frotz frotz1 && - rm -f frotz1' - -test_expect_success \ - '7 - local addition already has the same.' \ - 'rm -f .git/index nitfol bozbar rezrov frotz && - read_tree_u_must_succeed --reset -u $treeH && - echo frotz >frotz && - git update-index --add frotz && - echo frotz frotz >frotz && - read_tree_u_must_succeed -m -u $treeH $treeM && - git ls-files --stage >7.out && - test_cmp M.out 7.out && - check_cache_at frotz dirty && - test_cmp bozbar.M bozbar && - test_cmp nitfol.M nitfol && - : dirty index should have prevented -u from checking it out. && - echo frotz frotz >frotz1 && - diff frotz frotz1 && - rm -f frotz1' - -test_expect_success \ - '8 - conflicting addition.' \ - 'rm -f .git/index nitfol bozbar rezrov frotz && - read_tree_u_must_succeed --reset -u $treeH && - echo frotz frotz >frotz && - git update-index --add frotz && - ! read_tree_u_must_succeed -m -u $treeH $treeM' - -test_expect_success \ - '9 - conflicting addition.' \ - 'rm -f .git/index nitfol bozbar rezrov frotz && - read_tree_u_must_succeed --reset -u $treeH && - echo frotz frotz >frotz && - git update-index --add frotz && - echo frotz >frotz && - ! read_tree_u_must_succeed -m -u $treeH $treeM' - -test_expect_success \ - '10 - path removed.' \ - 'rm -f .git/index nitfol bozbar rezrov frotz && - read_tree_u_must_succeed --reset -u $treeH && - echo rezrov >rezrov && - git update-index --add rezrov && - read_tree_u_must_succeed -m -u $treeH $treeM && - git ls-files --stage >10.out && - cmp M.out 10.out && - test_cmp bozbar.M bozbar && - test_cmp frotz.M frotz && - test_cmp nitfol.M nitfol +test_expect_success setup ' + echo frotz >frotz && + echo nitfol >nitfol && + echo bozbar >bozbar && + echo rezrov >rezrov && + git update-index --add nitfol bozbar rezrov && + treeH=$(git write-tree) && + echo treeH $treeH && + git ls-tree $treeH && + + echo gnusto >bozbar && + git update-index --add frotz bozbar --force-remove rezrov && + git ls-files --stage >M.out && + treeM=$(git write-tree) && + echo treeM $treeM && + git ls-tree $treeM && + cp bozbar bozbar.M && + cp frotz frotz.M && + cp nitfol nitfol.M && + git diff-tree $treeH $treeM ' -test_expect_success \ - '11 - dirty path removed.' \ - 'rm -f .git/index nitfol bozbar rezrov frotz && - read_tree_u_must_succeed --reset -u $treeH && - echo rezrov >rezrov && - git update-index --add rezrov && - echo rezrov rezrov >rezrov && - ! read_tree_u_must_succeed -m -u $treeH $treeM' - -test_expect_success \ - '12 - unmatching local changes being removed.' \ - 'rm -f .git/index nitfol bozbar rezrov frotz && - read_tree_u_must_succeed --reset -u $treeH && - echo rezrov rezrov >rezrov && - git update-index --add rezrov && - ! read_tree_u_must_succeed -m -u $treeH $treeM' - -test_expect_success \ - '13 - unmatching local changes being removed.' \ - 'rm -f .git/index nitfol bozbar rezrov frotz && - read_tree_u_must_succeed --reset -u $treeH && - echo rezrov rezrov >rezrov && - git update-index --add rezrov && - echo rezrov >rezrov && - ! read_tree_u_must_succeed -m -u $treeH $treeM' +test_expect_success '1, 2, 3 - no carry forward' ' + rm -f .git/index nitfol bozbar rezrov frotz && + read_tree_u_must_succeed --reset -u $treeH && + read_tree_u_must_succeed -m -u $treeH $treeM && + git ls-files --stage >1-3.out && + cmp M.out 1-3.out && + test_cmp bozbar.M bozbar && + test_cmp frotz.M frotz && + test_cmp nitfol.M nitfol && + check_cache_at bozbar clean && + check_cache_at frotz clean && + check_cache_at nitfol clean +' + +test_expect_success '4 - carry forward local addition.' ' + rm -f .git/index nitfol bozbar rezrov frotz && + read_tree_u_must_succeed --reset -u $treeH && + echo "+100644 X 0 yomin" >expected && + echo yomin >yomin && + git update-index --add yomin && + read_tree_u_must_succeed -m -u $treeH $treeM && + git ls-files --stage >4.out && + test_might_fail git diff -U0 --no-index M.out 4.out >4diff.out && + compare_change 4diff.out expected && + check_cache_at yomin clean && + test_cmp bozbar.M bozbar && + test_cmp frotz.M frotz && + test_cmp nitfol.M nitfol && + echo yomin >yomin1 && + diff yomin yomin1 && + rm -f yomin1 +' + +test_expect_success '5 - carry forward local addition.' ' + rm -f .git/index nitfol bozbar rezrov frotz && + read_tree_u_must_succeed --reset -u $treeH && + read_tree_u_must_succeed -m -u $treeH && + echo yomin >yomin && + git update-index --add yomin && + echo yomin yomin >yomin && + read_tree_u_must_succeed -m -u $treeH $treeM && + git ls-files --stage >5.out && + test_might_fail git diff -U0 --no-index M.out 5.out >5diff.out && + compare_change 5diff.out expected && + check_cache_at yomin dirty && + test_cmp bozbar.M bozbar && + test_cmp frotz.M frotz && + test_cmp nitfol.M nitfol && + : dirty index should have prevented -u from checking it out. && + echo yomin yomin >yomin1 && + diff yomin yomin1 && + rm -f yomin1 +' + +test_expect_success '6 - local addition already has the same.' ' + rm -f .git/index nitfol bozbar rezrov frotz && + read_tree_u_must_succeed --reset -u $treeH && + echo frotz >frotz && + git update-index --add frotz && + read_tree_u_must_succeed -m -u $treeH $treeM && + git ls-files --stage >6.out && + test_cmp M.out 6.out && + check_cache_at frotz clean && + test_cmp bozbar.M bozbar && + test_cmp frotz.M frotz && + test_cmp nitfol.M nitfol && + echo frotz >frotz1 && + diff frotz frotz1 && + rm -f frotz1 +' + +test_expect_success '7 - local addition already has the same.' ' + rm -f .git/index nitfol bozbar rezrov frotz && + read_tree_u_must_succeed --reset -u $treeH && + echo frotz >frotz && + git update-index --add frotz && + echo frotz frotz >frotz && + read_tree_u_must_succeed -m -u $treeH $treeM && + git ls-files --stage >7.out && + test_cmp M.out 7.out && + check_cache_at frotz dirty && + test_cmp bozbar.M bozbar && + test_cmp nitfol.M nitfol && + : dirty index should have prevented -u from checking it out. && + echo frotz frotz >frotz1 && + diff frotz frotz1 && + rm -f frotz1 +' + +test_expect_success '8 - conflicting addition.' ' + rm -f .git/index nitfol bozbar rezrov frotz && + read_tree_u_must_succeed --reset -u $treeH && + echo frotz frotz >frotz && + git update-index --add frotz && + ! read_tree_u_must_succeed -m -u $treeH $treeM +' + +test_expect_success '9 - conflicting addition.' ' + rm -f .git/index nitfol bozbar rezrov frotz && + read_tree_u_must_succeed --reset -u $treeH && + echo frotz frotz >frotz && + git update-index --add frotz && + echo frotz >frotz && + ! read_tree_u_must_succeed -m -u $treeH $treeM +' + +test_expect_success '10 - path removed.' ' + rm -f .git/index nitfol bozbar rezrov frotz && + read_tree_u_must_succeed --reset -u $treeH && + echo rezrov >rezrov && + git update-index --add rezrov && + read_tree_u_must_succeed -m -u $treeH $treeM && + git ls-files --stage >10.out && + cmp M.out 10.out && + test_cmp bozbar.M bozbar && + test_cmp frotz.M frotz && + test_cmp nitfol.M nitfol +' + +test_expect_success '11 - dirty path removed.' ' + rm -f .git/index nitfol bozbar rezrov frotz && + read_tree_u_must_succeed --reset -u $treeH && + echo rezrov >rezrov && + git update-index --add rezrov && + echo rezrov rezrov >rezrov && + ! read_tree_u_must_succeed -m -u $treeH $treeM +' + +test_expect_success '12 - unmatching local changes being removed.' ' + rm -f .git/index nitfol bozbar rezrov frotz && + read_tree_u_must_succeed --reset -u $treeH && + echo rezrov rezrov >rezrov && + git update-index --add rezrov && + ! read_tree_u_must_succeed -m -u $treeH $treeM +' + +test_expect_success '13 - unmatching local changes being removed.' ' + rm -f .git/index nitfol bozbar rezrov frotz && + read_tree_u_must_succeed --reset -u $treeH && + echo rezrov rezrov >rezrov && + git update-index --add rezrov && + echo rezrov >rezrov && + ! read_tree_u_must_succeed -m -u $treeH $treeM +' cat >expected <<EOF -100644 X 0 nitfol +100644 X 0 nitfol EOF -test_expect_success \ - '14 - unchanged in two heads.' \ - 'rm -f .git/index nitfol bozbar rezrov frotz && - read_tree_u_must_succeed --reset -u $treeH && - echo nitfol nitfol >nitfol && - git update-index --add nitfol && - read_tree_u_must_succeed -m -u $treeH $treeM && - git ls-files --stage >14.out && - test_must_fail git diff -U0 --no-index M.out 14.out >14diff.out && - compare_change 14diff.out expected && - test_cmp bozbar.M bozbar && - test_cmp frotz.M frotz && - check_cache_at nitfol clean && - echo nitfol nitfol >nitfol1 && - diff nitfol nitfol1 && - rm -f nitfol1' - -test_expect_success \ - '15 - unchanged in two heads.' \ - 'rm -f .git/index nitfol bozbar rezrov frotz && - read_tree_u_must_succeed --reset -u $treeH && - echo nitfol nitfol >nitfol && - git update-index --add nitfol && - echo nitfol nitfol nitfol >nitfol && - read_tree_u_must_succeed -m -u $treeH $treeM && - git ls-files --stage >15.out && - test_must_fail git diff -U0 --no-index M.out 15.out >15diff.out && - compare_change 15diff.out expected && - check_cache_at nitfol dirty && - test_cmp bozbar.M bozbar && - test_cmp frotz.M frotz && - echo nitfol nitfol nitfol >nitfol1 && - diff nitfol nitfol1 && - rm -f nitfol1' - -test_expect_success \ - '16 - conflicting local change.' \ - 'rm -f .git/index nitfol bozbar rezrov frotz && - read_tree_u_must_succeed --reset -u $treeH && - echo bozbar bozbar >bozbar && - git update-index --add bozbar && - ! read_tree_u_must_succeed -m -u $treeH $treeM' - -test_expect_success \ - '17 - conflicting local change.' \ - 'rm -f .git/index nitfol bozbar rezrov frotz && - read_tree_u_must_succeed --reset -u $treeH && - echo bozbar bozbar >bozbar && - git update-index --add bozbar && - echo bozbar bozbar bozbar >bozbar && - ! read_tree_u_must_succeed -m -u $treeH $treeM' - -test_expect_success \ - '18 - local change already having a good result.' \ - 'rm -f .git/index nitfol bozbar rezrov frotz && - read_tree_u_must_succeed --reset -u $treeH && - echo gnusto >bozbar && - git update-index --add bozbar && - read_tree_u_must_succeed -m -u $treeH $treeM && - git ls-files --stage >18.out && - test_cmp M.out 18.out && - check_cache_at bozbar clean && - test_cmp bozbar.M bozbar && - test_cmp frotz.M frotz && - test_cmp nitfol.M nitfol +test_expect_success '14 - unchanged in two heads.' ' + rm -f .git/index nitfol bozbar rezrov frotz && + read_tree_u_must_succeed --reset -u $treeH && + echo nitfol nitfol >nitfol && + git update-index --add nitfol && + read_tree_u_must_succeed -m -u $treeH $treeM && + git ls-files --stage >14.out && + test_must_fail git diff -U0 --no-index M.out 14.out >14diff.out && + compare_change 14diff.out expected && + test_cmp bozbar.M bozbar && + test_cmp frotz.M frotz && + check_cache_at nitfol clean && + echo nitfol nitfol >nitfol1 && + diff nitfol nitfol1 && + rm -f nitfol1 ' -test_expect_success \ - '19 - local change already having a good result, further modified.' \ - 'rm -f .git/index nitfol bozbar rezrov frotz && - read_tree_u_must_succeed --reset -u $treeH && - echo gnusto >bozbar && - git update-index --add bozbar && - echo gnusto gnusto >bozbar && - read_tree_u_must_succeed -m -u $treeH $treeM && - git ls-files --stage >19.out && - test_cmp M.out 19.out && - check_cache_at bozbar dirty && - test_cmp frotz.M frotz && - test_cmp nitfol.M nitfol && - echo gnusto gnusto >bozbar1 && - diff bozbar bozbar1 && - rm -f bozbar1' - -test_expect_success \ - '20 - no local change, use new tree.' \ - 'rm -f .git/index nitfol bozbar rezrov frotz && - read_tree_u_must_succeed --reset -u $treeH && - echo bozbar >bozbar && - git update-index --add bozbar && - read_tree_u_must_succeed -m -u $treeH $treeM && - git ls-files --stage >20.out && - test_cmp M.out 20.out && - check_cache_at bozbar clean && - test_cmp bozbar.M bozbar && - test_cmp frotz.M frotz && - test_cmp nitfol.M nitfol +test_expect_success '15 - unchanged in two heads.' ' + rm -f .git/index nitfol bozbar rezrov frotz && + read_tree_u_must_succeed --reset -u $treeH && + echo nitfol nitfol >nitfol && + git update-index --add nitfol && + echo nitfol nitfol nitfol >nitfol && + read_tree_u_must_succeed -m -u $treeH $treeM && + git ls-files --stage >15.out && + test_must_fail git diff -U0 --no-index M.out 15.out >15diff.out && + compare_change 15diff.out expected && + check_cache_at nitfol dirty && + test_cmp bozbar.M bozbar && + test_cmp frotz.M frotz && + echo nitfol nitfol nitfol >nitfol1 && + diff nitfol nitfol1 && + rm -f nitfol1 ' -test_expect_success \ - '21 - no local change, dirty cache.' \ - 'rm -f .git/index nitfol bozbar rezrov frotz && - read_tree_u_must_succeed --reset -u $treeH && - echo bozbar >bozbar && - git update-index --add bozbar && - echo gnusto gnusto >bozbar && - ! read_tree_u_must_succeed -m -u $treeH $treeM' +test_expect_success '16 - conflicting local change.' ' + rm -f .git/index nitfol bozbar rezrov frotz && + read_tree_u_must_succeed --reset -u $treeH && + echo bozbar bozbar >bozbar && + git update-index --add bozbar && + ! read_tree_u_must_succeed -m -u $treeH $treeM +' + +test_expect_success '17 - conflicting local change.' ' + rm -f .git/index nitfol bozbar rezrov frotz && + read_tree_u_must_succeed --reset -u $treeH && + echo bozbar bozbar >bozbar && + git update-index --add bozbar && + echo bozbar bozbar bozbar >bozbar && + ! read_tree_u_must_succeed -m -u $treeH $treeM +' + +test_expect_success '18 - local change already having a good result.' ' + rm -f .git/index nitfol bozbar rezrov frotz && + read_tree_u_must_succeed --reset -u $treeH && + echo gnusto >bozbar && + git update-index --add bozbar && + read_tree_u_must_succeed -m -u $treeH $treeM && + git ls-files --stage >18.out && + test_cmp M.out 18.out && + check_cache_at bozbar clean && + test_cmp bozbar.M bozbar && + test_cmp frotz.M frotz && + test_cmp nitfol.M nitfol +' + +test_expect_success '19 - local change already having a good result, further modified.' ' + rm -f .git/index nitfol bozbar rezrov frotz && + read_tree_u_must_succeed --reset -u $treeH && + echo gnusto >bozbar && + git update-index --add bozbar && + echo gnusto gnusto >bozbar && + read_tree_u_must_succeed -m -u $treeH $treeM && + git ls-files --stage >19.out && + test_cmp M.out 19.out && + check_cache_at bozbar dirty && + test_cmp frotz.M frotz && + test_cmp nitfol.M nitfol && + echo gnusto gnusto >bozbar1 && + diff bozbar bozbar1 && + rm -f bozbar1 +' + +test_expect_success '20 - no local change, use new tree.' ' + rm -f .git/index nitfol bozbar rezrov frotz && + read_tree_u_must_succeed --reset -u $treeH && + echo bozbar >bozbar && + git update-index --add bozbar && + read_tree_u_must_succeed -m -u $treeH $treeM && + git ls-files --stage >20.out && + test_cmp M.out 20.out && + check_cache_at bozbar clean && + test_cmp bozbar.M bozbar && + test_cmp frotz.M frotz && + test_cmp nitfol.M nitfol +' + +test_expect_success '21 - no local change, dirty cache.' ' + rm -f .git/index nitfol bozbar rezrov frotz && + read_tree_u_must_succeed --reset -u $treeH && + echo bozbar >bozbar && + git update-index --add bozbar && + echo gnusto gnusto >bozbar && + ! read_tree_u_must_succeed -m -u $treeH $treeM +' # Also make sure we did not break DF vs DF/DF case. -test_expect_success \ - 'DF vs DF/DF case setup.' \ - 'rm -f .git/index && - echo DF >DF && - git update-index --add DF && - treeDF=$(git write-tree) && - echo treeDF $treeDF && - git ls-tree $treeDF && - - rm -f DF && - mkdir DF && - echo DF/DF >DF/DF && - git update-index --add --remove DF DF/DF && - treeDFDF=$(git write-tree) && - echo treeDFDF $treeDFDF && - git ls-tree $treeDFDF && - git ls-files --stage >DFDF.out' - -test_expect_success \ - 'DF vs DF/DF case test.' \ - 'rm -f .git/index && - rm -fr DF && - echo DF >DF && - git update-index --add DF && - read_tree_u_must_succeed -m -u $treeDF $treeDFDF && - git ls-files --stage >DFDFcheck.out && - test_cmp DFDF.out DFDFcheck.out && - check_cache_at DF/DF clean' +test_expect_success 'DF vs DF/DF case setup.' ' + rm -f .git/index && + echo DF >DF && + git update-index --add DF && + treeDF=$(git write-tree) && + echo treeDF $treeDF && + git ls-tree $treeDF && + + rm -f DF && + mkdir DF && + echo DF/DF >DF/DF && + git update-index --add --remove DF DF/DF && + treeDFDF=$(git write-tree) && + echo treeDFDF $treeDFDF && + git ls-tree $treeDFDF && + git ls-files --stage >DFDF.out +' + +test_expect_success 'DF vs DF/DF case test.' ' + rm -f .git/index && + rm -fr DF && + echo DF >DF && + git update-index --add DF && + read_tree_u_must_succeed -m -u $treeDF $treeDFDF && + git ls-files --stage >DFDFcheck.out && + test_cmp DFDF.out DFDFcheck.out && + check_cache_at DF/DF clean +' test_done diff --git a/t/t1005-read-tree-reset.sh b/t/t1005-read-tree-reset.sh index 12e30d77d0..26be4a2b5a 100755 --- a/t/t1005-read-tree-reset.sh +++ b/t/t1005-read-tree-reset.sh @@ -41,7 +41,8 @@ test_expect_success 'reset should remove remnants from a failed merge' ' git ls-files -s && read_tree_u_must_succeed --reset -u HEAD && git ls-files -s >actual && - ! test -f old + ! test -f old && + test_cmp expect actual ' test_expect_success 'two-way reset should remove remnants too' ' @@ -56,7 +57,8 @@ test_expect_success 'two-way reset should remove remnants too' ' git ls-files -s && read_tree_u_must_succeed --reset -u HEAD HEAD && git ls-files -s >actual && - ! test -f old + ! test -f old && + test_cmp expect actual ' test_expect_success 'Porcelain reset should remove remnants too' ' @@ -71,7 +73,8 @@ test_expect_success 'Porcelain reset should remove remnants too' ' git ls-files -s && git reset --hard && git ls-files -s >actual && - ! test -f old + ! test -f old && + test_cmp expect actual ' test_expect_success 'Porcelain checkout -f should remove remnants too' ' @@ -86,7 +89,8 @@ test_expect_success 'Porcelain checkout -f should remove remnants too' ' git ls-files -s && git checkout -f && git ls-files -s >actual && - ! test -f old + ! test -f old && + test_cmp expect actual ' test_expect_success 'Porcelain checkout -f HEAD should remove remnants too' ' @@ -101,7 +105,8 @@ test_expect_success 'Porcelain checkout -f HEAD should remove remnants too' ' git ls-files -s && git checkout -f HEAD && git ls-files -s >actual && - ! test -f old + ! test -f old && + test_cmp expect actual ' test_done diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh index 2d875b17d8..271c5e4fd3 100755 --- a/t/t1006-cat-file.sh +++ b/t/t1006-cat-file.sh @@ -6,7 +6,7 @@ test_description='git cat-file' test_cmdmode_usage () { test_expect_code 129 "$@" 2>err && - grep "^error:.*is incompatible with" err + grep "^error: .* cannot be used together" err } for switches in \ @@ -89,7 +89,8 @@ done for opt in --buffer \ --follow-symlinks \ --batch-all-objects \ - -z + -z \ + -Z do test_expect_success "usage: bad option combination: $opt without batch mode" ' test_incompatible_usage git cat-file $opt && @@ -109,26 +110,12 @@ strlen () { echo_without_newline "$1" | wc -c | sed -e 's/^ *//' } -maybe_remove_timestamp () { - if test -z "$2"; then - echo_without_newline "$1" - else - echo_without_newline "$(printf '%s\n' "$1" | remove_timestamp)" - fi -} - -remove_timestamp () { - sed -e 's/ [0-9][0-9]* [-+][0-9][0-9][0-9][0-9]$//' -} - - run_tests () { type=$1 sha1=$2 size=$3 content=$4 pretty_content=$5 - no_ts=$6 batch_output="$sha1 $type $size $content" @@ -163,21 +150,21 @@ $content" test -z "$content" || test_expect_success "Content of $type is correct" ' - maybe_remove_timestamp "$content" $no_ts >expect && - maybe_remove_timestamp "$(git cat-file $type $sha1)" $no_ts >actual && + echo_without_newline "$content" >expect && + git cat-file $type $sha1 >actual && test_cmp expect actual ' test_expect_success "Pretty content of $type is correct" ' - maybe_remove_timestamp "$pretty_content" $no_ts >expect && - maybe_remove_timestamp "$(git cat-file -p $sha1)" $no_ts >actual && + echo_without_newline "$pretty_content" >expect && + git cat-file -p $sha1 >actual && test_cmp expect actual ' test -z "$content" || test_expect_success "--batch output of $type is correct" ' - maybe_remove_timestamp "$batch_output" $no_ts >expect && - maybe_remove_timestamp "$(echo $sha1 | git cat-file --batch)" $no_ts >actual && + echo "$batch_output" >expect && + echo $sha1 | git cat-file --batch >actual && test_cmp expect actual ' @@ -191,9 +178,8 @@ $content" do test -z "$content" || test_expect_success "--batch-command $opt output of $type content is correct" ' - maybe_remove_timestamp "$batch_output" $no_ts >expect && - maybe_remove_timestamp "$(test_write_lines "contents $sha1" | - git cat-file --batch-command $opt)" $no_ts >actual && + echo "$batch_output" >expect && + test_write_lines "contents $sha1" | git cat-file --batch-command $opt >actual && test_cmp expect actual ' @@ -228,10 +214,9 @@ $content" test_expect_success "--batch without type ($type)" ' { echo "$size" && - maybe_remove_timestamp "$content" $no_ts + echo "$content" } >expect && - echo $sha1 | git cat-file --batch="%(objectsize)" >actual.full && - maybe_remove_timestamp "$(cat actual.full)" $no_ts >actual && + echo $sha1 | git cat-file --batch="%(objectsize)" >actual && test_cmp expect actual ' @@ -239,10 +224,9 @@ $content" test_expect_success "--batch without size ($type)" ' { echo "$type" && - maybe_remove_timestamp "$content" $no_ts + echo "$content" } >expect && - echo $sha1 | git cat-file --batch="%(objecttype)" >actual.full && - maybe_remove_timestamp "$(cat actual.full)" $no_ts >actual && + echo $sha1 | git cat-file --batch="%(objecttype)" >actual && test_cmp expect actual ' } @@ -284,7 +268,7 @@ test_expect_success '--batch-check without %(rest) considers whole line' ' tree_sha1=$(git write-tree) tree_size=$(($(test_oid rawsz) + 13)) -tree_pretty_content="100644 blob $hello_sha1 hello" +tree_pretty_content="100644 blob $hello_sha1 hello${LF}" run_tests 'tree' $tree_sha1 $tree_size "" "$tree_pretty_content" @@ -292,12 +276,12 @@ commit_message="Initial commit" commit_sha1=$(echo_without_newline "$commit_message" | git commit-tree $tree_sha1) commit_size=$(($(test_oid hexsz) + 137)) commit_content="tree $tree_sha1 -author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> 0 +0000 -committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 0 +0000 +author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> $GIT_AUTHOR_DATE +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE $commit_message" -run_tests 'commit' $commit_sha1 $commit_size "$commit_content" "$commit_content" 1 +run_tests 'commit' $commit_sha1 $commit_size "$commit_content" "$commit_content" tag_header_without_timestamp="object $hello_sha1 type blob @@ -311,11 +295,13 @@ $tag_description" tag_sha1=$(echo_without_newline "$tag_content" | git hash-object -t tag --stdin -w) tag_size=$(strlen "$tag_content") -run_tests 'tag' $tag_sha1 $tag_size "$tag_content" "$tag_content" 1 +run_tests 'tag' $tag_sha1 $tag_size "$tag_content" "$tag_content" -test_expect_success \ - "Reach a blob from a tag pointing to it" \ - "test '$hello_content' = \"\$(git cat-file blob $tag_sha1)\"" +test_expect_success "Reach a blob from a tag pointing to it" ' + echo_without_newline "$hello_content" >expect && + git cat-file blob $tag_sha1 >actual && + test_cmp expect actual +' for batch in batch batch-check batch-command do @@ -351,30 +337,47 @@ do done test_expect_success "--batch-check for a non-existent named object" ' - test "foobar42 missing -foobar84 missing" = \ - "$( ( echo foobar42 && echo_without_newline foobar84 ) | git cat-file --batch-check)" + cat >expect <<-EOF && + foobar42 missing + foobar84 missing + EOF + + printf "foobar42\nfoobar84" >in && + git cat-file --batch-check <in >actual && + test_cmp expect actual ' test_expect_success "--batch-check for a non-existent hash" ' - test "0000000000000000000000000000000000000042 missing -0000000000000000000000000000000000000084 missing" = \ - "$( ( echo 0000000000000000000000000000000000000042 && - echo_without_newline 0000000000000000000000000000000000000084 ) | - git cat-file --batch-check)" + cat >expect <<-EOF && + 0000000000000000000000000000000000000042 missing + 0000000000000000000000000000000000000084 missing + EOF + + printf "0000000000000000000000000000000000000042\n0000000000000000000000000000000000000084" >in && + git cat-file --batch-check <in >actual && + test_cmp expect actual ' test_expect_success "--batch for an existent and a non-existent hash" ' - test "$tag_sha1 tag $tag_size -$tag_content -0000000000000000000000000000000000000000 missing" = \ - "$( ( echo $tag_sha1 && - echo_without_newline 0000000000000000000000000000000000000000 ) | - git cat-file --batch)" + cat >expect <<-EOF && + $tag_sha1 tag $tag_size + $tag_content + 0000000000000000000000000000000000000000 missing + EOF + + printf "$tag_sha1\n0000000000000000000000000000000000000000" >in && + git cat-file --batch <in >actual && + test_cmp expect actual ' test_expect_success "--batch-check for an empty line" ' - test " missing" = "$(echo | git cat-file --batch-check)" + cat >expect <<-EOF && + missing + EOF + + echo >in && + git cat-file --batch-check <in >actual && + test_cmp expect actual ' test_expect_success 'empty --batch-check notices missing object' ' @@ -390,23 +393,34 @@ deadbeef " -batch_output="$hello_sha1 blob $hello_size -$hello_content -$commit_sha1 commit $commit_size -$commit_content -$tag_sha1 tag $tag_size -$tag_content -deadbeef missing - missing" +printf "%s\0" \ + "$hello_sha1 blob $hello_size" \ + "$hello_content" \ + "$commit_sha1 commit $commit_size" \ + "$commit_content" \ + "$tag_sha1 tag $tag_size" \ + "$tag_content" \ + "deadbeef missing" \ + " missing" >batch_output test_expect_success '--batch with multiple sha1s gives correct format' ' - test "$(maybe_remove_timestamp "$batch_output" 1)" = "$(maybe_remove_timestamp "$(echo_without_newline "$batch_input" | git cat-file --batch)" 1)" + tr "\0" "\n" <batch_output >expect && + echo_without_newline "$batch_input" >in && + git cat-file --batch <in >actual && + test_cmp expect actual ' test_expect_success '--batch, -z with multiple sha1s gives correct format' ' echo_without_newline_nul "$batch_input" >in && - test "$(maybe_remove_timestamp "$batch_output" 1)" = \ - "$(maybe_remove_timestamp "$(git cat-file --batch -z <in)" 1)" + tr "\0" "\n" <batch_output >expect && + git cat-file --batch -z <in >actual && + test_cmp expect actual +' + +test_expect_success '--batch, -Z with multiple sha1s gives correct format' ' + echo_without_newline_nul "$batch_input" >in && + git cat-file --batch -Z <in >actual && + test_cmp batch_output actual ' batch_check_input="$hello_sha1 @@ -417,36 +431,55 @@ deadbeef " -batch_check_output="$hello_sha1 blob $hello_size -$tree_sha1 tree $tree_size -$commit_sha1 commit $commit_size -$tag_sha1 tag $tag_size -deadbeef missing - missing" +printf "%s\0" \ + "$hello_sha1 blob $hello_size" \ + "$tree_sha1 tree $tree_size" \ + "$commit_sha1 commit $commit_size" \ + "$tag_sha1 tag $tag_size" \ + "deadbeef missing" \ + " missing" >batch_check_output test_expect_success "--batch-check with multiple sha1s gives correct format" ' - test "$batch_check_output" = \ - "$(echo_without_newline "$batch_check_input" | git cat-file --batch-check)" + tr "\0" "\n" <batch_check_output >expect && + echo_without_newline "$batch_check_input" >in && + git cat-file --batch-check <in >actual && + test_cmp expect actual ' test_expect_success "--batch-check, -z with multiple sha1s gives correct format" ' - echo_without_newline_nul "$batch_check_input" >in && - test "$batch_check_output" = "$(git cat-file --batch-check -z <in)" + tr "\0" "\n" <batch_check_output >expect && + echo_without_newline_nul "$batch_check_input" >in && + git cat-file --batch-check -z <in >actual && + test_cmp expect actual ' -test_expect_success FUNNYNAMES '--batch-check, -z with newline in input' ' +test_expect_success "--batch-check, -Z with multiple sha1s gives correct format" ' + echo_without_newline_nul "$batch_check_input" >in && + git cat-file --batch-check -Z <in >actual && + test_cmp batch_check_output actual +' + +test_expect_success FUNNYNAMES 'setup with newline in input' ' touch -- "newline${LF}embedded" && git add -- "newline${LF}embedded" && git commit -m "file with newline embedded" && test_tick && - printf "HEAD:newline${LF}embedded" >in && - git cat-file --batch-check -z <in >actual && + printf "HEAD:newline${LF}embedded" >in +' +test_expect_success FUNNYNAMES '--batch-check, -z with newline in input' ' + git cat-file --batch-check -z <in >actual && echo "$(git rev-parse "HEAD:newline${LF}embedded") blob 0" >expect && test_cmp expect actual ' +test_expect_success FUNNYNAMES '--batch-check, -Z with newline in input' ' + git cat-file --batch-check -Z <in >actual && + printf "%s\0" "$(git rev-parse "HEAD:newline${LF}embedded") blob 0" >expect && + test_cmp expect actual +' + batch_command_multiple_info="info $hello_sha1 info $tree_sha1 info $commit_sha1 @@ -470,7 +503,13 @@ test_expect_success '--batch-command with multiple info calls gives correct form echo "$batch_command_multiple_info" | tr "\n" "\0" >in && git cat-file --batch-command --buffer -z <in >actual && - test_cmp expect actual + test_cmp expect actual && + + echo "$batch_command_multiple_info" | tr "\n" "\0" >in && + tr "\n" "\0" <expect >expect_nul && + git cat-file --batch-command --buffer -Z <in >actual && + + test_cmp expect_nul actual ' batch_command_multiple_contents="contents $hello_sha1 @@ -480,27 +519,30 @@ contents deadbeef flush" test_expect_success '--batch-command with multiple command calls gives correct format' ' - remove_timestamp >expect <<-EOF && - $hello_sha1 blob $hello_size - $hello_content - $commit_sha1 commit $commit_size - $commit_content - $tag_sha1 tag $tag_size - $tag_content - deadbeef missing - EOF + printf "%s\0" \ + "$hello_sha1 blob $hello_size" \ + "$hello_content" \ + "$commit_sha1 commit $commit_size" \ + "$commit_content" \ + "$tag_sha1 tag $tag_size" \ + "$tag_content" \ + "deadbeef missing" >expect_nul && + tr "\0" "\n" <expect_nul >expect && echo "$batch_command_multiple_contents" >in && - git cat-file --batch-command --buffer <in >actual_raw && + git cat-file --batch-command --buffer <in >actual && - remove_timestamp <actual_raw >actual && test_cmp expect actual && echo "$batch_command_multiple_contents" | tr "\n" "\0" >in && - git cat-file --batch-command --buffer -z <in >actual_raw && + git cat-file --batch-command --buffer -z <in >actual && - remove_timestamp <actual_raw >actual && - test_cmp expect actual + test_cmp expect actual && + + echo "$batch_command_multiple_contents" | tr "\n" "\0" >in && + git cat-file --batch-command --buffer -Z <in >actual && + + test_cmp expect_nul actual ' test_expect_success 'setup blobs which are likely to delta' ' @@ -603,7 +645,8 @@ do fatal: Not a valid object name $(test_oid deadbeef_short) EOF test_must_fail git cat-file $arg1 $arg2 $(test_oid deadbeef_short) >out 2>err.actual && - test_must_be_empty out + test_must_be_empty out && + test_cmp expect.err err.actual ' test_expect_success "cat-file $arg1 $arg2 error on missing full OID" ' @@ -839,6 +882,13 @@ test_expect_success 'git cat-file --batch-check --follow-symlinks works for brok test_cmp expect actual ' +test_expect_success 'git cat-file --batch-check --follow-symlinks -Z works for broken in-repo, same-dir links' ' + printf "HEAD:broken-same-dir-link\0" >in && + printf "dangling 25\0HEAD:broken-same-dir-link\0" >expect && + git cat-file --batch-check --follow-symlinks -Z <in >actual && + test_cmp expect actual +' + test_expect_success 'git cat-file --batch-check --follow-symlinks works for same-dir links-to-links' ' echo HEAD:link-to-link | git cat-file --batch-check --follow-symlinks >actual && test_cmp found actual @@ -853,6 +903,15 @@ test_expect_success 'git cat-file --batch-check --follow-symlinks works for pare test_cmp expect actual ' +test_expect_success 'git cat-file --batch-check --follow-symlinks -Z works for parent-dir links' ' + echo HEAD:dir/parent-dir-link | git cat-file --batch-check --follow-symlinks >actual && + test_cmp found actual && + printf "notdir 29\0HEAD:dir/parent-dir-link/nope\0" >expect && + printf "HEAD:dir/parent-dir-link/nope\0" >in && + git cat-file --batch-check --follow-symlinks -Z <in >actual && + test_cmp expect actual +' + test_expect_success 'git cat-file --batch-check --follow-symlinks works for .. links' ' echo dangling 22 >expect && echo HEAD:dir/link-dir/nope >>expect && @@ -967,6 +1026,13 @@ test_expect_success 'git cat-file --batch-check --follow-symlink breaks loops' ' test_cmp expect actual ' +test_expect_success 'git cat-file --batch-check --follow-symlink -Z breaks loops' ' + printf "loop 10\0HEAD:loop1\0" >expect && + printf "HEAD:loop1\0" >in && + git cat-file --batch-check --follow-symlinks -Z <in >actual && + test_cmp expect actual +' + test_expect_success 'git cat-file --batch --follow-symlink returns correct sha and mode' ' echo HEAD:morx | git cat-file --batch >expect && echo HEAD:morx | git cat-file --batch --follow-symlinks >actual && diff --git a/t/t1010-mktree.sh b/t/t1010-mktree.sh index 3c08194526..22875ba598 100755 --- a/t/t1010-mktree.sh +++ b/t/t1010-mktree.sh @@ -60,11 +60,11 @@ test_expect_success 'allow missing object with --missing' ' ' test_expect_success 'mktree refuses to read ls-tree -r output (1)' ' - test_must_fail git mktree <all >actual + test_must_fail git mktree <all ' test_expect_success 'mktree refuses to read ls-tree -r output (2)' ' - test_must_fail git mktree <all.withsub >actual + test_must_fail git mktree <all.withsub ' test_done diff --git a/t/t1060-object-corruption.sh b/t/t1060-object-corruption.sh index 35261afc9d..5e0f0a334f 100755 --- a/t/t1060-object-corruption.sh +++ b/t/t1060-object-corruption.sh @@ -125,7 +125,7 @@ test_expect_success 'fetch into corrupted repo with index-pack' ' cd bit-error-cp && test_must_fail git -c transfer.unpackLimit=1 \ fetch ../no-bit-error 2>stderr && - test_i18ngrep ! -i collision stderr + test_grep ! -i collision stderr ) ' diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh index 627267be15..f67611da28 100755 --- a/t/t1091-sparse-checkout-builtin.sh +++ b/t/t1091-sparse-checkout-builtin.sh @@ -47,7 +47,7 @@ test_expect_success 'setup' ' test_expect_success 'git sparse-checkout list (not sparse)' ' test_must_fail git -C repo sparse-checkout list >list 2>err && test_must_be_empty list && - test_i18ngrep "this worktree is not sparse" err + test_grep "this worktree is not sparse" err ' test_expect_success 'git sparse-checkout list (not sparse)' ' @@ -55,7 +55,7 @@ test_expect_success 'git sparse-checkout list (not sparse)' ' rm repo/.git/info/sparse-checkout && git -C repo sparse-checkout list >list 2>err && test_must_be_empty list && - test_i18ngrep "this worktree is not sparse (sparse-checkout file may not exist)" err + test_grep "this worktree is not sparse (sparse-checkout file may not exist)" err ' test_expect_success 'git sparse-checkout list (populated)' ' @@ -230,7 +230,7 @@ test_expect_success 'cone mode: match patterns' ' git -C repo config --worktree core.sparseCheckoutCone true && rm -rf repo/a repo/folder1 repo/folder2 && git -C repo read-tree -mu HEAD 2>err && - test_i18ngrep ! "disabling cone patterns" err && + test_grep ! "disabling cone patterns" err && git -C repo reset --hard && check_files repo a folder1 folder2 ' @@ -240,7 +240,7 @@ test_expect_success 'cone mode: warn on bad pattern' ' cp repo/.git/info/sparse-checkout . && echo "!/deep/deeper/*/" >>repo/.git/info/sparse-checkout && git -C repo read-tree -mu HEAD 2>err && - test_i18ngrep "unrecognized negative pattern" err + test_grep "unrecognized negative pattern" err ' test_expect_success 'sparse-checkout disable' ' @@ -283,7 +283,7 @@ test_expect_success 'sparse-index enabled and disabled' ' test_expect_success 'cone mode: init and set' ' git -C repo sparse-checkout init --cone && git -C repo config --list >config && - test_i18ngrep "core.sparsecheckoutcone=true" config && + test_grep "core.sparsecheckoutcone=true" config && list_files repo >dir && echo a >expect && test_cmp expect dir && @@ -386,7 +386,7 @@ test_expect_success 'not-up-to-date does not block rest of sparsification' ' git -C repo sparse-checkout set deep/deeper1 2>err && - test_i18ngrep "The following paths are not up to date" err && + test_grep "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 && @@ -401,8 +401,8 @@ test_expect_success 'revert to old sparse-checkout on empty update' ' git add file && git commit -m "test" && git sparse-checkout set nothing 2>err && - test_i18ngrep ! "Sparse checkout leaves no entry on working directory" err && - test_i18ngrep ! ".git/index.lock" err && + test_grep ! "Sparse checkout leaves no entry on working directory" err && + test_grep ! ".git/index.lock" err && git sparse-checkout set --no-cone file ) ' @@ -411,14 +411,14 @@ test_expect_success 'fail when lock is taken' ' test_when_finished rm -rf repo/.git/info/sparse-checkout.lock && touch repo/.git/info/sparse-checkout.lock && test_must_fail git -C repo sparse-checkout set deep 2>err && - test_i18ngrep "Unable to create .*\.lock" err + test_grep "Unable to create .*\.lock" err ' test_expect_success '.gitignore should not warn about cone mode' ' git -C repo config --worktree core.sparseCheckoutCone true && echo "**/bin/*" >repo/.gitignore && git -C repo reset --hard 2>err && - test_i18ngrep ! "disabling cone patterns" err + test_grep ! "disabling cone patterns" err ' test_expect_success 'sparse-checkout (init|set|disable) warns with dirty status' ' @@ -426,10 +426,10 @@ test_expect_success 'sparse-checkout (init|set|disable) warns with dirty status' echo dirty >dirty/folder1/a && git -C dirty sparse-checkout init --no-cone 2>err && - test_i18ngrep "warning.*The following paths are not up to date" err && + test_grep "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_grep "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 && @@ -453,14 +453,14 @@ test_expect_success 'sparse-checkout (init|set|disable) warns with unmerged stat git -C unmerged update-index --index-info <input && git -C unmerged sparse-checkout init --no-cone 2>err && - test_i18ngrep "warning.*The following paths are unmerged" err && + test_grep "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_grep "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 && + test_grep "warning.*The following paths are unmerged" err && git -C unmerged reset --hard && git -C unmerged sparse-checkout init --no-cone && @@ -480,24 +480,24 @@ test_expect_failure 'sparse-checkout reapply' ' 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 && + test_grep "warning.*The following paths are not up to date" err && + test_grep "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 && + test_grep "warning.*The following paths are not up to date" err && + test_grep "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_grep "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_grep "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_grep ! "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_grep "warning.*The following paths are unmerged" err && test_path_is_file tweak/folder1/a && # NEEDSWORK: We are asking to update a file outside of the @@ -555,7 +555,7 @@ test_expect_success 'cone mode: set with core.ignoreCase=true' ' check_files repo a folder1 ' -test_expect_success 'interaction with submodules' ' +test_expect_success 'setup submodules' ' git clone repo super && ( cd super && @@ -566,11 +566,22 @@ test_expect_success 'interaction with submodules' ' git commit -m "add submodule" && git sparse-checkout init --cone && git sparse-checkout set folder1 - ) && + ) +' + +test_expect_success 'interaction with submodules' ' check_files super a folder1 modules && check_files super/modules/child a deep folder1 folder2 ' +test_expect_success 'check-rules interaction with submodules' ' + git -C super ls-tree --name-only -r HEAD >all-files && + git -C super sparse-checkout check-rules >check-rules-matches <all-files && + + test_grep ! "modules/" check-rules-matches && + test_grep "folder1/" check-rules-matches +' + test_expect_success 'different sparse-checkouts with worktrees' ' git -C repo sparse-checkout set --cone deep folder1 && git -C repo worktree add --detach ../worktree && @@ -605,7 +616,7 @@ check_read_tree_errors () { then test_must_be_empty err else - test_i18ngrep "$ERRORS" err + test_grep "$ERRORS" err fi && check_files $REPO $FILES } @@ -882,4 +893,156 @@ test_expect_success 'by default, non-cone mode will warn on individual files' ' grep "pass a leading slash before paths.*if you want a single file" warning ' +test_expect_success 'setup bare repo' ' + git clone --bare "file://$(pwd)/repo" bare +' +test_expect_success 'list fails outside work tree' ' + test_must_fail git -C bare sparse-checkout list 2>err && + test_grep "this operation must be run in a work tree" err +' + +test_expect_success 'add fails outside work tree' ' + test_must_fail git -C bare sparse-checkout add deeper 2>err && + test_grep "this operation must be run in a work tree" err +' + +test_expect_success 'set fails outside work tree' ' + test_must_fail git -C bare sparse-checkout set deeper 2>err && + test_grep "this operation must be run in a work tree" err +' + +test_expect_success 'init fails outside work tree' ' + test_must_fail git -C bare sparse-checkout init 2>err && + test_grep "this operation must be run in a work tree" err +' + +test_expect_success 'reapply fails outside work tree' ' + test_must_fail git -C bare sparse-checkout reapply 2>err && + test_grep "this operation must be run in a work tree" err +' + +test_expect_success 'disable fails outside work tree' ' + test_must_fail git -C bare sparse-checkout disable 2>err && + test_grep "this operation must be run in a work tree" err +' + +test_expect_success 'setup clean' ' + git -C repo clean -fdx +' + +test_expect_success 'check-rules cone mode' ' + cat >rules <<-\EOF && + folder1 + deep/deeper1/deepest + EOF + + git -C bare ls-tree -r --name-only HEAD >all-files && + git -C bare sparse-checkout check-rules --cone \ + --rules-file ../rules >check-rules-file <all-files && + + git -C repo sparse-checkout set --cone --stdin <rules&& + git -C repo ls-files -t >out && + sed -n "/^S /!s/^. //p" out >ls-files && + + git -C repo sparse-checkout check-rules >check-rules-default <all-files && + + test_grep "deep/deeper1/deepest/a" check-rules-file && + test_grep ! "deep/deeper2" check-rules-file && + + test_cmp check-rules-file ls-files && + test_cmp check-rules-file check-rules-default +' + +test_expect_success 'check-rules non-cone mode' ' + cat >rules <<-\EOF && + deep/deeper1/deepest/a + EOF + + git -C bare ls-tree -r --name-only HEAD >all-files && + git -C bare sparse-checkout check-rules --no-cone --rules-file ../rules\ + >check-rules-file <all-files && + + cat rules | git -C repo sparse-checkout set --no-cone --stdin && + git -C repo ls-files -t >out && + sed -n "/^S /!s/^. //p" out >ls-files && + + git -C repo sparse-checkout check-rules >check-rules-default <all-files && + + cat >expect <<-\EOF && + deep/deeper1/deepest/a + EOF + + test_cmp expect check-rules-file && + test_cmp check-rules-file ls-files && + test_cmp check-rules-file check-rules-default +' + +test_expect_success 'check-rules cone mode is default' ' + cat >rules <<-\EOF && + folder1 + EOF + + cat >all-files <<-\EOF && + toplevel + folder2/file + folder1/file + EOF + + cat >expect <<-\EOF && + toplevel + folder1/file + EOF + + git -C repo sparse-checkout set --no-cone && + git -C repo sparse-checkout check-rules \ + --rules-file ../rules >actual <all-files && + + git -C bare sparse-checkout check-rules \ + --rules-file ../rules >actual-bare <all-files && + + test_cmp expect actual && + test_cmp expect actual-bare +' + +test_expect_success 'check-rules quoting' ' + cat >rules <<-EOF && + "folder\" a" + EOF + cat >files <<-EOF && + "folder\" a/file" + "folder\" b/file" + EOF + cat >expect <<-EOF && + "folder\" a/file" + EOF + git sparse-checkout check-rules --cone \ + --rules-file rules >actual <files && + + test_cmp expect actual +' + +test_expect_success 'check-rules null termination' ' + cat >rules <<-EOF && + "folder\" a" + EOF + + lf_to_nul >files <<-EOF && + folder" a/a + folder" a/b + folder" b/fileQ + EOF + + cat >expect <<-EOF && + folder" a/aQfolder" a/bQ + EOF + + git sparse-checkout check-rules --cone -z \ + --rules-file rules >actual.nul <files && + nul_to_q <actual.nul >actual && + echo >>actual && + + test_cmp expect actual +' + + test_done diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh index 801919009e..2f1ae5fd3b 100755 --- a/t/t1092-sparse-checkout-compatibility.sh +++ b/t/t1092-sparse-checkout-compatibility.sh @@ -337,8 +337,8 @@ test_expect_success 'status reports sparse-checkout' ' init_repos && git -C sparse-checkout status >full && git -C sparse-index status >sparse && - test_i18ngrep "You are in a sparse checkout with " full && - test_i18ngrep "You are in a sparse checkout." sparse + test_grep "You are in a sparse checkout with " full && + test_grep "You are in a sparse checkout." sparse ' test_expect_success 'add, commit, checkout' ' @@ -1182,7 +1182,7 @@ test_expect_success 'checkout-index outside sparse definition' ' # Without --ignore-skip-worktree-bits, outside-of-cone files will trigger # an error test_sparse_match test_must_fail git checkout-index -- folder1/a && - test_i18ngrep "folder1/a has skip-worktree enabled" sparse-checkout-err && + test_grep "folder1/a has skip-worktree enabled" sparse-checkout-err && test_path_is_missing folder1/a && # With --ignore-skip-worktree-bits, outside-of-cone files are checked out @@ -1377,7 +1377,7 @@ test_expect_success 'index.sparse disabled inline uses full index' ' ! test_region index ensure_full_index trace2.txt ' -ensure_not_expanded () { +run_sparse_index_trace2 () { rm -f trace2.txt && if test -z "$WITHOUT_UNTRACKED_TXT" then @@ -1397,7 +1397,16 @@ ensure_not_expanded () { git -C sparse-index "$@" \ >sparse-index-out \ 2>sparse-index-error || return 1 - fi && + fi +} + +ensure_expanded () { + run_sparse_index_trace2 "$@" && + test_region index ensure_full_index trace2.txt +} + +ensure_not_expanded () { + run_sparse_index_trace2 "$@" && test_region ! index ensure_full_index trace2.txt } @@ -1514,6 +1523,31 @@ test_expect_success 'sparse-index is not expanded: stash' ' ensure_not_expanded stash pop ' +test_expect_success 'describe tested on all' ' + init_repos && + + # Add tag to be read by describe + + run_on_all git tag -a v1.0 -m "Version 1" && + test_all_match git describe --dirty && + run_on_all rm g && + test_all_match git describe --dirty +' + + +test_expect_success 'sparse-index is not expanded: describe' ' + init_repos && + + # Add tag to be read by describe + + git -C sparse-index tag -a v1.0 -m "Version 1" && + + ensure_not_expanded describe --dirty && + echo "test" >>sparse-index/g && + ensure_not_expanded describe --dirty && + ensure_not_expanded describe +' + test_expect_success 'sparse index is not expanded: diff' ' init_repos && @@ -2055,4 +2089,246 @@ test_expect_success 'grep sparse directory within submodules' ' test_cmp actual expect ' +test_expect_success 'write-tree' ' + init_repos && + + test_all_match git write-tree && + + write_script edit-contents <<-\EOF && + echo text >>"$1" + EOF + + # make a change inside the sparse cone + run_on_all ../edit-contents deep/a && + test_all_match git update-index deep/a && + test_all_match git write-tree && + test_all_match git status --porcelain=v2 && + + # make a change outside the sparse cone + run_on_all mkdir -p folder1 && + run_on_all cp a folder1/a && + run_on_all ../edit-contents folder1/a && + test_all_match git update-index folder1/a && + test_all_match git write-tree && + test_all_match git status --porcelain=v2 && + + # check that SKIP_WORKTREE files are not materialized + test_path_is_missing sparse-checkout/folder2/a && + test_path_is_missing sparse-index/folder2/a +' + +test_expect_success 'sparse-index is not expanded: write-tree' ' + init_repos && + + ensure_not_expanded write-tree && + + echo "test1" >>sparse-index/a && + git -C sparse-index update-index a && + ensure_not_expanded write-tree +' + +test_expect_success 'diff-files with pathspec inside sparse definition' ' + init_repos && + + write_script edit-contents <<-\EOF && + echo text >>"$1" + EOF + + run_on_all ../edit-contents deep/a && + + test_all_match git diff-files && + + test_all_match git diff-files -- deep/a && + + # test wildcard + test_all_match git diff-files -- "deep/*" +' + +test_expect_success 'diff-files with pathspec outside sparse definition' ' + init_repos && + + test_sparse_match git diff-files -- folder2/a && + + write_script edit-contents <<-\EOF && + echo text >>"$1" + EOF + + # The directory "folder1" is outside the cone of interest + # and will not exist in the sparse checkout repositories. + # Create it as needed, add file "folder1/a" there with + # contents that is different from the staged version. + run_on_all mkdir -p folder1 && + run_on_all cp a folder1/a && + + run_on_all ../edit-contents folder1/a && + test_all_match git diff-files && + test_all_match git diff-files -- folder1/a && + test_all_match git diff-files -- "folder*/a" +' + +test_expect_success 'sparse index is not expanded: diff-files' ' + init_repos && + + write_script edit-contents <<-\EOF && + echo text >>"$1" + EOF + + run_on_all ../edit-contents deep/a && + + ensure_not_expanded diff-files && + ensure_not_expanded diff-files -- deep/a && + ensure_not_expanded diff-files -- "deep/*" +' + +test_expect_success 'diff-tree' ' + init_repos && + + # Test change inside sparse cone + tree1=$(git -C sparse-index rev-parse HEAD^{tree}) && + tree2=$(git -C sparse-index rev-parse update-deep^{tree}) && + test_all_match git diff-tree $tree1 $tree2 && + test_all_match git diff-tree $tree1 $tree2 -- deep/a && + test_all_match git diff-tree HEAD update-deep && + test_all_match git diff-tree HEAD update-deep -- deep/a && + + # Test change outside sparse cone + tree3=$(git -C sparse-index rev-parse update-folder1^{tree}) && + test_all_match git diff-tree $tree1 $tree3 && + test_all_match git diff-tree $tree1 $tree3 -- folder1/a && + test_all_match git diff-tree HEAD update-folder1 && + test_all_match git diff-tree HEAD update-folder1 -- folder1/a && + + # Check that SKIP_WORKTREE files are not materialized + test_path_is_missing sparse-checkout/folder1/a && + test_path_is_missing sparse-index/folder1/a && + test_path_is_missing sparse-checkout/folder2/a && + test_path_is_missing sparse-index/folder2/a +' + +test_expect_success 'sparse-index is not expanded: diff-tree' ' + init_repos && + + tree1=$(git -C sparse-index rev-parse HEAD^{tree}) && + tree2=$(git -C sparse-index rev-parse update-deep^{tree}) && + tree3=$(git -C sparse-index rev-parse update-folder1^{tree}) && + + ensure_not_expanded diff-tree $tree1 $tree2 && + ensure_not_expanded diff-tree $tree1 $tree2 -- deep/a && + ensure_not_expanded diff-tree HEAD update-deep && + ensure_not_expanded diff-tree HEAD update-deep -- deep/a && + ensure_not_expanded diff-tree $tree1 $tree3 && + ensure_not_expanded diff-tree $tree1 $tree3 -- folder1/a && + ensure_not_expanded diff-tree HEAD update-folder1 && + ensure_not_expanded diff-tree HEAD update-folder1 -- folder1/a +' + +test_expect_success 'worktree' ' + init_repos && + + write_script edit-contents <<-\EOF && + echo text >>"$1" + EOF + + for repo in full-checkout sparse-checkout sparse-index + do + worktree=${repo}-wt && + git -C $repo worktree add ../$worktree && + + # Compare worktree content with "ls" + (cd $repo && ls) >worktree_contents && + (cd $worktree && ls) >new_worktree_contents && + test_cmp worktree_contents new_worktree_contents && + + # Compare index content with "ls-files --sparse" + git -C $repo ls-files --sparse >index_contents && + git -C $worktree ls-files --sparse >new_index_contents && + test_cmp index_contents new_index_contents && + + git -C $repo worktree remove ../$worktree || return 1 + done && + + test_all_match git worktree add .worktrees/hotfix && + run_on_all ../edit-contents .worktrees/hotfix/deep/a && + test_all_match test_must_fail git worktree remove .worktrees/hotfix +' + +test_expect_success 'worktree is not expanded' ' + init_repos && + + ensure_not_expanded worktree add .worktrees/hotfix && + ensure_not_expanded worktree remove .worktrees/hotfix +' + +test_expect_success 'check-attr with pathspec inside sparse definition' ' + init_repos && + + echo "a -crlf myAttr" >>.gitattributes && + run_on_all cp ../.gitattributes ./deep && + + test_all_match git check-attr -a -- deep/a && + + test_all_match git add deep/.gitattributes && + test_all_match git check-attr -a --cached -- deep/a +' + +test_expect_success 'check-attr with pathspec outside sparse definition' ' + init_repos && + + echo "a -crlf myAttr" >>.gitattributes && + run_on_sparse mkdir folder1 && + run_on_all cp ../.gitattributes ./folder1 && + run_on_all cp a folder1/a && + + test_all_match git check-attr -a -- folder1/a && + + git -C full-checkout add folder1/.gitattributes && + test_sparse_match git add --sparse folder1/.gitattributes && + test_all_match git commit -m "add .gitattributes" && + test_sparse_match git sparse-checkout reapply && + test_all_match git check-attr -a --cached -- folder1/a +' + +# NEEDSWORK: The 'diff --check' test is left as 'test_expect_failure' due +# to an underlying issue in oneway_diff() within diff-lib.c. +# 'do_oneway_diff()' is not called as expected for paths that could match +# inside of a sparse directory. Specifically, the 'ce_path_match()' function +# fails to recognize files inside a sparse directory (e.g., when 'folder1/' +# is a sparse directory, 'folder1/a' cannot be recognized). The goal is to +# proceed with 'do_oneway_diff()' if the pathspec could match inside of a +# sparse directory. +test_expect_failure 'diff --check with pathspec outside sparse definition' ' + init_repos && + + write_script edit-contents <<-\EOF && + echo "a " >"$1" + EOF + + test_all_match git config core.whitespace -trailing-space,-space-before-tab && + + echo "a whitespace=trailing-space,space-before-tab" >>.gitattributes && + run_on_all mkdir -p folder1 && + run_on_all cp ../.gitattributes ./folder1 && + test_all_match git add --sparse folder1/.gitattributes && + run_on_all ../edit-contents folder1/a && + test_all_match git add --sparse folder1/a && + + test_sparse_match git sparse-checkout reapply && + test_all_match test_must_fail git diff --check --cached -- folder1/a +' + +test_expect_success 'sparse-index is not expanded: check-attr' ' + init_repos && + + echo "a -crlf myAttr" >>.gitattributes && + mkdir ./sparse-index/folder1 && + cp ./sparse-index/a ./sparse-index/folder1/a && + cp .gitattributes ./sparse-index/deep && + cp .gitattributes ./sparse-index/folder1 && + + git -C sparse-index add deep/.gitattributes && + git -C sparse-index add --sparse folder1/.gitattributes && + ensure_not_expanded check-attr -a --cached -- deep/a && + ensure_not_expanded check-attr -a --cached -- folder1/a +' + test_done diff --git a/t/t1300-config.sh b/t/t1300-config.sh index f1d42b62b0..f4e2752134 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -98,6 +98,23 @@ test_expect_success 'subsections are not canonicalized by git-config' ' test_cmp_config two section.SubSection.key ' +test_missing_key () { + local key="$1" && + local title="$2" && + test_expect_success "value for $title is not printed" ' + test_must_fail git config "$key" >out 2>err && + test_must_be_empty out && + test_must_be_empty err + ' +} + +test_missing_key 'missingsection.missingkey' 'missing section and missing key' +test_missing_key 'missingsection.penguin' 'missing section and existing key' +test_missing_key 'section.missingkey' 'existing section and missing key' +test_missing_key 'section.MissingSubSection.missingkey' 'missing subsection and missing key' +test_missing_key 'section.SubSection.missingkey' 'existing subsection and missing key' +test_missing_key 'section.MissingSubSection.key' 'missing subsection and existing key' + cat > .git/config <<\EOF [alpha] bar = foo @@ -436,7 +453,7 @@ test_expect_success 'get bool variable with empty value' ' test_expect_success 'no arguments, but no crash' ' test_must_fail git config >output 2>&1 && - test_i18ngrep usage output + test_grep usage output ' cat > .git/config << EOF @@ -703,25 +720,25 @@ test_expect_success 'invalid unit' ' git config aninvalid.unit "1auto" && test_cmp_config 1auto aninvalid.unit && test_must_fail git config --int --get aninvalid.unit 2>actual && - test_i18ngrep "bad numeric config value .1auto. for .aninvalid.unit. in file .git/config: invalid unit" actual + test_grep "bad numeric config value .1auto. for .aninvalid.unit. in file .git/config: invalid unit" actual ' test_expect_success 'invalid unit boolean' ' git config commit.gpgsign "1true" && test_cmp_config 1true commit.gpgsign && test_must_fail git config --bool --get commit.gpgsign 2>actual && - test_i18ngrep "bad boolean config value .1true. for .commit.gpgsign." actual + test_grep "bad boolean config value .1true. for .commit.gpgsign." actual ' test_expect_success 'line number is reported correctly' ' printf "[bool]\n\tvar\n" >invalid && test_must_fail git config -f invalid --path bool.var 2>actual && - test_i18ngrep "line 2" actual + test_grep "line 2" actual ' test_expect_success 'invalid stdin config' ' echo "[broken" | test_must_fail git config --list --file - >output 2>&1 && - test_i18ngrep "bad config line 1 in standard input" output + test_grep "bad config line 1 in standard input" output ' cat > expect << EOF @@ -902,7 +919,7 @@ test_expect_success !MINGW 'get --path copes with unset $HOME' ' git config --get --path path.normal >>result && git config --get --path path.trailingtilde >>result ) && - test_i18ngrep "[Ff]ailed to expand.*~/" msg && + test_grep "[Ff]ailed to expand.*~/" msg && test_cmp expect result ' @@ -969,7 +986,7 @@ test_expect_success 'get --type=color barfs on non-color' ' test_expect_success 'set --type=color barfs on non-color' ' test_must_fail git config --type=color foo.color "not-a-color" 2>error && - test_i18ngrep "cannot parse color" error + test_grep "cannot parse color" error ' cat > expect << EOF @@ -1430,12 +1447,12 @@ test_expect_success 'git --config-env with missing value' ' test_expect_success 'git --config-env fails with invalid parameters' ' test_must_fail git --config-env=foo.flag config --bool foo.flag 2>error && - test_i18ngrep "invalid config format: foo.flag" error && + test_grep "invalid config format: foo.flag" error && test_must_fail git --config-env=foo.flag= config --bool foo.flag 2>error && - test_i18ngrep "missing environment variable name for configuration ${SQ}foo.flag${SQ}" error && + test_grep "missing environment variable name for configuration ${SQ}foo.flag${SQ}" error && sane_unset NONEXISTENT && test_must_fail git --config-env=foo.flag=NONEXISTENT config --bool foo.flag 2>error && - test_i18ngrep "missing environment variable ${SQ}NONEXISTENT${SQ} for configuration ${SQ}foo.flag${SQ}" error + test_grep "missing environment variable ${SQ}NONEXISTENT${SQ} for configuration ${SQ}foo.flag${SQ}" error ' test_expect_success 'git -c and --config-env work together' ' @@ -1488,55 +1505,49 @@ test_expect_success 'git config ignores pairs without count' ' test_must_be_empty error ' -test_expect_success 'git config ignores pairs with zero count' ' - test_must_fail env \ - GIT_CONFIG_COUNT=0 \ - GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \ - git config pair.one -' - test_expect_success 'git config ignores pairs exceeding count' ' GIT_CONFIG_COUNT=1 \ GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \ GIT_CONFIG_KEY_1="pair.two" GIT_CONFIG_VALUE_1="value" \ - git config --get-regexp "pair.*" >actual && + git config --get-regexp "pair.*" >actual 2>error && cat >expect <<-EOF && pair.one value EOF - test_cmp expect actual + test_cmp expect actual && + test_must_be_empty error ' test_expect_success 'git config ignores pairs with zero count' ' test_must_fail env \ GIT_CONFIG_COUNT=0 GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \ - git config pair.one >error && + git config pair.one 2>error && test_must_be_empty error ' test_expect_success 'git config ignores pairs with empty count' ' test_must_fail env \ GIT_CONFIG_COUNT= GIT_CONFIG_KEY_0="pair.one" GIT_CONFIG_VALUE_0="value" \ - git config pair.one >error && + git config pair.one 2>error && test_must_be_empty error ' test_expect_success 'git config fails with invalid count' ' test_must_fail env GIT_CONFIG_COUNT=10a git config --list 2>error && - test_i18ngrep "bogus count" error && + test_grep "bogus count" error && test_must_fail env GIT_CONFIG_COUNT=9999999999999999 git config --list 2>error && - test_i18ngrep "too many entries" error + test_grep "too many entries" error ' test_expect_success 'git config fails with missing config key' ' test_must_fail env GIT_CONFIG_COUNT=1 GIT_CONFIG_VALUE_0="value" \ git config --list 2>error && - test_i18ngrep "missing config key" error + test_grep "missing config key" error ' test_expect_success 'git config fails with missing config value' ' test_must_fail env GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0="pair.one" \ git config --list 2>error && - test_i18ngrep "missing config value" error + test_grep "missing config value" error ' test_expect_success 'git config fails with invalid config pair key' ' @@ -1601,12 +1612,12 @@ test_expect_success 'git config --edit respects core.editor' ' # malformed configuration files test_expect_success 'barf on syntax error' ' cat >.git/config <<-\EOF && - # broken section line + # broken key=value [section] key garbage EOF - test_must_fail git config --get section.key >actual 2>error && - test_i18ngrep " line 3 " error + test_must_fail git config --get section.key 2>error && + test_grep " line 3 " error ' test_expect_success 'barf on incomplete section header' ' @@ -1615,18 +1626,18 @@ test_expect_success 'barf on incomplete section header' ' [section key = value EOF - test_must_fail git config --get section.key >actual 2>error && - test_i18ngrep " line 2 " error + test_must_fail git config --get section.key 2>error && + test_grep " line 2 " error ' test_expect_success 'barf on incomplete string' ' cat >.git/config <<-\EOF && - # broken section line + # broken value string [section] key = "value string EOF - test_must_fail git config --get section.key >actual 2>error && - test_i18ngrep " line 3 " error + test_must_fail git config --get section.key 2>error && + test_grep " line 3 " error ' test_expect_success 'urlmatch' ' @@ -1657,6 +1668,21 @@ test_expect_success 'urlmatch' ' test_cmp expect actual ' +test_expect_success 'urlmatch with --show-scope' ' + cat >.git/config <<-\EOF && + [http "https://weak.example.com"] + sslVerify = false + cookieFile = /tmp/cookie.txt + EOF + + cat >expect <<-EOF && + local http.cookiefile /tmp/cookie.txt + local http.sslverify false + EOF + git config --get-urlmatch --show-scope HTTP https://weak.example.com >actual && + test_cmp expect actual +' + test_expect_success 'urlmatch favors more specific URLs' ' cat >.git/config <<-\EOF && [http "https://example.com/"] @@ -2044,6 +2070,12 @@ test_expect_success '--show-origin blob ref' ' test_cmp expect output ' +test_expect_success '--show-origin with --default' ' + git config --show-origin --default foo some.key >actual && + echo "command line: foo" >expect && + test_cmp expect actual +' + test_expect_success '--show-scope with --list' ' cat >expect <<-EOF && global user.global=true @@ -2112,6 +2144,12 @@ test_expect_success '--show-scope with --show-origin' ' test_cmp expect output ' +test_expect_success '--show-scope with --default' ' + git config --show-scope --default foo some.key >actual && + echo "command foo" >expect && + test_cmp expect actual +' + test_expect_success 'override global and system config' ' test_when_finished rm -f \"\$HOME\"/.gitconfig && cat >"$HOME"/.gitconfig <<-EOF && @@ -2228,17 +2266,17 @@ test_expect_success 'identical mixed --type specifiers are allowed' ' test_expect_success 'non-identical modern --type specifiers are not allowed' ' test_must_fail git config --type=int --type=bool section.big 2>error && - test_i18ngrep "only one type at a time" error + test_grep "only one type at a time" error ' test_expect_success 'non-identical legacy --type specifiers are not allowed' ' test_must_fail git config --int --bool section.big 2>error && - test_i18ngrep "only one type at a time" error + test_grep "only one type at a time" error ' test_expect_success 'non-identical mixed --type specifiers are not allowed' ' test_must_fail git config --type=int --bool section.big 2>error && - test_i18ngrep "only one type at a time" error + test_grep "only one type at a time" error ' test_expect_success '--type allows valid type specifiers' ' @@ -2255,7 +2293,7 @@ test_expect_success 'unset type specifiers may be reset to conflicting ones' ' test_expect_success '--type rejects unknown specifiers' ' test_must_fail git config --type=nonsense section.foo 2>error && - test_i18ngrep "unrecognized --type argument" error + test_grep "unrecognized --type argument" error ' test_expect_success '--type=int requires at least one digit' ' @@ -2301,7 +2339,7 @@ test_expect_success 'set all config with value-pattern' ' # multiple matches => failure test_must_fail git config --file=config abc.key three o+ 2>err && - test_i18ngrep "has multiple values" err && + test_grep "has multiple values" err && # multiple values, no match => add git config --file=config abc.key three a+ && diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh index 1b6437ec07..e5a0d65caa 100755 --- a/t/t1301-shared-repo.sh +++ b/t/t1301-shared-repo.sh @@ -52,6 +52,28 @@ test_expect_success 'shared=all' ' test 2 = $(git config core.sharedrepository) ' +test_expect_failure 'template can set core.bare' ' + test_when_finished "rm -rf subdir" && + test_when_finished "rm -rf templates" && + test_config core.bare true && + umask 0022 && + mkdir -p templates/ && + cp .git/config templates/config && + git init --template=templates subdir && + test_path_exists subdir/HEAD +' + +test_expect_success 'template can set core.bare but overridden by command line' ' + test_when_finished "rm -rf subdir" && + test_when_finished "rm -rf templates" && + test_config core.bare true && + umask 0022 && + mkdir -p templates/ && + cp .git/config templates/config && + git init --no-bare --template=templates subdir && + test_path_exists subdir/.git/HEAD +' + test_expect_success POSIXPERM 'update-server-info honors core.sharedRepository' ' : > a1 && git add a1 && @@ -89,7 +111,7 @@ do rm -f .git/info/refs && git update-server-info && actual="$(test_modebits .git/info/refs)" && - verbose test "x$actual" = "x-$y" + test "x$actual" = "x-$y" ' @@ -99,7 +121,7 @@ do rm -f .git/info/refs && git update-server-info && actual="$(test_modebits .git/info/refs)" && - verbose test "x$actual" = "x-$x" + test "x$actual" = "x-$x" ' diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh index 70389fa2eb..179474fa65 100755 --- a/t/t1302-repo-version.sh +++ b/t/t1302-repo-version.sh @@ -37,7 +37,7 @@ test_expect_success 'gitdir selection on normal repos' ' test_expect_success 'gitdir selection on unsupported repo' ' # Make sure it would stop at test2, not trash - test_expect_code 1 git -C test2 config core.repositoryformatversion >actual + test_expect_code 1 git -C test2 config core.repositoryformatversion ' test_expect_success 'gitdir not required mode' ' diff --git a/t/t1307-config-blob.sh b/t/t1307-config-blob.sh index 0a7099d6f5..b9852fe40e 100755 --- a/t/t1307-config-blob.sh +++ b/t/t1307-config-blob.sh @@ -63,7 +63,7 @@ test_expect_success 'parse errors in blobs are properly attributed' ' git commit -m broken && test_must_fail git config --blob=HEAD:config some.value 2>err && - test_i18ngrep "HEAD:config" err + test_grep "HEAD:config" err ' test_expect_success 'can parse blob ending with CR' ' diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh index b38e158d3b..3bfec07f1a 100755 --- a/t/t1308-config-set.sh +++ b/t/t1308-config-set.sh @@ -58,6 +58,8 @@ test_expect_success 'setup default config' ' skin = false nose = 1 horns + [value] + less EOF ' @@ -116,10 +118,53 @@ test_expect_success 'find value with the highest priority' ' check_config get_value case.baz "hask" ' +test_expect_success 'return value for an existing key' ' + test-tool config get lamb.chop >out 2>err && + test_must_be_empty out && + test_must_be_empty err +' + +test_expect_success 'return value for value-less key' ' + test-tool config get value.less >out 2>err && + test_must_be_empty out && + test_must_be_empty err +' + +test_expect_success 'return value for a missing key' ' + cat >expect <<-\EOF && + Value not found for "missing.key" + EOF + test_expect_code 1 test-tool config get missing.key >actual 2>err && + test_cmp actual expect && + test_must_be_empty err +' + +test_expect_success 'return value for a bad key: CONFIG_INVALID_KEY' ' + cat >expect <<-\EOF && + Key "fails.iskeychar.-" is invalid + EOF + test_expect_code 1 test-tool config get fails.iskeychar.- >actual 2>err && + test_cmp actual expect && + test_must_be_empty out +' + +test_expect_success 'return value for a bad key: CONFIG_NO_SECTION_OR_NAME' ' + cat >expect <<-\EOF && + Key "keynosection" has no section + EOF + test_expect_code 1 test-tool config get keynosection >actual 2>err && + test_cmp actual expect && + test_must_be_empty out +' + test_expect_success 'find integer value for a key' ' check_config get_int lamb.chop 65 ' +test_expect_success 'parse integer value during iteration' ' + check_config git_config_int lamb.chop 65 +' + test_expect_success 'find string value for a key' ' check_config get_string case.baz hask && check_config expect_code 1 get_string case.ba "Value not found for \"case.ba\"" @@ -127,13 +172,18 @@ test_expect_success 'find string value for a key' ' test_expect_success 'check line error when NULL string is queried' ' test_expect_code 128 test-tool config get_string case.foo 2>result && - test_i18ngrep "fatal: .*case\.foo.*\.git/config.*line 7" result + test_grep "fatal: .*case\.foo.*\.git/config.*line 7" result ' test_expect_success 'find integer if value is non parse-able' ' check_config expect_code 128 get_int lamb.head ' +test_expect_success 'non parse-able integer value during iteration' ' + check_config expect_code 128 git_config_int lamb.head 2>result && + grep "fatal: bad numeric config value .* in file \.git/config" result +' + test_expect_success 'find bool value for the entered key' ' check_config get_bool goat.head 1 && check_config get_bool goat.skin 0 && @@ -146,6 +196,71 @@ test_expect_success 'find multiple values' ' check_config get_value_multi case.baz sam bat hask ' +test_NULL_in_multi () { + local op="$1" && + local file="$2" && + + test_expect_success "$op: NULL value in config${file:+ in $file}" ' + config="$file" && + if test -z "$config" + then + config=.git/config && + test_when_finished "mv $config.old $config" && + mv "$config" "$config".old + fi && + + # Value-less in the middle of a list + cat >"$config" <<-\EOF && + [a]key=x + [a]key + [a]key=y + EOF + case "$op" in + *_multi) + cat >expect <<-\EOF + x + (NULL) + y + EOF + ;; + *) + cat >expect <<-\EOF + y + EOF + ;; + esac && + test-tool config "$op" a.key $file >actual && + test_cmp expect actual && + + # Value-less at the end of a least + cat >"$config" <<-\EOF && + [a]key=x + [a]key=y + [a]key + EOF + case "$op" in + *_multi) + cat >expect <<-\EOF + x + y + (NULL) + EOF + ;; + *) + cat >expect <<-\EOF + (NULL) + EOF + ;; + esac && + test-tool config "$op" a.key $file >actual && + test_cmp expect actual + ' +} + +test_NULL_in_multi "get_value_multi" +test_NULL_in_multi "configset_get_value" "my.config" +test_NULL_in_multi "configset_get_value_multi" "my.config" + test_expect_success 'find value from a configset' ' cat >config2 <<-\EOF && [case] @@ -207,7 +322,7 @@ test_expect_success 'proper error on error in default config files' ' cp .git/config .git/config.old && test_when_finished "mv .git/config.old .git/config" && echo "[" >>.git/config && - echo "fatal: bad config line 34 in file .git/config" >expect && + echo "fatal: bad config line 36 in file .git/config" >expect && test_expect_code 128 test-tool config get_value foo.bar 2>actual && test_cmp expect actual ' @@ -227,14 +342,14 @@ test_expect_success 'check line errors for malformed values' ' br EOF test_expect_code 128 git br 2>result && - test_i18ngrep "missing value for .alias\.br" result && - test_i18ngrep "fatal: .*\.git/config" result && - test_i18ngrep "fatal: .*line 2" result + test_grep "missing value for .alias\.br" result && + test_grep "fatal: .*\.git/config" result && + test_grep "fatal: .*line 2" result ' test_expect_success 'error on modifying repo config without repo' ' nongit test_must_fail git config a.b c 2>err && - test_i18ngrep "not in a git directory" err + test_grep "not in a git directory" err ' cmdline_config="'foo.bar=from-cmdline'" diff --git a/t/t1309-early-config.sh b/t/t1309-early-config.sh index 537435b90a..523aa99a1e 100755 --- a/t/t1309-early-config.sh +++ b/t/t1309-early-config.sh @@ -78,7 +78,7 @@ test_with_config () { test_expect_success 'ignore .git/ with incompatible repository version' ' test_with_config "[core]repositoryformatversion = 999999" 2>err && - test_i18ngrep "warning:.* Expected git repo version <= [1-9]" err + test_grep "warning:.* Expected git repo version <= [1-9]" err ' test_expect_failure 'ignore .git/ with invalid repository version' ' diff --git a/t/t1310-config-default.sh b/t/t1310-config-default.sh index 09b10c144b..1a90d31201 100755 --- a/t/t1310-config-default.sh +++ b/t/t1310-config-default.sh @@ -26,12 +26,12 @@ test_expect_success 'canonicalizes --default with appropriate type' ' test_expect_success 'dies when --default cannot be parsed' ' test_must_fail git config -f config --type=expiry-date --default=x --get \ not.a.section 2>error && - test_i18ngrep "failed to format default config value" error + test_grep "failed to format default config value" error ' test_expect_success 'does not allow --default without --get' ' test_must_fail git config --default=quux --unset a.section >output 2>&1 && - test_i18ngrep "\-\-default is only applicable to" output + test_grep "\-\-default is only applicable to" output ' test_done diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index cf58cf025c..f18843bf7a 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -9,8 +9,6 @@ test_description='Test git update-ref and basic ref logging' Z=$ZERO_OID m=refs/heads/main -n_dir=refs/heads/gu -n=$n_dir/fixes outside=refs/foo bare=bare-repo @@ -62,10 +60,10 @@ test_expect_success "delete $m without oldvalue verification" ' test_must_fail git show-ref --verify -q $m ' -test_expect_success "fail to create $n" ' - test_when_finished "rm -f .git/$n_dir" && - touch .git/$n_dir && - test_must_fail git update-ref $n $A +test_expect_success "fail to create $n due to file/directory conflict" ' + test_when_finished "git update-ref -d refs/heads/gu" && + git update-ref refs/heads/gu $A && + test_must_fail git update-ref refs/heads/gu/fixes $A ' test_expect_success "create $m (by HEAD)" ' @@ -92,7 +90,8 @@ test_expect_success "deleting current branch adds message to HEAD's log" ' git symbolic-ref HEAD $m && git update-ref -m delete-$m -d $m && test_must_fail git show-ref --verify -q $m && - grep "delete-$m$" .git/logs/HEAD + test-tool ref-store main for-each-reflog-ent HEAD >actual && + grep "delete-$m$" actual ' test_expect_success "deleting by HEAD adds message to HEAD's log" ' @@ -101,7 +100,8 @@ test_expect_success "deleting by HEAD adds message to HEAD's log" ' git symbolic-ref HEAD $m && git update-ref -m delete-by-head -d HEAD && test_must_fail git show-ref --verify -q $m && - grep "delete-by-head$" .git/logs/HEAD + test-tool ref-store main for-each-reflog-ent HEAD >actual && + grep "delete-by-head$" actual ' test_expect_success 'update-ref does not create reflogs by default' ' @@ -132,7 +132,7 @@ test_expect_success 'creates no reflog in bare repository' ' test_expect_success 'core.logAllRefUpdates=true creates reflog in bare repository' ' test_when_finished "git -C $bare config --unset core.logAllRefUpdates && \ - rm $bare/logs/$m" && + test-tool ref-store main delete-reflog $m" && git -C $bare config core.logAllRefUpdates true && git -C $bare update-ref $m $bareB && git -C $bare rev-parse $bareB >expect && @@ -221,27 +221,27 @@ test_expect_success 'delete symref without dereference when the referred ref is ' test_expect_success 'update-ref -d is not confused by self-reference' ' + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF refs/heads/self" && git symbolic-ref refs/heads/self refs/heads/self && - test_when_finished "rm -f .git/refs/heads/self" && - test_path_is_file .git/refs/heads/self && + git symbolic-ref --no-recurse refs/heads/self && test_must_fail git update-ref -d refs/heads/self && - test_path_is_file .git/refs/heads/self + git symbolic-ref --no-recurse refs/heads/self ' test_expect_success 'update-ref --no-deref -d can delete self-reference' ' + test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF refs/heads/self" && git symbolic-ref refs/heads/self refs/heads/self && - test_when_finished "rm -f .git/refs/heads/self" && - test_path_is_file .git/refs/heads/self && + git symbolic-ref --no-recurse refs/heads/self && git update-ref --no-deref -d refs/heads/self && test_must_fail git show-ref --verify -q refs/heads/self ' -test_expect_success 'update-ref --no-deref -d can delete reference to bad ref' ' +test_expect_success REFFILES 'update-ref --no-deref -d can delete reference to bad ref' ' >.git/refs/heads/bad && test_when_finished "rm -f .git/refs/heads/bad" && git symbolic-ref refs/heads/ref-to-bad refs/heads/bad && test_when_finished "git update-ref -d refs/heads/ref-to-bad" && - test_path_is_file .git/refs/heads/ref-to-bad && + git symbolic-ref --no-recurse refs/heads/ref-to-bad && git update-ref --no-deref -d refs/heads/ref-to-bad && test_must_fail git show-ref --verify -q refs/heads/ref-to-bad ' @@ -265,7 +265,10 @@ test_expect_success "(not) changed .git/$m" ' ! test $B = $(git show-ref -s --verify $m) ' -rm -f .git/logs/refs/heads/main +test_expect_success "clean up reflog" ' + test-tool ref-store main delete-reflog $m +' + test_expect_success "create $m (logged by touch)" ' test_config core.logAllRefUpdates false && GIT_COMMITTER_DATE="2005-05-26 23:30" \ @@ -285,7 +288,7 @@ test_expect_success "set $m (logged by touch)" ' test $A = $(git show-ref -s --verify $m) ' -test_expect_success 'empty directory removal' ' +test_expect_success REFFILES 'empty directory removal' ' git branch d1/d2/r1 HEAD && git branch d1/r2 HEAD && test_path_is_file .git/refs/heads/d1/d2/r1 && @@ -297,7 +300,7 @@ test_expect_success 'empty directory removal' ' test_path_is_file .git/logs/refs/heads/d1/r2 ' -test_expect_success 'symref empty directory removal' ' +test_expect_success REFFILES 'symref empty directory removal' ' git branch e1/e2/r1 HEAD && git branch e1/r2 HEAD && git checkout e1/e2/r1 && @@ -318,7 +321,7 @@ $A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150260 +0000 Switch $B $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150860 +0000 EOF test_expect_success "verifying $m's log (logged by touch)" ' - test_when_finished "git update-ref -d $m && rm -rf .git/logs actual expect" && + test_when_finished "git update-ref -d $m && git reflog expire --expire=all --all && rm -rf actual expect" && test-tool ref-store main for-each-reflog-ent $m >actual && test_cmp actual expect ' @@ -348,20 +351,34 @@ $A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150380 +0000 Switch $B $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150980 +0000 EOF test_expect_success "verifying $m's log (logged by config)" ' - test_when_finished "git update-ref -d $m && rm -rf .git/logs actual expect" && + test_when_finished "git update-ref -d $m && git reflog expire --expire=all --all && rm -rf actual expect" && test-tool ref-store main for-each-reflog-ent $m >actual && test_cmp actual expect ' test_expect_success 'set up for querying the reflog' ' + git update-ref -d $m && + test-tool ref-store main delete-reflog $m && + + GIT_COMMITTER_DATE="1117150320 -0500" git update-ref $m $C && + GIT_COMMITTER_DATE="1117150350 -0500" git update-ref $m $A && + GIT_COMMITTER_DATE="1117150380 -0500" git update-ref $m $B && + GIT_COMMITTER_DATE="1117150680 -0500" git update-ref $m $F && + GIT_COMMITTER_DATE="1117150980 -0500" git update-ref $m $E && git update-ref $m $D && - cat >.git/logs/$m <<-EOF + # Delete the last reflog entry so that the tip of m and the reflog for + # it disagree. + git reflog delete $m@{0} && + + cat >expect <<-EOF && $Z $C $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500 $C $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150350 -0500 $A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150380 -0500 - $F $Z $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150680 -0500 - $Z $E $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150980 -0500 + $B $F $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150680 -0500 + $F $E $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150980 -0500 EOF + test-tool ref-store main for-each-reflog-ent $m >actual && + test_cmp expect actual ' ed="Thu, 26 May 2005 18:32:00 -0500" @@ -409,13 +426,12 @@ test_expect_success 'Query "main@{2005-05-26 23:33:01}" (middle of history with test_when_finished "rm -f o e" && git rev-parse --verify "main@{2005-05-26 23:33:01}" >o 2>e && echo "$B" >expect && - test_cmp expect o && - test_i18ngrep -F "warning: log for ref $m has gap after $gd" e + test_cmp expect o ' test_expect_success 'Query "main@{2005-05-26 23:38:00}" (middle of history)' ' test_when_finished "rm -f o e" && git rev-parse --verify "main@{2005-05-26 23:38:00}" >o 2>e && - echo "$Z" >expect && + echo "$F" >expect && test_cmp expect o && test_must_be_empty e ' @@ -431,10 +447,27 @@ test_expect_success 'Query "main@{2005-05-28}" (past end of history)' ' git rev-parse --verify "main@{2005-05-28}" >o 2>e && echo "$D" >expect && test_cmp expect o && - test_i18ngrep -F "warning: log for ref $m unexpectedly ended on $ld" e + test_grep -F "warning: log for ref $m unexpectedly ended on $ld" e ' -rm -f .git/$m .git/logs/$m expect +rm -f expect +git update-ref -d $m + +test_expect_success REFFILES 'query reflog with gap' ' + test_when_finished "git update-ref -d $m" && + + git update-ref $m $F && + cat >.git/logs/$m <<-EOF && + $Z $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500 + $A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150380 -0500 + $D $F $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150680 -0500 + EOF + + git rev-parse --verify "main@{2005-05-26 23:33:01}" >actual 2>stderr && + echo "$B" >expect && + test_cmp expect actual && + test_grep -F "warning: log for ref $m has gap after $gd" stderr +' test_expect_success 'creating initial files' ' test_when_finished rm -f M && @@ -486,7 +519,7 @@ test_expect_success 'git cat-file blob main@{2005-05-26 23:42}:F (expect OTHER)' test_expect_success 'given old value for missing pseudoref, do not create' ' test_must_fail git update-ref PSEUDOREF $A $B 2>err && test_must_fail git rev-parse PSEUDOREF && - test_i18ngrep "unable to resolve reference" err + test_grep "unable to resolve reference" err ' test_expect_success 'create pseudoref' ' @@ -507,7 +540,7 @@ test_expect_success 'overwrite pseudoref with correct old value' ' test_expect_success 'do not overwrite pseudoref with wrong old value' ' test_must_fail git update-ref PSEUDOREF $D $E 2>err && test $C = $(git rev-parse PSEUDOREF) && - test_i18ngrep "cannot lock ref.*expected" err + test_grep "cannot lock ref.*expected" err ' test_expect_success 'delete pseudoref' ' @@ -519,7 +552,7 @@ test_expect_success 'do not delete pseudoref with wrong old value' ' git update-ref PSEUDOREF $A && test_must_fail git update-ref -d PSEUDOREF $B 2>err && test $A = $(git rev-parse PSEUDOREF) && - test_i18ngrep "cannot lock ref.*expected" err + test_grep "cannot lock ref.*expected" err ' test_expect_success 'delete pseudoref with correct old value' ' @@ -536,7 +569,7 @@ test_expect_success 'do not overwrite pseudoref with old OID zero' ' test_when_finished git update-ref -d PSEUDOREF && test_must_fail git update-ref PSEUDOREF $B $Z 2>err && test $A = $(git rev-parse PSEUDOREF) && - test_i18ngrep "already exists" err + test_grep "already exists" err ' # Test --stdin @@ -556,7 +589,7 @@ test_expect_success 'stdin test setup' ' test_expect_success '-z fails without --stdin' ' test_must_fail git update-ref -z $m $m $m 2>err && - test_i18ngrep "usage: git update-ref" err + test_grep "usage: git update-ref" err ' test_expect_success 'stdin works with no input' ' @@ -674,7 +707,7 @@ test_expect_success 'stdin fails with duplicate refs' ' create $a $m EOF test_must_fail git update-ref --stdin <stdin 2>err && - test_i18ngrep "fatal: multiple updates for ref '"'"'$a'"'"' not allowed" err + test_grep "fatal: multiple updates for ref '"'"'$a'"'"' not allowed" err ' test_expect_success 'stdin create ref works' ' @@ -1107,7 +1140,7 @@ test_expect_success 'stdin -z fails option with unknown name' ' test_expect_success 'stdin -z fails with duplicate refs' ' printf $F "create $a" "$m" "create $b" "$m" "create $a" "$m" >stdin && test_must_fail git update-ref -z --stdin <stdin 2>err && - test_i18ngrep "fatal: multiple updates for ref '"'"'$a'"'"' not allowed" err + test_grep "fatal: multiple updates for ref '"'"'$a'"'"' not allowed" err ' test_expect_success 'stdin -z create ref works' ' @@ -1338,7 +1371,7 @@ test_expect_success 'fails with duplicate HEAD update' ' update HEAD $B EOF test_must_fail git update-ref --stdin <stdin 2>err && - test_i18ngrep "fatal: multiple updates for '\''HEAD'\'' (including one via its referent .refs/heads/target1.) are not allowed" err && + test_grep "fatal: multiple updates for '\''HEAD'\'' (including one via its referent .refs/heads/target1.) are not allowed" err && echo "refs/heads/target1" >expect && git symbolic-ref HEAD >actual && test_cmp expect actual && @@ -1355,7 +1388,7 @@ test_expect_success 'fails with duplicate ref update via symref' ' update refs/heads/symref2 $B EOF test_must_fail git update-ref --stdin <stdin 2>err && - test_i18ngrep "fatal: multiple updates for '\''refs/heads/target2'\'' (including one via symref .refs/heads/symref2.) are not allowed" err && + test_grep "fatal: multiple updates for '\''refs/heads/target2'\'' (including one via symref .refs/heads/symref2.) are not allowed" err && echo "refs/heads/target2" >expect && git symbolic-ref refs/heads/symref2 >actual && test_cmp expect actual && @@ -1568,6 +1601,7 @@ test_expect_success 'transaction can create and delete' ' EOF git update-ref --stdin <stdin >actual && printf "%s: ok\n" start commit start commit >expect && + test_cmp expect actual && test_must_fail git show-ref --verify refs/heads/create-and-delete ' @@ -1595,6 +1629,8 @@ test_expect_success 'transaction cannot restart ongoing transaction' ' commit EOF test_must_fail git update-ref --stdin <stdin >actual && + printf "%s: ok\n" start >expect && + test_cmp expect actual && test_must_fail git show-ref --verify refs/heads/restart ' @@ -1632,7 +1668,7 @@ test_expect_success PIPE 'transaction flushes status updates' ' test_cmp expected actual ' -test_expect_success 'directory not created deleting packed ref' ' +test_expect_success REFFILES 'directory not created deleting packed ref' ' git branch d1/d2/r1 HEAD && git pack-refs --all && test_path_is_missing .git/refs/heads/d1/d2 && diff --git a/t/t1401-symbolic-ref.sh b/t/t1401-symbolic-ref.sh index be23be30c7..3241d35917 100755 --- a/t/t1401-symbolic-ref.sh +++ b/t/t1401-symbolic-ref.sh @@ -33,7 +33,8 @@ test_expect_success 'symbolic-ref refuses non-ref for HEAD' ' reset_to_sane test_expect_success 'symbolic-ref refuses bare sha1' ' - test_must_fail git symbolic-ref HEAD $(git rev-parse HEAD) + rev=$(git rev-parse HEAD) && + test_must_fail git symbolic-ref HEAD "$rev" ' reset_to_sane @@ -170,8 +171,8 @@ test_expect_success 'symbolic-ref refuses invalid target for non-HEAD' ' ' test_expect_success 'symbolic-ref allows top-level target for non-HEAD' ' - git symbolic-ref refs/heads/top-level FETCH_HEAD && - git update-ref FETCH_HEAD HEAD && + git symbolic-ref refs/heads/top-level ORIG_HEAD && + git update-ref ORIG_HEAD HEAD && test_cmp_rev top-level HEAD ' diff --git a/t/t1403-show-ref.sh b/t/t1403-show-ref.sh index 9252a581ab..b50ae6fcf1 100755 --- a/t/t1403-show-ref.sh +++ b/t/t1403-show-ref.sh @@ -196,4 +196,74 @@ test_expect_success 'show-ref --verify with dangling ref' ' ) ' +test_expect_success 'show-ref sub-modes are mutually exclusive' ' + cat >expect <<-EOF && + fatal: only one of ${SQ}--exclude-existing${SQ}, ${SQ}--verify${SQ} or ${SQ}--exists${SQ} can be given + EOF + + test_must_fail git show-ref --verify --exclude-existing 2>err && + test_cmp expect err && + + test_must_fail git show-ref --verify --exists 2>err && + test_cmp expect err && + + test_must_fail git show-ref --exclude-existing --exists 2>err && + test_cmp expect err +' + +test_expect_success '--exists with existing reference' ' + git show-ref --exists refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +' + +test_expect_success '--exists with missing reference' ' + test_expect_code 2 git show-ref --exists refs/heads/does-not-exist +' + +test_expect_success '--exists does not use DWIM' ' + test_expect_code 2 git show-ref --exists $GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME 2>err && + grep "reference does not exist" err +' + +test_expect_success '--exists with HEAD' ' + git show-ref --exists HEAD +' + +test_expect_success '--exists with bad reference name' ' + test_when_finished "git update-ref -d refs/heads/bad...name" && + new_oid=$(git rev-parse HEAD) && + test-tool ref-store main update-ref msg refs/heads/bad...name $new_oid $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && + git show-ref --exists refs/heads/bad...name +' + +test_expect_success '--exists with arbitrary symref' ' + test_when_finished "git symbolic-ref -d refs/symref" && + git symbolic-ref refs/symref refs/heads/$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME && + git show-ref --exists refs/symref +' + +test_expect_success '--exists with dangling symref' ' + test_when_finished "git symbolic-ref -d refs/heads/dangling" && + git symbolic-ref refs/heads/dangling refs/heads/does-not-exist && + git show-ref --exists refs/heads/dangling +' + +test_expect_success '--exists with nonexistent object ID' ' + test-tool ref-store main update-ref msg refs/heads/missing-oid $(test_oid 001) $ZERO_OID REF_SKIP_OID_VERIFICATION && + git show-ref --exists refs/heads/missing-oid +' + +test_expect_success '--exists with non-commit object' ' + tree_oid=$(git rev-parse HEAD^{tree}) && + test-tool ref-store main update-ref msg refs/heads/tree ${tree_oid} $ZERO_OID REF_SKIP_OID_VERIFICATION && + git show-ref --exists refs/heads/tree +' + +test_expect_success '--exists with directory fails with generic error' ' + cat >expect <<-EOF && + error: failed to look up reference: Is a directory + EOF + test_expect_code 1 git show-ref --exists refs/heads 2>err && + test_cmp expect err +' + test_done diff --git a/t/t1404-update-ref-errors.sh b/t/t1404-update-ref-errors.sh index b5606d93b5..0369beea33 100755 --- a/t/t1404-update-ref-errors.sh +++ b/t/t1404-update-ref-errors.sh @@ -29,7 +29,7 @@ test_update_rejected () { fi && printf "create $prefix/%s $C\n" $create >input && test_must_fail git update-ref --stdin <input 2>output.err && - test_i18ngrep -F "$error" output.err && + test_grep -F "$error" output.err && git for-each-ref $prefix >actual && test_cmp unchanged actual } @@ -551,7 +551,6 @@ test_expect_success REFFILES 'no bogus intermediate values during delete' ' git update-ref $prefix/foo $C && git pack-refs --all && git update-ref $prefix/foo $D && - git for-each-ref $prefix >unchanged && # Now try to update the reference, but hold the `packed-refs` lock # for a while to see what happens while the process is blocked: : >.git/packed-refs.lock && @@ -614,7 +613,7 @@ test_expect_success REFFILES 'delete fails cleanly if packed-refs file is locked test_when_finished "rm -f .git/packed-refs.lock" && test_must_fail git update-ref -d $prefix/foo >out 2>err && git for-each-ref $prefix >actual && - test_i18ngrep "Unable to create $SQ.*packed-refs.lock$SQ: " err && + test_grep "Unable to create $SQ.*packed-refs.lock$SQ: " err && test_cmp unchanged actual ' diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh index 6c45965b1e..a0ff8d51f0 100755 --- a/t/t1410-reflog.sh +++ b/t/t1410-reflog.sh @@ -29,7 +29,7 @@ check_fsck () { '') test_must_be_empty fsck.output ;; *) - test_i18ngrep "$1" fsck.output ;; + test_grep "$1" fsck.output ;; esac } @@ -308,9 +308,9 @@ test_expect_success 'git reflog expire unknown reference' ' test_config gc.reflogexpireunreachable never && test_must_fail git reflog expire main@{123} 2>stderr && - test_i18ngrep "points nowhere" stderr && + test_grep "points nowhere" stderr && test_must_fail git reflog expire does-not-exist 2>stderr && - test_i18ngrep "points nowhere" stderr + test_grep "points nowhere" stderr ' test_expect_success 'checkout should not delete log for packed ref' ' @@ -446,11 +446,34 @@ test_expect_success 'expire with multiple worktrees' ' ) ' -test_expect_success REFFILES 'empty reflog' ' +test_expect_success 'expire one of multiple worktrees' ' + git init main-wt2 && + ( + cd main-wt2 && + test_tick && + test_commit foo && + git worktree add link-wt && + test_tick && + test_commit -C link-wt foobar && + test_tick && + test-tool ref-store worktree:link-wt for-each-reflog-ent HEAD \ + >expect-link-wt && + git reflog expire --verbose --all --expire=$test_tick \ + --single-worktree && + test-tool ref-store worktree:main for-each-reflog-ent HEAD \ + >actual-main && + test-tool ref-store worktree:link-wt for-each-reflog-ent HEAD \ + >actual-link-wt && + test_must_be_empty actual-main && + test_cmp expect-link-wt actual-link-wt + ) +' + +test_expect_success 'empty reflog' ' test_when_finished "rm -rf empty" && git init empty && test_commit -C empty A && - >empty/.git/logs/refs/heads/foo && + test-tool ref-store main create-reflog refs/heads/foo && git -C empty reflog expire --all 2>err && test_must_be_empty err ' diff --git a/t/t1416-ref-transaction-hooks.sh b/t/t1416-ref-transaction-hooks.sh index b32ca798f9..2092488090 100755 --- a/t/t1416-ref-transaction-hooks.sh +++ b/t/t1416-ref-transaction-hooks.sh @@ -37,7 +37,7 @@ test_expect_success 'hook aborts updating ref in prepared state' ' fi EOF test_must_fail git update-ref HEAD POST 2>err && - test_i18ngrep "ref updates aborted by hook" err + test_grep "ref updates aborted by hook" err ' test_expect_success 'hook gets all queued updates in prepared state' ' diff --git a/t/t1417-reflog-updateref.sh b/t/t1417-reflog-updateref.sh index 14f13b57c6..0eb5e674bc 100755 --- a/t/t1417-reflog-updateref.sh +++ b/t/t1417-reflog-updateref.sh @@ -14,9 +14,13 @@ test_expect_success 'setup' ' test_commit B && test_commit C && - cp .git/logs/HEAD HEAD.old && + git reflog HEAD >expect && git reset --hard HEAD~ && - cp HEAD.old .git/logs/HEAD + # Make sure that the reflog does not point to the same commit + # as HEAD. + git reflog delete HEAD@{0} && + git reflog HEAD >actual && + test_cmp expect actual ) ' @@ -25,7 +29,7 @@ test_reflog_updateref () { shift args="$@" - test_expect_success REFFILES "get '$exp' with '$args'" ' + test_expect_success "get '$exp' with '$args'" ' test_when_finished "rm -rf copy" && cp -R repo copy && diff --git a/t/t1419-exclude-refs.sh b/t/t1419-exclude-refs.sh new file mode 100755 index 0000000000..5d8c86b657 --- /dev/null +++ b/t/t1419-exclude-refs.sh @@ -0,0 +1,122 @@ +#!/bin/sh + +test_description='test exclude_patterns functionality in main ref store' + +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh + +for_each_ref__exclude () { + GIT_TRACE2_PERF=1 test-tool ref-store main \ + for-each-ref--exclude "$@" >actual.raw + cut -d ' ' -f 2 actual.raw +} + +for_each_ref () { + git for-each-ref --format='%(refname)' "$@" +} + +assert_jumps () { + local nr="$1" + local trace="$2" + + grep -q "name:jumps_made value:$nr$" $trace +} + +assert_no_jumps () { + ! assert_jumps ".*" "$1" +} + +test_expect_success 'setup' ' + test_commit --no-tag base && + base="$(git rev-parse HEAD)" && + + for name in foo bar baz quux + do + for i in 1 2 3 + do + echo "create refs/heads/$name/$i $base" || return 1 + done || return 1 + done >in && + echo "delete refs/heads/main" >>in && + + git update-ref --stdin <in && + git pack-refs --all +' + +test_expect_success 'excluded region in middle' ' + for_each_ref__exclude refs/heads refs/heads/foo >actual 2>perf && + for_each_ref refs/heads/bar refs/heads/baz refs/heads/quux >expect && + + test_cmp expect actual && + assert_jumps 1 perf +' + +test_expect_success 'excluded region at beginning' ' + for_each_ref__exclude refs/heads refs/heads/bar >actual 2>perf && + for_each_ref refs/heads/baz refs/heads/foo refs/heads/quux >expect && + + test_cmp expect actual && + assert_jumps 1 perf +' + +test_expect_success 'excluded region at end' ' + for_each_ref__exclude refs/heads refs/heads/quux >actual 2>perf && + for_each_ref refs/heads/foo refs/heads/bar refs/heads/baz >expect && + + test_cmp expect actual && + assert_jumps 1 perf +' + +test_expect_success 'disjoint excluded regions' ' + for_each_ref__exclude refs/heads refs/heads/bar refs/heads/quux >actual 2>perf && + for_each_ref refs/heads/baz refs/heads/foo >expect && + + test_cmp expect actual && + assert_jumps 2 perf +' + +test_expect_success 'adjacent, non-overlapping excluded regions' ' + for_each_ref__exclude refs/heads refs/heads/bar refs/heads/baz >actual 2>perf && + for_each_ref refs/heads/foo refs/heads/quux >expect && + + test_cmp expect actual && + assert_jumps 1 perf +' + +test_expect_success 'overlapping excluded regions' ' + for_each_ref__exclude refs/heads refs/heads/ba refs/heads/baz >actual 2>perf && + for_each_ref refs/heads/foo refs/heads/quux >expect && + + test_cmp expect actual && + assert_jumps 1 perf +' + +test_expect_success 'several overlapping excluded regions' ' + for_each_ref__exclude refs/heads \ + refs/heads/bar refs/heads/baz refs/heads/foo >actual 2>perf && + for_each_ref refs/heads/quux >expect && + + test_cmp expect actual && + assert_jumps 1 perf +' + +test_expect_success 'non-matching excluded section' ' + for_each_ref__exclude refs/heads refs/heads/does/not/exist >actual 2>perf && + for_each_ref >expect && + + test_cmp expect actual && + assert_no_jumps perf +' + +test_expect_success 'meta-characters are discarded' ' + for_each_ref__exclude refs/heads "refs/heads/ba*" >actual 2>perf && + for_each_ref >expect && + + test_cmp expect actual && + assert_no_jumps perf +' + +test_done diff --git a/t/t1430-bad-ref-name.sh b/t/t1430-bad-ref-name.sh index ff1c967d55..0c00118c2b 100755 --- a/t/t1430-bad-ref-name.sh +++ b/t/t1430-bad-ref-name.sh @@ -47,7 +47,7 @@ test_expect_success 'git branch shows badly named ref as warning' ' test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && git branch >output 2>error && - test_i18ngrep -e "ignoring ref with broken name refs/heads/broken\.\.\.ref" error && + test_grep -e "ignoring ref with broken name refs/heads/broken\.\.\.ref" error && ! grep -e "broken\.\.\.ref" output ' @@ -158,23 +158,23 @@ test_expect_success 'rev-parse skips symref pointing to broken name' ' git rev-parse --verify one >expect && git rev-parse --verify shadow >actual 2>err && test_cmp expect actual && - test_i18ngrep "ignoring dangling symref refs/tags/shadow" err + test_grep "ignoring dangling symref refs/tags/shadow" err ' test_expect_success 'for-each-ref emits warnings for broken names' ' test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && - printf "ref: refs/heads/broken...ref\n" >.git/refs/heads/badname && + test-tool ref-store main create-symref refs/heads/badname refs/heads/broken...ref && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/badname" && - printf "ref: refs/heads/main\n" >.git/refs/heads/broken...symref && + test-tool ref-store main create-symref refs/heads/broken...symref refs/heads/main && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...symref" && git for-each-ref >output 2>error && ! grep -e "broken\.\.\.ref" output && ! grep -e "badname" output && ! grep -e "broken\.\.\.symref" output && - test_i18ngrep "ignoring ref with broken name refs/heads/broken\.\.\.ref" error && - test_i18ngrep ! "ignoring broken ref refs/heads/badname" error && - test_i18ngrep "ignoring ref with broken name refs/heads/broken\.\.\.symref" error + test_grep "ignoring ref with broken name refs/heads/broken\.\.\.ref" error && + test_grep ! "ignoring broken ref refs/heads/badname" error && + test_grep "ignoring ref with broken name refs/heads/broken\.\.\.symref" error ' test_expect_success 'update-ref -d can delete broken name' ' @@ -192,7 +192,7 @@ test_expect_success 'branch -d can delete broken name' ' test-tool ref-store main update-ref msg "refs/heads/broken...ref" $main_sha1 $ZERO_OID REF_SKIP_REFNAME_VERIFICATION && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && git branch -d broken...ref >output 2>error && - test_i18ngrep "Deleted branch broken...ref (was broken)" output && + test_grep "Deleted branch broken...ref (was broken)" output && test_must_be_empty error && git branch >output 2>error && ! grep -e "broken\.\.\.ref" error && @@ -205,8 +205,9 @@ test_expect_success 'update-ref --no-deref -d can delete symref to broken name' test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && test-tool ref-store main create-symref refs/heads/badname refs/heads/broken...ref msg && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/badname" && + test_ref_exists refs/heads/badname && git update-ref --no-deref -d refs/heads/badname >output 2>error && - test_path_is_missing .git/refs/heads/badname && + test_ref_missing refs/heads/badname && test_must_be_empty output && test_must_be_empty error ' @@ -216,17 +217,19 @@ test_expect_success 'branch -d can delete symref to broken name' ' test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && test-tool ref-store main create-symref refs/heads/badname refs/heads/broken...ref msg && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/badname" && + test_ref_exists refs/heads/badname && git branch -d badname >output 2>error && - test_path_is_missing .git/refs/heads/badname && - test_i18ngrep "Deleted branch badname (was refs/heads/broken\.\.\.ref)" output && + test_ref_missing refs/heads/badname && + test_grep "Deleted branch badname (was refs/heads/broken\.\.\.ref)" output && test_must_be_empty error ' test_expect_success 'update-ref --no-deref -d can delete dangling symref to broken name' ' test-tool ref-store main create-symref refs/heads/badname refs/heads/broken...ref msg && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/badname" && + test_ref_exists refs/heads/badname && git update-ref --no-deref -d refs/heads/badname >output 2>error && - test_path_is_missing .git/refs/heads/badname && + test_ref_missing refs/heads/badname && test_must_be_empty output && test_must_be_empty error ' @@ -234,9 +237,10 @@ test_expect_success 'update-ref --no-deref -d can delete dangling symref to brok test_expect_success 'branch -d can delete dangling symref to broken name' ' test-tool ref-store main create-symref refs/heads/badname refs/heads/broken...ref msg && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/badname" && + test_ref_exists refs/heads/badname && git branch -d badname >output 2>error && - test_path_is_missing .git/refs/heads/badname && - test_i18ngrep "Deleted branch badname (was refs/heads/broken\.\.\.ref)" output && + test_ref_missing refs/heads/badname && + test_grep "Deleted branch badname (was refs/heads/broken\.\.\.ref)" output && test_must_be_empty error ' @@ -245,45 +249,50 @@ test_expect_success 'update-ref -d can delete broken name through symref' ' test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...ref" && test-tool ref-store main create-symref refs/heads/badname refs/heads/broken...ref msg && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/badname" && + test_ref_exists refs/heads/broken...ref && git update-ref -d refs/heads/badname >output 2>error && - test_path_is_missing .git/refs/heads/broken...ref && + test_ref_missing refs/heads/broken...ref && test_must_be_empty output && test_must_be_empty error ' test_expect_success 'update-ref --no-deref -d can delete symref with broken name' ' - printf "ref: refs/heads/main\n" >.git/refs/heads/broken...symref && + test-tool ref-store main create-symref refs/heads/broken...symref refs/heads/main && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...symref" && + test_ref_exists refs/heads/broken...symref && git update-ref --no-deref -d refs/heads/broken...symref >output 2>error && - test_path_is_missing .git/refs/heads/broken...symref && + test_ref_missing refs/heads/broken...symref && test_must_be_empty output && test_must_be_empty error ' test_expect_success 'branch -d can delete symref with broken name' ' - printf "ref: refs/heads/main\n" >.git/refs/heads/broken...symref && + test-tool ref-store main create-symref refs/heads/broken...symref refs/heads/main && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...symref" && + test_ref_exists refs/heads/broken...symref && git branch -d broken...symref >output 2>error && - test_path_is_missing .git/refs/heads/broken...symref && - test_i18ngrep "Deleted branch broken...symref (was refs/heads/main)" output && + test_ref_missing refs/heads/broken...symref && + test_grep "Deleted branch broken...symref (was refs/heads/main)" output && test_must_be_empty error ' test_expect_success 'update-ref --no-deref -d can delete dangling symref with broken name' ' - printf "ref: refs/heads/idonotexist\n" >.git/refs/heads/broken...symref && + test-tool ref-store main create-symref refs/heads/broken...symref refs/heads/idonotexist && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...symref" && + test_ref_exists refs/heads/broken...symref && git update-ref --no-deref -d refs/heads/broken...symref >output 2>error && - test_path_is_missing .git/refs/heads/broken...symref && + test_ref_missing refs/heads/broken...symref && test_must_be_empty output && test_must_be_empty error ' test_expect_success 'branch -d can delete dangling symref with broken name' ' - printf "ref: refs/heads/idonotexist\n" >.git/refs/heads/broken...symref && + test-tool ref-store main create-symref refs/heads/broken...symref refs/heads/idonotexist && test_when_finished "test-tool ref-store main delete-refs REF_NO_DEREF msg refs/heads/broken...symref" && + test_ref_exists refs/heads/broken...symref && git branch -d broken...symref >output 2>error && - test_path_is_missing .git/refs/heads/broken...symref && - test_i18ngrep "Deleted branch broken...symref (was refs/heads/idonotexist)" output && + test_ref_missing refs/heads/broken...symref && + test_grep "Deleted branch broken...symref (was refs/heads/idonotexist)" output && test_must_be_empty error ' @@ -292,7 +301,7 @@ test_expect_success 'update-ref -d cannot delete non-ref in .git dir' ' echo precious >expect && test_must_fail git update-ref -d my-private-file >output 2>error && test_must_be_empty output && - test_i18ngrep -e "refusing to update ref with bad name" error && + test_grep -e "refusing to update ref with bad name" error && test_cmp expect .git/my-private-file ' diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index fdb886dfe4..8a456b1142 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -15,6 +15,7 @@ test_expect_success setup ' git config --unset i18n.commitencoding && git checkout HEAD^0 && test_commit B fileB two && + orig_head=$(git rev-parse HEAD) && git tag -d A B && git reflog expire --expire=now --all ' @@ -115,63 +116,62 @@ test_expect_success 'zlib corrupt loose object output ' ' ' test_expect_success 'branch pointing to non-commit' ' - git rev-parse HEAD^{tree} >.git/refs/heads/invalid && + tree_oid=$(git rev-parse --verify HEAD^{tree}) && test_when_finished "git update-ref -d refs/heads/invalid" && + test-tool ref-store main update-ref msg refs/heads/invalid $tree_oid $ZERO_OID REF_SKIP_OID_VERIFICATION && test_must_fail git fsck 2>out && - test_i18ngrep "not a commit" out + test_grep "not a commit" out ' -test_expect_success 'HEAD link pointing at a funny object' ' - test_when_finished "mv .git/SAVED_HEAD .git/HEAD" && - mv .git/HEAD .git/SAVED_HEAD && +test_expect_success REFFILES 'HEAD link pointing at a funny object' ' + test_when_finished "git update-ref HEAD $orig_head" && echo $ZERO_OID >.git/HEAD && # avoid corrupt/broken HEAD from interfering with repo discovery test_must_fail env GIT_DIR=.git git fsck 2>out && - test_i18ngrep "detached HEAD points" out + test_grep "detached HEAD points" out ' test_expect_success 'HEAD link pointing at a funny place' ' - test_when_finished "mv .git/SAVED_HEAD .git/HEAD" && - mv .git/HEAD .git/SAVED_HEAD && - echo "ref: refs/funny/place" >.git/HEAD && + test_when_finished "git update-ref --no-deref HEAD $orig_head" && + test-tool ref-store main create-symref HEAD refs/funny/place && # avoid corrupt/broken HEAD from interfering with repo discovery test_must_fail env GIT_DIR=.git git fsck 2>out && - test_i18ngrep "HEAD points to something strange" out + test_grep "HEAD points to something strange" out ' -test_expect_success 'HEAD link pointing at a funny object (from different wt)' ' - test_when_finished "mv .git/SAVED_HEAD .git/HEAD" && - test_when_finished "rm -rf .git/worktrees wt" && +test_expect_success REFFILES 'HEAD link pointing at a funny object (from different wt)' ' + test_when_finished "git update-ref HEAD $orig_head" && + test_when_finished "git worktree remove -f wt" && git worktree add wt && - mv .git/HEAD .git/SAVED_HEAD && echo $ZERO_OID >.git/HEAD && # avoid corrupt/broken HEAD from interfering with repo discovery test_must_fail git -C wt fsck 2>out && - test_i18ngrep "main-worktree/HEAD: detached HEAD points" out + test_grep "main-worktree/HEAD: detached HEAD points" out ' -test_expect_success 'other worktree HEAD link pointing at a funny object' ' - test_when_finished "rm -rf .git/worktrees other" && +test_expect_success REFFILES 'other worktree HEAD link pointing at a funny object' ' + test_when_finished "git worktree remove -f other" && git worktree add other && echo $ZERO_OID >.git/worktrees/other/HEAD && test_must_fail git fsck 2>out && - test_i18ngrep "worktrees/other/HEAD: detached HEAD points" out + test_grep "worktrees/other/HEAD: detached HEAD points" out ' test_expect_success 'other worktree HEAD link pointing at missing object' ' - test_when_finished "rm -rf .git/worktrees other" && + test_when_finished "git worktree remove -f other" && git worktree add other && - echo "Contents missing from repo" | git hash-object --stdin >.git/worktrees/other/HEAD && + object_id=$(echo "Contents missing from repo" | git hash-object --stdin) && + test-tool -C other ref-store main update-ref msg HEAD $object_id "" REF_NO_DEREF,REF_SKIP_OID_VERIFICATION && test_must_fail git fsck 2>out && - test_i18ngrep "worktrees/other/HEAD: invalid sha1 pointer" out + test_grep "worktrees/other/HEAD: invalid sha1 pointer" out ' test_expect_success 'other worktree HEAD link pointing at a funny place' ' - test_when_finished "rm -rf .git/worktrees other" && + test_when_finished "git worktree remove -f other" && git worktree add other && - echo "ref: refs/funny/place" >.git/worktrees/other/HEAD && + git -C other symbolic-ref HEAD refs/funny/place && test_must_fail git fsck 2>out && - test_i18ngrep "worktrees/other/HEAD points to something strange" out + test_grep "worktrees/other/HEAD points to something strange" out ' test_expect_success 'commit with multiple signatures is okay' ' @@ -217,7 +217,7 @@ test_expect_success 'email with embedded > is not okay' ' git update-ref refs/heads/bogus "$new" && test_when_finished "git update-ref -d refs/heads/bogus" && test_must_fail git fsck 2>out && - test_i18ngrep "error in commit $new" out + test_grep "error in commit $new" out ' test_expect_success 'missing < email delimiter is reported nicely' ' @@ -228,7 +228,7 @@ test_expect_success 'missing < email delimiter is reported nicely' ' git update-ref refs/heads/bogus "$new" && test_when_finished "git update-ref -d refs/heads/bogus" && test_must_fail git fsck 2>out && - test_i18ngrep "error in commit $new.* - bad name" out + test_grep "error in commit $new.* - bad name" out ' test_expect_success 'missing email is reported nicely' ' @@ -239,7 +239,7 @@ test_expect_success 'missing email is reported nicely' ' git update-ref refs/heads/bogus "$new" && test_when_finished "git update-ref -d refs/heads/bogus" && test_must_fail git fsck 2>out && - test_i18ngrep "error in commit $new.* - missing email" out + test_grep "error in commit $new.* - missing email" out ' test_expect_success '> in name is reported' ' @@ -250,7 +250,7 @@ test_expect_success '> in name is reported' ' git update-ref refs/heads/bogus "$new" && test_when_finished "git update-ref -d refs/heads/bogus" && test_must_fail git fsck 2>out && - test_i18ngrep "error in commit $new" out + test_grep "error in commit $new" out ' # date is 2^64 + 1 @@ -263,7 +263,7 @@ test_expect_success 'integer overflow in timestamps is reported' ' git update-ref refs/heads/bogus "$new" && test_when_finished "git update-ref -d refs/heads/bogus" && test_must_fail git fsck 2>out && - test_i18ngrep "error in commit $new.*integer overflow" out + test_grep "error in commit $new.*integer overflow" out ' test_expect_success 'commit with NUL in header' ' @@ -274,7 +274,7 @@ test_expect_success 'commit with NUL in header' ' git update-ref refs/heads/bogus "$new" && test_when_finished "git update-ref -d refs/heads/bogus" && test_must_fail git fsck 2>out && - test_i18ngrep "error in commit $new.*unterminated header: NUL at offset" out + test_grep "error in commit $new.*unterminated header: NUL at offset" out ' test_expect_success 'tree object with duplicate entries' ' @@ -295,7 +295,7 @@ test_expect_success 'tree object with duplicate entries' ' git hash-object --literally -w -t tree --stdin ) && test_must_fail git fsck 2>out && - test_i18ngrep "error in tree .*contains duplicate file entries" out + test_grep "error in tree .*contains duplicate file entries" out ' check_duplicate_names () { @@ -318,8 +318,8 @@ check_duplicate_names () { done >badtree && badtree=$(git mktree <badtree) && test_must_fail git fsck 2>out && - test_i18ngrep "$badtree" out && - test_i18ngrep "error in tree .*contains duplicate file entries" out + test_grep "$badtree" out && + test_grep "error in tree .*contains duplicate file entries" out ' } @@ -341,9 +341,9 @@ test_expect_success 'unparseable tree object' ' commit_sha1=$(git commit-tree $tree_sha1) && git update-ref refs/heads/wrong $commit_sha1 && test_must_fail git fsck 2>out && - test_i18ngrep "error: empty filename in tree entry" out && - test_i18ngrep "$tree_sha1" out && - test_i18ngrep ! "fatal: empty filename in tree entry" out + test_grep "error: empty filename in tree entry" out && + test_grep "$tree_sha1" out && + test_grep ! "fatal: empty filename in tree entry" out ' test_expect_success 'tree entry with type mismatch' ' @@ -360,8 +360,8 @@ test_expect_success 'tree entry with type mismatch' ' commit=$(git commit-tree $tree) && git update-ref refs/heads/type_mismatch $commit && test_must_fail git fsck >out 2>&1 && - test_i18ngrep "is a blob, not a tree" out && - test_i18ngrep ! "dangling blob" out + test_grep "is a blob, not a tree" out && + test_grep ! "dangling blob" out ' test_expect_success 'tree entry with bogus mode' ' @@ -391,10 +391,10 @@ test_expect_success 'tag pointing to nonexistent' ' tag=$(git hash-object -t tag -w --stdin <invalid-tag) && test_when_finished "remove_object $tag" && - echo $tag >.git/refs/tags/invalid && + git update-ref refs/tags/invalid $tag && test_when_finished "git update-ref -d refs/tags/invalid" && test_must_fail git fsck --tags >out && - test_i18ngrep "broken link" out + test_grep "broken link" out ' test_expect_success 'tag pointing to something else than its type' ' @@ -411,7 +411,7 @@ test_expect_success 'tag pointing to something else than its type' ' tag=$(git hash-object -t tag -w --stdin <wrong-tag) && test_when_finished "remove_object $tag" && - echo $tag >.git/refs/tags/wrong && + git update-ref refs/tags/wrong $tag && test_when_finished "git update-ref -d refs/tags/wrong" && test_must_fail git fsck --tags ' @@ -428,7 +428,7 @@ test_expect_success 'tag with incorrect tag name & missing tagger' ' tag=$(git hash-object --literally -t tag -w --stdin <wrong-tag) && test_when_finished "remove_object $tag" && - echo $tag >.git/refs/tags/wrong && + git update-ref refs/tags/wrong $tag && test_when_finished "git update-ref -d refs/tags/wrong" && git fsck --tags 2>out && @@ -452,10 +452,10 @@ test_expect_success 'tag with bad tagger' ' tag=$(git hash-object --literally -t tag -w --stdin <wrong-tag) && test_when_finished "remove_object $tag" && - echo $tag >.git/refs/tags/wrong && + git update-ref refs/tags/wrong $tag && test_when_finished "git update-ref -d refs/tags/wrong" && test_must_fail git fsck --tags 2>out && - test_i18ngrep "error in tag .*: invalid author/committer" out + test_grep "error in tag .*: invalid author/committer" out ' test_expect_success 'tag with NUL in header' ' @@ -471,10 +471,10 @@ test_expect_success 'tag with NUL in header' ' tag=$(git hash-object --literally -t tag -w --stdin <tag-NUL-header) && test_when_finished "remove_object $tag" && - echo $tag >.git/refs/tags/wrong && + git update-ref refs/tags/wrong $tag && test_when_finished "git update-ref -d refs/tags/wrong" && test_must_fail git fsck --tags 2>out && - test_i18ngrep "error in tag $tag.*unterminated header: NUL at offset" out + test_grep "error in tag $tag.*unterminated header: NUL at offset" out ' test_expect_success 'cleaned up' ' @@ -504,7 +504,7 @@ test_expect_success 'rev-list --verify-objects with bad sha1' ' test_when_finished "git update-ref -d refs/heads/bogus" && test_might_fail git rev-list --verify-objects refs/heads/bogus >/dev/null 2>out && - test_i18ngrep -q "error: hash mismatch $(dirname $new)$(test_oid ff_2)" out + test_grep -q "error: hash mismatch $(dirname $new)$(test_oid ff_2)" out ' # An actual bit corruption is more likely than swapped commits, but @@ -575,7 +575,7 @@ test_expect_success 'fsck notices blob entry pointing to null sha1' ' sha=$(printf "100644 file$_bz$_bzoid" | git hash-object --literally -w --stdin -t tree) && git fsck 2>out && - test_i18ngrep "warning.*null sha1" out + test_grep "warning.*null sha1" out ) ' @@ -585,7 +585,17 @@ test_expect_success 'fsck notices submodule entry pointing to null sha1' ' sha=$(printf "160000 submodule$_bz$_bzoid" | git hash-object --literally -w --stdin -t tree) && git fsck 2>out && - test_i18ngrep "warning.*null sha1" out + test_grep "warning.*null sha1" out + ) +' + +test_expect_success 'fsck notices excessively large tree entry name' ' + git init large-name && + ( + cd large-name && + test_commit a-long-name && + git -c fsck.largePathname=warn:10 fsck 2>out && + grep "warning.*large pathname" out ) ' @@ -606,7 +616,7 @@ while read name path pretty; do printf "$mode $type %s\t%s" "$value" "$path" >bad && bad_tree=$(git mktree <bad) && git fsck 2>out && - test_i18ngrep "warning.*tree $bad_tree" out + test_grep "warning.*tree $bad_tree" out )' done <<-\EOF 100644 blob @@ -652,9 +662,9 @@ test_expect_success 'NUL in commit' ' git branch bad $(cat name) && test_must_fail git -c fsck.nulInCommit=error fsck 2>warn.1 && - test_i18ngrep nulInCommit warn.1 && + test_grep nulInCommit warn.1 && git fsck 2>warn.2 && - test_i18ngrep nulInCommit warn.2 + test_grep nulInCommit warn.2 ) ' @@ -774,7 +784,7 @@ test_expect_success 'fsck --name-objects' ' tree=$(git rev-parse --verify julius:) && git tag -d julius && test_must_fail git fsck --name-objects >out && - test_i18ngrep "$tree (refs/tags/augustus44\\^:" out + test_grep "$tree (refs/tags/augustus44\\^:" out ) ' @@ -787,7 +797,7 @@ test_expect_success 'alternate objects are correctly blamed' ' mkdir alt.git/objects/$(dirname $path) && >alt.git/objects/$(dirname $path)/$(basename $path) && test_must_fail git fsck >out 2>&1 && - test_i18ngrep alt.git out + test_grep alt.git out ' test_expect_success 'fsck errors in packed objects' ' @@ -806,8 +816,8 @@ test_expect_success 'fsck errors in packed objects' ' remove_object $one && remove_object $two && test_must_fail git fsck 2>out && - test_i18ngrep "error in commit $one.* - bad name" out && - test_i18ngrep "error in commit $two.* - bad name" out && + test_grep "error in commit $one.* - bad name" out && + test_grep "error in commit $two.* - bad name" out && ! grep corrupt out ' @@ -824,7 +834,7 @@ test_expect_success 'fsck fails on corrupt packfile' ' test_when_finished "rm -f .git/objects/pack/pack-$pack.*" && remove_object $hsh && test_must_fail git fsck 2>out && - test_i18ngrep "checksum mismatch" out + test_grep "checksum mismatch" out ' test_expect_success 'fsck finds problems in duplicate loose objects' ' @@ -861,7 +871,7 @@ test_expect_success 'fsck detects trailing loose garbage (commit)' ' chmod +w "$file" && echo garbage >>"$file" && test_must_fail git fsck 2>out && - test_i18ngrep "garbage.*$commit" out + test_grep "garbage.*$commit" out ' test_expect_success 'fsck detects trailing loose garbage (large blob)' ' @@ -871,7 +881,7 @@ test_expect_success 'fsck detects trailing loose garbage (large blob)' ' chmod +w "$file" && echo garbage >>"$file" && test_must_fail git -c core.bigfilethreshold=5 fsck 2>out && - test_i18ngrep "garbage.*$blob" out + test_grep "garbage.*$blob" out ' test_expect_success 'fsck detects truncated loose object' ' @@ -887,10 +897,10 @@ test_expect_success 'fsck detects truncated loose object' ' # check both regular and streaming code paths test_must_fail git fsck 2>out && - test_i18ngrep corrupt.*$blob out && + test_grep corrupt.*$blob out && test_must_fail git -c core.bigfilethreshold=128 fsck 2>out && - test_i18ngrep corrupt.*$blob out + test_grep corrupt.*$blob out ' # for each of type, we have one version which is referenced by another object @@ -979,7 +989,7 @@ test_expect_success 'detect corrupt index file in fsck' ' test_when_finished "mv .git/index.backup .git/index" && corrupt_index_checksum && test_must_fail git fsck --cache 2>errors && - test_i18ngrep "bad index file" errors + test_grep "bad index file" errors ' test_expect_success 'fsck error and recovery on invalid object type' ' @@ -989,10 +999,7 @@ test_expect_success 'fsck error and recovery on invalid object type' ' garbage_blob=$(git hash-object --stdin -w -t garbage --literally </dev/null) && - cat >err.expect <<-\EOF && - fatal: invalid object type - EOF - test_must_fail git fsck >out 2>err && + test_must_fail git fsck 2>err && grep -e "^error" -e "^fatal" err >errors && test_line_count = 1 errors && grep "$garbage_blob: object is of unknown type '"'"'garbage'"'"':" err @@ -1023,4 +1030,34 @@ test_expect_success 'fsck error on gitattributes with excessive size' ' test_cmp expected actual ' +test_expect_success 'fsck detects problems in worktree index' ' + test_when_finished "git worktree remove -f wt" && + git worktree add wt && + + echo "this will be removed to break the worktree index" >wt/file && + git -C wt add file && + blob=$(git -C wt rev-parse :file) && + remove_object $blob && + + test_must_fail git fsck --name-objects >actual 2>&1 && + cat >expect <<-EOF && + missing blob $blob (.git/worktrees/wt/index:file) + EOF + test_cmp expect actual +' + +test_expect_success 'fsck reports problems in current worktree index without filename' ' + test_when_finished "rm -f .git/index && git read-tree HEAD" && + echo "this object will be removed to break current worktree index" >file && + git add file && + blob=$(git rev-parse :file) && + remove_object $blob && + + test_must_fail git fsck --name-objects >actual 2>&1 && + cat >expect <<-EOF && + missing blob $blob (:file) + EOF + test_cmp expect actual +' + test_done diff --git a/t/t1500-rev-parse.sh b/t/t1500-rev-parse.sh index 37ee5091b5..3f9e7f62e4 100755 --- a/t/t1500-rev-parse.sh +++ b/t/t1500-rev-parse.sh @@ -264,4 +264,27 @@ test_expect_success 'rev-parse --since= unsqueezed ordering' ' test_cmp expect actual ' +test_expect_success 'rev-parse --bisect includes bad, excludes good' ' + test_commit_bulk 6 && + + git update-ref refs/bisect/bad-1 HEAD~1 && + git update-ref refs/bisect/b HEAD~2 && + git update-ref refs/bisect/bad-3 HEAD~3 && + git update-ref refs/bisect/good-3 HEAD~3 && + git update-ref refs/bisect/bad-4 HEAD~4 && + git update-ref refs/bisect/go HEAD~4 && + + # Note: refs/bisect/b and refs/bisect/go should be ignored because they + # do not match the refs/bisect/bad or refs/bisect/good prefixes. + cat >expect <<-EOF && + refs/bisect/bad-1 + refs/bisect/bad-3 + refs/bisect/bad-4 + ^refs/bisect/good-3 + EOF + + git rev-parse --symbolic-full-name --bisect >actual && + test_cmp expect actual +' + test_done diff --git a/t/t1502-rev-parse-parseopt.sh b/t/t1502-rev-parse-parseopt.sh index de1d48f3ba..f0737593c3 100755 --- a/t/t1502-rev-parse-parseopt.sh +++ b/t/t1502-rev-parse-parseopt.sh @@ -3,13 +3,29 @@ test_description='test git rev-parse --parseopt' . ./test-lib.sh +check_invalid_long_option () { + spec="$1" + opt="$2" + test_expect_success "test --parseopt invalid switch $opt help output for $spec" ' + { + cat <<-\EOF && + error: unknown option `'${opt#--}\'' + EOF + sed -e 1d -e \$d <"$TEST_DIRECTORY/t1502/$spec.help" + } >expect && + test_expect_code 129 git rev-parse --parseopt -- $opt \ + 2>output <"$TEST_DIRECTORY/t1502/$spec" && + test_cmp expect output + ' +} + test_expect_success 'setup optionspec' ' sed -e "s/^|//" >optionspec <<\EOF |some-command [options] <args>... | |some-command does foo and bar! |-- -|h,help show the help +|h,help! show the help | |foo some nifty option --foo |bar= some cool option --bar with an argument @@ -58,44 +74,8 @@ EOF ' test_expect_success 'test --parseopt help output' ' - sed -e "s/^|//" >expect <<\END_EXPECT && -|cat <<\EOF -|usage: some-command [options] <args>... -| -| some-command does foo and bar! -| -| -h, --help show the help -| --foo some nifty option --foo -| --bar ... some cool option --bar with an argument -| -b, --baz a short and long option -| -|An option group Header -| -C[...] option C with an optional argument -| -d, --data[=...] short and long option with an optional argument -| -|Argument hints -| -B <arg> short option required argument -| --bar2 <arg> long option required argument -| -e, --fuz <with-space> -| short and long option required argument -| -s[<some>] short option optional argument -| --long[=<data>] long option optional argument -| -g, --fluf[=<path>] short and long option optional argument -| --longest <very-long-argument-hint> -| a very long argument hint -| --pair <key=value> with an equals sign in the hint -| --aswitch help te=t contains? fl*g characters!` -| --bswitch <hint> hint has trailing tab character -| --cswitch switch has trailing tab character -| --short-hint <a> with a one symbol hint -| -|Extras -| --extra1 line above used to cause a segfault but no longer does -| -|EOF -END_EXPECT test_expect_code 129 git rev-parse --parseopt -- -h > output < optionspec && - test_cmp expect output + test_cmp "$TEST_DIRECTORY/t1502/optionspec.help" output ' test_expect_success 'test --parseopt help output no switches' ' @@ -131,7 +111,7 @@ test_expect_success 'test --parseopt help-all output hidden switches' ' | | some-command does foo and bar! | -| --hidden1 A hidden switch +| --[no-]hidden1 A hidden switch | |EOF END_EXPECT @@ -140,41 +120,12 @@ END_EXPECT ' test_expect_success 'test --parseopt invalid switch help output' ' - sed -e "s/^|//" >expect <<\END_EXPECT && -|error: unknown option `does-not-exist'\'' -|usage: some-command [options] <args>... -| -| some-command does foo and bar! -| -| -h, --help show the help -| --foo some nifty option --foo -| --bar ... some cool option --bar with an argument -| -b, --baz a short and long option -| -|An option group Header -| -C[...] option C with an optional argument -| -d, --data[=...] short and long option with an optional argument -| -|Argument hints -| -B <arg> short option required argument -| --bar2 <arg> long option required argument -| -e, --fuz <with-space> -| short and long option required argument -| -s[<some>] short option optional argument -| --long[=<data>] long option optional argument -| -g, --fluf[=<path>] short and long option optional argument -| --longest <very-long-argument-hint> -| a very long argument hint -| --pair <key=value> with an equals sign in the hint -| --aswitch help te=t contains? fl*g characters!` -| --bswitch <hint> hint has trailing tab character -| --cswitch switch has trailing tab character -| --short-hint <a> with a one symbol hint -| -|Extras -| --extra1 line above used to cause a segfault but no longer does -| -END_EXPECT + { + cat <<-\EOF && + error: unknown option `does-not-exist'\'' + EOF + sed -e 1d -e \$d <"$TEST_DIRECTORY/t1502/optionspec.help" + } >expect && test_expect_code 129 git rev-parse --parseopt -- --does-not-exist 1>/dev/null 2>output < optionspec && test_cmp expect output ' @@ -288,7 +239,7 @@ test_expect_success 'test --parseopt help output: "wrapped" options normal "or:" | [--another-option] |cmd [--yet-another-option] |-- - |h,help show the help + |h,help! show the help EOF sed -e "s/^|//" >expect <<-\END_EXPECT && @@ -302,14 +253,14 @@ test_expect_success 'test --parseopt help output: "wrapped" options normal "or:" |EOF END_EXPECT - test_must_fail git rev-parse --parseopt -- -h >out <spec >actual && + test_must_fail git rev-parse --parseopt -- -h <spec >actual && test_cmp expect actual ' test_expect_success 'test --parseopt invalid opt-spec' ' test_write_lines x -- "=, x" >spec && echo "fatal: missing opt-spec before option flags" >expect && - test_must_fail git rev-parse --parseopt -- >out <spec 2>err && + test_must_fail git rev-parse --parseopt -- <spec 2>err && test_cmp expect err ' @@ -322,7 +273,7 @@ test_expect_success 'test --parseopt help output: multi-line blurb after empty l |line |blurb |-- - |h,help show the help + |h,help! show the help EOF sed -e "s/^|//" >expect <<-\END_EXPECT && @@ -339,8 +290,36 @@ test_expect_success 'test --parseopt help output: multi-line blurb after empty l |EOF END_EXPECT - test_must_fail git rev-parse --parseopt -- -h >out <spec >actual && + test_must_fail git rev-parse --parseopt -- -h <spec >actual && test_cmp expect actual ' +test_expect_success 'test --parseopt help output for optionspec-neg' ' + test_expect_code 129 git rev-parse --parseopt -- \ + -h >output <"$TEST_DIRECTORY/t1502/optionspec-neg" && + test_cmp "$TEST_DIRECTORY/t1502/optionspec-neg.help" output +' + +test_expect_success 'test --parseopt valid options for optionspec-neg' ' + cat >expect <<-\EOF && + set -- --foo --no-foo --no-bar --positive-only --no-negative -- + EOF + git rev-parse --parseopt -- <"$TEST_DIRECTORY/t1502/optionspec-neg" >output \ + --foo --no-foo --no-bar --positive-only --no-negative && + test_cmp expect output +' + +test_expect_success 'test --parseopt positivated option for optionspec-neg' ' + cat >expect <<-\EOF && + set -- --no-no-bar --no-no-bar -- + EOF + git rev-parse --parseopt -- <"$TEST_DIRECTORY/t1502/optionspec-neg" >output \ + --no-no-bar --bar && + test_cmp expect output +' + +check_invalid_long_option optionspec-neg --no-positive-only +check_invalid_long_option optionspec-neg --negative +check_invalid_long_option optionspec-neg --no-no-negative + test_done diff --git a/t/t1502/.gitattributes b/t/t1502/.gitattributes new file mode 100644 index 0000000000..562b12e16e --- /dev/null +++ b/t/t1502/.gitattributes @@ -0,0 +1 @@ +* -whitespace diff --git a/t/t1502/optionspec-neg b/t/t1502/optionspec-neg new file mode 100644 index 0000000000..392f43eb0b --- /dev/null +++ b/t/t1502/optionspec-neg @@ -0,0 +1,8 @@ +some-command [options] <args>... + +some-command does foo and bar! +-- +foo can be negated +no-bar can be positivated +positive-only! cannot be negated +no-negative! cannot be positivated diff --git a/t/t1502/optionspec-neg.help b/t/t1502/optionspec-neg.help new file mode 100644 index 0000000000..7a29f8cb03 --- /dev/null +++ b/t/t1502/optionspec-neg.help @@ -0,0 +1,12 @@ +cat <<\EOF +usage: some-command [options] <args>... + + some-command does foo and bar! + + --[no-]foo can be negated + --no-bar can be positivated + --bar opposite of --no-bar + --positive-only cannot be negated + --no-negative cannot be positivated + +EOF diff --git a/t/t1502/optionspec.help b/t/t1502/optionspec.help new file mode 100755 index 0000000000..cbdd54d41b --- /dev/null +++ b/t/t1502/optionspec.help @@ -0,0 +1,36 @@ +cat <<\EOF +usage: some-command [options] <args>... + + some-command does foo and bar! + + -h, --help show the help + --[no-]foo some nifty option --foo + --[no-]bar ... some cool option --bar with an argument + -b, --[no-]baz a short and long option + +An option group Header + -C[...] option C with an optional argument + -d, --[no-]data[=...] short and long option with an optional argument + +Argument hints + -B <arg> short option required argument + --[no-]bar2 <arg> long option required argument + -e, --[no-]fuz <with-space> + short and long option required argument + -s[<some>] short option optional argument + --[no-]long[=<data>] long option optional argument + -g, --[no-]fluf[=<path>] + short and long option optional argument + --[no-]longest <very-long-argument-hint> + a very long argument hint + --[no-]pair <key=value> + with an equals sign in the hint + --[no-]aswitch help te=t contains? fl*g characters!` + --[no-]bswitch <hint> hint has trailing tab character + --[no-]cswitch switch has trailing tab character + --[no-]short-hint <a> with a one symbol hint + +Extras + --[no-]extra1 line above used to cause a segfault but no longer does + +EOF diff --git a/t/t1504-ceiling-dirs.sh b/t/t1504-ceiling-dirs.sh index 0fafcf9dde..c1679e31d8 100755 --- a/t/t1504-ceiling-dirs.sh +++ b/t/t1504-ceiling-dirs.sh @@ -6,8 +6,12 @@ TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_prefix() { - test_expect_success "$1" \ - "test '$2' = \"\$(git rev-parse --show-prefix)\"" + local expect="$2" && + test_expect_success "$1: git rev-parse --show-prefix is '$2'" ' + echo "$expect" >expect && + git rev-parse --show-prefix >actual && + test_cmp expect actual + ' } test_fail() { diff --git a/t/t1506-rev-parse-diagnosis.sh b/t/t1506-rev-parse-diagnosis.sh index 18688cae17..ef40511d89 100755 --- a/t/t1506-rev-parse-diagnosis.sh +++ b/t/t1506-rev-parse-diagnosis.sh @@ -107,16 +107,16 @@ test_expect_success 'correct relative file objects (6)' ' test_expect_success 'incorrect revision id' ' test_must_fail git rev-parse foobar:file.txt 2>error && - test_i18ngrep "invalid object name .foobar." error && + test_grep "invalid object name .foobar." error && test_must_fail git rev-parse foobar 2>error && - test_i18ngrep "unknown revision or path not in the working tree." error + test_grep "unknown revision or path not in the working tree." error ' test_expect_success 'incorrect file in sha1:path' ' test_must_fail git rev-parse HEAD:nothing.txt 2>error && - test_i18ngrep "path .nothing.txt. does not exist in .HEAD." error && + test_grep "path .nothing.txt. does not exist in .HEAD." error && test_must_fail git rev-parse HEAD:index-only.txt 2>error && - test_i18ngrep "path .index-only.txt. exists on disk, but not in .HEAD." error && + test_grep "path .index-only.txt. exists on disk, but not in .HEAD." error && (cd subdir && test_must_fail git rev-parse HEAD:file2.txt 2>error && test_did_you_mean HEAD subdir/ file2.txt exists ) @@ -124,9 +124,9 @@ test_expect_success 'incorrect file in sha1:path' ' test_expect_success 'incorrect file in :path and :N:path' ' test_must_fail git rev-parse :nothing.txt 2>error && - test_i18ngrep "path .nothing.txt. does not exist (neither on disk nor in the index)" error && + test_grep "path .nothing.txt. does not exist (neither on disk nor in the index)" error && test_must_fail git rev-parse :1:nothing.txt 2>error && - test_i18ngrep "path .nothing.txt. does not exist (neither on disk nor in the index)" error && + test_grep "path .nothing.txt. does not exist (neither on disk nor in the index)" error && test_must_fail git rev-parse :1:file.txt 2>error && test_did_you_mean ":0" "" file.txt "is in the index" "at stage 1" && (cd subdir && @@ -137,42 +137,42 @@ test_expect_success 'incorrect file in :path and :N:path' ' test_must_fail git rev-parse :2:file2.txt 2>error && test_did_you_mean :0 subdir/ file2.txt "is in the index") && test_must_fail git rev-parse :disk-only.txt 2>error && - test_i18ngrep "path .disk-only.txt. exists on disk, but not in the index" error + test_grep "path .disk-only.txt. exists on disk, but not in the index" error ' test_expect_success 'invalid @{n} reference' ' test_must_fail git rev-parse main@{99999} >output 2>error && test_must_be_empty output && - test_i18ngrep "log for [^ ]* only has [0-9][0-9]* entries" error && + test_grep "log for [^ ]* only has [0-9][0-9]* entries" error && test_must_fail git rev-parse --verify main@{99999} >output 2>error && test_must_be_empty output && - test_i18ngrep "log for [^ ]* only has [0-9][0-9]* entries" error + test_grep "log for [^ ]* only has [0-9][0-9]* entries" error ' test_expect_success 'relative path not found' ' ( cd subdir && test_must_fail git rev-parse HEAD:./nonexistent.txt 2>error && - test_i18ngrep subdir/nonexistent.txt error + test_grep subdir/nonexistent.txt error ) ' test_expect_success 'relative path outside worktree' ' test_must_fail git rev-parse HEAD:../file.txt >output 2>error && test_must_be_empty output && - test_i18ngrep "outside repository" error + test_grep "outside repository" error ' test_expect_success 'relative path when cwd is outside worktree' ' test_must_fail git --git-dir=.git --work-tree=subdir rev-parse HEAD:./file.txt >output 2>error && test_must_be_empty output && - test_i18ngrep "relative path syntax can.t be used outside working tree" error + test_grep "relative path syntax can.t be used outside working tree" error ' test_expect_success '<commit>:file correctly diagnosed after a pathname' ' test_must_fail git rev-parse file.txt HEAD:file.txt 1>actual 2>error && - test_i18ngrep ! "exists on disk" error && - test_i18ngrep "no such path in the working tree" error && + test_grep ! "exists on disk" error && + test_grep "no such path in the working tree" error && cat >expect <<-\EOF && file.txt HEAD:file.txt @@ -214,13 +214,13 @@ test_expect_success 'dotdot does not peel endpoints' ' test_expect_success 'arg before dashdash must be a revision (missing)' ' test_must_fail git rev-parse foobar -- 2>stderr && - test_i18ngrep "bad revision" stderr + test_grep "bad revision" stderr ' test_expect_success 'arg before dashdash must be a revision (file)' ' >foobar && test_must_fail git rev-parse foobar -- 2>stderr && - test_i18ngrep "bad revision" stderr + test_grep "bad revision" stderr ' test_expect_success 'arg before dashdash must be a revision (ambiguous)' ' @@ -269,7 +269,7 @@ test_expect_success 'arg after dashdash not interpreted as option' ' test_expect_success 'arg after end-of-options not interpreted as option' ' test_must_fail git rev-parse --end-of-options --not-real -- 2>err && - test_i18ngrep bad.revision.*--not-real err + test_grep bad.revision.*--not-real err ' test_expect_success 'end-of-options still allows --' ' diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh index c34714ffe3..b9af6b3ac0 100755 --- a/t/t1507-rev-parse-upstream.sh +++ b/t/t1507-rev-parse-upstream.sh @@ -5,6 +5,7 @@ test_description='test <branch>@{upstream} syntax' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh @@ -97,7 +98,8 @@ test_expect_success 'my-side@{u} resolves to correct commit' ' commit_subject my-side >actual && test_cmp expect actual && echo 5 >expect && - commit_subject my-side@{u} >actual + commit_subject my-side@{u} >actual && + test_cmp expect actual ' test_expect_success 'not-tracking@{u} fails' ' @@ -183,6 +185,11 @@ test_expect_success '@{u} error message when no upstream' ' test_cmp expect actual ' +test_expect_success '@{u} silent error when no upstream' ' + test_must_fail git rev-parse --verify --quiet @{u} 2>actual && + test_must_be_empty actual +' + test_expect_success 'branch@{u} error message with misspelt branch' ' cat >expect <<-EOF && fatal: no such branch: ${SQ}no-such-branch${SQ} @@ -258,7 +265,8 @@ test_expect_success '@{reflog}-parsing does not look beyond colon' ' git add @{yesterday} && git commit -m "funny reflog file" && git hash-object @{yesterday} >expect && - git rev-parse HEAD:@{yesterday} >actual + git rev-parse HEAD:@{yesterday} >actual && + test_cmp expect actual ' test_expect_success '@{upstream}-parsing does not look beyond colon' ' @@ -266,7 +274,8 @@ test_expect_success '@{upstream}-parsing does not look beyond colon' ' git add @{upstream} && git commit -m "funny upstream file" && git hash-object @{upstream} >expect && - git rev-parse HEAD:@{upstream} >actual + git rev-parse HEAD:@{upstream} >actual && + test_cmp expect actual ' test_done diff --git a/t/t1508-at-combinations.sh b/t/t1508-at-combinations.sh index 87a4286414..e841309d0e 100755 --- a/t/t1508-at-combinations.sh +++ b/t/t1508-at-combinations.sh @@ -4,6 +4,7 @@ test_description='test various @{X} syntax combinations together' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh check() { diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index 98cefe3b70..70f1e0a998 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -129,7 +129,7 @@ test_expect_success 'blob and tree' ' test_expect_success 'warn ambiguity when no candidate matches type hint' ' test_must_fail git rev-parse --verify 000000000^{commit} 2>actual && - test_i18ngrep "short object ID 000000000 is ambiguous" actual + test_grep "short object ID 000000000 is ambiguous" actual ' test_expect_success 'disambiguate tree-ish' ' @@ -470,10 +470,10 @@ test_expect_success 'cat-file --batch and --batch-check show ambiguous' ' echo "0000 ambiguous" >expect && echo 0000 | git cat-file --batch-check >actual 2>err && test_cmp expect actual && - test_i18ngrep hint: err && + test_grep hint: err && echo 0000 | git cat-file --batch >actual 2>err && test_cmp expect actual && - test_i18ngrep hint: err + test_grep hint: err ' test_done diff --git a/t/t1514-rev-parse-push.sh b/t/t1514-rev-parse-push.sh index d868a08110..a835a196aa 100755 --- a/t/t1514-rev-parse-push.sh +++ b/t/t1514-rev-parse-push.sh @@ -4,6 +4,7 @@ test_description='test <branch>@{push} syntax' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh resolve () { diff --git a/t/t1600-index.sh b/t/t1600-index.sh index 9368d82f7d..62e7fd1596 100755 --- a/t/t1600-index.sh +++ b/t/t1600-index.sh @@ -118,7 +118,7 @@ test_index_version () { fi && git add a && echo $EXPECTED_OUTPUT_VERSION >expect && - test-tool index-version <.git/index >actual && + git update-index --show-index-version >actual && test_cmp expect actual ) } diff --git a/t/t1700-split-index.sh b/t/t1700-split-index.sh index b4ab166369..a7b7263b35 100755 --- a/t/t1700-split-index.sh +++ b/t/t1700-split-index.sh @@ -43,7 +43,7 @@ test_expect_success 'enable split index' ' git config splitIndex.maxPercentChange 100 && git update-index --split-index && test-tool dump-split-index .git/index >actual && - indexversion=$(test-tool index-version <.git/index) && + indexversion=$(git update-index --show-index-version) && # NEEDSWORK: Stop hard-coding checksums. if test "$indexversion" = "4" diff --git a/t/t1800-hook.sh b/t/t1800-hook.sh index 3506f627b6..8b0234cf2d 100755 --- a/t/t1800-hook.sh +++ b/t/t1800-hook.sh @@ -156,25 +156,15 @@ test_expect_success 'git hook run a hook with a bad shebang' ' mkdir bad-hooks && write_script bad-hooks/test-hook "/bad/path/no/spaces" </dev/null && - # TODO: We should emit the same (or at least a more similar) - # error on MINGW (essentially Git for Windows) and all other - # platforms.. See the OS-specific code in start_command() - if test_have_prereq !MINGW - then - cat >expect <<-\EOF - fatal: cannot run bad-hooks/test-hook: ... - EOF - else - cat >expect <<-\EOF - error: cannot spawn bad-hooks/test-hook: ... - EOF - fi && test_expect_code 1 git \ -c core.hooksPath=bad-hooks \ hook run test-hook >out 2>err && test_must_be_empty out && - sed -e "s/test-hook: .*/test-hook: .../" <err >actual && - test_cmp expect actual + + # TODO: We should emit the same (or at least a more similar) + # error on MINGW (essentially Git for Windows) and all other + # platforms.. See the OS-specific code in start_command() + grep -E "^(error|fatal): cannot (exec|spawn) .*bad-hooks/test-hook" err ' test_expect_success 'stdin to hooks' ' diff --git a/t/t2004-checkout-cache-temp.sh b/t/t2004-checkout-cache-temp.sh index b16d69ca4a..98e818f09f 100755 --- a/t/t2004-checkout-cache-temp.sh +++ b/t/t2004-checkout-cache-temp.sh @@ -93,7 +93,7 @@ test_expect_success 'checkout all stages of unknown path' ' rm -f path* .merge_* actual && test_must_fail git checkout-index --stage=all --temp \ -- does-not-exist 2>stderr && - test_i18ngrep not.in.the.cache stderr + test_grep not.in.the.cache stderr ' test_expect_success 'checkout all stages/one file to nothing' ' @@ -117,6 +117,26 @@ test_expect_success 'checkout all stages/one file to temporary files' ' test $(cat $s3) = tree3path1) ' +test_expect_success '--stage=all implies --temp' ' + rm -f path* .merge_* actual && + git checkout-index --stage=all -- path1 && + test_path_is_missing path1 +' + +test_expect_success 'overriding --stage=all resets implied --temp' ' + rm -f path* .merge_* actual && + git checkout-index --stage=all --stage=2 -- path1 && + echo tree2path1 >expect && + test_cmp expect path1 +' + +test_expect_success '--stage=all --no-temp is rejected' ' + rm -f path* .merge_* actual && + test_must_fail git checkout-index --stage=all --no-temp -- path1 2>err && + grep -v "already exists" err && + grep "options .--stage=all. and .--no-temp. cannot be used together" err +' + test_expect_success 'checkout some stages/one file to temporary files' ' rm -f path* .merge_* actual && git checkout-index --stage=all --temp -- path2 >actual && diff --git a/t/t2005-checkout-index-symlinks.sh b/t/t2005-checkout-index-symlinks.sh index 112682a45a..67d18cfa10 100755 --- a/t/t2005-checkout-index-symlinks.sh +++ b/t/t2005-checkout-index-symlinks.sh @@ -22,8 +22,10 @@ test_expect_success \ git checkout-index symlink && test -f symlink' -test_expect_success \ -'the file must be the blob we added during the setup' ' -test "$(git hash-object -t blob symlink)" = $l' +test_expect_success 'the file must be the blob we added during the setup' ' + echo "$l" >expect && + git hash-object -t blob symlink >actual && + test_cmp expect actual +' test_done diff --git a/t/t2006-checkout-index-basic.sh b/t/t2006-checkout-index-basic.sh index 5d119871d4..570ba38580 100755 --- a/t/t2006-checkout-index-basic.sh +++ b/t/t2006-checkout-index-basic.sh @@ -8,7 +8,7 @@ TEST_PASSES_SANITIZE_LEAK=true test_expect_success 'checkout-index --gobbledegook' ' test_expect_code 129 git checkout-index --gobbledegook 2>err && - test_i18ngrep "[Uu]sage" err + test_grep "[Uu]sage" err ' test_expect_success 'checkout-index -h in broken repository' ' @@ -19,18 +19,18 @@ test_expect_success 'checkout-index -h in broken repository' ' >.git/index && test_expect_code 129 git checkout-index -h >usage 2>&1 ) && - test_i18ngrep "[Uu]sage" broken/usage + test_grep "[Uu]sage" broken/usage ' test_expect_success 'checkout-index reports errors (cmdline)' ' test_must_fail git checkout-index -- does-not-exist 2>stderr && - test_i18ngrep not.in.the.cache stderr + test_grep not.in.the.cache stderr ' test_expect_success 'checkout-index reports errors (stdin)' ' echo does-not-exist | test_must_fail git checkout-index --stdin 2>stderr && - test_i18ngrep not.in.the.cache stderr + test_grep not.in.the.cache stderr ' for mode in 'case' 'utf-8' do @@ -88,8 +88,8 @@ test_expect_success 'checkout-index --temp correctly reports error on missing bl git update-index --index-info <objs && test_must_fail git checkout-index --temp symlink file 2>stderr && - test_i18ngrep "unable to read sha1 file of file ($missing_blob)" stderr && - test_i18ngrep "unable to read sha1 file of symlink ($missing_blob)" stderr + test_grep "unable to read sha1 file of file ($missing_blob)" stderr && + test_grep "unable to read sha1 file of symlink ($missing_blob)" stderr ' test_expect_success 'checkout-index --temp correctly reports error for submodules' ' @@ -98,7 +98,7 @@ test_expect_success 'checkout-index --temp correctly reports error for submodule git submodule add ./sub && git commit -m sub && test_must_fail git checkout-index --temp sub 2>stderr && - test_i18ngrep "cannot create temporary submodule sub" stderr + test_grep "cannot create temporary submodule sub" stderr ' test_done diff --git a/t/t2010-checkout-ambiguous.sh b/t/t2010-checkout-ambiguous.sh index 9d4b37526a..82c3bfeac1 100755 --- a/t/t2010-checkout-ambiguous.sh +++ b/t/t2010-checkout-ambiguous.sh @@ -62,8 +62,8 @@ test_expect_success 'disambiguate checking out from a tree-ish' ' test_expect_success 'accurate error message with more than one ref' ' test_must_fail git checkout HEAD main -- 2>actual && - test_i18ngrep 2 actual && - test_i18ngrep "one reference expected, 2 given" actual + test_grep 2 actual && + test_grep "one reference expected, 2 given" actual ' test_done diff --git a/t/t2011-checkout-invalid-head.sh b/t/t2011-checkout-invalid-head.sh index d9997e7b6b..3c8135831b 100755 --- a/t/t2011-checkout-invalid-head.sh +++ b/t/t2011-checkout-invalid-head.sh @@ -18,18 +18,18 @@ test_expect_success 'checkout should not start branch from a tree' ' test_must_fail git checkout -b newbranch main^{tree} ' -test_expect_success 'checkout main from invalid HEAD' ' +test_expect_success REFFILES 'checkout main from invalid HEAD' ' echo $ZERO_OID >.git/HEAD && git checkout main -- ' -test_expect_success 'checkout notices failure to lock HEAD' ' +test_expect_success REFFILES 'checkout notices failure to lock HEAD' ' test_when_finished "rm -f .git/HEAD.lock" && >.git/HEAD.lock && test_must_fail git checkout -b other ' -test_expect_success 'create ref directory/file conflict scenario' ' +test_expect_success REFFILES 'create ref directory/file conflict scenario' ' git update-ref refs/heads/outer/inner main && # do not rely on symbolic-ref to get a known state, @@ -39,26 +39,26 @@ test_expect_success 'create ref directory/file conflict scenario' ' } ' -test_expect_success 'checkout away from d/f HEAD (unpacked, to branch)' ' +test_expect_success REFFILES 'checkout away from d/f HEAD (unpacked, to branch)' ' reset_to_df && git checkout main ' -test_expect_success 'checkout away from d/f HEAD (unpacked, to detached)' ' +test_expect_success REFFILES 'checkout away from d/f HEAD (unpacked, to detached)' ' reset_to_df && git checkout --detach main ' -test_expect_success 'pack refs' ' +test_expect_success REFFILES 'pack refs' ' git pack-refs --all --prune ' -test_expect_success 'checkout away from d/f HEAD (packed, to branch)' ' +test_expect_success REFFILES 'checkout away from d/f HEAD (packed, to branch)' ' reset_to_df && git checkout main ' -test_expect_success 'checkout away from d/f HEAD (packed, to detached)' ' +test_expect_success REFFILES 'checkout away from d/f HEAD (packed, to detached)' ' reset_to_df && git checkout --detach main ' diff --git a/t/t2018-checkout-branch.sh b/t/t2018-checkout-branch.sh index 8581ad3437..43551cc148 100755 --- a/t/t2018-checkout-branch.sh +++ b/t/t2018-checkout-branch.sh @@ -278,12 +278,12 @@ test_expect_success 'checkout -b to a new branch preserves mergeable changes des test_expect_success 'checkout -b rejects an invalid start point' ' test_must_fail git checkout -b branch4 file1 2>err && - test_i18ngrep "is not a commit" err + test_grep "is not a commit" err ' test_expect_success 'checkout -b rejects an extra path argument' ' test_must_fail git checkout -b branch5 branch1 file1 2>err && - test_i18ngrep "Cannot update paths and switch to branch" err + test_grep "Cannot update paths and switch to branch" err ' test_done diff --git a/t/t2019-checkout-ambiguous-ref.sh b/t/t2019-checkout-ambiguous-ref.sh index 2c8c926b4d..c67261e2b6 100755 --- a/t/t2019-checkout-ambiguous-ref.sh +++ b/t/t2019-checkout-ambiguous-ref.sh @@ -16,7 +16,7 @@ test_expect_success 'setup ambiguous refs' ' ' test_expect_success 'checkout ambiguous ref succeeds' ' - git checkout ambiguity >stdout 2>stderr + git checkout ambiguity 2>stderr ' test_expect_success 'checkout produces ambiguity warning' ' @@ -32,12 +32,12 @@ test_expect_success 'checkout chooses branch over tag' ' ' test_expect_success 'checkout reports switch to branch' ' - test_i18ngrep "Switched to branch" stderr && - test_i18ngrep ! "^HEAD is now at" stderr + test_grep "Switched to branch" stderr && + test_grep ! "^HEAD is now at" stderr ' test_expect_success 'checkout vague ref succeeds' ' - git checkout vagueness >stdout 2>stderr && + git checkout vagueness 2>stderr && test_set_prereq VAGUENESS_SUCCESS ' @@ -54,8 +54,8 @@ test_expect_success VAGUENESS_SUCCESS 'checkout chooses branch over tag' ' ' test_expect_success VAGUENESS_SUCCESS 'checkout reports switch to branch' ' - test_i18ngrep "Switched to branch" stderr && - test_i18ngrep ! "^HEAD is now at" stderr + test_grep "Switched to branch" stderr && + test_grep ! "^HEAD is now at" stderr ' test_done diff --git a/t/t2020-checkout-detach.sh b/t/t2020-checkout-detach.sh index 2eab6474f8..8202ef8c74 100755 --- a/t/t2020-checkout-detach.sh +++ b/t/t2020-checkout-detach.sh @@ -17,12 +17,12 @@ check_not_detached () { PREV_HEAD_DESC='Previous HEAD position was' check_orphan_warning() { - test_i18ngrep "you are leaving $2 behind" "$1" && - test_i18ngrep ! "$PREV_HEAD_DESC" "$1" + test_grep "you are leaving $2 behind" "$1" && + test_grep ! "$PREV_HEAD_DESC" "$1" } check_no_orphan_warning() { - test_i18ngrep ! "you are leaving .* commit.*behind" "$1" && - test_i18ngrep "$PREV_HEAD_DESC" "$1" + test_grep ! "you are leaving .* commit.*behind" "$1" && + test_grep "$PREV_HEAD_DESC" "$1" } reset () { diff --git a/t/t2021-checkout-overwrite.sh b/t/t2021-checkout-overwrite.sh index 713c3fa603..ecfacf0f7f 100755 --- a/t/t2021-checkout-overwrite.sh +++ b/t/t2021-checkout-overwrite.sh @@ -50,10 +50,13 @@ test_expect_success 'checkout commit with dir must not remove untracked a/b' ' test_expect_success SYMLINKS 'the symlink remained' ' - test_when_finished "rm a/b" && test -h a/b ' +test_expect_success 'cleanup after previous symlink tests' ' + rm a/b +' + test_expect_success SYMLINKS 'checkout -f must not follow symlinks when removing entries' ' git checkout -f start && mkdir dir && @@ -66,4 +69,15 @@ test_expect_success SYMLINKS 'checkout -f must not follow symlinks when removing test_path_is_file untracked/f ' +test_expect_success 'checkout --overwrite-ignore should succeed if only ignored files in the way' ' + git checkout -b df_conflict && + test_commit contents some_dir && + git checkout start && + mkdir some_dir && + echo autogenerated information >some_dir/ignore && + echo ignore >.git/info/exclude && + git checkout --overwrite-ignore df_conflict && + test_path_is_file some_dir +' + test_done diff --git a/t/t2024-checkout-dwim.sh b/t/t2024-checkout-dwim.sh index 4a1c901456..a97416ce65 100755 --- a/t/t2024-checkout-dwim.sh +++ b/t/t2024-checkout-dwim.sh @@ -93,7 +93,7 @@ test_expect_success 'when arg matches multiple remotes, do not fallback to inter test_must_fail git checkout ambiguous_branch_and_file 2>err && - test_i18ngrep "matched multiple (2) remote tracking branches" err && + test_grep "matched multiple (2) remote tracking branches" err && # file must not be altered test_cmp expect ambiguous_branch_and_file @@ -105,12 +105,12 @@ test_expect_success 'checkout of branch from multiple remotes fails with advice' test_must_fail git checkout foo 2>stderr && test_branch main && status_uno_is_clean && - test_i18ngrep "^hint: " stderr && + test_grep "^hint: " stderr && test_must_fail git -c advice.checkoutAmbiguousRemoteBranchName=false \ checkout foo 2>stderr && test_branch main && status_uno_is_clean && - test_i18ngrep ! "^hint: " stderr + test_grep ! "^hint: " stderr ' test_expect_success PERL 'checkout -p with multiple remotes does not print advice' ' @@ -118,7 +118,7 @@ test_expect_success PERL 'checkout -p with multiple remotes does not print advic test_might_fail git branch -D foo && git checkout -p foo 2>stderr && - test_i18ngrep ! "^hint: " stderr && + test_grep ! "^hint: " stderr && status_uno_is_clean ' @@ -305,10 +305,13 @@ test_expect_success 'loosely defined local base branch is reported correctly' ' test_config branch.strict.merge refs/heads/main && test_config branch.loose.merge main && - git checkout strict | sed -e "s/strict/BRANCHNAME/g" >expect && + git checkout strict >expect.raw 2>&1 && + sed -e "s/strict/BRANCHNAME/g" <expect.raw >expect && status_uno_is_clean && - git checkout loose | sed -e "s/loose/BRANCHNAME/g" >actual && + git checkout loose >actual.raw 2>&1 && + sed -e "s/loose/BRANCHNAME/g" <actual.raw >actual && status_uno_is_clean && + grep BRANCHNAME actual && test_cmp expect actual ' diff --git a/t/t2025-checkout-no-overlay.sh b/t/t2025-checkout-no-overlay.sh index 3832c3de81..246609d54d 100755 --- a/t/t2025-checkout-no-overlay.sh +++ b/t/t2025-checkout-no-overlay.sh @@ -26,7 +26,7 @@ test_expect_success 'checkout --no-overlay removing last file from directory' ' test_expect_success 'checkout -p --overlay is disallowed' ' test_must_fail git checkout -p --overlay HEAD 2>actual && - test_i18ngrep "fatal: options .-p. and .--overlay. cannot be used together" actual + test_grep "fatal: options .-p. and .--overlay. cannot be used together" actual ' test_expect_success '--no-overlay --theirs with D/F conflict deletes file' ' diff --git a/t/t2026-checkout-pathspec-file.sh b/t/t2026-checkout-pathspec-file.sh index 9c651aefbc..acd55217a6 100755 --- a/t/t2026-checkout-pathspec-file.sh +++ b/t/t2026-checkout-pathspec-file.sh @@ -149,16 +149,16 @@ test_expect_success 'error conditions' ' echo fileA.t >list && test_must_fail git checkout --pathspec-from-file=list --detach 2>err && - test_i18ngrep -e "options .--pathspec-from-file. and .--detach. cannot be used together" err && + test_grep -e "options .--pathspec-from-file. and .--detach. cannot be used together" err && test_must_fail git checkout --pathspec-from-file=list --patch 2>err && - test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err && + test_grep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err && test_must_fail git checkout --pathspec-from-file=list -- fileA.t 2>err && - test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err && + test_grep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err && test_must_fail git checkout --pathspec-file-nul 2>err && - test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err + test_grep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err ' test_done diff --git a/t/t2027-checkout-track.sh b/t/t2027-checkout-track.sh index dca35aa3e3..98f16c7239 100755 --- a/t/t2027-checkout-track.sh +++ b/t/t2027-checkout-track.sh @@ -5,6 +5,7 @@ test_description='tests for git branch --track' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' @@ -21,7 +22,7 @@ test_expect_success 'checkout --track -b creates a new tracking branch' ' test_expect_success 'checkout --track -b rejects an extra path argument' ' test_must_fail git checkout --track -b branch2 main one.t 2>err && - test_i18ngrep "cannot be used with updating paths" err + test_grep "cannot be used with updating paths" err ' test_expect_success 'checkout --track -b overrides autoSetupMerge=inherit' ' diff --git a/t/t2030-unresolve-info.sh b/t/t2030-unresolve-info.sh index 2d8c70b03a..be3fcdde07 100755 --- a/t/t2030-unresolve-info.sh +++ b/t/t2030-unresolve-info.sh @@ -37,11 +37,17 @@ prime_resolve_undo () { git checkout second^0 && test_tick && test_must_fail git merge third^0 && - echo merge does not leave anything && check_resolve_undo empty && - echo different >fi/le && - git add fi/le && - echo resolving records && + + # how should the conflict be resolved? + case "$1" in + remove) + rm -f file/le && git rm fi/le + ;; + *) # modify + echo different >fi/le && git add fi/le + ;; + esac check_resolve_undo recorded fi/le initial:fi/le second:fi/le third:fi/le } @@ -122,6 +128,37 @@ test_expect_success 'add records checkout -m undoes' ' test_expect_success 'unmerge with plumbing' ' prime_resolve_undo && git update-index --unresolve fi/le && + git ls-files --resolve-undo fi/le >actual && + test_must_be_empty actual && + git ls-files -u >actual && + test_line_count = 3 actual +' + +test_expect_success 'unmerge can be done even after committing' ' + prime_resolve_undo && + git commit -m "record to nuke MERGE_HEAD" && + git update-index --unresolve fi/le && + git ls-files --resolve-undo fi/le >actual && + test_must_be_empty actual && + git ls-files -u >actual && + test_line_count = 3 actual +' + +test_expect_success 'unmerge removal' ' + prime_resolve_undo remove && + git update-index --unresolve fi/le && + git ls-files --resolve-undo fi/le >actual && + test_must_be_empty actual && + git ls-files -u >actual && + test_line_count = 3 actual +' + +test_expect_success 'unmerge removal after committing' ' + prime_resolve_undo remove && + git commit -m "record to nuke MERGE_HEAD" && + git update-index --unresolve fi/le && + git ls-files --resolve-undo fi/le >actual && + test_must_be_empty actual && git ls-files -u >actual && test_line_count = 3 actual ' @@ -191,7 +228,7 @@ test_expect_success 'rerere forget (add-add conflict)' ' git commit -m "add differently" && test_must_fail git merge fifth && git rerere forget add-differently 2>actual && - test_i18ngrep "no remembered" actual + test_grep "no remembered" actual ' test_expect_success 'resolve-undo keeps blobs from gc' ' diff --git a/t/t2060-switch.sh b/t/t2060-switch.sh index 5a7caf958c..e247a4735b 100755 --- a/t/t2060-switch.sh +++ b/t/t2060-switch.sh @@ -146,4 +146,33 @@ test_expect_success 'tracking info copied with autoSetupMerge=inherit' ' test_cmp_config "" --default "" branch.main2.merge ' +test_expect_success 'switch back when temporarily detached and checked out elsewhere ' ' + test_when_finished " + git worktree remove wt1 ||: + git worktree remove wt2 ||: + git checkout - ||: + git branch -D shared ||: + " && + git checkout -b shared && + test_commit shared-first && + HASH1=$(git rev-parse --verify HEAD) && + test_commit shared-second && + test_commit shared-third && + HASH2=$(git rev-parse --verify HEAD) && + git worktree add wt1 -f shared && + git -C wt1 bisect start && + git -C wt1 bisect good $HASH1 && + git -C wt1 bisect bad $HASH2 && + git worktree add wt2 -f shared && + git -C wt2 bisect start && + git -C wt2 bisect good $HASH1 && + git -C wt2 bisect bad $HASH2 && + # we test in both worktrees to ensure that works + # as expected with "first" and "next" worktrees + test_must_fail git -C wt1 switch shared && + git -C wt1 switch --ignore-other-worktrees shared && + test_must_fail git -C wt2 switch shared && + git -C wt2 switch --ignore-other-worktrees shared +' + test_done diff --git a/t/t2070-restore.sh b/t/t2070-restore.sh index 7c43ddf1d9..16d6348b69 100755 --- a/t/t2070-restore.sh +++ b/t/t2070-restore.sh @@ -137,4 +137,87 @@ test_expect_success 'restore --staged invalidates cache tree for deletions' ' test_must_fail git rev-parse HEAD:new1 ' +test_expect_success 'restore --merge to unresolve' ' + O=$(echo original | git hash-object -w --stdin) && + A=$(echo ourside | git hash-object -w --stdin) && + B=$(echo theirside | git hash-object -w --stdin) && + { + echo "100644 $O 1 file" && + echo "100644 $A 2 file" && + echo "100644 $B 3 file" + } | git update-index --index-info && + echo nothing >file && + git restore --worktree --merge file && + cat >expect <<-\EOF && + <<<<<<< ours + ourside + ======= + theirside + >>>>>>> theirs + EOF + test_cmp expect file +' + +test_expect_success 'restore --merge to unresolve after (mistaken) resolution' ' + O=$(echo original | git hash-object -w --stdin) && + A=$(echo ourside | git hash-object -w --stdin) && + B=$(echo theirside | git hash-object -w --stdin) && + { + echo "100644 $O 1 file" && + echo "100644 $A 2 file" && + echo "100644 $B 3 file" + } | git update-index --index-info && + echo nothing >file && + git add file && + git restore --worktree --merge file && + cat >expect <<-\EOF && + <<<<<<< ours + ourside + ======= + theirside + >>>>>>> theirs + EOF + test_cmp expect file +' + +test_expect_success 'restore --merge to unresolve after (mistaken) resolution' ' + O=$(echo original | git hash-object -w --stdin) && + A=$(echo ourside | git hash-object -w --stdin) && + B=$(echo theirside | git hash-object -w --stdin) && + { + echo "100644 $O 1 file" && + echo "100644 $A 2 file" && + echo "100644 $B 3 file" + } | git update-index --index-info && + git rm -f file && + git restore --worktree --merge file && + cat >expect <<-\EOF && + <<<<<<< ours + ourside + ======= + theirside + >>>>>>> theirs + EOF + test_cmp expect file +' + +test_expect_success 'restore with merge options are incompatible with certain options' ' + for opts in \ + "--staged --ours" \ + "--staged --theirs" \ + "--staged --merge" \ + "--source=HEAD --ours" \ + "--source=HEAD --theirs" \ + "--source=HEAD --merge" \ + "--staged --conflict=diff3" \ + "--staged --worktree --ours" \ + "--staged --worktree --theirs" \ + "--staged --worktree --merge" \ + "--staged --worktree --conflict=zdiff3" + do + test_must_fail git restore $opts . 2>err && + grep "cannot be used" err || return + done +' + test_done diff --git a/t/t2072-restore-pathspec-file.sh b/t/t2072-restore-pathspec-file.sh index c22669b39f..8198a1e578 100755 --- a/t/t2072-restore-pathspec-file.sh +++ b/t/t2072-restore-pathspec-file.sh @@ -152,16 +152,16 @@ test_expect_success 'error conditions' ' >empty_list && test_must_fail git restore --pathspec-from-file=list --patch --source=HEAD^1 2>err && - test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err && + test_grep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err && test_must_fail git restore --pathspec-from-file=list --source=HEAD^1 -- fileA.t 2>err && - test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err && + test_grep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err && test_must_fail git restore --pathspec-file-nul --source=HEAD^1 2>err && - test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err && + test_grep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err && test_must_fail git restore --pathspec-from-file=empty_list --source=HEAD^1 2>err && - test_i18ngrep -e "you must specify path(s) to restore" err + test_grep -e "you must specify path(s) to restore" err ' test_expect_success 'wildcard pathspec matches file in subdirectory' ' diff --git a/t/t2104-update-index-skip-worktree.sh b/t/t2104-update-index-skip-worktree.sh index b8686aabd3..0bab134d71 100755 --- a/t/t2104-update-index-skip-worktree.sh +++ b/t/t2104-update-index-skip-worktree.sh @@ -39,7 +39,7 @@ test_expect_success 'setup' ' ' test_expect_success 'index is at version 2' ' - test "$(test-tool index-version < .git/index)" = 2 + test "$(git update-index --show-index-version)" = 2 ' test_expect_success 'update-index --skip-worktree' ' @@ -48,7 +48,7 @@ test_expect_success 'update-index --skip-worktree' ' ' test_expect_success 'index is at version 3 after having some skip-worktree entries' ' - test "$(test-tool index-version < .git/index)" = 3 + test "$(git update-index --show-index-version)" = 3 ' test_expect_success 'ls-files -t' ' @@ -61,7 +61,7 @@ test_expect_success 'update-index --no-skip-worktree' ' ' test_expect_success 'index version is back to 2 when there is no skip-worktree entry' ' - test "$(test-tool index-version < .git/index)" = 2 + test "$(git update-index --show-index-version)" = 2 ' test_done diff --git a/t/t2106-update-index-assume-unchanged.sh b/t/t2106-update-index-assume-unchanged.sh index d943ddf47e..95c004dc5c 100755 --- a/t/t2106-update-index-assume-unchanged.sh +++ b/t/t2106-update-index-assume-unchanged.sh @@ -22,7 +22,7 @@ test_expect_success 'do not switch branches with dirty file' ' echo dirt >file && git update-index --assume-unchanged file && test_must_fail git checkout - 2>err && - test_i18ngrep overwritten err + test_grep overwritten err ' test_done diff --git a/t/t2107-update-index-basic.sh b/t/t2107-update-index-basic.sh index 07e6de84e6..cc72ead79f 100755 --- a/t/t2107-update-index-basic.sh +++ b/t/t2107-update-index-basic.sh @@ -14,7 +14,7 @@ test_expect_success 'update-index --nonsense fails' ' test_expect_success 'update-index --nonsense dumps usage' ' test_expect_code 129 git update-index --nonsense 2>err && - test_i18ngrep "[Uu]sage: git update-index" err + test_grep "[Uu]sage: git update-index" err ' test_expect_success 'update-index -h with corrupt index' ' @@ -25,7 +25,7 @@ test_expect_success 'update-index -h with corrupt index' ' >.git/index && test_expect_code 129 git update-index -h >usage 2>&1 ) && - test_i18ngrep "[Uu]sage: git update-index" broken/usage + test_grep "[Uu]sage: git update-index" broken/usage ' test_expect_success '--cacheinfo complains of missing arguments' ' @@ -83,7 +83,7 @@ test_expect_success '.lock files cleaned up' ' cd repo && git config core.worktree ../../worktree && # --refresh triggers late setup_work_tree, - # active_cache_changed is zero, rollback_lock_file fails + # the_index.cache_changed is zero, rollback_lock_file fails git update-index --refresh --verbose >out && test_must_be_empty out && ! test -f .git/index.lock @@ -111,4 +111,35 @@ test_expect_success '--chmod=+x and chmod=-x in the same argument list' ' test_cmp expect actual ' +test_expect_success '--index-version' ' + git commit --allow-empty -m snap && + git reset --hard && + git rm -f -r --cached . && + + # The default index version is 2 --- update this test + # when you change it in the code + git update-index --show-index-version >actual && + echo 2 >expect && + test_cmp expect actual && + + # The next test wants us to be using version 2 + git update-index --index-version 2 && + + git update-index --index-version 4 --verbose >actual && + echo "index-version: was 2, set to 4" >expect && + test_cmp expect actual && + + git update-index --index-version 4 --verbose >actual && + echo "index-version: was 4, set to 4" >expect && + test_cmp expect actual && + + git update-index --index-version 2 --verbose >actual && + echo "index-version: was 4, set to 2" >expect && + test_cmp expect actual && + + # non-verbose should be silent + git update-index --index-version 4 >actual && + test_must_be_empty actual +' + test_done diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh index be394f1131..c01492f33f 100755 --- a/t/t2200-add-update.sh +++ b/t/t2200-add-update.sh @@ -197,4 +197,15 @@ test_expect_success '"add -u non-existent" should fail' ' ! grep "non-existent" actual ' +test_expect_success '"commit -a" implies "add -u" if index becomes empty' ' + git rm -rf \* && + git commit -m clean-slate && + test_commit file1 && + rm file1.t && + test_tick && + git commit -a -m remove && + git ls-tree HEAD: >out && + test_must_be_empty out +' + test_done diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh index ebf58db2d1..8fa44a92a2 100755 --- a/t/t2203-add-intent.sh +++ b/t/t2203-add-intent.sh @@ -173,7 +173,7 @@ test_expect_success 'rename detection finds the right names' ' git add -N third && git status | grep -v "^?" >actual.1 && - test_i18ngrep "renamed: *first -> third" actual.1 && + test_grep "renamed: *first -> third" actual.1 && git status --porcelain | grep -v "^?" >actual.2 && cat >expected.2 <<-\EOF && @@ -213,8 +213,8 @@ test_expect_success 'double rename detection in status' ' git add -N third && git status | grep -v "^?" >actual.1 && - test_i18ngrep "renamed: *first -> second" actual.1 && - test_i18ngrep "renamed: *second -> third" actual.1 && + test_grep "renamed: *first -> second" actual.1 && + test_grep "renamed: *second -> third" actual.1 && git status --porcelain | grep -v "^?" >actual.2 && cat >expected.2 <<-\EOF && diff --git a/t/t2204-add-ignored.sh b/t/t2204-add-ignored.sh index 89424abccd..b7cf1e492c 100755 --- a/t/t2204-add-ignored.sh +++ b/t/t2204-add-ignored.sh @@ -36,7 +36,7 @@ do ' test_expect_success "complaints for ignored $i output" ' - test_i18ngrep -e "Use -f if" err + test_grep -e "Use -f if" err ' test_expect_success "complaints for ignored $i with unignored file" ' @@ -46,7 +46,7 @@ do test_must_be_empty out ' test_expect_success "complaints for ignored $i with unignored file output" ' - test_i18ngrep -e "Use -f if" err + test_grep -e "Use -f if" err ' done @@ -65,7 +65,7 @@ do test_expect_success "complaints for ignored $i in dir output" ' ( cd dir && - test_i18ngrep -e "Use -f if" err + test_grep -e "Use -f if" err ) ' done @@ -85,7 +85,7 @@ do test_expect_success "complaints for ignored $i in sub output" ' ( cd sub && - test_i18ngrep -e "Use -f if" err + test_grep -e "Use -f if" err ) ' done diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh index d587e0b20d..245656b53a 100755 --- a/t/t2400-worktree-add.sh +++ b/t/t2400-worktree-add.sh @@ -121,7 +121,8 @@ test_expect_success '"add" worktree creating new branch' ' test_expect_success 'die the same branch is already checked out' ' ( cd here && - test_must_fail git checkout newmain + test_must_fail git checkout newmain 2>actual && + grep "already used by worktree at" actual ) ' @@ -298,17 +299,24 @@ test_expect_success '"add" no auto-vivify with --detach and <branch> omitted' ' test_must_fail git -C mish/mash symbolic-ref HEAD ' -test_expect_success '"add" -b/-B mutually exclusive' ' - test_must_fail git worktree add -b poodle -B poodle bamboo main -' - -test_expect_success '"add" -b/--detach mutually exclusive' ' - test_must_fail git worktree add -b poodle --detach bamboo main -' +# Helper function to test mutually exclusive options. +# +# Note: Quoted arguments containing spaces are not supported. +test_wt_add_excl () { + local opts="$*" && + test_expect_success "'worktree add' with '$opts' has mutually exclusive options" ' + test_must_fail git worktree add $opts 2>actual && + grep -E "fatal:( options)? .* cannot be used together" actual + ' +} -test_expect_success '"add" -B/--detach mutually exclusive' ' - test_must_fail git worktree add -B poodle --detach bamboo main -' +test_wt_add_excl -b poodle -B poodle bamboo main +test_wt_add_excl -b poodle --detach bamboo main +test_wt_add_excl -B poodle --detach bamboo main +test_wt_add_excl --orphan --detach bamboo +test_wt_add_excl --orphan --no-checkout bamboo +test_wt_add_excl --orphan bamboo main +test_wt_add_excl --orphan -b bamboo wtdir/ main test_expect_success '"add -B" fails if the branch is checked out' ' git rev-parse newmain >before && @@ -326,10 +334,111 @@ test_expect_success 'add -B' ' ' test_expect_success 'add --quiet' ' + test_when_finished "git worktree remove -f -f another-worktree" && git worktree add --quiet another-worktree main 2>actual && test_must_be_empty actual ' +test_expect_success 'add --quiet -b' ' + test_when_finished "git branch -D quietnewbranch" && + test_when_finished "git worktree remove -f -f another-worktree" && + git worktree add --quiet -b quietnewbranch another-worktree 2>actual && + test_must_be_empty actual +' + +test_expect_success '"add --orphan"' ' + test_when_finished "git worktree remove -f -f orphandir" && + git worktree add --orphan -b neworphan orphandir && + echo refs/heads/neworphan >expected && + git -C orphandir symbolic-ref HEAD >actual && + test_cmp expected actual +' + +test_expect_success '"add --orphan (no -b)"' ' + test_when_finished "git worktree remove -f -f neworphan" && + git worktree add --orphan neworphan && + echo refs/heads/neworphan >expected && + git -C neworphan symbolic-ref HEAD >actual && + test_cmp expected actual +' + +test_expect_success '"add --orphan --quiet"' ' + test_when_finished "git worktree remove -f -f orphandir" && + git worktree add --quiet --orphan -b neworphan orphandir 2>log.actual && + test_must_be_empty log.actual && + echo refs/heads/neworphan >expected && + git -C orphandir symbolic-ref HEAD >actual && + test_cmp expected actual +' + +test_expect_success '"add --orphan" fails if the branch already exists' ' + test_when_finished "git branch -D existingbranch" && + git worktree add -b existingbranch orphandir main && + git worktree remove orphandir && + test_must_fail git worktree add --orphan -b existingbranch orphandir +' + +test_expect_success '"add --orphan" with empty repository' ' + test_when_finished "rm -rf empty_repo" && + echo refs/heads/newbranch >expected && + GIT_DIR="empty_repo" git init --bare && + git -C empty_repo worktree add --orphan -b newbranch worktreedir && + git -C empty_repo/worktreedir symbolic-ref HEAD >actual && + test_cmp expected actual +' + +test_expect_success '"add" worktree with orphan branch and lock' ' + git worktree add --lock --orphan -b orphanbr orphan-with-lock && + test_when_finished "git worktree unlock orphan-with-lock || :" && + test -f .git/worktrees/orphan-with-lock/locked +' + +test_expect_success '"add" worktree with orphan branch, lock, and reason' ' + lock_reason="why not" && + git worktree add --detach --lock --reason "$lock_reason" orphan-with-lock-reason main && + test_when_finished "git worktree unlock orphan-with-lock-reason || :" && + test -f .git/worktrees/orphan-with-lock-reason/locked && + echo "$lock_reason" >expect && + test_cmp expect .git/worktrees/orphan-with-lock-reason/locked +' + +# Note: Quoted arguments containing spaces are not supported. +test_wt_add_orphan_hint () { + local context="$1" && + local use_branch=$2 && + shift 2 && + local opts="$*" && + test_expect_success "'worktree add' show orphan hint in bad/orphan HEAD w/ $context" ' + test_when_finished "rm -rf repo" && + git init repo && + (cd repo && test_commit commit) && + git -C repo switch --orphan noref && + test_must_fail git -C repo worktree add $opts foobar/ 2>actual && + ! grep "error: unknown switch" actual && + grep "hint: If you meant to create a worktree containing a new orphan branch" actual && + if [ $use_branch -eq 1 ] + then + grep -E "^hint: +git worktree add --orphan -b [^ ]+ [^ ]+$" actual + else + grep -E "^hint: +git worktree add --orphan [^ ]+$" actual + fi + + ' +} + +test_wt_add_orphan_hint 'no opts' 0 +test_wt_add_orphan_hint '-b' 1 -b foobar_branch +test_wt_add_orphan_hint '-B' 1 -B foobar_branch + +test_expect_success "'worktree add' doesn't show orphan hint in bad/orphan HEAD w/ --quiet" ' + test_when_finished "rm -rf repo" && + git init repo && + (cd repo && test_commit commit) && + test_must_fail git -C repo worktree add --quiet foobar_branch foobar/ 2>actual && + ! grep "error: unknown switch" actual && + ! grep "hint: If you meant to create a worktree containing a new orphan branch" actual +' + test_expect_success 'local clone from linked checkout' ' git clone --local here here-clone && ( cd here-clone && git fsck ) @@ -446,6 +555,14 @@ setup_remote_repo () { ) } +test_expect_success '"add" <path> <remote/branch> w/ no HEAD' ' + test_when_finished rm -rf repo_upstream repo_local foo && + setup_remote_repo repo_upstream repo_local && + git -C repo_local config --bool core.bare true && + git -C repo_local branch -D main && + git -C repo_local worktree add ./foo repo_upstream/foo +' + test_expect_success '--no-track avoids setting up tracking' ' test_when_finished rm -rf repo_upstream repo_local foo && setup_remote_repo repo_upstream repo_local && @@ -528,6 +645,35 @@ test_expect_success 'git worktree add --guess-remote sets up tracking' ' test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo ) ' +test_expect_success 'git worktree add --guess-remote sets up tracking (quiet)' ' + test_when_finished rm -rf repo_a repo_b foo && + setup_remote_repo repo_a repo_b && + ( + cd repo_b && + git worktree add --quiet --guess-remote ../foo 2>actual && + test_must_be_empty actual + ) && + ( + cd foo && + test_branch_upstream foo repo_a foo && + test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo + ) +' + +test_expect_success 'git worktree --no-guess-remote (quiet)' ' + test_when_finished rm -rf repo_a repo_b foo && + setup_remote_repo repo_a repo_b && + ( + cd repo_b && + git worktree add --quiet --no-guess-remote ../foo + ) && + ( + cd foo && + test_must_fail git config "branch.foo.remote" && + test_must_fail git config "branch.foo.merge" && + test_cmp_rev ! refs/remotes/repo_a/foo refs/heads/foo + ) +' test_expect_success 'git worktree add with worktree.guessRemote sets up tracking' ' test_when_finished rm -rf repo_a repo_b foo && @@ -560,6 +706,348 @@ test_expect_success 'git worktree --no-guess-remote option overrides config' ' ) ' +test_dwim_orphan () { + local info_text="No possible source branch, inferring '--orphan'" && + local fetch_error_text="fatal: No local or remote refs exist despite at least one remote" && + local orphan_hint="hint: If you meant to create a worktree containing a new orphan branch" && + local invalid_ref_regex="^fatal: invalid reference: " && + local bad_combo_regex="^fatal: options '[-a-z]*' and '[-a-z]*' cannot be used together" && + + local git_ns="repo" && + local dashc_args="-C $git_ns" && + local use_cd=0 && + + local bad_head=0 && + local empty_repo=1 && + local local_ref=0 && + local use_quiet=0 && + local remote=0 && + local remote_ref=0 && + local use_detach=0 && + local use_new_branch=0 && + + local outcome="$1" && + local outcome_text && + local success && + shift && + local args="" && + local context="" && + case "$outcome" in + "infer") + success=1 && + outcome_text='"add" DWIM infer --orphan' + ;; + "no_infer") + success=1 && + outcome_text='"add" DWIM doesnt infer --orphan' + ;; + "fetch_error") + success=0 && + outcome_text='"add" error need fetch' + ;; + "fatal_orphan_bad_combo") + success=0 && + outcome_text='"add" error inferred "--orphan" gives illegal opts combo' + ;; + "warn_bad_head") + success=0 && + outcome_text='"add" error, warn on bad HEAD, hint use orphan' + ;; + *) + echo "test_dwim_orphan(): invalid outcome: '$outcome'" >&2 && + return 1 + ;; + esac && + while [ $# -gt 0 ] + do + case "$1" in + # How and from where to create the worktree + "-C_repo") + use_cd=0 && + git_ns="repo" && + dashc_args="-C $git_ns" && + context="$context, 'git -C repo'" + ;; + "-C_wt") + use_cd=0 && + git_ns="wt" && + dashc_args="-C $git_ns" && + context="$context, 'git -C wt'" + ;; + "cd_repo") + use_cd=1 && + git_ns="repo" && + dashc_args="" && + context="$context, 'cd repo && git'" + ;; + "cd_wt") + use_cd=1 && + git_ns="wt" && + dashc_args="" && + context="$context, 'cd wt && git'" + ;; + + # Bypass the "pull first" warning + "force") + args="$args --force" && + context="$context, --force" + ;; + + # Try to use remote refs when DWIM + "guess_remote") + args="$args --guess-remote" && + context="$context, --guess-remote" + ;; + "no_guess_remote") + args="$args --no-guess-remote" && + context="$context, --no-guess-remote" + ;; + + # Whether there is at least one local branch present + "local_ref") + empty_repo=0 && + local_ref=1 && + context="$context, >=1 local branches" + ;; + "no_local_ref") + empty_repo=0 && + context="$context, 0 local branches" + ;; + + # Whether the HEAD points at a valid ref (skip this opt when no refs) + "good_head") + # requires: local_ref + context="$context, valid HEAD" + ;; + "bad_head") + bad_head=1 && + context="$context, invalid (or orphan) HEAD" + ;; + + # Whether the code path is tested with the base add command, -b, or --detach + "no_-b") + use_new_branch=0 && + context="$context, no --branch" + ;; + "-b") + use_new_branch=1 && + context="$context, --branch" + ;; + "detach") + use_detach=1 && + context="$context, --detach" + ;; + + # Whether to check that all output is suppressed (except errors) + # or that the output is as expected + "quiet") + use_quiet=1 && + args="$args --quiet" && + context="$context, --quiet" + ;; + "no_quiet") + use_quiet=0 && + context="$context, no --quiet (expect output)" + ;; + + # Whether there is at least one remote attached to the repo + "remote") + empty_repo=0 && + remote=1 && + context="$context, >=1 remotes" + ;; + "no_remote") + empty_repo=0 && + remote=0 && + context="$context, 0 remotes" + ;; + + # Whether there is at least one valid remote ref + "remote_ref") + # requires: remote + empty_repo=0 && + remote_ref=1 && + context="$context, >=1 fetched remote branches" + ;; + "no_remote_ref") + empty_repo=0 && + remote_ref=0 && + context="$context, 0 fetched remote branches" + ;; + + # Options or flags that become illegal when --orphan is inferred + "no_checkout") + args="$args --no-checkout" && + context="$context, --no-checkout" + ;; + "track") + args="$args --track" && + context="$context, --track" + ;; + + # All other options are illegal + *) + echo "test_dwim_orphan(): invalid arg: '$1'" >&2 && + return 1 + ;; + esac && + shift + done && + context="${context#', '}" && + if [ $use_new_branch -eq 1 ] + then + args="$args -b foo" + elif [ $use_detach -eq 1 ] + then + args="$args --detach" + else + context="DWIM (no --branch), $context" + fi && + if [ $empty_repo -eq 1 ] + then + context="empty repo, $context" + fi && + args="$args ../foo" && + context="${context%', '}" && + test_expect_success "$outcome_text w/ $context" ' + test_when_finished "rm -rf repo" && + git init repo && + if [ $local_ref -eq 1 ] && [ "$git_ns" = "repo" ] + then + (cd repo && test_commit commit) && + if [ $bad_head -eq 1 ] + then + git -C repo symbolic-ref HEAD refs/heads/badbranch + fi + elif [ $local_ref -eq 1 ] && [ "$git_ns" = "wt" ] + then + test_when_finished "git -C repo worktree remove -f ../wt" && + git -C repo worktree add --orphan -b main ../wt && + (cd wt && test_commit commit) && + if [ $bad_head -eq 1 ] + then + git -C wt symbolic-ref HEAD refs/heads/badbranch + fi + elif [ $local_ref -eq 0 ] && [ "$git_ns" = "wt" ] + then + test_when_finished "git -C repo worktree remove -f ../wt" && + git -C repo worktree add --orphan -b orphanbranch ../wt + fi && + + if [ $remote -eq 1 ] + then + test_when_finished "rm -rf upstream" && + git init upstream && + (cd upstream && test_commit commit) && + git -C upstream switch -c foo && + git -C repo remote add upstream ../upstream + fi && + + if [ $remote_ref -eq 1 ] + then + git -C repo fetch + fi && + if [ $success -eq 1 ] + then + test_when_finished git -C repo worktree remove ../foo + fi && + ( + if [ $use_cd -eq 1 ] + then + cd $git_ns + fi && + if [ "$outcome" = "infer" ] + then + git $dashc_args worktree add $args 2>actual && + if [ $use_quiet -eq 1 ] + then + test_must_be_empty actual + else + grep "$info_text" actual + fi + elif [ "$outcome" = "no_infer" ] + then + git $dashc_args worktree add $args 2>actual && + if [ $use_quiet -eq 1 ] + then + test_must_be_empty actual + else + ! grep "$info_text" actual + fi + elif [ "$outcome" = "fetch_error" ] + then + test_must_fail git $dashc_args worktree add $args 2>actual && + grep "$fetch_error_text" actual + elif [ "$outcome" = "fatal_orphan_bad_combo" ] + then + test_must_fail git $dashc_args worktree add $args 2>actual && + if [ $use_quiet -eq 1 ] + then + ! grep "$info_text" actual + else + grep "$info_text" actual + fi && + grep "$bad_combo_regex" actual + elif [ "$outcome" = "warn_bad_head" ] + then + test_must_fail git $dashc_args worktree add $args 2>actual && + if [ $use_quiet -eq 1 ] + then + grep "$invalid_ref_regex" actual && + ! grep "$orphan_hint" actual + else + headpath=$(git $dashc_args rev-parse --path-format=absolute --git-path HEAD) && + headcontents=$(cat "$headpath") && + grep "HEAD points to an invalid (or orphaned) reference" actual && + grep "HEAD path: .$headpath." actual && + grep "HEAD contents: .$headcontents." actual && + grep "$orphan_hint" actual && + ! grep "$info_text" actual + fi && + grep "$invalid_ref_regex" actual + else + # Unreachable + false + fi + ) && + if [ $success -ne 1 ] + then + test_path_is_missing foo + fi + ' +} + +for quiet_mode in "no_quiet" "quiet" +do + for changedir_type in "cd_repo" "cd_wt" "-C_repo" "-C_wt" + do + dwim_test_args="$quiet_mode $changedir_type" + test_dwim_orphan 'infer' $dwim_test_args no_-b + test_dwim_orphan 'no_infer' $dwim_test_args no_-b local_ref good_head + test_dwim_orphan 'infer' $dwim_test_args no_-b no_local_ref no_remote no_remote_ref no_guess_remote + test_dwim_orphan 'infer' $dwim_test_args no_-b no_local_ref remote no_remote_ref no_guess_remote + test_dwim_orphan 'fetch_error' $dwim_test_args no_-b no_local_ref remote no_remote_ref guess_remote + test_dwim_orphan 'infer' $dwim_test_args no_-b no_local_ref remote no_remote_ref guess_remote force + test_dwim_orphan 'no_infer' $dwim_test_args no_-b no_local_ref remote remote_ref guess_remote + + test_dwim_orphan 'infer' $dwim_test_args -b + test_dwim_orphan 'no_infer' $dwim_test_args -b local_ref good_head + test_dwim_orphan 'infer' $dwim_test_args -b no_local_ref no_remote no_remote_ref no_guess_remote + test_dwim_orphan 'infer' $dwim_test_args -b no_local_ref remote no_remote_ref no_guess_remote + test_dwim_orphan 'infer' $dwim_test_args -b no_local_ref remote no_remote_ref guess_remote + test_dwim_orphan 'infer' $dwim_test_args -b no_local_ref remote remote_ref guess_remote + + test_dwim_orphan 'warn_bad_head' $dwim_test_args no_-b local_ref bad_head + test_dwim_orphan 'warn_bad_head' $dwim_test_args -b local_ref bad_head + test_dwim_orphan 'warn_bad_head' $dwim_test_args detach local_ref bad_head + done + + test_dwim_orphan 'fatal_orphan_bad_combo' $quiet_mode no_-b no_checkout + test_dwim_orphan 'fatal_orphan_bad_combo' $quiet_mode no_-b track + test_dwim_orphan 'fatal_orphan_bad_combo' $quiet_mode -b no_checkout + test_dwim_orphan 'fatal_orphan_bad_combo' $quiet_mode -b track +done + post_checkout_hook () { test_when_finished "rm -rf .git/hooks" && mkdir .git/hooks && diff --git a/t/t2401-worktree-prune.sh b/t/t2401-worktree-prune.sh index 568a47ec42..71aa9bcd62 100755 --- a/t/t2401-worktree-prune.sh +++ b/t/t2401-worktree-prune.sh @@ -47,7 +47,7 @@ test_expect_success SANITY 'prune directories with unreadable gitdir' ' : >.git/worktrees/def/gitdir && chmod u-r .git/worktrees/def/gitdir && git worktree prune --verbose 2>actual && - test_i18ngrep "Removing worktrees/def: unable to read gitdir file" actual && + test_grep "Removing worktrees/def: unable to read gitdir file" actual && ! test -d .git/worktrees/def && ! test -d .git/worktrees ' @@ -57,7 +57,7 @@ test_expect_success 'prune directories with invalid gitdir' ' : >.git/worktrees/def/def && : >.git/worktrees/def/gitdir && git worktree prune --verbose 2>actual && - test_i18ngrep "Removing worktrees/def: invalid gitdir file" actual && + test_grep "Removing worktrees/def: invalid gitdir file" actual && ! test -d .git/worktrees/def && ! test -d .git/worktrees ' @@ -67,7 +67,7 @@ test_expect_success 'prune directories with gitdir pointing to nowhere' ' : >.git/worktrees/def/def && echo "$(pwd)"/nowhere >.git/worktrees/def/gitdir && git worktree prune --verbose 2>actual && - test_i18ngrep "Removing worktrees/def: gitdir file points to non-existent location" actual && + test_grep "Removing worktrees/def: gitdir file points to non-existent location" actual && ! test -d .git/worktrees/def && ! test -d .git/worktrees ' @@ -103,7 +103,7 @@ test_expect_success 'prune duplicate (linked/linked)' ' sed "s/w2/w1/" .git/worktrees/w2/gitdir >.git/worktrees/w2/gitdir.new && mv .git/worktrees/w2/gitdir.new .git/worktrees/w2/gitdir && git worktree prune --verbose 2>actual && - test_i18ngrep "duplicate entry" actual && + test_grep "duplicate entry" actual && test -d .git/worktrees/w1 && ! test -d .git/worktrees/w2 ' @@ -116,7 +116,7 @@ test_expect_success 'prune duplicate (main/linked)' ' rm -fr wt && mv repo wt && git -C wt worktree prune --verbose 2>actual && - test_i18ngrep "duplicate entry" actual && + test_grep "duplicate entry" actual && ! test -d .git/worktrees/wt ' diff --git a/t/t2402-worktree-list.sh b/t/t2402-worktree-list.sh index 9ad9be0c20..33ea9cb21b 100755 --- a/t/t2402-worktree-list.sh +++ b/t/t2402-worktree-list.sh @@ -143,7 +143,7 @@ test_expect_success '"list" all worktrees --porcelain with prunable' ' rm -rf prunable && git worktree list --porcelain >out && sed -n "/^worktree .*\/prunable$/,/^$/p" <out >only_prunable && - test_i18ngrep "^prunable gitdir file points to non-existent location$" only_prunable + test_grep "^prunable gitdir file points to non-existent location$" only_prunable ' test_expect_success '"list" all worktrees with prunable consistent with "prune"' ' @@ -155,8 +155,8 @@ test_expect_success '"list" all worktrees with prunable consistent with "prune"' grep "/prunable *[0-9a-f].* prunable$" out && ! grep "/unprunable *[0-9a-f].* unprunable$" out && git worktree prune --verbose 2>out && - test_i18ngrep "^Removing worktrees/prunable" out && - test_i18ngrep ! "^Removing worktrees/unprunable" out + test_grep "^Removing worktrees/prunable" out && + test_grep ! "^Removing worktrees/unprunable" out ' test_expect_success '"list" --verbose and --porcelain mutually exclusive' ' diff --git a/t/t2403-worktree-move.sh b/t/t2403-worktree-move.sh index 230a55e99a..901342ea09 100755 --- a/t/t2403-worktree-move.sh +++ b/t/t2403-worktree-move.sh @@ -202,7 +202,7 @@ test_expect_success 'proper error when worktree not found' ' for i in noodle noodle/bork do test_must_fail git worktree lock $i 2>err && - test_i18ngrep "not a working tree" err || return 1 + test_grep "not a working tree" err || return 1 done ' diff --git a/t/t2406-worktree-repair.sh b/t/t2406-worktree-repair.sh index 8970780efc..edbf502ec5 100755 --- a/t/t2406-worktree-repair.sh +++ b/t/t2406-worktree-repair.sh @@ -25,7 +25,7 @@ test_expect_success 'worktree path not directory' ' >notdir && test_must_fail git worktree repair >out 2>err && test_must_be_empty out && - test_i18ngrep "not a directory" err + test_grep "not a directory" err ' test_expect_success "don't clobber .git repo" ' @@ -35,7 +35,7 @@ test_expect_success "don't clobber .git repo" ' test_create_repo repo && test_must_fail git worktree repair >out 2>err && test_must_be_empty out && - test_i18ngrep ".git is not a file" err + test_grep ".git is not a file" err ' test_corrupt_gitfile () { @@ -47,7 +47,7 @@ test_corrupt_gitfile () { git -C corrupt rev-parse --absolute-git-dir >expect && eval "$butcher" && git -C "$repairdir" worktree repair 2>err && - test_i18ngrep "$problem" err && + test_grep "$problem" err && git -C corrupt rev-parse --absolute-git-dir >actual && test_cmp expect actual } @@ -93,7 +93,7 @@ test_expect_success 'repair .git file from bare.git' ' test_expect_success 'invalid worktree path' ' test_must_fail git worktree repair /notvalid >out 2>err && test_must_be_empty out && - test_i18ngrep "not a valid path" err + test_grep "not a valid path" err ' test_expect_success 'repo not found; .git not file' ' @@ -101,7 +101,7 @@ test_expect_success 'repo not found; .git not file' ' test_create_repo not-a-worktree && test_must_fail git worktree repair not-a-worktree >out 2>err && test_must_be_empty out && - test_i18ngrep ".git is not a file" err + test_grep ".git is not a file" err ' test_expect_success 'repo not found; .git not referencing repo' ' @@ -111,7 +111,7 @@ test_expect_success 'repo not found; .git not referencing repo' ' mv side/.newgit side/.git && mkdir not-a-repo && test_must_fail git worktree repair side 2>err && - test_i18ngrep ".git file does not reference a repository" err + test_grep ".git file does not reference a repository" err ' test_expect_success 'repo not found; .git file broken' ' @@ -121,7 +121,7 @@ test_expect_success 'repo not found; .git file broken' ' mv orig moved && test_must_fail git worktree repair moved >out 2>err && test_must_be_empty out && - test_i18ngrep ".git file broken" err + test_grep ".git file broken" err ' test_expect_success 'repair broken gitdir' ' @@ -132,7 +132,7 @@ test_expect_success 'repair broken gitdir' ' mv orig moved && git worktree repair moved 2>err && test_cmp expect .git/worktrees/orig/gitdir && - test_i18ngrep "gitdir unreadable" err + test_grep "gitdir unreadable" err ' test_expect_success 'repair incorrect gitdir' ' @@ -142,7 +142,7 @@ test_expect_success 'repair incorrect gitdir' ' mv orig moved && git worktree repair moved 2>err && test_cmp expect .git/worktrees/orig/gitdir && - test_i18ngrep "gitdir incorrect" err + test_grep "gitdir incorrect" err ' test_expect_success 'repair gitdir (implicit) from linked worktree' ' @@ -152,7 +152,7 @@ test_expect_success 'repair gitdir (implicit) from linked worktree' ' mv orig moved && git -C moved worktree repair 2>err && test_cmp expect .git/worktrees/orig/gitdir && - test_i18ngrep "gitdir incorrect" err + test_grep "gitdir incorrect" err ' test_expect_success 'unable to repair gitdir (implicit) from main worktree' ' @@ -177,8 +177,8 @@ test_expect_success 'repair multiple gitdir files' ' git worktree repair moved1 moved2 2>err && test_cmp expect1 .git/worktrees/orig1/gitdir && test_cmp expect2 .git/worktrees/orig2/gitdir && - test_i18ngrep "gitdir incorrect:.*orig1/gitdir$" err && - test_i18ngrep "gitdir incorrect:.*orig2/gitdir$" err + test_grep "gitdir incorrect:.*orig1/gitdir$" err && + test_grep "gitdir incorrect:.*orig2/gitdir$" err ' test_expect_success 'repair moved main and linked worktrees' ' diff --git a/t/t2407-worktree-heads.sh b/t/t2407-worktree-heads.sh index 019a40df2c..f6835c91dc 100755 --- a/t/t2407-worktree-heads.sh +++ b/t/t2407-worktree-heads.sh @@ -45,7 +45,7 @@ test_expect_success 'refuse to overwrite: checked out in worktree' ' grep "cannot force update the branch" err && test_must_fail git branch -D wt-$i 2>err && - grep "Cannot delete branch" err || return 1 + grep "cannot delete branch" err || return 1 done ' @@ -58,7 +58,7 @@ test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in bisect' ' git -C wt-4 bisect good wt-1 && test_must_fail git branch -f wt-4 HEAD 2>err && - grep "cannot force update the branch '\''wt-4'\'' checked out at.*wt-4" err + grep "cannot force update the branch '\''wt-4'\'' used by worktree at.*wt-4" err ' test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (apply)' ' @@ -68,7 +68,7 @@ test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (app test_must_fail git -C wt-2 rebase --apply conflict-2 && test_must_fail git branch -f wt-2 HEAD 2>err && - grep "cannot force update the branch '\''wt-2'\'' checked out at.*wt-2" err + grep "cannot force update the branch '\''wt-2'\'' used by worktree at.*wt-2" err ' test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (merge)' ' @@ -78,7 +78,7 @@ test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase (mer test_must_fail git -C wt-2 rebase conflict-2 && test_must_fail git branch -f wt-2 HEAD 2>err && - grep "cannot force update the branch '\''wt-2'\'' checked out at.*wt-2" err + grep "cannot force update the branch '\''wt-2'\'' used by worktree at.*wt-2" err ' test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase with --update-refs' ' @@ -90,7 +90,7 @@ test_expect_success !SANITIZE_LEAK 'refuse to overwrite: worktree in rebase with for i in 3 4 do test_must_fail git branch -f can-be-updated HEAD 2>err && - grep "cannot force update the branch '\''can-be-updated'\'' checked out at.*wt-3" err || + grep "cannot force update the branch '\''can-be-updated'\'' used by worktree at.*wt-3" err || return 1 done ' @@ -150,7 +150,7 @@ test_expect_success 'refuse to overwrite when in error states' ' for i in 1 2 do test_must_fail git branch -f fake-$i HEAD 2>err && - grep "cannot force update the branch '\''fake-$i'\'' checked out at" err || + grep "cannot force update the branch '\''fake-$i'\'' used by worktree at" err || return 1 done ' diff --git a/t/t3004-ls-files-basic.sh b/t/t3004-ls-files-basic.sh index a16e25c79b..12e41a7b40 100755 --- a/t/t3004-ls-files-basic.sh +++ b/t/t3004-ls-files-basic.sh @@ -21,7 +21,7 @@ test_expect_success 'ls-files with nonexistent path' ' test_expect_success 'ls-files with nonsense option' ' test_expect_code 129 git ls-files --nonsense 2>actual && - test_i18ngrep "[Uu]sage: git ls-files" actual + test_grep "[Uu]sage: git ls-files" actual ' test_expect_success 'ls-files -h in corrupt repository' ' @@ -32,7 +32,7 @@ test_expect_success 'ls-files -h in corrupt repository' ' >.git/index && test_expect_code 129 git ls-files -h >usage 2>&1 ) && - test_i18ngrep "[Uu]sage: git ls-files " broken/usage + test_grep "[Uu]sage: git ls-files " broken/usage ' test_expect_success SYMLINKS 'ls-files with absolute paths to symlinks' ' diff --git a/t/t3007-ls-files-recurse-submodules.sh b/t/t3007-ls-files-recurse-submodules.sh index dd7770e85d..61771eec83 100755 --- a/t/t3007-ls-files-recurse-submodules.sh +++ b/t/t3007-ls-files-recurse-submodules.sh @@ -296,13 +296,46 @@ test_expect_success '--recurse-submodules and relative paths' ' test_expect_success '--recurse-submodules does not support --error-unmatch' ' test_must_fail git ls-files --recurse-submodules --error-unmatch 2>actual && - test_i18ngrep "does not support --error-unmatch" actual + test_grep "does not support --error-unmatch" actual +' + +test_expect_success '--recurse-submodules parses submodule repo config' ' + test_config -C submodule index.sparse "invalid non-boolean value" && + test_must_fail git ls-files --recurse-submodules 2>err && + grep "bad boolean config value" err +' + +test_expect_success '--recurse-submodules parses submodule worktree config' ' + test_config -C submodule extensions.worktreeConfig true && + test_config -C submodule --worktree index.sparse "invalid non-boolean value" && + + test_must_fail git ls-files --recurse-submodules 2>err && + grep "bad boolean config value" err +' + +test_expect_success '--recurse-submodules submodules ignore super project worktreeConfig extension' ' + # Enable worktree config in both super project & submodule, set an + # invalid config in the submodule worktree config + test_config extensions.worktreeConfig true && + test_config -C submodule extensions.worktreeConfig true && + test_config -C submodule --worktree index.sparse "invalid non-boolean value" && + + # Now, disable the worktree config in the submodule. Note that we need + # to manually re-enable extensions.worktreeConfig when the test is + # finished, otherwise the test_unconfig of index.sparse will not work. + test_unconfig -C submodule extensions.worktreeConfig && + test_when_finished "git -C submodule config extensions.worktreeConfig true" && + + # With extensions.worktreeConfig disabled in the submodule, the invalid + # worktree config is not picked up. + git ls-files --recurse-submodules 2>err && + ! grep "bad boolean config value" err ' test_incompatible_with_recurse_submodules () { test_expect_success "--recurse-submodules and $1 are incompatible" " test_must_fail git ls-files --recurse-submodules $1 2>actual && - test_i18ngrep 'unsupported mode' actual + test_grep 'unsupported mode' actual " } diff --git a/t/t3013-ls-files-format.sh b/t/t3013-ls-files-format.sh index efb7450bf1..6e6ea0b6f3 100755 --- a/t/t3013-ls-files-format.sh +++ b/t/t3013-ls-files-format.sh @@ -38,6 +38,41 @@ test_expect_success 'git ls-files --format objectname v.s. -s' ' test_cmp expect actual ' +test_expect_success 'git ls-files --format objecttype' ' + git ls-files --format="%(objectname)" o1.txt o4.txt o6.txt >objectname && + git cat-file --batch-check="%(objecttype)" >expect <objectname && + git ls-files --format="%(objecttype)" o1.txt o4.txt o6.txt >actual && + test_cmp expect actual +' + +test_expect_success 'git ls-files --format objectsize' ' + cat>expect <<-\EOF && +26 +29 +27 +26 +- +26 + EOF + git ls-files --format="%(objectsize)" >actual && + + test_cmp expect actual +' + +test_expect_success 'git ls-files --format objectsize:padded' ' + cat>expect <<-\EOF && + 26 + 29 + 27 + 26 + - + 26 + EOF + git ls-files --format="%(objectsize:padded)" >actual && + + test_cmp expect actual +' + test_expect_success 'git ls-files --format v.s. --eol' ' git ls-files --eol >tmp && sed -e "s/ / /g" -e "s/ */ /g" tmp >expect 2>err && @@ -54,6 +89,22 @@ test_expect_success 'git ls-files --format path v.s. -s' ' test_cmp expect actual ' +test_expect_success 'git ls-files --format with relative path' ' + cat >expect <<-\EOF && + ../o1.txt + ../o2.txt + ../o3.txt + ../o4.txt + ../o5.txt + ../o6.txt + EOF + mkdir sub && + cd sub && + git ls-files --format="%(path)" ":/" >../actual && + cd .. && + test_cmp expect actual +' + test_expect_success 'git ls-files --format with -m' ' echo change >o1.txt && cat >expect <<-\EOF && diff --git a/t/t3060-ls-files-with-tree.sh b/t/t3060-ls-files-with-tree.sh index c4a72ae446..5a06732ca7 100755 --- a/t/t3060-ls-files-with-tree.sh +++ b/t/t3060-ls-files-with-tree.sh @@ -40,7 +40,7 @@ test_expect_success 'setup' ' git commit -a -m "remove them all" && # The bug also requires some entry before our directory so that - # prune_path will modify the_index.cache + # prune_index will modify the_repository->index.cache mkdir a_directory_that_sorts_before_sub && >a_directory_that_sorts_before_sub/file && @@ -56,7 +56,7 @@ test_expect_success 'usage' ' ' test_expect_success 'git ls-files --with-tree should succeed from subdir' ' - # We have to run from a sub-directory to trigger prune_path + # We have to run from a sub-directory to trigger prune_index # Then we finally get to run our --with-tree test ( cd sub && diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh index 5d871fde96..4dd42df38c 100755 --- a/t/t3070-wildmatch.sh +++ b/t/t3070-wildmatch.sh @@ -431,4 +431,15 @@ match 1 1 1 1 'a' '[B-a]' match 0 1 0 1 'z' '[Z-y]' match 1 1 1 1 'Z' '[Z-y]' +test_expect_success 'matching does not exhibit exponential behavior' ' + { + test-tool wildmatch wildmatch \ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab \ + "*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a" & + pid=$! + } && + sleep 2 && + ! kill $! +' + test_done diff --git a/t/t3101-ls-tree-dirname.sh b/t/t3101-ls-tree-dirname.sh index 217006d1bf..5af2dac0e4 100755 --- a/t/t3101-ls-tree-dirname.sh +++ b/t/t3101-ls-tree-dirname.sh @@ -154,6 +154,14 @@ EOF test_output ' +test_expect_success 'ls-tree --no-full-name' ' + git -C path0 ls-tree --no-full-name $tree a >current && + cat >expected <<-EOF && + 040000 tree X a + EOF + test_output +' + test_expect_success 'ls-tree --full-tree' ' ( cd path1/b/c && diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index 5a169b68d6..6a316f081e 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -8,6 +8,7 @@ test_description='git branch assorted tests' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-rebase.sh @@ -24,10 +25,10 @@ test_expect_success 'prepare a trivial repository' ' test_expect_success 'git branch --help should not have created a bogus branch' ' test_might_fail git branch --man --help </dev/null >/dev/null 2>&1 && - test_path_is_missing .git/refs/heads/--help + test_ref_missing refs/heads/--help ' -test_expect_success 'branch -h in broken repository' ' +test_expect_success REFFILES 'branch -h in broken repository' ' mkdir broken && ( cd broken && @@ -35,11 +36,12 @@ test_expect_success 'branch -h in broken repository' ' >.git/refs/heads/main && test_expect_code 129 git branch -h >usage 2>&1 ) && - test_i18ngrep "[Uu]sage" broken/usage + test_grep "[Uu]sage" broken/usage ' test_expect_success 'git branch abc should create a branch' ' - git branch abc && test_path_is_file .git/refs/heads/abc + git branch abc && + test_ref_exists refs/heads/abc ' test_expect_success 'git branch abc should fail when abc exists' ' @@ -60,11 +62,13 @@ test_expect_success 'git branch --force abc should succeed when abc exists' ' ' test_expect_success 'git branch a/b/c should create a branch' ' - git branch a/b/c && test_path_is_file .git/refs/heads/a/b/c + git branch a/b/c && + test_ref_exists refs/heads/a/b/c ' test_expect_success 'git branch mb main... should create a branch' ' - git branch mb main... && test_path_is_file .git/refs/heads/mb + git branch mb main... && + test_ref_exists refs/heads/mb ' test_expect_success 'git branch HEAD should fail' ' @@ -72,19 +76,19 @@ test_expect_success 'git branch HEAD should fail' ' ' cat >expect <<EOF -$ZERO_OID $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 branch: Created from main +$HEAD refs/heads/d/e/f@{0}: branch: Created from main EOF test_expect_success 'git branch --create-reflog d/e/f should create a branch and a log' ' GIT_COMMITTER_DATE="2005-05-26 23:30" \ git -c core.logallrefupdates=false branch --create-reflog d/e/f && - test_path_is_file .git/refs/heads/d/e/f && - test_path_is_file .git/logs/refs/heads/d/e/f && - test_cmp expect .git/logs/refs/heads/d/e/f + test_ref_exists refs/heads/d/e/f && + git reflog show --no-abbrev-commit refs/heads/d/e/f >actual && + test_cmp expect actual ' test_expect_success 'git branch -d d/e/f should delete a branch and a log' ' git branch -d d/e/f && - test_path_is_missing .git/refs/heads/d/e/f && + test_ref_missing refs/heads/d/e/f && test_must_fail git reflog exists refs/heads/d/e/f ' @@ -102,7 +106,7 @@ test_expect_success 'git branch l should work after branch l/m has been deleted' test_expect_success 'git branch -m dumps usage' ' test_expect_code 128 git branch -m 2>err && - test_i18ngrep "branch name required" err + test_grep "branch name required" err ' test_expect_success 'git branch -m m broken_symref should work' ' @@ -199,10 +203,9 @@ test_expect_success 'git branch -M baz bam should succeed when baz is checked ou test $(git rev-parse --abbrev-ref HEAD) = bam ' -test_expect_success 'git branch -M baz bam should add entries to .git/logs/HEAD' ' - msg="Branch: renamed refs/heads/baz to refs/heads/bam" && - grep " $ZERO_OID.*$msg$" .git/logs/HEAD && - grep "^$ZERO_OID.*$msg$" .git/logs/HEAD +test_expect_success 'git branch -M baz bam should add entries to HEAD reflog' ' + git reflog show HEAD >actual && + grep "HEAD@{0}: Branch: renamed refs/heads/baz to refs/heads/bam" actual ' test_expect_success 'git branch -M should leave orphaned HEAD alone' ' @@ -211,17 +214,20 @@ test_expect_success 'git branch -M should leave orphaned HEAD alone' ' cd orphan && test_commit initial && git checkout --orphan lonely && - grep lonely .git/HEAD && - test_path_is_missing .git/refs/head/lonely && + git symbolic-ref HEAD >expect && + echo refs/heads/lonely >actual && + test_cmp expect actual && + test_ref_missing refs/head/lonely && git branch -M main mistress && - grep lonely .git/HEAD + git symbolic-ref HEAD >expect && + test_cmp expect actual ) ' test_expect_success 'resulting reflog can be shown by log -g' ' oid=$(git rev-parse HEAD) && cat >expect <<-EOF && - HEAD@{0} $oid $msg + HEAD@{0} $oid Branch: renamed refs/heads/baz to refs/heads/bam HEAD@{2} $oid checkout: moving from foo to baz EOF git log -g --format="%gd %H %gs" -2 HEAD >actual && @@ -239,15 +245,34 @@ test_expect_success 'git branch -M baz bam should succeed when baz is checked ou git worktree prune ' +test_expect_success REFFILES 'git branch -M fails if updating any linked working tree fails' ' + git worktree add -b baz bazdir1 && + git worktree add -f bazdir2 baz && + touch .git/worktrees/bazdir1/HEAD.lock && + test_must_fail git branch -M baz bam && + test $(git -C bazdir2 rev-parse --abbrev-ref HEAD) = bam && + git branch -M bam baz && + rm .git/worktrees/bazdir1/HEAD.lock && + touch .git/worktrees/bazdir2/HEAD.lock && + test_must_fail git branch -M baz bam && + test $(git -C bazdir1 rev-parse --abbrev-ref HEAD) = bam && + rm -rf bazdir1 bazdir2 && + git worktree prune +' + test_expect_success 'git branch -M baz bam should succeed within a worktree in which baz is checked out' ' git checkout -b baz && git worktree add -f bazdir baz && ( cd bazdir && git branch -M baz bam && - test $(git rev-parse --abbrev-ref HEAD) = bam + echo bam >expect && + git rev-parse --abbrev-ref HEAD >actual && + test_cmp expect actual ) && - test $(git rev-parse --abbrev-ref HEAD) = bam && + echo bam >expect && + git rev-parse --abbrev-ref HEAD >actual && + test_cmp expect actual && rm -r bazdir && git worktree prune ' @@ -271,14 +296,28 @@ test_expect_success 'git branch -M topic topic should work when main is checked test_expect_success 'git branch -M and -C fail on detached HEAD' ' git checkout HEAD^{} && test_when_finished git checkout - && - echo "fatal: cannot rename the current branch while not on any." >expect && + echo "fatal: cannot rename the current branch while not on any" >expect && test_must_fail git branch -M must-fail 2>err && test_cmp expect err && - echo "fatal: cannot copy the current branch while not on any." >expect && + echo "fatal: cannot copy the current branch while not on any" >expect && test_must_fail git branch -C must-fail 2>err && test_cmp expect err ' +test_expect_success 'git branch -m should work with orphan branches' ' + test_when_finished git checkout - && + test_when_finished git worktree remove -f wt && + git worktree add wt --detach && + # rename orphan in another worktreee + git -C wt checkout --orphan orphan-foo-wt && + git branch -m orphan-foo-wt orphan-bar-wt && + test orphan-bar-wt=$(git -C orphan-worktree branch --show-current) && + # rename orphan in the current worktree + git checkout --orphan orphan-foo && + git branch -m orphan-foo orphan-bar && + test orphan-bar=$(git branch --show-current) +' + test_expect_success 'git branch -d on orphan HEAD (merged)' ' test_when_finished git checkout main && git checkout --orphan orphan && @@ -547,12 +586,12 @@ EOF test_expect_success 'git branch -c dumps usage' ' test_expect_code 128 git branch -c 2>err && - test_i18ngrep "branch name required" err + test_grep "branch name required" err ' test_expect_success 'git branch --copy dumps usage' ' test_expect_code 128 git branch --copy 2>err && - test_i18ngrep "branch name required" err + test_grep "branch name required" err ' test_expect_success 'git branch -c d e should work' ' @@ -662,7 +701,8 @@ test_expect_success 'git branch -C c1 c2 should succeed when c1 is checked out' test_expect_success 'git branch -C c1 c2 should never touch HEAD' ' msg="Branch: copied refs/heads/c1 to refs/heads/c2" && - ! grep "$msg$" .git/logs/HEAD + git reflog HEAD >actual && + ! grep "$msg$" actual ' test_expect_success 'git branch -C main should work when main is checked out' ' @@ -765,26 +805,26 @@ test_expect_success 'deleting a symref' ' git symbolic-ref refs/heads/symref refs/heads/target && echo "Deleted branch symref (was refs/heads/target)." >expect && git branch -d symref >actual && - test_path_is_file .git/refs/heads/target && - test_path_is_missing .git/refs/heads/symref && + test_ref_exists refs/heads/target && + test_ref_missing refs/heads/symref && test_cmp expect actual ' test_expect_success 'deleting a dangling symref' ' git symbolic-ref refs/heads/dangling-symref nowhere && - test_path_is_file .git/refs/heads/dangling-symref && + git symbolic-ref --no-recurse refs/heads/dangling-symref && echo "Deleted branch dangling-symref (was nowhere)." >expect && git branch -d dangling-symref >actual && - test_path_is_missing .git/refs/heads/dangling-symref && + test_ref_missing refs/heads/dangling-symref && test_cmp expect actual ' test_expect_success 'deleting a self-referential symref' ' git symbolic-ref refs/heads/self-reference refs/heads/self-reference && - test_path_is_file .git/refs/heads/self-reference && + test_ref_exists refs/heads/self-reference && echo "Deleted branch self-reference (was refs/heads/self-reference)." >expect && git branch -d self-reference >actual && - test_path_is_missing .git/refs/heads/self-reference && + test_ref_missing refs/heads/self-reference && test_cmp expect actual ' @@ -792,18 +832,18 @@ test_expect_success 'renaming a symref is not allowed' ' git symbolic-ref refs/heads/topic refs/heads/main && test_must_fail git branch -m topic new-topic && git symbolic-ref refs/heads/topic && - test_path_is_file .git/refs/heads/main && - test_path_is_missing .git/refs/heads/new-topic + test_ref_exists refs/heads/main && + test_ref_missing refs/heads/new-topic ' -test_expect_success SYMLINKS 'git branch -m u v should fail when the reflog for u is a symlink' ' +test_expect_success SYMLINKS,REFFILES 'git branch -m u v should fail when the reflog for u is a symlink' ' git branch --create-reflog u && mv .git/logs/refs/heads/u real-u && ln -s real-u .git/logs/refs/heads/u && test_must_fail git branch -m u v ' -test_expect_success SYMLINKS 'git branch -m with symlinked .git/refs' ' +test_expect_success SYMLINKS,REFFILES 'git branch -m with symlinked .git/refs' ' test_when_finished "rm -rf subdir" && git init --bare subdir && @@ -908,7 +948,19 @@ test_expect_success 'test deleting branch without config' ' test_expect_success 'deleting currently checked out branch fails' ' git worktree add -b my7 my7 && test_must_fail git -C my7 branch -d my7 && - test_must_fail git branch -d my7 && + test_must_fail git branch -d my7 2>actual && + grep "^error: cannot delete branch .my7. used by worktree at " actual && + rm -r my7 && + git worktree prune +' + +test_expect_success 'deleting in-use branch fails' ' + git worktree add my7 && + test_commit -C my7 bt7 && + git -C my7 bisect start HEAD HEAD~2 && + test_must_fail git -C my7 branch -d my7 && + test_must_fail git branch -d my7 2>actual && + grep "^error: cannot delete branch .my7. used by worktree at " actual && rm -r my7 && git worktree prune ' @@ -978,7 +1030,7 @@ test_expect_success '--set-upstream-to fails on multiple branches' ' test_expect_success '--set-upstream-to fails on detached HEAD' ' git checkout HEAD^{} && test_when_finished git checkout - && - echo "fatal: could not set upstream of HEAD to main when it does not point to any branch." >expect && + echo "fatal: could not set upstream of HEAD to main when it does not point to any branch" >expect && test_must_fail git branch --set-upstream-to main 2>err && test_cmp expect err ' @@ -991,7 +1043,7 @@ test_expect_success '--set-upstream-to fails on a missing dst branch' ' test_expect_success '--set-upstream-to fails on a missing src branch' ' test_must_fail git branch --set-upstream-to does-not-exist main 2>err && - test_i18ngrep "the requested upstream branch '"'"'does-not-exist'"'"' does not exist" err + test_grep "the requested upstream branch '"'"'does-not-exist'"'"' does not exist" err ' test_expect_success '--set-upstream-to fails on a non-ref' ' @@ -1005,7 +1057,7 @@ test_expect_success '--set-upstream-to fails on locked config' ' >.git/config.lock && git branch locked && test_must_fail git branch --set-upstream-to locked 2>err && - test_i18ngrep "could not lock config file .git/config" err + test_grep "could not lock config file .git/config" err ' test_expect_success 'use --set-upstream-to modify HEAD' ' @@ -1026,7 +1078,7 @@ test_expect_success 'use --set-upstream-to modify a particular branch' ' ' test_expect_success '--unset-upstream should fail if given a non-existent branch' ' - echo "fatal: Branch '"'"'i-dont-exist'"'"' has no upstream information" >expect && + echo "fatal: branch '"'"'i-dont-exist'"'"' has no upstream information" >expect && test_must_fail git branch --unset-upstream i-dont-exist 2>err && test_cmp expect err ' @@ -1036,7 +1088,7 @@ test_expect_success '--unset-upstream should fail if config is locked' ' git branch --set-upstream-to locked && >.git/config.lock && test_must_fail git branch --unset-upstream 2>err && - test_i18ngrep "could not lock config file .git/config" err + test_grep "could not lock config file .git/config" err ' test_expect_success 'test --unset-upstream on HEAD' ' @@ -1048,7 +1100,7 @@ test_expect_success 'test --unset-upstream on HEAD' ' test_must_fail git config branch.main.remote && test_must_fail git config branch.main.merge && # fail for a branch without upstream set - echo "fatal: Branch '"'"'main'"'"' has no upstream information" >expect && + echo "fatal: branch '"'"'main'"'"' has no upstream information" >expect && test_must_fail git branch --unset-upstream 2>err && test_cmp expect err ' @@ -1062,7 +1114,7 @@ test_expect_success '--unset-upstream should fail on multiple branches' ' test_expect_success '--unset-upstream should fail on detached HEAD' ' git checkout HEAD^{} && test_when_finished git checkout - && - echo "fatal: could not unset upstream of HEAD when it does not point to any branch." >expect && + echo "fatal: could not unset upstream of HEAD when it does not point to any branch" >expect && test_must_fail git branch --unset-upstream 2>err && test_cmp expect err ' @@ -1091,14 +1143,14 @@ test_expect_success '--set-upstream-to notices an error to set branch as own ups # Keep this test last, as it changes the current branch cat >expect <<EOF -$ZERO_OID $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 branch: Created from main +$HEAD refs/heads/g/h/i@{0}: branch: Created from main EOF test_expect_success 'git checkout -b g/h/i -l should create a branch and a log' ' GIT_COMMITTER_DATE="2005-05-26 23:30" \ git checkout -b g/h/i -l main && - test_path_is_file .git/refs/heads/g/h/i && - test_path_is_file .git/logs/refs/heads/g/h/i && - test_cmp expect .git/logs/refs/heads/g/h/i + test_ref_exists refs/heads/g/h/i && + git reflog show --no-abbrev-commit refs/heads/g/h/i >actual && + test_cmp expect actual ' test_expect_success 'checkout -b makes reflog by default' ' @@ -1472,7 +1524,7 @@ test_expect_success '--list during rebase' ' set_fake_editor && git rebase -i HEAD~2 && git branch --list >actual && - test_i18ngrep "rebasing main" actual + test_grep "rebasing main" actual ' test_expect_success '--list during rebase from detached HEAD' ' @@ -1484,7 +1536,7 @@ test_expect_success '--list during rebase from detached HEAD' ' set_fake_editor && git rebase -i HEAD~2 && git branch --list >actual && - test_i18ngrep "rebasing detached HEAD $oid" actual + test_grep "rebasing detached HEAD $oid" actual ' test_expect_success 'tracking with unexpected .fetch refspec' ' @@ -1524,9 +1576,10 @@ test_expect_success 'tracking with unexpected .fetch refspec' ' test_expect_success 'configured committerdate sort' ' git init -b main sort && + test_config -C sort branch.sort "committerdate" && + ( cd sort && - git config branch.sort committerdate && test_commit initial && git checkout -b a && test_commit a && @@ -1546,9 +1599,10 @@ test_expect_success 'configured committerdate sort' ' ' test_expect_success 'option override configured sort' ' + test_config -C sort branch.sort "committerdate" && + ( cd sort && - git config branch.sort committerdate && git branch --sort=refname >actual && cat >expect <<-\EOF && a @@ -1560,10 +1614,70 @@ test_expect_success 'option override configured sort' ' ) ' +test_expect_success '--no-sort cancels config sort keys' ' + test_config -C sort branch.sort "-refname" && + + ( + cd sort && + + # objecttype is identical for all of them, so sort falls back on + # default (ascending refname) + git branch \ + --no-sort \ + --sort="objecttype" >actual && + cat >expect <<-\EOF && + a + * b + c + main + EOF + test_cmp expect actual + ) + +' + +test_expect_success '--no-sort cancels command line sort keys' ' + ( + cd sort && + + # objecttype is identical for all of them, so sort falls back on + # default (ascending refname) + git branch \ + --sort="-refname" \ + --no-sort \ + --sort="objecttype" >actual && + cat >expect <<-\EOF && + a + * b + c + main + EOF + test_cmp expect actual + ) +' + +test_expect_success '--no-sort without subsequent --sort prints expected branches' ' + ( + cd sort && + + # Sort the results with `sort` for a consistent comparison + # against expected + git branch --no-sort | sort >actual && + cat >expect <<-\EOF && + a + c + main + * b + EOF + test_cmp expect actual + ) +' + test_expect_success 'invalid sort parameter in configuration' ' + test_config -C sort branch.sort "v:notvalid" && + ( cd sort && - git config branch.sort "v:notvalid" && # this works in the "listing" mode, so bad sort key # is a dying offence. diff --git a/t/t3202-show-branch.sh b/t/t3202-show-branch.sh index ea7cfd1951..6a98b2df76 100755 --- a/t/t3202-show-branch.sh +++ b/t/t3202-show-branch.sh @@ -10,7 +10,7 @@ GIT_TEST_DATE_NOW=1251660000; export GIT_TEST_DATE_NOW test_expect_success 'error descriptions on empty repository' ' current=$(git branch --show-current) && cat >expect <<-EOF && - error: No commit on branch '\''$current'\'' yet. + error: no commit on branch '\''$current'\'' yet EOF test_must_fail git branch --edit-description 2>actual && test_cmp expect actual && @@ -21,7 +21,7 @@ test_expect_success 'error descriptions on empty repository' ' test_expect_success 'fatal descriptions on empty repository' ' current=$(git branch --show-current) && cat >expect <<-EOF && - fatal: No commit on branch '\''$current'\'' yet. + fatal: no commit on branch '\''$current'\'' yet EOF test_must_fail git branch --set-upstream-to=non-existent 2>actual && test_cmp expect actual && @@ -119,6 +119,22 @@ test_expect_success 'show branch --remotes' ' test_must_be_empty actual.out ' +test_expect_success 'show-branch --sparse' ' + test_when_finished "git checkout branch10 && git branch -D branchA" && + git checkout -b branchA branch10 && + git merge -s ours -m "merge 1 and 10 to make A" branch1 && + git commit --allow-empty -m "another" && + + git show-branch --sparse >out && + grep "merge 1 and 10 to make A" out && + + git show-branch >out && + ! grep "merge 1 and 10 to make A" out && + + git show-branch --no-sparse >out && + ! grep "merge 1 and 10 to make A" out +' + test_expect_success 'setup show branch --list' ' sed "s/^> //" >expect <<-\EOF > [branch1] branch1 @@ -197,9 +213,18 @@ done <<\EOF --reflog --current EOF +# unnegatable options +for opt in topo-order date-order reflog +do + test_expect_success "show-branch --no-$opt (should fail)" ' + test_must_fail git show-branch --no-$opt 2>err && + grep "unknown option .no-$opt." err + ' +done + test_expect_success 'error descriptions on non-existent branch' ' cat >expect <<-EOF && - error: No branch named '\''non-existent'\'.' + error: no branch named '\''non-existent'\'' EOF test_must_fail git branch --edit-description non-existent 2>actual && test_cmp expect actual @@ -213,7 +238,7 @@ test_expect_success 'fatal descriptions on non-existent branch' ' test_cmp expect actual && cat >expect <<-EOF && - fatal: No branch named '\''non-existent'\''. + fatal: no branch named '\''non-existent'\'' EOF test_must_fail git branch -c non-existent new-branch 2>actual && test_cmp expect actual && @@ -221,4 +246,22 @@ test_expect_success 'fatal descriptions on non-existent branch' ' test_cmp expect actual ' +test_expect_success 'error descriptions on orphan branch' ' + test_when_finished git worktree remove -f wt && + git worktree add wt --detach && + git -C wt checkout --orphan orphan-branch && + test_branch_op_in_wt() { + test_orphan_error() { + test_must_fail git $* 2>actual && + test_grep "no commit on branch .orphan-branch. yet$" actual + } && + test_orphan_error -C wt branch $1 $2 && # implicit branch + test_orphan_error -C wt branch $1 orphan-branch $2 && # explicit branch + test_orphan_error branch $1 orphan-branch $2 # different worktree + } && + test_branch_op_in_wt --edit-description && + test_branch_op_in_wt --set-upstream-to=ne && + test_branch_op_in_wt -c new-branch +' + test_done diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh index d34d77f893..758963b189 100755 --- a/t/t3203-branch-output.sh +++ b/t/t3203-branch-output.sh @@ -55,9 +55,17 @@ cat >expect <<'EOF' EOF test_expect_success 'git branch -r shows remote branches' ' git branch -r >actual && + test_cmp expect actual && + + git branch --remotes >actual && test_cmp expect actual ' +test_expect_success 'git branch --no-remotes is rejected' ' + test_must_fail git branch --no-remotes 2>err && + grep "unknown option .no-remotes." err +' + cat >expect <<'EOF' branch-one branch-two @@ -68,9 +76,17 @@ cat >expect <<'EOF' EOF test_expect_success 'git branch -a shows local and remote branches' ' git branch -a >actual && + test_cmp expect actual && + + git branch --all >actual && test_cmp expect actual ' +test_expect_success 'git branch --no-all is rejected' ' + test_must_fail git branch --no-all 2>err && + grep "unknown option .no-all." err +' + cat >expect <<'EOF' two one @@ -337,10 +353,48 @@ test_expect_success 'git branch --format option' ' test_cmp expect actual ' +test_expect_success 'git branch --format with ahead-behind' ' + cat >expect <<-\EOF && + (HEAD detached from fromtag) 0 0 + refs/heads/ambiguous 0 0 + refs/heads/branch-one 1 0 + refs/heads/branch-two 0 0 + refs/heads/main 1 0 + refs/heads/ref-to-branch 1 0 + refs/heads/ref-to-remote 1 0 + EOF + git branch --format="%(refname) %(ahead-behind:HEAD)" >actual && + test_cmp expect actual +' + test_expect_success 'git branch with --format=%(rest) must fail' ' test_must_fail git branch --format="%(rest)" >actual ' +test_expect_success 'git branch --format --omit-empty' ' + cat >expect <<-\EOF && + Refname is (HEAD detached from fromtag) + Refname is refs/heads/ambiguous + Refname is refs/heads/branch-one + Refname is refs/heads/branch-two + + Refname is refs/heads/ref-to-branch + Refname is refs/heads/ref-to-remote + EOF + git branch --format="%(if:notequals=refs/heads/main)%(refname)%(then)Refname is %(refname)%(end)" >actual && + test_cmp expect actual && + cat >expect <<-\EOF && + Refname is (HEAD detached from fromtag) + Refname is refs/heads/ambiguous + Refname is refs/heads/branch-one + Refname is refs/heads/branch-two + Refname is refs/heads/ref-to-branch + Refname is refs/heads/ref-to-remote + EOF + git branch --omit-empty --format="%(if:notequals=refs/heads/main)%(refname)%(then)Refname is %(refname)%(end)" >actual && + test_cmp expect actual +' + test_expect_success 'worktree colors correct' ' cat >expect <<-EOF && * <GREEN>(HEAD detached from fromtag)<RESET> diff --git a/t/t3204-branch-name-interpretation.sh b/t/t3204-branch-name-interpretation.sh index 3399344f25..594e3e43e1 100755 --- a/t/t3204-branch-name-interpretation.sh +++ b/t/t3204-branch-name-interpretation.sh @@ -9,6 +9,7 @@ This script aims to check the behavior of those corner cases. GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh expect_branch() { diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh index b5f4d6a653..7b05bf3961 100755 --- a/t/t3206-range-diff.sh +++ b/t/t3206-range-diff.sh @@ -195,7 +195,7 @@ test_expect_success 'A^! and A^-<n> (unmodified)' ' test_expect_success 'A^{/..} is not mistaken for a range' ' test_must_fail git range-diff topic^.. topic^{/..} -- 2>error && - test_i18ngrep "not a commit range" error + test_grep "not a commit range" error ' test_expect_success 'trivial reordering' ' @@ -537,7 +537,7 @@ do main..unmodified >actual && test_when_finished "rm 000?-*" && test_line_count = 5 actual && - test_i18ngrep "^Range-diff:$" 0000-* && + test_grep "^Range-diff:$" 0000-* && grep "= 1: .* s/5/A" 0000-* && grep "= 2: .* s/4/A" 0000-* && grep "= 3: .* s/11/B" 0000-* && @@ -549,7 +549,7 @@ test_expect_success 'format-patch --range-diff as commentary' ' git format-patch --range-diff=HEAD~1 HEAD~1 >actual && test_when_finished "rm 0001-*" && test_line_count = 1 actual && - test_i18ngrep "^Range-diff:$" 0001-* && + test_grep "^Range-diff:$" 0001-* && grep "> 1: .* new message" 0001-* ' @@ -557,7 +557,7 @@ test_expect_success 'format-patch --range-diff reroll-count with a non-integer' git format-patch --range-diff=HEAD~1 -v2.9 HEAD~1 >actual && test_when_finished "rm v2.9-0001-*" && test_line_count = 1 actual && - test_i18ngrep "^Range-diff:$" v2.9-0001-* && + test_grep "^Range-diff:$" v2.9-0001-* && grep "> 1: .* new message" v2.9-0001-* ' @@ -565,7 +565,7 @@ test_expect_success 'format-patch --range-diff reroll-count with a integer' ' git format-patch --range-diff=HEAD~1 -v2 HEAD~1 >actual && test_when_finished "rm v2-0001-*" && test_line_count = 1 actual && - test_i18ngrep "^Range-diff ..* v1:$" v2-0001-* && + test_grep "^Range-diff ..* v1:$" v2-0001-* && grep "> 1: .* new message" v2-0001-* ' @@ -573,7 +573,7 @@ test_expect_success 'format-patch --range-diff with v0' ' git format-patch --range-diff=HEAD~1 -v0 HEAD~1 >actual && test_when_finished "rm v0-0001-*" && test_line_count = 1 actual && - test_i18ngrep "^Range-diff:$" v0-0001-* && + test_grep "^Range-diff:$" v0-0001-* && grep "> 1: .* new message" v0-0001-* ' @@ -662,6 +662,20 @@ test_expect_success 'range-diff with multiple --notes' ' test_cmp expect actual ' +# `range-diff` should act like `log` with regards to notes +test_expect_success 'range-diff with --notes=custom does not show default notes' ' + git notes add -m "topic note" topic && + git notes add -m "unmodified note" unmodified && + git notes --ref=custom add -m "topic note" topic && + git notes --ref=custom add -m "unmodified note" unmodified && + test_when_finished git notes remove topic unmodified && + test_when_finished git notes --ref=custom remove topic unmodified && + git range-diff --notes=custom main..topic main..unmodified \ + >actual && + ! grep "## Notes ##" actual && + grep "## Notes (custom) ##" actual +' + test_expect_success 'format-patch --range-diff does not compare notes by default' ' git notes add -m "topic note" topic && git notes add -m "unmodified note" unmodified && @@ -670,7 +684,7 @@ test_expect_success 'format-patch --range-diff does not compare notes by default main..unmodified >actual && test_when_finished "rm 000?-*" && test_line_count = 5 actual && - test_i18ngrep "^Range-diff:$" 0000-* && + test_grep "^Range-diff:$" 0000-* && grep "= 1: .* s/5/A" 0000-* && grep "= 2: .* s/4/A" 0000-* && grep "= 3: .* s/11/B" 0000-* && @@ -679,6 +693,20 @@ test_expect_success 'format-patch --range-diff does not compare notes by default ! grep "note" 0000-* ' +test_expect_success 'format-patch --notes=custom --range-diff only compares custom notes' ' + git notes add -m "topic note" topic && + git notes --ref=custom add -m "topic note (custom)" topic && + git notes add -m "unmodified note" unmodified && + git notes --ref=custom add -m "unmodified note (custom)" unmodified && + test_when_finished git notes remove topic unmodified && + test_when_finished git notes --ref=custom remove topic unmodified && + git format-patch --notes=custom --cover-letter --range-diff=$prev \ + main..unmodified >actual && + test_when_finished "rm 000?-*" && + grep "## Notes (custom) ##" 0000-* && + ! grep "## Notes ##" 0000-* +' + test_expect_success 'format-patch --range-diff with --no-notes' ' git notes add -m "topic note" topic && git notes add -m "unmodified note" unmodified && @@ -687,7 +715,7 @@ test_expect_success 'format-patch --range-diff with --no-notes' ' main..unmodified >actual && test_when_finished "rm 000?-*" && test_line_count = 5 actual && - test_i18ngrep "^Range-diff:$" 0000-* && + test_grep "^Range-diff:$" 0000-* && grep "= 1: .* s/5/A" 0000-* && grep "= 2: .* s/4/A" 0000-* && grep "= 3: .* s/11/B" 0000-* && @@ -704,7 +732,7 @@ test_expect_success 'format-patch --range-diff with --notes' ' main..unmodified >actual && test_when_finished "rm 000?-*" && test_line_count = 5 actual && - test_i18ngrep "^Range-diff:$" 0000-* && + test_grep "^Range-diff:$" 0000-* && grep "= 1: .* s/5/A" 0000-* && grep "= 2: .* s/4/A" 0000-* && grep "= 3: .* s/11/B" 0000-* && @@ -733,7 +761,7 @@ test_expect_success 'format-patch --range-diff with format.notes config' ' main..unmodified >actual && test_when_finished "rm 000?-*" && test_line_count = 5 actual && - test_i18ngrep "^Range-diff:$" 0000-* && + test_grep "^Range-diff:$" 0000-* && grep "= 1: .* s/5/A" 0000-* && grep "= 2: .* s/4/A" 0000-* && grep "= 3: .* s/11/B" 0000-* && @@ -764,7 +792,7 @@ test_expect_success 'format-patch --range-diff with multiple notes' ' main..unmodified >actual && test_when_finished "rm 000?-*" && test_line_count = 5 actual && - test_i18ngrep "^Range-diff:$" 0000-* && + test_grep "^Range-diff:$" 0000-* && grep "= 1: .* s/5/A" 0000-* && grep "= 2: .* s/4/A" 0000-* && grep "= 3: .* s/11/B" 0000-* && diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh index 07a0ff93de..7f4e98db7d 100755 --- a/t/t3210-pack-refs.sh +++ b/t/t3210-pack-refs.sh @@ -19,101 +19,138 @@ test_expect_success 'enable reflogs' ' git config core.logallrefupdates true ' -test_expect_success \ - 'prepare a trivial repository' \ - 'echo Hello > A && - git update-index --add A && - git commit -m "Initial commit." && - HEAD=$(git rev-parse --verify HEAD)' +test_expect_success 'prepare a trivial repository' ' + echo Hello > A && + git update-index --add A && + git commit -m "Initial commit." && + HEAD=$(git rev-parse --verify HEAD) +' SHA1= -test_expect_success \ - 'see if git show-ref works as expected' \ - 'git branch a && - SHA1=$(cat .git/refs/heads/a) && - echo "$SHA1 refs/heads/a" >expect && - git show-ref a >result && - test_cmp expect result' - -test_expect_success \ - 'see if a branch still exists when packed' \ - 'git branch b && - git pack-refs --all && - rm -f .git/refs/heads/b && - echo "$SHA1 refs/heads/b" >expect && - git show-ref b >result && - test_cmp expect result' +test_expect_success 'see if git show-ref works as expected' ' + git branch a && + SHA1=$(cat .git/refs/heads/a) && + echo "$SHA1 refs/heads/a" >expect && + git show-ref a >result && + test_cmp expect result +' + +test_expect_success 'see if a branch still exists when packed' ' + git branch b && + git pack-refs --all && + rm -f .git/refs/heads/b && + echo "$SHA1 refs/heads/b" >expect && + git show-ref b >result && + test_cmp expect result +' test_expect_success 'git branch c/d should barf if branch c exists' ' - git branch c && - git pack-refs --all && - rm -f .git/refs/heads/c && - test_must_fail git branch c/d + git branch c && + git pack-refs --all && + rm -f .git/refs/heads/c && + test_must_fail git branch c/d ' -test_expect_success \ - 'see if a branch still exists after git pack-refs --prune' \ - 'git branch e && - git pack-refs --all --prune && - echo "$SHA1 refs/heads/e" >expect && - git show-ref e >result && - test_cmp expect result' +test_expect_success 'see if a branch still exists after git pack-refs --prune' ' + git branch e && + git pack-refs --all --prune && + echo "$SHA1 refs/heads/e" >expect && + git show-ref e >result && + test_cmp expect result +' test_expect_success 'see if git pack-refs --prune remove ref files' ' - git branch f && - git pack-refs --all --prune && - ! test -f .git/refs/heads/f + git branch f && + git pack-refs --all --prune && + ! test -f .git/refs/heads/f ' test_expect_success 'see if git pack-refs --prune removes empty dirs' ' - git branch r/s/t && - git pack-refs --all --prune && - ! test -e .git/refs/heads/r + git branch r/s/t && + git pack-refs --all --prune && + ! test -e .git/refs/heads/r ' -test_expect_success \ - 'git branch g should work when git branch g/h has been deleted' \ - 'git branch g/h && - git pack-refs --all --prune && - git branch -d g/h && - git branch g && - git pack-refs --all && - git branch -d g' +test_expect_success 'git branch g should work when git branch g/h has been deleted' ' + git branch g/h && + git pack-refs --all --prune && + git branch -d g/h && + git branch g && + git pack-refs --all && + git branch -d g +' test_expect_success 'git branch i/j/k should barf if branch i exists' ' - git branch i && - git pack-refs --all --prune && - test_must_fail git branch i/j/k + git branch i && + git pack-refs --all --prune && + test_must_fail git branch i/j/k +' + +test_expect_success 'test git branch k after branch k/l/m and k/lm have been deleted' ' + git branch k/l && + git branch k/lm && + git branch -d k/l && + git branch k/l/m && + git branch -d k/l/m && + git branch -d k/lm && + git branch k ' -test_expect_success \ - 'test git branch k after branch k/l/m and k/lm have been deleted' \ - 'git branch k/l && - git branch k/lm && - git branch -d k/l && - git branch k/l/m && - git branch -d k/l/m && - git branch -d k/lm && - git branch k' - -test_expect_success \ - 'test git branch n after some branch deletion and pruning' \ - 'git branch n/o && - git branch n/op && - git branch -d n/o && - git branch n/o/p && - git branch -d n/op && - git pack-refs --all --prune && - git branch -d n/o/p && - git branch n' - -test_expect_success \ - 'see if up-to-date packed refs are preserved' \ - 'git branch q && - git pack-refs --all --prune && - git update-ref refs/heads/q refs/heads/q && - ! test -f .git/refs/heads/q' +test_expect_success 'test git branch n after some branch deletion and pruning' ' + git branch n/o && + git branch n/op && + git branch -d n/o && + git branch n/o/p && + git branch -d n/op && + git pack-refs --all --prune && + git branch -d n/o/p && + git branch n +' + +test_expect_success 'test excluded refs are not packed' ' + git branch dont_pack1 && + git branch dont_pack2 && + git branch pack_this && + git pack-refs --all --exclude "refs/heads/dont_pack*" && + test -f .git/refs/heads/dont_pack1 && + test -f .git/refs/heads/dont_pack2 && + ! test -f .git/refs/heads/pack_this' + +test_expect_success 'test --no-exclude refs clears excluded refs' ' + git branch dont_pack3 && + git branch dont_pack4 && + git pack-refs --all --exclude "refs/heads/dont_pack*" --no-exclude && + ! test -f .git/refs/heads/dont_pack3 && + ! test -f .git/refs/heads/dont_pack4' + +test_expect_success 'test only included refs are packed' ' + git branch pack_this1 && + git branch pack_this2 && + git tag dont_pack5 && + git pack-refs --include "refs/heads/pack_this*" && + test -f .git/refs/tags/dont_pack5 && + ! test -f .git/refs/heads/pack_this1 && + ! test -f .git/refs/heads/pack_this2' + +test_expect_success 'test --no-include refs clears included refs' ' + git branch pack1 && + git branch pack2 && + git pack-refs --include "refs/heads/pack*" --no-include && + test -f .git/refs/heads/pack1 && + test -f .git/refs/heads/pack2' + +test_expect_success 'test --exclude takes precedence over --include' ' + git branch dont_pack5 && + git pack-refs --include "refs/heads/pack*" --exclude "refs/heads/pack*" && + test -f .git/refs/heads/dont_pack5' + +test_expect_success 'see if up-to-date packed refs are preserved' ' + git branch q && + git pack-refs --all --prune && + git update-ref refs/heads/q refs/heads/q && + ! test -f .git/refs/heads/q +' test_expect_success 'pack, prune and repack' ' git tag foo && @@ -190,7 +227,7 @@ test_expect_success 'notice d/f conflict with existing directory' ' test_expect_success 'existing directory reports concrete ref' ' test_must_fail git branch foo 2>stderr && - test_i18ngrep refs/heads/foo/bar/baz stderr + test_grep refs/heads/foo/bar/baz stderr ' test_expect_success 'notice d/f conflict with existing ref' ' diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh index 3288aaec7d..cf23c06c09 100755 --- a/t/t3301-notes.sh +++ b/t/t3301-notes.sh @@ -362,6 +362,7 @@ test_expect_success 'do not create empty note with -m ""' ' ' test_expect_success 'create note with combination of -m and -F' ' + test_when_finished git notes remove HEAD && cat >expect-combine_m_and_F <<-EOF && foo @@ -380,6 +381,41 @@ test_expect_success 'create note with combination of -m and -F' ' test_cmp expect-combine_m_and_F actual ' +test_expect_success 'create note with combination of -m and -F and --separator' ' + test_when_finished git notes remove HEAD && + cat >expect-combine_m_and_F <<-\EOF && + foo + ------- + xyzzy + ------- + bar + ------- + zyxxy + ------- + baz + EOF + echo "xyzzy" >note_a && + echo "zyxxy" >note_b && + git notes add -m "foo" -F note_a -m "bar" -F note_b -m "baz" --separator="-------" && + git notes show >actual && + test_cmp expect-combine_m_and_F actual +' + +test_expect_success 'create note with combination of -m and -F and --no-separator' ' + cat >expect-combine_m_and_F <<-\EOF && + foo + xyzzy + bar + zyxxy + baz + EOF + echo "xyzzy" >note_a && + echo "zyxxy" >note_b && + git notes add -m "foo" -F note_a -m "bar" -F note_b -m "baz" --no-separator && + git notes show >actual && + test_cmp expect-combine_m_and_F actual +' + test_expect_success 'remove note with "git notes remove"' ' git notes remove HEAD^ && git notes remove && @@ -521,6 +557,112 @@ test_expect_success 'listing non-existing notes fails' ' test_must_be_empty actual ' +test_expect_success 'append: specify a separator with an empty arg' ' + test_when_finished git notes remove HEAD && + cat >expect <<-\EOF && + notes-1 + + notes-2 + EOF + + git notes add -m "notes-1" && + git notes append --separator="" -m "notes-2" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'append: specify a separator without arg' ' + test_when_finished git notes remove HEAD && + cat >expect <<-\EOF && + notes-1 + + notes-2 + EOF + + git notes add -m "notes-1" && + git notes append --separator -m "notes-2" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'append: specify as --no-separator' ' + test_when_finished git notes remove HEAD && + cat >expect <<-\EOF && + notes-1 + notes-2 + EOF + + git notes add -m "notes-1" && + git notes append --no-separator -m "notes-2" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'append: specify separator with line break' ' + test_when_finished git notes remove HEAD && + cat >expect <<-\EOF && + notes-1 + ------- + notes-2 + EOF + + git notes add -m "notes-1" && + git notes append --separator="-------$LF" -m "notes-2" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'append: specify separator without line break' ' + test_when_finished git notes remove HEAD && + cat >expect <<-\EOF && + notes-1 + ------- + notes-2 + EOF + + git notes add -m "notes-1" && + git notes append --separator="-------" -m "notes-2" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'append: specify separator with multiple messages' ' + test_when_finished git notes remove HEAD && + cat >expect <<-\EOF && + notes-1 + ------- + notes-2 + ------- + notes-3 + EOF + + git notes add -m "notes-1" && + git notes append --separator="-------" -m "notes-2" -m "notes-3" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'append note with combination of -m and -F and --separator' ' + test_when_finished git notes remove HEAD && + cat >expect-combine_m_and_F <<-\EOF && + m-notes-1 + ------- + f-notes-1 + ------- + m-notes-2 + ------- + f-notes-2 + ------- + m-notes-3 + EOF + + echo "f-notes-1" >note_a && + echo "f-notes-2" >note_b && + git notes append -m "m-notes-1" -F note_a -m "m-notes-2" -F note_b -m "m-notes-3" --separator="-------" && + git notes show >actual && + test_cmp expect-combine_m_and_F actual +' + test_expect_success 'append to existing note with "git notes append"' ' cat >expect <<-EOF && Initial set of notes @@ -818,6 +960,33 @@ test_expect_success 'create note from blob with "git notes add -C" reuses blob i test_cmp blob actual ' +test_expect_success 'create note from blob with "-C", also specify "-m", "-F" and "--separator"' ' + # 8th will be reuseed in following tests, so rollback when the test is done + test_when_finished "git notes remove && git notes add -C $(cat blob)" && + commit=$(git rev-parse HEAD) && + cat >expect <<-EOF && + commit $commit + Author: A U Thor <author@example.com> + Date: Thu Apr 7 15:20:13 2005 -0700 + + ${indent}8th + + Notes: + ${indent}This is a blob object + ${indent}------- + ${indent}This is created by -m + ${indent}------- + ${indent}This is created by -F + EOF + + git notes remove && + echo "This is a blob object" | git hash-object -w --stdin >blob && + echo "This is created by -F" >note_a && + git notes add -C $(cat blob) -m "This is created by -m" -F note_a --separator="-------" && + git log -1 >actual && + test_cmp expect actual +' + test_expect_success 'create note from other note with "git notes add -c"' ' test_commit 9th && commit=$(git rev-parse HEAD) && @@ -1300,9 +1469,9 @@ test_expect_success 'GIT_NOTES_REWRITE_REF overrides config' ' test_expect_success 'git notes copy diagnoses too many or too few arguments' ' test_must_fail git notes copy 2>error && - test_i18ngrep "too few arguments" error && + test_grep "too few arguments" error && test_must_fail git notes copy one two three 2>error && - test_i18ngrep "too many arguments" error + test_grep "too many arguments" error ' test_expect_success 'git notes get-ref expands refs/heads/main to refs/notes/refs/heads/main' ' diff --git a/t/t3309-notes-merge-auto-resolve.sh b/t/t3309-notes-merge-auto-resolve.sh index 141d3e4ca4..9bd5dbf341 100755 --- a/t/t3309-notes-merge-auto-resolve.sh +++ b/t/t3309-notes-merge-auto-resolve.sh @@ -360,7 +360,12 @@ test_expect_success 'merge z into y with invalid strategy => Fail/No changes' ' test_expect_success 'merge z into y with invalid configuration option => Fail/No changes' ' git config core.notesRef refs/notes/y && - test_must_fail git -c notes.mergeStrategy="foo" notes merge z && + cat >expect <<-\EOF && + error: unknown notes merge strategy foo + fatal: unable to parse '\''notes.mergeStrategy'\'' from command-line config + EOF + test_must_fail git -c notes.mergeStrategy="foo" notes merge z 2>actual && + test_cmp expect actual && # Verify no changes (y) verify_notes y y ' diff --git a/t/t3310-notes-merge-manual-resolve.sh b/t/t3310-notes-merge-manual-resolve.sh index d3d72e25fe..597df5ebc0 100755 --- a/t/t3310-notes-merge-manual-resolve.sh +++ b/t/t3310-notes-merge-manual-resolve.sh @@ -216,7 +216,7 @@ test_expect_success 'merge z into m (== y) with default ("manual") resolver => C git config core.notesRef refs/notes/m && test_must_fail git notes merge z >output 2>&1 && # Output should point to where to resolve conflicts - test_i18ngrep "\\.git/NOTES_MERGE_WORKTREE" output && + test_grep "\\.git/NOTES_MERGE_WORKTREE" output && # Inspect merge conflicts ls .git/NOTES_MERGE_WORKTREE >output_conflicts && test_cmp expect_conflicts output_conflicts && @@ -263,7 +263,7 @@ test_expect_success 'cannot do merge w/conflicts when previous merge is unfinish test -d .git/NOTES_MERGE_WORKTREE && test_must_fail git notes merge z >output 2>&1 && # Output should indicate what is wrong - test_i18ngrep -q "\\.git/NOTES_MERGE_\\* exists" output + test_grep -q "\\.git/NOTES_MERGE_\\* exists" output ' # Setup non-conflicting merge between x and new notes ref w @@ -417,7 +417,7 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol git config core.notesRef refs/notes/m && test_must_fail git notes merge z >output 2>&1 && # Output should point to where to resolve conflicts - test_i18ngrep "\\.git/NOTES_MERGE_WORKTREE" output && + test_grep "\\.git/NOTES_MERGE_WORKTREE" output && # Inspect merge conflicts ls .git/NOTES_MERGE_WORKTREE >output_conflicts && test_cmp expect_conflicts output_conflicts && @@ -449,7 +449,7 @@ git rev-parse refs/notes/z > pre_merge_z test_expect_success 'redo merge of z into m (== y) with default ("manual") resolver => Conflicting 3-way merge' ' test_must_fail git notes merge z >output 2>&1 && # Output should point to where to resolve conflicts - test_i18ngrep "\\.git/NOTES_MERGE_WORKTREE" output && + test_grep "\\.git/NOTES_MERGE_WORKTREE" output && # Inspect merge conflicts ls .git/NOTES_MERGE_WORKTREE >output_conflicts && test_cmp expect_conflicts output_conflicts && @@ -528,7 +528,7 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol git update-ref refs/notes/m refs/notes/y && test_must_fail git notes merge z >output 2>&1 && # Output should point to where to resolve conflicts - test_i18ngrep "\\.git/NOTES_MERGE_WORKTREE" output && + test_grep "\\.git/NOTES_MERGE_WORKTREE" output && # Inspect merge conflicts ls .git/NOTES_MERGE_WORKTREE >output_conflicts && test_cmp expect_conflicts output_conflicts && @@ -561,9 +561,9 @@ y and z notes on 4th commit EOF # Fail to finalize merge test_must_fail git notes merge --commit >output 2>&1 && - # .git/NOTES_MERGE_* must remain - test -f .git/NOTES_MERGE_PARTIAL && - test -f .git/NOTES_MERGE_REF && + # NOTES_MERGE_* refs and .git/NOTES_MERGE_* state files must remain + git rev-parse --verify NOTES_MERGE_PARTIAL && + git rev-parse --verify NOTES_MERGE_REF && test -f .git/NOTES_MERGE_WORKTREE/$commit_sha1 && test -f .git/NOTES_MERGE_WORKTREE/$commit_sha2 && test -f .git/NOTES_MERGE_WORKTREE/$commit_sha3 && @@ -573,9 +573,9 @@ EOF test "$(git rev-parse refs/notes/y)" = "$(git rev-parse NOTES_MERGE_PARTIAL^1)" && test "$(git rev-parse refs/notes/m)" != "$(git rev-parse NOTES_MERGE_PARTIAL^1)" && # Mention refs/notes/m, and its current and expected value in output - test_i18ngrep -q "refs/notes/m" output && - test_i18ngrep -q "$(git rev-parse refs/notes/m)" output && - test_i18ngrep -q "$(git rev-parse NOTES_MERGE_PARTIAL^1)" output && + test_grep -q "refs/notes/m" output && + test_grep -q "$(git rev-parse refs/notes/m)" output && + test_grep -q "$(git rev-parse NOTES_MERGE_PARTIAL^1)" output && # Verify that other notes refs has not changed (w, x, y and z) verify_notes w && verify_notes x && diff --git a/t/t3320-notes-merge-worktrees.sh b/t/t3320-notes-merge-worktrees.sh index bff0aea550..0fd33280cf 100755 --- a/t/t3320-notes-merge-worktrees.sh +++ b/t/t3320-notes-merge-worktrees.sh @@ -57,7 +57,7 @@ test_expect_success 'merge z into y while mid-merge in another workdir fails' ' cd worktree && git config core.notesRef refs/notes/y && test_must_fail git notes merge z 2>err && - test_i18ngrep "a notes merge into refs/notes/y is already in-progress at" err + test_grep "a notes merge into refs/notes/y is already in-progress at" err ) && test_must_fail git -C worktree symbolic-ref NOTES_MERGE_REF ' @@ -67,7 +67,7 @@ test_expect_success 'merge z into x while mid-merge on y succeeds' ' cd worktree2 && git config core.notesRef refs/notes/x && test_must_fail git notes merge z >out 2>&1 && - test_i18ngrep "Automatic notes merge failed" out && + test_grep "Automatic notes merge failed" out && grep -v "A notes merge into refs/notes/x is already in-progress in" out ) && echo "refs/notes/x" >expect && diff --git a/t/t3321-notes-stripspace.sh b/t/t3321-notes-stripspace.sh new file mode 100755 index 0000000000..088a852dd4 --- /dev/null +++ b/t/t3321-notes-stripspace.sh @@ -0,0 +1,578 @@ +#!/bin/sh +# +# Copyright (c) 2023 Teng Long +# + +test_description='Test commit notes with stripspace behavior' + +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh + +MULTI_LF="$LF$LF$LF" +write_script fake_editor <<\EOF +echo "$MSG" >"$1" +echo "$MSG" >&2 +EOF +GIT_EDITOR=./fake_editor +export GIT_EDITOR + +test_expect_success 'setup the commit' ' + test_commit 1st +' + +test_expect_success 'add note by editor' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + first-line + + second-line + EOF + + MSG="${LF}first-line${MULTI_LF}second-line${LF}" git notes add && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'add note by specifying single "-m", "--stripspace" is the default behavior' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + first-line + + second-line + EOF + + git notes add -m "${LF}first-line${MULTI_LF}second-line${LF}" && + git notes show >actual && + test_cmp expect actual && + git notes remove && + git notes add --stripspace -m "${LF}first-line${MULTI_LF}second-line${LF}" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'add note by specifying single "-m" and "--no-stripspace" ' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + ${LF}first-line${MULTI_LF}second-line + EOF + + git notes add --no-stripspace \ + -m "${LF}first-line${MULTI_LF}second-line${LF}" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'add note by specifying multiple "-m", "--stripspace" is the default behavior' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + first-line + + second-line + EOF + + git notes add -m "${LF}" \ + -m "first-line" \ + -m "${MULTI_LF}" \ + -m "second-line" \ + -m "${LF}" && + git notes show >actual && + test_cmp expect actual && + git notes remove && + git notes add --stripspace -m "${LF}" \ + -m "first-line" \ + -m "${MULTI_LF}" \ + -m "second-line" \ + -m "${LF}" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'add notes by specifying multiple "-m" and "--no-stripspace"' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + ${LF} + first-line + ${MULTI_LF} + second-line${LF} + EOF + + git notes add --no-stripspace \ + -m "${LF}" \ + -m "first-line" \ + -m "${MULTI_LF}" \ + -m "second-line" \ + -m "${LF}" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'add note by specifying single "-F", "--stripspace" is the default behavior' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + first-line + + second-line + EOF + + cat >note-file <<-EOF && + ${LF} + first-line + ${MULTI_LF} + second-line + ${LF} + EOF + + git notes add -F note-file && + git notes show >actual && + test_cmp expect actual && + git notes remove && + git notes add --stripspace -F note-file && + git notes show >actual +' + +test_expect_success 'add note by specifying single "-F" and "--no-stripspace"' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + ${LF} + first-line + ${MULTI_LF} + second-line + ${LF} + EOF + + cat >note-file <<-EOF && + ${LF} + first-line + ${MULTI_LF} + second-line + ${LF} + EOF + + git notes add --no-stripspace -F note-file && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'add note by specifying multiple "-F", "--stripspace" is the default behavior' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + file-1-first-line + + file-1-second-line + + file-2-first-line + + file-2-second-line + EOF + + cat >note-file-1 <<-EOF && + ${LF} + file-1-first-line + ${MULTI_LF} + file-1-second-line + ${LF} + EOF + + cat >note-file-2 <<-EOF && + ${LF} + file-2-first-line + ${MULTI_LF} + file-2-second-line + ${LF} + EOF + + git notes add -F note-file-1 -F note-file-2 && + git notes show >actual && + test_cmp expect actual && + git notes remove && + git notes add --stripspace -F note-file-1 -F note-file-2 && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'add note by specifying multiple "-F" with "--no-stripspace"' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + ${LF} + file-1-first-line + ${MULTI_LF} + file-1-second-line + ${LF} + + ${LF} + file-2-first-line + ${MULTI_LF} + file-2-second-line + ${LF} + EOF + + cat >note-file-1 <<-EOF && + ${LF} + file-1-first-line + ${MULTI_LF} + file-1-second-line + ${LF} + EOF + + cat >note-file-2 <<-EOF && + ${LF} + file-2-first-line + ${MULTI_LF} + file-2-second-line + ${LF} + EOF + + git notes add --no-stripspace -F note-file-1 -F note-file-2 && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'append note by editor' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + first-line + + second-line + EOF + + git notes add -m "first-line" && + MSG="${MULTI_LF}second-line${LF}" git notes append && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'append note by specifying single "-m"' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + first-line + + second-line + EOF + + git notes add -m "${LF}first-line" && + git notes append -m "${MULTI_LF}second-line${LF}" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'append note by specifying multiple "-m"' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + first-line + + second-line + EOF + + git notes add -m "${LF}first-line" && + git notes append -m "${MULTI_LF}" \ + -m "second-line" \ + -m "${LF}" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'add note by specifying single "-F"' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + first-line + + second-line + EOF + + cat >note-file <<-EOF && + ${LF} + first-line + ${MULTI_LF} + second-line + ${LF} + EOF + + git notes add -F note-file && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'add notes by specifying multiple "-F"' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + file-1-first-line + + file-1-second-line + + file-2-first-line + + file-2-second-line + EOF + + cat >note-file-1 <<-EOF && + ${LF} + file-1-first-line + ${MULTI_LF} + file-1-second-line + ${LF} + EOF + + cat >note-file-2 <<-EOF && + ${LF} + file-2-first-line + ${MULTI_LF} + file-2-second-line + ${LF} + EOF + + git notes add -F note-file-1 -F note-file-2 && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'append note by specifying single "-F"' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + initial-line + + first-line + + second-line + EOF + + cat >note-file <<-EOF && + ${LF} + first-line + ${MULTI_LF} + second-line + ${LF} + EOF + + git notes add -m "initial-line" && + git notes append -F note-file && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'append notes by specifying multiple "-F"' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + initial-line + + file-1-first-line + + file-1-second-line + + file-2-first-line + + file-2-second-line + EOF + + cat >note-file-1 <<-EOF && + ${LF} + file-1-first-line + ${MULTI_LF} + file-1-second-line + ${LF} + EOF + + cat >note-file-2 <<-EOF && + ${LF} + file-2-first-line + ${MULTI_LF} + file-2-second-line + ${LF} + EOF + + git notes add -m "initial-line" && + git notes append -F note-file-1 -F note-file-2 && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'append note by specifying multiple "-F" with "--no-stripspace"' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + initial-line + ${LF}${LF} + file-1-first-line + ${MULTI_LF} + file-1-second-line + ${LF} + + ${LF} + file-2-first-line + ${MULTI_LF} + file-2-second-line + ${LF} + EOF + + cat >note-file-1 <<-EOF && + ${LF} + file-1-first-line + ${MULTI_LF} + file-1-second-line + ${LF} + EOF + + cat >note-file-2 <<-EOF && + ${LF} + file-2-first-line + ${MULTI_LF} + file-2-second-line + ${LF} + EOF + + git notes add -m "initial-line" && + git notes append --no-stripspace -F note-file-1 -F note-file-2 && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'add notes with empty messages' ' + rev=$(git rev-parse HEAD) && + git notes add -m "${LF}" \ + -m "${MULTI_LF}" \ + -m "${LF}" >actual 2>&1 && + test_grep "Removing note for object" actual +' + +test_expect_success 'add note by specifying "-C", "--no-stripspace" is the default behavior' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + ${LF} + first-line + ${MULTI_LF} + second-line + ${LF} + EOF + + cat expect | git hash-object -w --stdin >blob && + git notes add -C $(cat blob) && + git notes show >actual && + test_cmp expect actual && + git notes remove && + git notes add --no-stripspace -C $(cat blob) && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'reuse note by specifying "-C" and "--stripspace"' ' + test_when_finished "git notes remove" && + cat >data <<-EOF && + ${LF} + first-line + ${MULTI_LF} + second-line + ${LF} + EOF + + cat >expect <<-EOF && + first-line + + second-line + EOF + + cat data | git hash-object -w --stdin >blob && + git notes add --stripspace -C $(cat blob) && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'reuse with "-C" and add note with "-m", "-m" will stripspace all together' ' + test_when_finished "git notes remove" && + cat >data <<-EOF && + ${LF} + first-line + ${MULTI_LF} + second-line + ${LF} + EOF + + cat >expect <<-EOF && + first-line + + second-line + + third-line + EOF + + cat data | git hash-object -w --stdin >blob && + git notes add -C $(cat blob) -m "third-line" && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'add note with "-m" and reuse note with "-C", "-C" will not stripspace all together' ' + test_when_finished "git notes remove" && + cat >data <<-EOF && + + second-line + EOF + + cat >expect <<-EOF && + first-line + ${LF} + second-line + EOF + + cat data | git hash-object -w --stdin >blob && + git notes add -m "first-line" -C $(cat blob) && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'add note by specifying "-c", "--stripspace" is the default behavior' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + first-line + + second-line + EOF + + echo "initial-line" | git hash-object -w --stdin >blob && + MSG="${LF}first-line${MULTI_LF}second-line${LF}" git notes add -c $(cat blob) && + git notes show >actual && + test_cmp expect actual && + git notes remove && + MSG="${LF}first-line${MULTI_LF}second-line${LF}" git notes add --stripspace -c $(cat blob) && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'add note by specifying "-c" with "--no-stripspace"' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + ${LF}first-line${MULTI_LF}second-line${LF} + EOF + + echo "initial-line" | git hash-object -w --stdin >blob && + MSG="${LF}first-line${MULTI_LF}second-line${LF}" git notes add --no-stripspace -c $(cat blob) && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'edit note by specifying "-c", "--stripspace" is the default behavior' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + first-line + + second-line + EOF + + MSG="${LF}first-line${MULTI_LF}second-line${LF}" git notes edit && + git notes show >actual && + test_cmp expect actual && + git notes remove && + MSG="${LF}first-line${MULTI_LF}second-line${LF}" git notes edit --stripspace && + git notes show >actual && + test_cmp expect actual +' + +test_expect_success 'edit note by specifying "-c" with "--no-stripspace"' ' + test_when_finished "git notes remove" && + cat >expect <<-EOF && + ${LF}first-line${MULTI_LF}second-line${LF} + EOF + + MSG="${LF}first-line${MULTI_LF}second-line${LF}" git notes add --no-stripspace && + git notes show >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh index d5a8ee39fc..57f1392926 100755 --- a/t/t3400-rebase.sh +++ b/t/t3400-rebase.sh @@ -143,8 +143,8 @@ test_expect_success 'Show verbose error when HEAD could not be detached' ' >B && test_when_finished "rm -f B" && test_must_fail git rebase topic 2>output.err >output.out && - test_i18ngrep "The following untracked working tree files would be overwritten by checkout:" output.err && - test_i18ngrep B output.err + test_grep "The following untracked working tree files would be overwritten by checkout:" output.err && + test_grep B output.err ' test_expect_success 'fail when upstream arg is missing and not on branch' ' @@ -388,6 +388,20 @@ test_expect_success 'switch to branch checked out here' ' git rebase main main ' +test_expect_success 'switch to branch checked out elsewhere fails' ' + test_when_finished " + git worktree remove wt1 && + git worktree remove wt2 && + git branch -d shared + " && + git worktree add wt1 -b shared && + git worktree add wt2 -f shared && + # we test in both worktrees to ensure that works + # as expected with "first" and "next" worktrees + test_must_fail git -C wt1 rebase shared shared && + test_must_fail git -C wt2 rebase shared shared +' + test_expect_success 'switch to branch not checked out' ' git checkout main && git branch other && @@ -407,10 +421,10 @@ test_expect_success 'refuse to switch to branch checked out elsewhere' ' git checkout main && git worktree add wt && test_must_fail git -C wt rebase main main 2>err && - test_i18ngrep "already checked out" err + test_grep "already used by worktree at" err ' -test_expect_success MINGW,SYMLINKS_WINDOWS 'rebase when .git/logs is a symlink' ' +test_expect_success REFFILES,MINGW,SYMLINKS_WINDOWS 'rebase when .git/logs is a symlink' ' git checkout main && mv .git/logs actual_logs && cmd //c "mklink /D .git\logs ..\actual_logs" && diff --git a/t/t3402-rebase-merge.sh b/t/t3402-rebase-merge.sh index 7e46f4ca85..5c67d07ba3 100755 --- a/t/t3402-rebase-merge.sh +++ b/t/t3402-rebase-merge.sh @@ -8,6 +8,7 @@ test_description='git rebase --merge test' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh T="A quick brown fox @@ -131,27 +132,6 @@ test_expect_success 'picking rebase' ' esac ' -test_expect_success 'rebase -s funny -Xopt' ' - test_when_finished "rm -fr test-bin funny.was.run" && - mkdir test-bin && - cat >test-bin/git-merge-funny <<-EOF && - #!$SHELL_PATH - case "\$1" in --opt) ;; *) exit 2 ;; esac - shift && - >funny.was.run && - exec git merge-recursive "\$@" - EOF - chmod +x test-bin/git-merge-funny && - git reset --hard && - git checkout -b test-funny main^ && - test_commit funny && - ( - PATH=./test-bin:$PATH && - git rebase -s funny -Xopt main - ) && - test -f funny.was.run -' - test_expect_success 'rebase --skip works with two conflicts in a row' ' git checkout second-side && tr "[A-Z]" "[a-z]" <newfile >tmp && @@ -191,7 +171,7 @@ test_expect_success '--reapply-cherry-picks' ' # Regular rebase fails, because the 1-11 commit is deduplicated test_must_fail git -C repo rebase --merge main 2> err && - test_i18ngrep "error: could not apply.*add 12 in another branch" err && + test_grep "error: could not apply.*add 12 in another branch" err && git -C repo rebase --abort && # With --reapply-cherry-picks, it works diff --git a/t/t3403-rebase-skip.sh b/t/t3403-rebase-skip.sh index f6e4864497..a1911c4a9d 100755 --- a/t/t3403-rebase-skip.sh +++ b/t/t3403-rebase-skip.sh @@ -108,10 +108,10 @@ test_expect_success 'correct advice upon picking empty commit' ' test_when_finished "git rebase --abort" && test_must_fail git rebase -i --onto goodbye \ amended-goodbye^ amended-goodbye 2>err && - test_i18ngrep "previous cherry-pick is now empty" err && - test_i18ngrep "git rebase --skip" err && + test_grep "previous cherry-pick is now empty" err && + test_grep "git rebase --skip" err && test_must_fail git commit && - test_i18ngrep "git rebase --skip" err + test_grep "git rebase --skip" err ' test_expect_success 'correct authorship when committing empty pick' ' @@ -131,10 +131,10 @@ test_expect_success 'correct advice upon rewording empty commit' ' test_must_fail env FAKE_LINES="reword 1" git rebase -i \ --onto goodbye amended-goodbye^ amended-goodbye 2>err ) && - test_i18ngrep "previous cherry-pick is now empty" err && - test_i18ngrep "git rebase --skip" err && + test_grep "previous cherry-pick is now empty" err && + test_grep "git rebase --skip" err && test_must_fail git commit && - test_i18ngrep "git rebase --skip" err + test_grep "git rebase --skip" err ' test_expect_success 'correct advice upon editing empty commit' ' @@ -144,10 +144,10 @@ test_expect_success 'correct advice upon editing empty commit' ' test_must_fail env FAKE_LINES="edit 1" git rebase -i \ --onto goodbye amended-goodbye^ amended-goodbye 2>err ) && - test_i18ngrep "previous cherry-pick is now empty" err && - test_i18ngrep "git rebase --skip" err && + test_grep "previous cherry-pick is now empty" err && + test_grep "git rebase --skip" err && test_must_fail git commit && - test_i18ngrep "git rebase --skip" err + test_grep "git rebase --skip" err ' test_expect_success 'correct advice upon cherry-picking an empty commit during a rebase' ' @@ -157,10 +157,10 @@ test_expect_success 'correct advice upon cherry-picking an empty commit during a test_must_fail env FAKE_LINES="1 exec_git_cherry-pick_amended-goodbye" \ git rebase -i goodbye^ goodbye 2>err ) && - test_i18ngrep "previous cherry-pick is now empty" err && - test_i18ngrep "git cherry-pick --skip" err && + test_grep "previous cherry-pick is now empty" err && + test_grep "git cherry-pick --skip" err && test_must_fail git commit 2>err && - test_i18ngrep "git cherry-pick --skip" err + test_grep "git cherry-pick --skip" err ' test_expect_success 'correct advice upon multi cherry-pick picking an empty commit during a rebase' ' @@ -170,10 +170,10 @@ test_expect_success 'correct advice upon multi cherry-pick picking an empty comm test_must_fail env FAKE_LINES="1 exec_git_cherry-pick_goodbye_amended-goodbye" \ git rebase -i goodbye^^ goodbye 2>err ) && - test_i18ngrep "previous cherry-pick is now empty" err && - test_i18ngrep "git cherry-pick --skip" err && + test_grep "previous cherry-pick is now empty" err && + test_grep "git cherry-pick --skip" err && test_must_fail git commit 2>err && - test_i18ngrep "git cherry-pick --skip" err + test_grep "git cherry-pick --skip" err ' test_expect_success 'fixup that empties commit fails' ' diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index ff0afad63e..64b641002e 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -291,9 +291,9 @@ test_expect_success 'abort with error when new base cannot be checked out' ' git rm --cached file1 && git commit -m "remove file in base" && test_must_fail git rebase -i primary > output 2>&1 && - test_i18ngrep "The following untracked working tree files would be overwritten by checkout:" \ + test_grep "The following untracked working tree files would be overwritten by checkout:" \ output && - test_i18ngrep "file1" output && + test_grep "file1" output && test_path_is_missing .git/rebase-merge && rm file1 && git reset --hard HEAD^ @@ -604,7 +604,8 @@ test_expect_success 'clean error after failed "exec"' ' echo "edited again" > file7 && git add file7 && test_must_fail git rebase --continue 2>error && - test_i18ngrep "you have staged changes in your working tree" error + test_grep "you have staged changes in your working tree" error && + test_grep ! "could not open.*for reading" error ' test_expect_success 'rebase a detached HEAD' ' @@ -758,7 +759,7 @@ test_expect_success 'reword' ' git show HEAD~2 | grep "C changed" ' -test_expect_success 'no uncommited changes when rewording the todo list is reloaded' ' +test_expect_success 'no uncommitted changes when rewording and the todo list is reloaded' ' git checkout E && test_when_finished "git checkout @{-1}" && ( @@ -955,7 +956,7 @@ test_expect_success 'rebase --exec works without -i ' ' git reset --hard execute && rm -rf exec_output && EDITOR="echo >invoked_editor" git rebase --exec "echo a line >>exec_output" HEAD~2 2>actual && - test_i18ngrep "Successfully rebased and updated" actual && + test_grep "Successfully rebased and updated" actual && test_line_count = 2 exec_output && test_path_is_missing invoked_editor ' @@ -963,7 +964,7 @@ test_expect_success 'rebase --exec works without -i ' ' test_expect_success 'rebase -i --exec without <CMD>' ' git reset --hard execute && test_must_fail git rebase -i --exec 2>actual && - test_i18ngrep "requires a value" actual && + test_grep "requires a value" actual && git checkout primary ' @@ -1272,24 +1273,38 @@ test_expect_success 'todo count' ' test_set_editor "$(pwd)/dump-raw.sh" && git rebase -i HEAD~4 >actual ) && - test_i18ngrep "^# Rebase ..* onto ..* ([0-9]" actual + test_grep "^# Rebase ..* onto ..* ([0-9]" actual ' test_expect_success 'rebase -i commits that overwrite untracked files (pick)' ' - git checkout --force branch2 && + git checkout --force A && git clean -f && + cat >todo <<-EOF && + exec >file2 + pick $(git rev-parse B) B + pick $(git rev-parse C) C + pick $(git rev-parse D) D + exec cat .git/rebase-merge/done >actual + EOF ( - set_fake_editor && - FAKE_LINES="edit 1 2" git rebase -i A - ) && - test_cmp_rev HEAD F && - test_path_is_missing file6 && - >file6 && - test_must_fail git rebase --continue && - test_cmp_rev HEAD F && - rm file6 && + set_replace_editor todo && + test_must_fail git rebase -i A + ) && + test_cmp_rev HEAD B && + test_cmp_rev REBASE_HEAD C && + head -n3 todo >expect && + test_cmp expect .git/rebase-merge/done && + rm file2 && + test_path_is_missing .git/rebase-merge/patch && + echo changed >file1 && + git add file1 && + test_must_fail git rebase --continue 2>err && + grep "error: you have staged changes in your working tree" err && + git reset --hard HEAD && git rebase --continue && - test_cmp_rev HEAD I + test_cmp_rev HEAD D && + tail -n3 todo >>expect && + test_cmp expect actual ' test_expect_success 'rebase -i commits that overwrite untracked files (squash)' ' @@ -1305,7 +1320,14 @@ test_expect_success 'rebase -i commits that overwrite untracked files (squash)' >file6 && test_must_fail git rebase --continue && test_cmp_rev HEAD F && + test_cmp_rev REBASE_HEAD I && rm file6 && + test_path_is_missing .git/rebase-merge/patch && + echo changed >file1 && + git add file1 && + test_must_fail git rebase --continue 2>err && + grep "error: you have staged changes in your working tree" err && + git reset --hard HEAD && git rebase --continue && test $(git cat-file commit HEAD | sed -ne \$p) = I && git reset --hard original-branch2 @@ -1323,7 +1345,14 @@ test_expect_success 'rebase -i commits that overwrite untracked files (no ff)' ' >file6 && test_must_fail git rebase --continue && test $(git cat-file commit HEAD | sed -ne \$p) = F && + test_cmp_rev REBASE_HEAD I && rm file6 && + test_path_is_missing .git/rebase-merge/patch && + echo changed >file1 && + git add file1 && + test_must_fail git rebase --continue 2>err && + grep "error: you have staged changes in your working tree" err && + git reset --hard HEAD && git rebase --continue && test $(git cat-file commit HEAD | sed -ne \$p) = I ' @@ -1379,7 +1408,7 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = ignore' ' FAKE_LINES="1 2 3 4" git rebase -i --root 2>actual ) && test D = $(git cat-file commit HEAD | sed -ne \$p) && - test_i18ngrep \ + test_grep \ "Successfully rebased and updated refs/heads/missing-commit" \ actual ' @@ -1442,7 +1471,7 @@ test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = ig git rebase --continue 2>actual ) && test D = $(git cat-file commit HEAD | sed -ne \$p) && - test_i18ngrep \ + test_grep \ "Successfully rebased and updated refs/heads/missing-commit" \ actual ' @@ -1477,7 +1506,7 @@ test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = wa git rebase --continue 2>actual ) && test D = $(git cat-file commit HEAD | sed -ne \$p) && - test_i18ngrep \ + test_grep \ "Successfully rebased and updated refs/heads/missing-commit" \ actual ' @@ -1525,7 +1554,7 @@ test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = er git rebase --continue 2>actual ) && test D = $(git cat-file commit HEAD | sed -ne \$p) && - test_i18ngrep \ + test_grep \ "Successfully rebased and updated refs/heads/missing-commit" \ actual ' @@ -1585,9 +1614,9 @@ test_expect_success 'static check of bad command' ' set_fake_editor && test_must_fail env FAKE_LINES="1 2 3 bad 4 5" \ git rebase -i --root 2>actual && - test_i18ngrep "pickled $(git rev-list --oneline -1 primary~1)" \ + test_grep "pickled $(git rev-list --oneline -1 primary~1)" \ actual && - test_i18ngrep "You can fix this with .git rebase --edit-todo.." \ + test_grep "You can fix this with .git rebase --edit-todo.." \ actual && FAKE_LINES="1 2 3 drop 4 5" git rebase --edit-todo ) && @@ -1596,6 +1625,32 @@ test_expect_success 'static check of bad command' ' test C = $(git cat-file commit HEAD^ | sed -ne \$p) ' +test_expect_success 'the first command cannot be a fixup' ' + rebase_setup_and_clean fixup-first && + + cat >orig <<-EOF && + fixup $(git log -1 --format="%h %s" B) + pick $(git log -1 --format="%h %s" C) + EOF + + ( + set_replace_editor orig && + test_must_fail git rebase -i A 2>actual + ) && + grep "cannot .fixup. without a previous commit" actual && + grep "You can fix this with .git rebase --edit-todo.." actual && + # verify that the todo list has not been truncated + grep -v "^#" .git/rebase-merge/git-rebase-todo >actual && + test_cmp orig actual && + + test_must_fail git rebase --edit-todo 2>actual && + grep "cannot .fixup. without a previous commit" actual && + grep "You can fix this with .git rebase --edit-todo.." actual && + # verify that the todo list has not been truncated + grep -v "^#" .git/rebase-merge/git-rebase-todo >actual && + test_cmp orig actual +' + test_expect_success 'tabs and spaces are accepted in the todolist' ' rebase_setup_and_clean indented-comment && write_script add-indent.sh <<-\EOF && @@ -1619,8 +1674,8 @@ test_expect_success 'static check of bad SHA-1' ' set_fake_editor && test_must_fail env FAKE_LINES="1 2 edit fakesha 3 4 5 #" \ git rebase -i --root 2>actual && - test_i18ngrep "edit XXXXXXX False commit" actual && - test_i18ngrep "You can fix this with .git rebase --edit-todo.." \ + test_grep "edit XXXXXXX False commit" actual && + test_grep "You can fix this with .git rebase --edit-todo.." \ actual && FAKE_LINES="1 2 4 5 6" git rebase --edit-todo ) && @@ -1647,7 +1702,7 @@ test_expect_success 'rebase -i --gpg-sign=<key-id>' ' FAKE_LINES="edit 1" git rebase -i --gpg-sign="\"S I Gner\"" \ HEAD^ >out 2>err ) && - test_i18ngrep "$SQ-S\"S I Gner\"$SQ" err + test_grep "$SQ-S\"S I Gner\"$SQ" err ' test_expect_success 'rebase -i --gpg-sign=<key-id> overrides commit.gpgSign' ' @@ -1658,7 +1713,7 @@ test_expect_success 'rebase -i --gpg-sign=<key-id> overrides commit.gpgSign' ' FAKE_LINES="edit 1" git rebase -i --gpg-sign="\"S I Gner\"" \ HEAD^ >out 2>err ) && - test_i18ngrep "$SQ-S\"S I Gner\"$SQ" err + test_grep "$SQ-S\"S I Gner\"$SQ" err ' test_expect_success 'valid author header after --root swap' ' @@ -1712,7 +1767,7 @@ test_expect_success 'correct error message for partial commit after empty pick' ) && echo x >file1 && test_must_fail git commit file1 2>err && - test_i18ngrep "cannot do a partial commit during a rebase." err + test_grep "cannot do a partial commit during a rebase." err ' test_expect_success 'correct error message for commit --amend after empty pick' ' @@ -1725,13 +1780,13 @@ test_expect_success 'correct error message for commit --amend after empty pick' ) && echo x>file1 && test_must_fail git commit -a --amend 2>err && - test_i18ngrep "middle of a rebase -- cannot amend." err + test_grep "middle of a rebase -- cannot amend." err ' test_expect_success 'todo has correct onto hash' ' GIT_SEQUENCE_EDITOR=cat git rebase -i no-conflict-branch~4 no-conflict-branch >actual && onto=$(git rev-parse --short HEAD~4) && - test_i18ngrep "^# Rebase ..* onto $onto" actual + test_grep "^# Rebase ..* onto $onto" actual ' test_expect_success 'ORIG_HEAD is updated correctly' ' @@ -2105,7 +2160,7 @@ test_expect_success '--update-refs: check failed ref update' ' # recorded in the update-refs file. We will force-update the # "second" ref, but "git branch -f" will not work because of # the lock in the update-refs file. - git rev-parse third >.git/refs/heads/second && + git update-ref refs/heads/second third && test_must_fail git rebase --continue 2>err && grep "update_ref failed for ref '\''refs/heads/second'\''" err && diff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh index ceca160005..a1d7fa7f7c 100755 --- a/t/t3406-rebase-message.sh +++ b/t/t3406-rebase-message.sh @@ -33,24 +33,24 @@ test_expect_success 'rebase -m' ' test_expect_success 'rebase against main twice' ' git rebase --apply main >out && - test_i18ngrep "Current branch topic is up to date" out + test_grep "Current branch topic is up to date" out ' test_expect_success 'rebase against main twice with --force' ' git rebase --force-rebase --apply main >out && - test_i18ngrep "Current branch topic is up to date, rebase forced" out + test_grep "Current branch topic is up to date, rebase forced" out ' test_expect_success 'rebase against main twice from another branch' ' git checkout topic^ && git rebase --apply main topic >out && - test_i18ngrep "Current branch topic is up to date" out + test_grep "Current branch topic is up to date" out ' test_expect_success 'rebase fast-forward to main' ' git checkout topic^ && git rebase --apply topic >out && - test_i18ngrep "Fast-forwarded HEAD to topic" out + test_grep "Fast-forwarded HEAD to topic" out ' test_expect_success 'rebase --stat' ' @@ -75,14 +75,14 @@ test_expect_success 'rebase -n overrides config rebase.stat config' ' test_expect_success 'rebase --onto outputs the invalid ref' ' test_must_fail git rebase --onto invalid-ref HEAD HEAD 2>err && - test_i18ngrep "invalid-ref" err + test_grep "invalid-ref" err ' test_expect_success 'error out early upon -C<n> or --whitespace=<bad>' ' test_must_fail git rebase -Cnot-a-number HEAD 2>err && - test_i18ngrep "numerical value" err && + test_grep "numerical value" err && test_must_fail git rebase --whitespace=bad HEAD 2>err && - test_i18ngrep "Invalid whitespace option" err + test_grep "Invalid whitespace option" err ' write_reflog_expect () { @@ -251,8 +251,8 @@ test_expect_success 'rebase -i onto unrelated history' ' git -C unrelated remote add -f origin "$PWD" && git -C unrelated branch --set-upstream-to=origin/main && git -C unrelated -c core.editor=true rebase -i -v --stat >actual && - test_i18ngrep "Changes to " actual && - test_i18ngrep "5 files changed" actual + test_grep "Changes to " actual && + test_grep "5 files changed" actual ' test_done diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh index a364530d76..fcc40d6fe1 100755 --- a/t/t3415-rebase-autosquash.sh +++ b/t/t3415-rebase-autosquash.sh @@ -43,7 +43,7 @@ test_auto_fixup () { git tag $1 && test_tick && - git rebase $2 -i HEAD^^^ && + git rebase $2 HEAD^^^ && git log --oneline >actual && if test -n "$no_squash" then @@ -61,15 +61,24 @@ test_auto_fixup () { } test_expect_success 'auto fixup (option)' ' - test_auto_fixup final-fixup-option --autosquash + test_auto_fixup fixup-option --autosquash && + test_auto_fixup fixup-option-i "--autosquash -i" ' -test_expect_success 'auto fixup (config)' ' +test_expect_success 'auto fixup (config true)' ' git config rebase.autosquash true && - test_auto_fixup final-fixup-config-true && + test_auto_fixup ! fixup-config-true && + test_auto_fixup fixup-config-true-i -i && test_auto_fixup ! fixup-config-true-no --no-autosquash && + test_auto_fixup ! fixup-config-true-i-no "-i --no-autosquash" +' + +test_expect_success 'auto fixup (config false)' ' git config rebase.autosquash false && - test_auto_fixup ! final-fixup-config-false + test_auto_fixup ! fixup-config-false && + test_auto_fixup ! fixup-config-false-i -i && + test_auto_fixup fixup-config-false-yes --autosquash && + test_auto_fixup fixup-config-false-i-yes "-i --autosquash" ' test_auto_squash () { @@ -87,7 +96,7 @@ test_auto_squash () { git commit -m "squash! first" -m "extra para for first" && git tag $1 && test_tick && - git rebase $2 -i HEAD^^^ && + git rebase $2 HEAD^^^ && git log --oneline >actual && if test -n "$no_squash" then @@ -105,15 +114,24 @@ test_auto_squash () { } test_expect_success 'auto squash (option)' ' - test_auto_squash final-squash --autosquash + test_auto_squash squash-option --autosquash && + test_auto_squash squash-option-i "--autosquash -i" ' -test_expect_success 'auto squash (config)' ' +test_expect_success 'auto squash (config true)' ' git config rebase.autosquash true && - test_auto_squash final-squash-config-true && + test_auto_squash ! squash-config-true && + test_auto_squash squash-config-true-i -i && test_auto_squash ! squash-config-true-no --no-autosquash && + test_auto_squash ! squash-config-true-i-no "-i --no-autosquash" +' + +test_expect_success 'auto squash (config false)' ' git config rebase.autosquash false && - test_auto_squash ! final-squash-config-false + test_auto_squash ! squash-config-false && + test_auto_squash ! squash-config-false-i -i && + test_auto_squash squash-config-false-yes --autosquash && + test_auto_squash squash-config-false-i-yes "-i --autosquash" ' test_expect_success 'misspelled auto squash' ' diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh index 130e2f9b55..127216f722 100755 --- a/t/t3418-rebase-continue.sh +++ b/t/t3418-rebase-continue.sh @@ -62,61 +62,39 @@ test_expect_success 'rebase --continue remembers merge strategy and options' ' rm -fr .git/rebase-* && git reset --hard commit-new-file-F2-on-topic-branch && test_commit "commit-new-file-F3-on-topic-branch" F3 32 && - test_when_finished "rm -fr test-bin funny.was.run" && + test_when_finished "rm -fr test-bin" && mkdir test-bin && - cat >test-bin/git-merge-funny <<-EOF && - #!$SHELL_PATH - case "\$1" in --opt) ;; *) exit 2 ;; esac - shift && - >funny.was.run && - exec git merge-recursive "\$@" + + write_script test-bin/git-merge-funny <<-\EOF && + printf "[%s]\n" $# "$1" "$2" "$3" "$5" >actual + shift 3 && + exec git merge-recursive "$@" EOF - chmod +x test-bin/git-merge-funny && - ( - PATH=./test-bin:$PATH && - test_must_fail git rebase -s funny -Xopt main topic - ) && - test -f funny.was.run && - rm funny.was.run && - echo "Resolved" >F2 && - git add F2 && - ( - PATH=./test-bin:$PATH && - git rebase --continue - ) && - test -f funny.was.run -' -test_expect_success 'rebase -i --continue handles merge strategy and options' ' - rm -fr .git/rebase-* && - git reset --hard commit-new-file-F2-on-topic-branch && - test_commit "commit-new-file-F3-on-topic-branch-for-dash-i" F3 32 && - test_when_finished "rm -fr test-bin funny.was.run funny.args" && - mkdir test-bin && - cat >test-bin/git-merge-funny <<-EOF && - #!$SHELL_PATH - echo "\$@" >>funny.args - case "\$1" in --opt) ;; *) exit 2 ;; esac - case "\$2" in --foo) ;; *) exit 2 ;; esac - case "\$4" in --) ;; *) exit 2 ;; esac - shift 2 && - >funny.was.run && - exec git merge-recursive "\$@" + cat >expect <<-\EOF && + [7] + [--option=arg with space] + [--op"tion\] + [--new + line ] + [--] EOF - chmod +x test-bin/git-merge-funny && + + rm -f actual && ( PATH=./test-bin:$PATH && - test_must_fail git rebase -i -s funny -Xopt -Xfoo main topic + test_must_fail git rebase -s funny -X"option=arg with space" \ + -Xop\"tion\\ -X"new${LF}line " main topic ) && - test -f funny.was.run && - rm funny.was.run && + test_cmp expect actual && + rm actual && echo "Resolved" >F2 && git add F2 && ( PATH=./test-bin:$PATH && git rebase --continue ) && - test -f funny.was.run + test_cmp expect actual ' test_expect_success 'rebase -r passes merge strategy options correctly' ' @@ -137,15 +115,23 @@ test_expect_success '--skip after failed fixup cleans commit message' ' test_when_finished "test_might_fail git rebase --abort" && git checkout -b with-conflicting-fixup && test_commit wants-fixup && - test_commit "fixup! wants-fixup" wants-fixup.t 1 wants-fixup-1 && - test_commit "fixup! wants-fixup" wants-fixup.t 2 wants-fixup-2 && - test_commit "fixup! wants-fixup" wants-fixup.t 3 wants-fixup-3 && + test_commit "fixup 1" wants-fixup.t 1 wants-fixup-1 && + test_commit "fixup 2" wants-fixup.t 2 wants-fixup-2 && + test_commit "fixup 3" wants-fixup.t 3 wants-fixup-3 && test_must_fail env FAKE_LINES="1 fixup 2 squash 4" \ git rebase -i HEAD~4 && : now there is a conflict, and comments in the commit message && - git show HEAD >out && - grep "fixup! wants-fixup" out && + test_commit_message HEAD <<-\EOF && + # This is a combination of 2 commits. + # This is the 1st commit message: + + wants-fixup + + # The commit message #2 will be skipped: + + # fixup 1 + EOF : skip and continue && echo "cp \"\$1\" .git/copy.txt" | write_script copy-editor.sh && @@ -155,33 +141,49 @@ test_expect_success '--skip after failed fixup cleans commit message' ' test_path_is_missing .git/copy.txt && : now the comments in the commit message should have been cleaned up && - git show HEAD >out && - ! grep "fixup! wants-fixup" out && + test_commit_message HEAD -m wants-fixup && : now, let us ensure that "squash" is handled correctly && git reset --hard wants-fixup-3 && - test_must_fail env FAKE_LINES="1 squash 4 squash 2 squash 4" \ + test_must_fail env FAKE_LINES="1 squash 2 squash 1 squash 3 squash 1" \ git rebase -i HEAD~4 && - : the first squash failed, but there are two more in the chain && + : the second squash failed, but there are two more in the chain && (test_set_editor "$PWD/copy-editor.sh" && test_must_fail git rebase --skip) && : not the final squash, no need to edit the commit message && test_path_is_missing .git/copy.txt && - : The first squash was skipped, therefore: && - git show HEAD >out && - test_i18ngrep "# This is a combination of 2 commits" out && - test_i18ngrep "# This is the commit message #2:" out && + : The first and third squashes succeeded, therefore: && + test_commit_message HEAD <<-\EOF && + # This is a combination of 3 commits. + # This is the 1st commit message: + + wants-fixup + + # This is the commit message #2: + + fixup 1 + + # This is the commit message #3: + + fixup 2 + EOF (test_set_editor "$PWD/copy-editor.sh" && git rebase --skip) && - git show HEAD >out && - test_i18ngrep ! "# This is a combination" out && + test_commit_message HEAD <<-\EOF && + wants-fixup + + fixup 1 + + fixup 2 + EOF : Final squash failed, but there was still a squash && - test_i18ngrep "# This is a combination of 2 commits" .git/copy.txt && - test_i18ngrep "# This is the commit message #2:" .git/copy.txt + head -n1 .git/copy.txt >first-line && + test_grep "# This is a combination of 3 commits" first-line && + test_grep "# This is the commit message #3:" .git/copy.txt ' test_expect_success 'setup rerere database' ' @@ -266,6 +268,24 @@ test_expect_success 'the todo command "break" works' ' test_path_is_file execed ' +test_expect_success 'patch file is removed before break command' ' + test_when_finished "git rebase --abort" && + cat >todo <<-\EOF && + pick commit-new-file-F2-on-topic-branch + break + EOF + + ( + set_replace_editor todo && + test_must_fail git rebase -i --onto commit-new-file-F2 HEAD + ) && + test_path_is_file .git/rebase-merge/patch && + echo 22>F2 && + git add F2 && + git rebase --continue && + test_path_is_missing .git/rebase-merge/patch +' + test_expect_success '--reschedule-failed-exec' ' test_when_finished "git rebase --abort" && test_must_fail git rebase -x false --reschedule-failed-exec HEAD^ && @@ -274,7 +294,7 @@ test_expect_success '--reschedule-failed-exec' ' test_must_fail git -c rebase.rescheduleFailedExec=true \ rebase -x false HEAD^ 2>err && grep "^exec false" .git/rebase-merge/git-rebase-todo && - test_i18ngrep "has been rescheduled" err + test_grep "has been rescheduled" err ' test_expect_success 'rebase.rescheduleFailedExec only affects `rebase -i`' ' diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh index 4711b37a28..b40f26250b 100755 --- a/t/t3422-rebase-incompatible-options.sh +++ b/t/t3422-rebase-incompatible-options.sh @@ -85,6 +85,11 @@ test_rebase_am_only () { test_must_fail git rebase $opt --reapply-cherry-picks A " + test_expect_success "$opt incompatible with --rebase-merges" " + git checkout B^0 && + test_must_fail git rebase $opt --rebase-merges A + " + test_expect_success "$opt incompatible with --update-refs" " git checkout B^0 && test_must_fail git rebase $opt --update-refs A @@ -95,10 +100,10 @@ test_rebase_am_only () { test_must_fail git rebase $opt --root A " - test_expect_success "$opt incompatible with rebase.autosquash" " + test_expect_success "$opt incompatible with rebase.rebaseMerges" " git checkout B^0 && - test_must_fail git -c rebase.autosquash=true rebase $opt A 2>err && - grep -e --no-autosquash err + test_must_fail git -c rebase.rebaseMerges=true rebase $opt A 2>err && + grep -e --no-rebase-merges err " test_expect_success "$opt incompatible with rebase.updateRefs" " @@ -107,10 +112,10 @@ test_rebase_am_only () { grep -e --no-update-refs err " - test_expect_success "$opt okay with overridden rebase.autosquash" " + test_expect_success "$opt okay with overridden rebase.rebaseMerges" " test_when_finished \"git reset --hard B^0\" && git checkout B^0 && - git -c rebase.autosquash=true rebase --no-autosquash $opt A + git -c rebase.rebaseMerges=true rebase --no-rebase-merges $opt A " test_expect_success "$opt okay with overridden rebase.updateRefs" " diff --git a/t/t3427-rebase-subtree.sh b/t/t3427-rebase-subtree.sh index 48b76f8232..1b3e97c875 100755 --- a/t/t3427-rebase-subtree.sh +++ b/t/t3427-rebase-subtree.sh @@ -74,9 +74,9 @@ test_expect_success 'Rebase -Xsubtree --empty=ask --onto commit' ' test_must_fail git rebase -Xsubtree=files_subtree --empty=ask --onto files-main main && : first pick results in no changes && git rebase --skip && - verbose test "$(commit_message HEAD~2)" = "topic_4" && - verbose test "$(commit_message HEAD~)" = "files_subtree/topic_5" && - verbose test "$(commit_message HEAD)" = "Empty commit" + test "$(commit_message HEAD~2)" = "topic_4" && + test "$(commit_message HEAD~)" = "files_subtree/topic_5" && + test "$(commit_message HEAD)" = "Empty commit" ' test_expect_success 'Rebase -Xsubtree --empty=ask --rebase-merges --onto commit' ' @@ -85,9 +85,9 @@ test_expect_success 'Rebase -Xsubtree --empty=ask --rebase-merges --onto commit' test_must_fail git rebase -Xsubtree=files_subtree --empty=ask --rebase-merges --onto files-main --root && : first pick results in no changes && git rebase --skip && - verbose test "$(commit_message HEAD~2)" = "topic_4" && - verbose test "$(commit_message HEAD~)" = "files_subtree/topic_5" && - verbose test "$(commit_message HEAD)" = "Empty commit" + test "$(commit_message HEAD~2)" = "topic_4" && + test "$(commit_message HEAD~)" = "files_subtree/topic_5" && + test "$(commit_message HEAD)" = "Empty commit" ' test_done diff --git a/t/t3430-rebase-merges.sh b/t/t3430-rebase-merges.sh index fa2a06c19f..59b5d6b6f2 100755 --- a/t/t3430-rebase-merges.sh +++ b/t/t3430-rebase-merges.sh @@ -128,14 +128,24 @@ test_expect_success 'generate correct todo list' ' ' test_expect_success '`reset` refuses to overwrite untracked files' ' - git checkout -b refuse-to-reset && + git checkout B && test_commit dont-overwrite-untracked && - git checkout @{-1} && - : >dont-overwrite-untracked.t && - echo "reset refs/tags/dont-overwrite-untracked" >script-from-scratch && + cat >script-from-scratch <<-EOF && + exec >dont-overwrite-untracked.t + pick $(git rev-parse B) B + reset refs/tags/dont-overwrite-untracked + pick $(git rev-parse C) C + exec cat .git/rebase-merge/done >actual + EOF test_config sequence.editor \""$PWD"/replace-editor.sh\" && - test_must_fail git rebase -ir HEAD && - git rebase --abort + test_must_fail git rebase -ir A && + test_cmp_rev HEAD B && + head -n3 script-from-scratch >expect && + test_cmp expect .git/rebase-merge/done && + rm dont-overwrite-untracked.t && + git rebase --continue && + tail -n3 script-from-scratch >>expect && + test_cmp expect actual ' test_expect_success '`reset` rejects trees' ' @@ -165,12 +175,16 @@ test_expect_success 'failed `merge -C` writes patch (may be rescheduled, too)' ' test_config sequence.editor \""$PWD"/replace-editor.sh\" && test_tick && test_must_fail git rebase -ir HEAD && + test_cmp_rev REBASE_HEAD H^0 && grep "^merge -C .* G$" .git/rebase-merge/done && grep "^merge -C .* G$" .git/rebase-merge/git-rebase-todo && - test_path_is_file .git/rebase-merge/patch && + test_path_is_missing .git/rebase-merge/patch && + echo changed >file1 && + git add file1 && + test_must_fail git rebase --continue 2>err && + grep "error: you have staged changes in your working tree" err && : fail because of merge conflict && - rm G.t .git/rebase-merge/patch && git reset --hard conflicting-G && test_must_fail git rebase --continue && ! grep "^merge -C .* G$" .git/rebase-merge/git-rebase-todo && @@ -250,6 +264,16 @@ test_expect_success 'with a branch tip that was cherry-picked already' ' EOF ' +test_expect_success '--no-rebase-merges countermands --rebase-merges' ' + git checkout -b no-rebase-merges E && + git rebase --rebase-merges --no-rebase-merges C && + test_cmp_graph C.. <<-\EOF + * B + * D + o C + EOF +' + test_expect_success 'do not rebase cousins unless asked for' ' git checkout -b cousins main && before="$(git rev-parse --verify HEAD)" && @@ -268,6 +292,40 @@ test_expect_success 'do not rebase cousins unless asked for' ' EOF ' +test_expect_success 'rebase.rebaseMerges=rebase-cousins is equivalent to --rebase-merges=rebase-cousins' ' + test_config rebase.rebaseMerges rebase-cousins && + git checkout -b config-rebase-cousins main && + git rebase HEAD^ && + test_cmp_graph HEAD^.. <<-\EOF + * Merge the topic branch '\''onebranch'\'' + |\ + | * D + | * G + |/ + o H + EOF +' + +test_expect_success '--no-rebase-merges overrides rebase.rebaseMerges=no-rebase-cousins' ' + test_config rebase.rebaseMerges no-rebase-cousins && + git checkout -b override-config-no-rebase-cousins E && + git rebase --no-rebase-merges C && + test_cmp_graph C.. <<-\EOF + * B + * D + o C + EOF +' + +test_expect_success '--rebase-merges overrides rebase.rebaseMerges=rebase-cousins' ' + test_config rebase.rebaseMerges rebase-cousins && + git checkout -b override-config-rebase-cousins E && + before="$(git rev-parse --verify HEAD)" && + test_tick && + git rebase --rebase-merges C && + test_cmp_rev HEAD $before +' + test_expect_success 'refs/rewritten/* is worktree-local' ' git worktree add wt && cat >wt/script-from-scratch <<-\EOF && @@ -534,4 +592,23 @@ test_expect_success '--rebase-merges with message matched with onto label' ' EOF ' +test_expect_success 'progress shows the correct total' ' + git checkout -b progress H && + git rebase --rebase-merges --force-rebase --verbose A 2> err && + # Expecting "Rebasing (N/14)" here, no bogus total number + grep "^Rebasing.*/14.$" err >progress && + test_line_count = 14 progress +' + +test_expect_success 'truncate label names' ' + commit=$(git commit-tree -p HEAD^ -p HEAD -m "0123456789 我 123" HEAD^{tree}) && + git merge --ff-only $commit && + + done="$(git rev-parse --git-path rebase-merge/done)" && + git -c rebase.maxLabelLength=14 rebase --rebase-merges -x "cp \"$done\" out" --root && + grep "label 0123456789-我$" out && + git -c rebase.maxLabelLength=13 rebase --rebase-merges -x "cp \"$done\" out" --root && + grep "label 0123456789-$" out +' + test_done diff --git a/t/t3431-rebase-fork-point.sh b/t/t3431-rebase-fork-point.sh index 4bfc779bb8..0bb284d61d 100755 --- a/t/t3431-rebase-fork-point.sh +++ b/t/t3431-rebase-fork-point.sh @@ -84,7 +84,7 @@ test_expect_success 'git rebase --fork-point with ambigous refname' ' test_expect_success '--fork-point and --root both given' ' test_must_fail git rebase --fork-point --root 2>err && - test_i18ngrep "cannot be used together" err + test_grep "cannot be used together" err ' test_expect_success 'rebase.forkPoint set to false' ' diff --git a/t/t3437-rebase-fixup-options.sh b/t/t3437-rebase-fixup-options.sh index dd3b301fa7..7929e2e2e3 100755 --- a/t/t3437-rebase-fixup-options.sh +++ b/t/t3437-rebase-fixup-options.sh @@ -21,21 +21,6 @@ TEST_PASSES_SANITIZE_LEAK=true EMPTY="" -# test_commit_message <rev> -m <msg> -# test_commit_message <rev> <path> -# Verify that the commit message of <rev> matches -# <msg> or the content of <path>. -test_commit_message () { - git show --no-patch --pretty=format:%B "$1" >actual && - case "$2" in - -m) - echo "$3" >expect && - test_cmp expect actual ;; - *) - test_cmp "$2" actual ;; - esac -} - get_author () { rev="$1" && git log -1 --pretty=format:"%an %ae %at" "$rev" diff --git a/t/t3500-cherry.sh b/t/t3500-cherry.sh index 0458a58b4b..78c3eac54b 100755 --- a/t/t3500-cherry.sh +++ b/t/t3500-cherry.sh @@ -16,46 +16,43 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME GIT_AUTHOR_EMAIL=bogus_email_address export GIT_AUTHOR_EMAIL -test_expect_success \ - 'prepare repository with topic branch, and check cherry finds the 2 patches from there' \ - 'echo First > A && - git update-index --add A && - test_tick && - git commit -m "Add A." && - - git checkout -b my-topic-branch && - - echo Second > B && - git update-index --add B && - test_tick && - git commit -m "Add B." && - - echo AnotherSecond > C && - git update-index --add C && - test_tick && - git commit -m "Add C." && - - git checkout -f main && - rm -f B C && - - echo Third >> A && - git update-index A && - test_tick && - git commit -m "Modify A." && - - expr "$(echo $(git cherry main my-topic-branch) )" : "+ [^ ]* + .*" +test_expect_success 'prepare repository with topic branch, and check cherry finds the 2 patches from there' ' + echo First > A && + git update-index --add A && + test_tick && + git commit -m "Add A." && + + git checkout -b my-topic-branch && + + echo Second > B && + git update-index --add B && + test_tick && + git commit -m "Add B." && + + echo AnotherSecond > C && + git update-index --add C && + test_tick && + git commit -m "Add C." && + + git checkout -f main && + rm -f B C && + + echo Third >> A && + git update-index A && + test_tick && + git commit -m "Modify A." && + + expr "$(echo $(git cherry main my-topic-branch) )" : "+ [^ ]* + .*" ' -test_expect_success \ - 'check that cherry with limit returns only the top patch'\ - 'expr "$(echo $(git cherry main my-topic-branch my-topic-branch^1) )" : "+ [^ ]*" +test_expect_success 'check that cherry with limit returns only the top patch' ' + expr "$(echo $(git cherry main my-topic-branch my-topic-branch^1) )" : "+ [^ ]*" ' -test_expect_success \ - 'cherry-pick one of the 2 patches, and check cherry recognized one and only one as new' \ - 'git cherry-pick my-topic-branch^0 && - echo $(git cherry main my-topic-branch) && - expr "$(echo $(git cherry main my-topic-branch) )" : "+ [^ ]* - .*" +test_expect_success 'cherry-pick one of the 2 patches, and check cherry recognized one and only one as new' ' + git cherry-pick my-topic-branch^0 && + echo $(git cherry main my-topic-branch) && + expr "$(echo $(git cherry main my-topic-branch) )" : "+ [^ ]* - .*" ' test_expect_success 'cherry ignores whitespace' ' diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh index 2f3e3e2416..aeab689a98 100755 --- a/t/t3501-revert-cherry-pick.sh +++ b/t/t3501-revert-cherry-pick.sh @@ -1,14 +1,6 @@ #!/bin/sh -test_description='test cherry-pick and revert with renames - - -- - + rename2: renames oops to opos - + rename1: renames oops to spoo - + added: adds extra line to oops - ++ initial: has lines in oops - -' +test_description='miscellaneous basic tests for cherry-pick and revert' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME @@ -51,7 +43,7 @@ test_expect_success 'cherry-pick --nonsense' ' git diff --exit-code HEAD && test_must_fail git cherry-pick --nonsense 2>msg && git diff --exit-code HEAD "$pos" && - test_i18ngrep "[Uu]sage:" msg + test_grep "[Uu]sage:" msg ' test_expect_success 'revert --nonsense' ' @@ -60,9 +52,17 @@ test_expect_success 'revert --nonsense' ' git diff --exit-code HEAD && test_must_fail git revert --nonsense 2>msg && git diff --exit-code HEAD "$pos" && - test_i18ngrep "[Uu]sage:" msg + test_grep "[Uu]sage:" msg ' +# the following two test cherry-pick and revert with renames +# +# -- +# + rename2: renames oops to opos +# + rename1: renames oops to spoo +# + added: adds extra line to oops +# ++ initial: has lines in oops + test_expect_success 'cherry-pick after renaming branch' ' git checkout rename2 && @@ -99,7 +99,7 @@ test_expect_success 'revert forbidden on dirty working tree' ' echo content >extra_file && git add extra_file && test_must_fail git revert HEAD 2>errors && - test_i18ngrep "your local changes would be overwritten by " errors + test_grep "your local changes would be overwritten by " errors ' @@ -176,6 +176,29 @@ test_expect_success 'advice from failed revert' ' test_cmp expected actual ' +test_expect_subject () { + echo "$1" >expect && + git log -1 --pretty=%s >actual && + test_cmp expect actual +} + +test_expect_success 'titles of fresh reverts' ' + test_commit --no-tag A file1 && + test_commit --no-tag B file1 && + git revert --no-edit HEAD && + test_expect_subject "Revert \"B\"" && + git revert --no-edit HEAD && + test_expect_subject "Reapply \"B\"" && + git revert --no-edit HEAD && + test_expect_subject "Revert \"Reapply \"B\"\"" +' + +test_expect_success 'title of legacy double revert' ' + test_commit --no-tag "Revert \"Revert \"B\"\"" file1 && + git revert --no-edit HEAD && + test_expect_subject "Revert \"Revert \"Revert \"B\"\"\"" +' + test_expect_success 'identification of reverted commit (default)' ' test_commit to-ident && test_when_finished "git reset --hard to-ident" && diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh index f32799e046..c88d597b12 100755 --- a/t/t3507-cherry-pick-conflict.sh +++ b/t/t3507-cherry-pick-conflict.sh @@ -177,7 +177,7 @@ test_expect_success 'partial commit of cherry-pick fails' ' git add foo && test_must_fail git commit foo 2>err && - test_i18ngrep "cannot do a partial commit during a cherry-pick." err + test_grep "cannot do a partial commit during a cherry-pick." err ' test_expect_success 'commit --amend of cherry-pick fails' ' @@ -188,7 +188,7 @@ test_expect_success 'commit --amend of cherry-pick fails' ' git add foo && test_must_fail git commit --amend 2>err && - test_i18ngrep "in the middle of a cherry-pick -- cannot amend." err + test_grep "in the middle of a cherry-pick -- cannot amend." err ' test_expect_success 'successful final commit clears cherry-pick state' ' @@ -498,7 +498,7 @@ test_expect_success \ test_expect_success 'failed cherry-pick does not forget -s' ' pristine_detach initial && test_must_fail git cherry-pick -s picked && - test_i18ngrep -e "Signed-off-by" .git/MERGE_MSG + test_grep -e "Signed-off-by" .git/MERGE_MSG ' test_expect_success 'commit after failed cherry-pick does not add duplicated -s' ' @@ -563,7 +563,7 @@ test_expect_success 'cherry-pick preserves sparse-checkout' ' echo /unrelated >.git/info/sparse-checkout && git read-tree --reset -u HEAD && test_must_fail git cherry-pick -Xours picked>actual && - test_i18ngrep ! "Changes not staged for commit:" actual + test_grep ! "Changes not staged for commit:" actual ' test_expect_success 'cherry-pick --continue remembers --keep-redundant-commits' ' diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh index 3b0fa66c33..72020a51c4 100755 --- a/t/t3510-cherry-pick-sequence.sh +++ b/t/t3510-cherry-pick-sequence.sh @@ -154,7 +154,7 @@ test_expect_success 'skip "empty" commit' ' pristine_detach picked && test_commit dummy foo d && test_must_fail git cherry-pick anotherpick 2>err && - test_i18ngrep "git cherry-pick --skip" err && + test_grep "git cherry-pick --skip" err && git cherry-pick --skip && test_cmp_rev dummy HEAD ' @@ -314,7 +314,7 @@ test_expect_success '--abort does not unsafely change HEAD' ' git reset --hard base && test_must_fail git cherry-pick picked anotherpick && git cherry-pick --abort 2>actual && - test_i18ngrep "You seem to have moved HEAD" actual && + test_grep "You seem to have moved HEAD" actual && test_cmp_rev base HEAD ' @@ -520,7 +520,7 @@ test_expect_success '--continue asks for help after resolving patch to nil' ' test_cmp_rev unrelatedpick CHERRY_PICK_HEAD && git checkout HEAD -- unrelated && test_must_fail git cherry-pick --continue 2>msg && - test_i18ngrep "The previous cherry-pick is now empty" msg + test_grep "The previous cherry-pick is now empty" msg ' test_expect_success 'follow advice and skip nil patch' ' diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh index 0e8afe49ed..98259e2ada 100755 --- a/t/t3600-rm.sh +++ b/t/t3600-rm.sh @@ -276,7 +276,7 @@ test_expect_success 'Resolving by removal is not a warning-worthy event' ' blob=$(echo blob | git hash-object -w --stdin) && printf "100644 $blob %d\tblob\n" 1 2 3 | git update-index --index-info && git rm blob >msg 2>&1 && - test_i18ngrep ! "needs merge" msg && + test_grep ! "needs merge" msg && test_must_fail git ls-files -s --error-unmatch blob ' @@ -631,7 +631,7 @@ test_expect_success 'rm of a populated submodule with a .git directory migrates test_path_is_missing submod/.git && git status -s -uno --ignore-submodules=none >actual && test_file_not_empty actual && - test_i18ngrep Migrating output.err + test_grep Migrating output.err ' cat >expect.deepmodified <<EOF @@ -722,7 +722,7 @@ test_expect_success "rm absorbs submodule's nested .git directory" ' test_path_is_missing submod/subsubmod/.git && git status -s -uno --ignore-submodules=none >actual && test_file_not_empty actual && - test_i18ngrep Migrating output.err + test_grep Migrating output.err ' test_expect_success 'checking out a commit after submodule removal needs manual updates' ' @@ -731,7 +731,7 @@ test_expect_success 'checking out a commit after submodule removal needs manual git submodule update && git checkout -q HEAD^ && git checkout -q main 2>actual && - test_i18ngrep "^warning: unable to rmdir '\''submod'\'':" actual && + test_grep "^warning: unable to rmdir '\''submod'\'':" actual && git status -s submod >actual && echo "?? submod/" >expected && test_cmp expected actual && diff --git a/t/t3601-rm-pathspec-file.sh b/t/t3601-rm-pathspec-file.sh index a2a0c820fe..7cef12981c 100755 --- a/t/t3601-rm-pathspec-file.sh +++ b/t/t3601-rm-pathspec-file.sh @@ -67,14 +67,14 @@ test_expect_success 'error conditions' ' echo fileA.t >list && test_must_fail git rm --pathspec-from-file=list -- fileA.t 2>err && - test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err && + test_grep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err && test_must_fail git rm --pathspec-file-nul 2>err && - test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err && + test_grep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err && >empty_list && test_must_fail git rm --pathspec-from-file=empty_list 2>err && - test_i18ngrep -e "No pathspec was given. Which files should I remove?" err + test_grep -e "No pathspec was given. Which files should I remove?" err ' test_done diff --git a/t/t3650-replay-basics.sh b/t/t3650-replay-basics.sh new file mode 100755 index 0000000000..389670262e --- /dev/null +++ b/t/t3650-replay-basics.sh @@ -0,0 +1,198 @@ +#!/bin/sh + +test_description='basic git replay tests' + +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + +. ./test-lib.sh + +GIT_AUTHOR_NAME=author@name +GIT_AUTHOR_EMAIL=bogus@email@address +export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL + +test_expect_success 'setup' ' + test_commit A && + test_commit B && + + git switch -c topic1 && + test_commit C && + git switch -c topic2 && + test_commit D && + test_commit E && + git switch topic1 && + test_commit F && + git switch -c topic3 && + test_commit G && + test_commit H && + git switch -c topic4 main && + test_commit I && + test_commit J && + + git switch -c next main && + test_commit K && + git merge -m "Merge topic1" topic1 && + git merge -m "Merge topic2" topic2 && + git merge -m "Merge topic3" topic3 && + >evil && + git add evil && + git commit --amend && + git merge -m "Merge topic4" topic4 && + + git switch main && + test_commit L && + test_commit M && + + git switch -c conflict B && + test_commit C.conflict C.t conflict +' + +test_expect_success 'setup bare' ' + git clone --bare . bare +' + +test_expect_success 'using replay to rebase two branches, one on top of other' ' + git replay --onto main topic1..topic2 >result && + + test_line_count = 1 result && + + git log --format=%s $(cut -f 3 -d " " result) >actual && + test_write_lines E D M L B A >expect && + test_cmp expect actual && + + printf "update refs/heads/topic2 " >expect && + printf "%s " $(cut -f 3 -d " " result) >>expect && + git rev-parse topic2 >>expect && + + test_cmp expect result +' + +test_expect_success 'using replay on bare repo to rebase two branches, one on top of other' ' + git -C bare replay --onto main topic1..topic2 >result-bare && + test_cmp expect result-bare +' + +test_expect_success 'using replay to rebase with a conflict' ' + test_expect_code 1 git replay --onto topic1 B..conflict +' + +test_expect_success 'using replay on bare repo to rebase with a conflict' ' + test_expect_code 1 git -C bare replay --onto topic1 B..conflict +' + +test_expect_success 'using replay to perform basic cherry-pick' ' + # The differences between this test and previous ones are: + # --advance vs --onto + # 2nd field of result is refs/heads/main vs. refs/heads/topic2 + # 4th field of result is hash for main instead of hash for topic2 + + git replay --advance main topic1..topic2 >result && + + test_line_count = 1 result && + + git log --format=%s $(cut -f 3 -d " " result) >actual && + test_write_lines E D M L B A >expect && + test_cmp expect actual && + + printf "update refs/heads/main " >expect && + printf "%s " $(cut -f 3 -d " " result) >>expect && + git rev-parse main >>expect && + + test_cmp expect result +' + +test_expect_success 'using replay on bare repo to perform basic cherry-pick' ' + git -C bare replay --advance main topic1..topic2 >result-bare && + test_cmp expect result-bare +' + +test_expect_success 'replay on bare repo fails with both --advance and --onto' ' + test_must_fail git -C bare replay --advance main --onto main topic1..topic2 >result-bare +' + +test_expect_success 'replay fails when both --advance and --onto are omitted' ' + test_must_fail git replay topic1..topic2 >result +' + +test_expect_success 'using replay to also rebase a contained branch' ' + git replay --contained --onto main main..topic3 >result && + + test_line_count = 2 result && + cut -f 3 -d " " result >new-branch-tips && + + git log --format=%s $(head -n 1 new-branch-tips) >actual && + test_write_lines F C M L B A >expect && + test_cmp expect actual && + + git log --format=%s $(tail -n 1 new-branch-tips) >actual && + test_write_lines H G F C M L B A >expect && + test_cmp expect actual && + + printf "update refs/heads/topic1 " >expect && + printf "%s " $(head -n 1 new-branch-tips) >>expect && + git rev-parse topic1 >>expect && + printf "update refs/heads/topic3 " >>expect && + printf "%s " $(tail -n 1 new-branch-tips) >>expect && + git rev-parse topic3 >>expect && + + test_cmp expect result +' + +test_expect_success 'using replay on bare repo to also rebase a contained branch' ' + git -C bare replay --contained --onto main main..topic3 >result-bare && + test_cmp expect result-bare +' + +test_expect_success 'using replay to rebase multiple divergent branches' ' + git replay --onto main ^topic1 topic2 topic4 >result && + + test_line_count = 2 result && + cut -f 3 -d " " result >new-branch-tips && + + git log --format=%s $(head -n 1 new-branch-tips) >actual && + test_write_lines E D M L B A >expect && + test_cmp expect actual && + + git log --format=%s $(tail -n 1 new-branch-tips) >actual && + test_write_lines J I M L B A >expect && + test_cmp expect actual && + + printf "update refs/heads/topic2 " >expect && + printf "%s " $(head -n 1 new-branch-tips) >>expect && + git rev-parse topic2 >>expect && + printf "update refs/heads/topic4 " >>expect && + printf "%s " $(tail -n 1 new-branch-tips) >>expect && + git rev-parse topic4 >>expect && + + test_cmp expect result +' + +test_expect_success 'using replay on bare repo to rebase multiple divergent branches, including contained ones' ' + git -C bare replay --contained --onto main ^main topic2 topic3 topic4 >result && + + test_line_count = 4 result && + cut -f 3 -d " " result >new-branch-tips && + + >expect && + for i in 2 1 3 4 + do + printf "update refs/heads/topic$i " >>expect && + printf "%s " $(grep topic$i result | cut -f 3 -d " ") >>expect && + git -C bare rev-parse topic$i >>expect || return 1 + done && + + test_cmp expect result && + + test_write_lines F C M L B A >expect1 && + test_write_lines E D C M L B A >expect2 && + test_write_lines H G F C M L B A >expect3 && + test_write_lines J I M L B A >expect4 && + + for i in 1 2 3 4 + do + git -C bare log --format=%s $(grep topic$i result | cut -f 3 -d " ") >actual && + test_cmp expect$i actual || return 1 + done +' + +test_done diff --git a/t/t3700-add.sh b/t/t3700-add.sh index 51afbd7b24..f23d39f0d5 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -24,17 +24,17 @@ test_mode_in_index () { esac } -test_expect_success \ - 'Test of git add' \ - 'touch foo && git add foo' +test_expect_success 'Test of git add' ' + touch foo && git add foo +' -test_expect_success \ - 'Post-check that foo is in the index' \ - 'git ls-files foo | grep foo' +test_expect_success 'Post-check that foo is in the index' ' + git ls-files foo | grep foo +' -test_expect_success \ - 'Test that "git add -- -q" works' \ - 'touch -- -q && git add -- -q' +test_expect_success 'Test that "git add -- -q" works' ' + touch -- -q && git add -- -q +' BATCH_CONFIGURATION='-c core.fsync=loose-object -c core.fsyncmethod=batch' @@ -106,24 +106,32 @@ test_expect_success '.gitignore test setup' ' test_expect_success '.gitignore is honored' ' git add . && - ! (git ls-files | grep "\\.ig") + git ls-files >files && + sed -n "/\\.ig/p" <files >actual && + test_must_be_empty actual ' test_expect_success 'error out when attempting to add ignored ones without -f' ' test_must_fail git add a.?? && - ! (git ls-files | grep "\\.ig") + git ls-files >files && + sed -n "/\\.ig/p" <files >actual && + test_must_be_empty actual ' test_expect_success 'error out when attempting to add ignored ones without -f' ' test_must_fail git add d.?? && - ! (git ls-files | grep "\\.ig") + git ls-files >files && + sed -n "/\\.ig/p" <files >actual && + test_must_be_empty actual ' test_expect_success 'error out when attempting to add ignored ones but add others' ' touch a.if && test_must_fail git add a.?? && - ! (git ls-files | grep "\\.ig") && - (git ls-files | grep a.if) + git ls-files >files && + sed -n "/\\.ig/p" <files >actual && + test_must_be_empty actual && + grep a.if files ' test_expect_success 'add ignored ones with -f' ' @@ -276,14 +284,14 @@ test_expect_success POSIXPERM,SANITY 'git add (add.ignore-errors = false)' ' rm -f foo2 test_expect_success POSIXPERM,SANITY '--no-ignore-errors overrides config' ' - git config add.ignore-errors 1 && - git reset --hard && - date >foo1 && - date >foo2 && - chmod 0 foo2 && - test_must_fail git add --verbose --no-ignore-errors . && - ! ( git ls-files foo1 | grep foo1 ) && - git config add.ignore-errors 0 + git config add.ignore-errors 1 && + git reset --hard && + date >foo1 && + date >foo2 && + chmod 0 foo2 && + test_must_fail git add --verbose --no-ignore-errors . && + ! ( git ls-files foo1 | grep foo1 ) && + git config add.ignore-errors 0 ' rm -f foo2 @@ -430,7 +438,7 @@ test_expect_success 'git add --chmod fails with non regular files (but updates t test_ln_s_add foo foo3 && touch foo4 && test_must_fail git add --chmod=+x foo3 foo4 2>stderr && - test_i18ngrep "cannot chmod +x .foo3." stderr && + test_grep "cannot chmod +x .foo3." stderr && test_mode_in_index 120000 foo3 && test_mode_in_index 100755 foo4 ' @@ -447,12 +455,12 @@ test_expect_success 'git add --chmod --dry-run reports error for non regular fil git reset --hard && test_ln_s_add foo foo4 && test_must_fail git add --chmod=+x --dry-run foo4 2>stderr && - test_i18ngrep "cannot chmod +x .foo4." stderr + test_grep "cannot chmod +x .foo4." stderr ' test_expect_success 'git add --chmod --dry-run reports error for unmatched pathspec' ' test_must_fail git add --chmod=+x --dry-run nonexistent 2>stderr && - test_i18ngrep "pathspec .nonexistent. did not match any files" stderr + test_grep "pathspec .nonexistent. did not match any files" stderr ' test_expect_success 'no file status change if no pathspec is given' ' diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index 3a99837d9b..0b5339ac6c 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -7,12 +7,6 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh . "$TEST_DIRECTORY"/lib-terminal.sh -if test_have_prereq !PERL -then - skip_all='skipping add -i (scripted) tests, perl not available' - test_done -fi - diff_cmp () { for x do @@ -311,9 +305,11 @@ test_expect_success FILEMODE 'stage mode and hunk' ' echo content >>file && chmod +x file && printf "y\\ny\\n" | git add -p && - git diff --cached file | grep "new mode" && - git diff --cached file | grep "+content" && - test -z "$(git diff file)" + git diff --cached file >out && + grep "new mode" out && + grep "+content" out && + git diff file >out && + test_must_be_empty out ' # end of tests disabled when filemode is not usable @@ -339,12 +335,12 @@ test_expect_success 'different prompts for mode change/deleted' ' test_expect_success 'correct message when there is nothing to do' ' git reset --hard && git add -p 2>err && - test_i18ngrep "No changes" err && + test_grep "No changes" err && printf "\\0123" >binary && git add binary && printf "\\0abc" >binary && git add -p 2>err && - test_i18ngrep "Only binary files changed" err + test_grep "Only binary files changed" err ' test_expect_success 'setup again' ' @@ -501,7 +497,7 @@ test_expect_success 'adding an empty file' ' echo y | git checkout -p added-file -- >actual && test_path_is_file empty && - test_i18ngrep "Apply addition to index and worktree" actual + test_grep "Apply addition to index and worktree" actual ) ' @@ -738,6 +734,44 @@ test_expect_success 'colors can be overridden' ' test_cmp expect actual ' +test_expect_success 'brackets appear without color' ' + git reset --hard && + test_when_finished "git rm -f bracket-test" && + test_write_lines context old more-context >bracket-test && + git add bracket-test && + test_write_lines context new more-context another-one >bracket-test && + + test_write_lines quit >input && + git add -i >actual <input && + + sed "s/^|//" >expect <<-\EOF && + | staged unstaged path + | 1: +3/-0 +2/-1 bracket-test + | + |*** Commands *** + | 1: [s]tatus 2: [u]pdate 3: [r]evert 4: [a]dd untracked + | 5: [p]atch 6: [d]iff 7: [q]uit 8: [h]elp + |What now> Bye. + EOF + + test_cmp expect actual +' + +test_expect_success 'colors can be skipped with color.ui=false' ' + git reset --hard && + test_when_finished "git rm -f color-test" && + test_write_lines context old more-context >color-test && + git add color-test && + test_write_lines context new more-context another-one >color-test && + + test_write_lines help quit >input && + force_color git \ + -c color.ui=false \ + add -i >actual.raw <input && + test_decode_color <actual.raw >actual && + test_cmp actual.raw actual +' + test_expect_success 'colorized diffs respect diff.wsErrorHighlight' ' git reset --hard && @@ -804,7 +838,7 @@ test_expect_success 'diff.algorithm is passed to `git diff-files`' ' git add file && echo changed >file && test_must_fail git -c diff.algorithm=bogus add -p 2>err && - test_i18ngrep "error: option diff-algorithm accepts " err + test_grep "error: option diff-algorithm accepts " err ' test_expect_success 'patch-mode via -i prompts for files' ' @@ -1075,4 +1109,25 @@ test_expect_success 'show help from add--helper' ' test_cmp expect actual ' +test_expect_success 'reset -p with unmerged files' ' + test_when_finished "git checkout --force main" && + test_commit one conflict && + git checkout -B side HEAD^ && + test_commit two conflict && + test_must_fail git merge one && + + # this is a noop with only an unmerged entry + git reset -p && + + # add files that sort before and after unmerged entry + echo a >a && + echo z >z && + git add a z && + + # confirm that we can reset those files + printf "%s\n" y y | git reset -p && + git diff-index --cached --diff-filter=u HEAD >staged && + test_must_be_empty staged +' + test_done diff --git a/t/t3704-add-pathspec-file.sh b/t/t3704-add-pathspec-file.sh index 4e6b5177c9..3aa59f6f63 100755 --- a/t/t3704-add-pathspec-file.sh +++ b/t/t3704-add-pathspec-file.sh @@ -138,23 +138,23 @@ test_expect_success 'error conditions' ' >empty_list && test_must_fail git add --pathspec-from-file=list --interactive 2>err && - test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err && + test_grep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err && test_must_fail git add --pathspec-from-file=list --patch 2>err && - test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err && + test_grep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err && test_must_fail git add --pathspec-from-file=list --edit 2>err && - test_i18ngrep -e "options .--pathspec-from-file. and .--edit. cannot be used together" err && + test_grep -e "options .--pathspec-from-file. and .--edit. cannot be used together" err && test_must_fail git add --pathspec-from-file=list -- fileA.t 2>err && - test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err && + test_grep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err && test_must_fail git add --pathspec-file-nul 2>err && - test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err && + test_grep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err && # This case succeeds, but still prints to stderr git add --pathspec-from-file=empty_list 2>err && - test_i18ngrep -e "Nothing specified, nothing added." err + test_grep -e "Nothing specified, nothing added." err ' test_done diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh index bfab245eb3..f27d09cfd9 100755 --- a/t/t3900-i18n-commit.sh +++ b/t/t3900-i18n-commit.sh @@ -45,7 +45,7 @@ test_expect_success 'UTF-8 invalid characters refused' ' printf "Commit message\n\nInvalid surrogate:\355\240\200\n" \ >"$HOME/invalid" && git commit -a -F "$HOME/invalid" 2>"$HOME"/stderr && - test_i18ngrep "did not conform" "$HOME"/stderr + test_grep "did not conform" "$HOME"/stderr ' test_expect_success 'UTF-8 overlong sequences rejected' ' @@ -55,7 +55,7 @@ test_expect_success 'UTF-8 overlong sequences rejected' ' printf "\340\202\251ommit message\n\nThis is not a space:\300\240\n" \ >"$HOME/invalid" && git commit -a -F "$HOME/invalid" 2>"$HOME"/stderr && - test_i18ngrep "did not conform" "$HOME"/stderr + test_grep "did not conform" "$HOME"/stderr ' test_expect_success 'UTF-8 non-characters refused' ' @@ -64,7 +64,7 @@ test_expect_success 'UTF-8 non-characters refused' ' printf "Commit message\n\nNon-character:\364\217\277\276\n" \ >"$HOME/invalid" && git commit -a -F "$HOME/invalid" 2>"$HOME"/stderr && - test_i18ngrep "did not conform" "$HOME"/stderr + test_grep "did not conform" "$HOME"/stderr ' test_expect_success 'UTF-8 non-characters refused' ' @@ -73,7 +73,7 @@ test_expect_success 'UTF-8 non-characters refused' ' printf "Commit message\n\nNon-character:\357\267\220\n" \ >"$HOME/invalid" && git commit -a -F "$HOME/invalid" 2>"$HOME"/stderr && - test_i18ngrep "did not conform" "$HOME"/stderr + test_grep "did not conform" "$HOME"/stderr ' for H in ISO8859-1 eucJP ISO-2022-JP diff --git a/t/t3901-i18n-patch.sh b/t/t3901-i18n-patch.sh index 4f16a735d9..4b37f78829 100755 --- a/t/t3901-i18n-patch.sh +++ b/t/t3901-i18n-patch.sh @@ -298,7 +298,7 @@ test_expect_success 'am --no-utf8 (U/L)' ' # commit-tree will warn that the commit message does not contain valid UTF-8 # as mailinfo did not convert it - test_i18ngrep "did not conform" err && + test_grep "did not conform" err && check_encoding 2 ' diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh index 376cc8f4ab..34faeac3f1 100755 --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@ -395,7 +395,7 @@ test_expect_success 'stash --staged' ' test_expect_success 'dont assume push with non-option args' ' test_must_fail git stash -q drop 2>err && - test_i18ngrep -e "subcommand wasn'\''t specified; '\''push'\'' can'\''t be assumed due to unexpected token '\''drop'\''" err + test_grep -e "subcommand wasn'\''t specified; '\''push'\'' can'\''t be assumed due to unexpected token '\''drop'\''" err ' test_expect_success 'stash --invalid-option' ' @@ -596,7 +596,7 @@ test_expect_success 'giving too many ref arguments does not modify files' ' for type in apply pop "branch stash-branch" do test_must_fail git stash $type stash@{0} stash@{1} 2>err && - test_i18ngrep "Too many revisions" err && + test_grep "Too many revisions" err && test 123456789 = $(test-tool chmtime -g file2) || return 1 done ' @@ -604,14 +604,14 @@ test_expect_success 'giving too many ref arguments does not modify files' ' test_expect_success 'drop: too many arguments errors out (does nothing)' ' git stash list >expect && test_must_fail git stash drop stash@{0} stash@{1} 2>err && - test_i18ngrep "Too many revisions" err && + test_grep "Too many revisions" err && git stash list >actual && test_cmp expect actual ' test_expect_success 'show: too many arguments errors out (does nothing)' ' test_must_fail git stash show stash@{0} stash@{1} 2>err 1>out && - test_i18ngrep "Too many revisions" err && + test_grep "Too many revisions" err && test_must_be_empty out ' @@ -654,7 +654,7 @@ test_expect_success 'stash branch - stashes on stack, stash-like argument' ' test_expect_success 'stash branch complains with no arguments' ' test_must_fail git stash branch 2>err && - test_i18ngrep "No branch name specified" err + test_grep "No branch name specified" err ' test_expect_success 'stash show format defaults to --stat' ' @@ -931,6 +931,10 @@ test_expect_success 'store called with invalid commit' ' test_must_fail git stash store foo ' +test_expect_success 'store called with non-stash commit' ' + test_must_fail git stash store HEAD +' + test_expect_success 'store updates stash ref and reflog' ' git stash clear && git reset --hard && @@ -1211,19 +1215,19 @@ test_expect_success 'stash with file including $IFS character' ' ' test_expect_success 'stash with pathspec matching multiple paths' ' - echo original >file && - echo original >other-file && - git commit -m "two" file other-file && - echo modified >file && - echo modified >other-file && - git stash push -- "*file" && - echo original >expect && - test_cmp expect file && - test_cmp expect other-file && - git stash pop && - echo modified >expect && - test_cmp expect file && - test_cmp expect other-file + echo original >file && + echo original >other-file && + git commit -m "two" file other-file && + echo modified >file && + echo modified >other-file && + git stash push -- "*file" && + echo original >expect && + test_cmp expect file && + test_cmp expect other-file && + git stash pop && + echo modified >expect && + test_cmp expect file && + test_cmp expect other-file ' test_expect_success 'stash push -p with pathspec shows no changes only once' ' diff --git a/t/t3905-stash-include-untracked.sh b/t/t3905-stash-include-untracked.sh index 5390eec4e3..1289ae3e07 100755 --- a/t/t3905-stash-include-untracked.sh +++ b/t/t3905-stash-include-untracked.sh @@ -404,7 +404,7 @@ test_expect_success 'stash show --include-untracked errors on duplicate files' ' ) && w_commit=$(git commit-tree -p HEAD -p "$i_commit" -p "$u_commit" -m "WIP on any-branch" "$tree") && test_must_fail git stash show --include-untracked "$w_commit" 2>err && - test_i18ngrep "worktree and untracked commit have duplicate entries: tracked" err + test_grep "worktree and untracked commit have duplicate entries: tracked" err ' test_expect_success 'stash show --{include,only}-untracked on stashes without untracked entries' ' diff --git a/t/t3909-stash-pathspec-file.sh b/t/t3909-stash-pathspec-file.sh index dead9f18d9..73f2dbdeb0 100755 --- a/t/t3909-stash-pathspec-file.sh +++ b/t/t3909-stash-pathspec-file.sh @@ -88,13 +88,13 @@ test_expect_success 'error conditions' ' echo fileA.t >list && test_must_fail git stash push --pathspec-from-file=list --patch 2>err && - test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err && + test_grep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err && test_must_fail git stash push --pathspec-from-file=list -- fileA.t 2>err && - test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err && + test_grep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err && test_must_fail git stash push --pathspec-file-nul 2>err && - test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err + test_grep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err ' test_done diff --git a/t/t4000-diff-format.sh b/t/t4000-diff-format.sh index bfcaae390f..8d50331b8c 100755 --- a/t/t4000-diff-format.sh +++ b/t/t4000-diff-format.sh @@ -5,6 +5,9 @@ test_description='Test built-in diff output engine. +We happen to know that all diff plumbing and diff Porcelain share the +same command line parser, so testing one should be sufficient; pick +diff-files as a representative. ' TEST_PASSES_SANITIZE_LEAK=true @@ -16,9 +19,11 @@ Line 2 line 3' cat path0 >path1 chmod +x path1 +mkdir path2 +>path2/path3 test_expect_success 'update-index --add two files with and without +x.' ' - git update-index --add path0 path1 + git update-index --add path0 path1 path2/path3 ' mv path0 path0- @@ -91,4 +96,31 @@ test_expect_success 'git diff-files --patch --no-patch does not show the patch' test_must_be_empty err ' + +# Smudge path2/path3 so that dirstat has something to show +date >path2/path3 + +for format in stat raw numstat shortstat summary \ + dirstat cumulative dirstat-by-file \ + patch-with-raw patch-with-stat compact-summary +do + test_expect_success "--no-patch in 'git diff-files --no-patch --$format' is a no-op" ' + git diff-files --no-patch "--$format" >actual && + git diff-files "--$format" >expect && + test_cmp expect actual + ' + + test_expect_success "--no-patch clears all previous ones" ' + git diff-files --$format -s -p >actual && + git diff-files -p >expect && + test_cmp expect actual + ' + + test_expect_success "--no-patch in 'git diff --no-patch --$format' is a no-op" ' + git diff --no-patch "--$format" >actual && + git diff "--$format" >expect && + test_cmp expect actual + ' +done + test_done diff --git a/t/t4001-diff-rename.sh b/t/t4001-diff-rename.sh index 3dc9047044..85be1367de 100755 --- a/t/t4001-diff-rename.sh +++ b/t/t4001-diff-rename.sh @@ -135,25 +135,25 @@ test_expect_success 'favour same basenames over different ones' ' mkdir subdir && git mv another-path subdir/path1 && git status >out && - test_i18ngrep "renamed: .*path1 -> subdir/path1" out + test_grep "renamed: .*path1 -> subdir/path1" out ' test_expect_success 'test diff.renames=true for git status' ' git -c diff.renames=true status >out && - test_i18ngrep "renamed: .*path1 -> subdir/path1" out + test_grep "renamed: .*path1 -> subdir/path1" out ' test_expect_success 'test diff.renames=false for git status' ' git -c diff.renames=false status >out && - test_i18ngrep ! "renamed: .*path1 -> subdir/path1" out && - test_i18ngrep "new file: .*subdir/path1" out && - test_i18ngrep "deleted: .*[^/]path1" out + test_grep ! "renamed: .*path1 -> subdir/path1" out && + test_grep "new file: .*subdir/path1" out && + test_grep "deleted: .*[^/]path1" out ' test_expect_success 'favour same basenames even with minor differences' ' git show HEAD:path1 | sed "s/15/16/" > subdir/path1 && git status >out && - test_i18ngrep "renamed: .*path1 -> subdir/path1" out + test_grep "renamed: .*path1 -> subdir/path1" out ' test_expect_success 'two files with same basename and same content' ' @@ -165,7 +165,7 @@ test_expect_success 'two files with same basename and same content' ' git commit -m 2 && git mv dir other-dir && git status >out && - test_i18ngrep "renamed: .*dir/A/file -> other-dir/A/file" out + test_grep "renamed: .*dir/A/file -> other-dir/A/file" out ' test_expect_success 'setup for many rename source candidates' ' @@ -202,9 +202,9 @@ test_expect_success 'rename pretty print with nothing in common' ' git mv a/b/c c/b/a && git commit -m "a/b/c -> c/b/a" && git diff -M --summary HEAD^ HEAD >output && - test_i18ngrep " a/b/c => c/b/a " output && + test_grep " a/b/c => c/b/a " output && git diff -M --stat HEAD^ HEAD >output && - test_i18ngrep " a/b/c => c/b/a " output + test_grep " a/b/c => c/b/a " output ' test_expect_success 'rename pretty print with common prefix' ' @@ -212,9 +212,9 @@ test_expect_success 'rename pretty print with common prefix' ' git mv c/b/a c/d/e && git commit -m "c/b/a -> c/d/e" && git diff -M --summary HEAD^ HEAD >output && - test_i18ngrep " c/{b/a => d/e} " output && + test_grep " c/{b/a => d/e} " output && git diff -M --stat HEAD^ HEAD >output && - test_i18ngrep " c/{b/a => d/e} " output + test_grep " c/{b/a => d/e} " output ' test_expect_success 'rename pretty print with common suffix' ' @@ -222,9 +222,9 @@ test_expect_success 'rename pretty print with common suffix' ' git mv c/d/e d/e && git commit -m "c/d/e -> d/e" && git diff -M --summary HEAD^ HEAD >output && - test_i18ngrep " {c/d => d}/e " output && + test_grep " {c/d => d}/e " output && git diff -M --stat HEAD^ HEAD >output && - test_i18ngrep " {c/d => d}/e " output + test_grep " {c/d => d}/e " output ' test_expect_success 'rename pretty print with common prefix and suffix' ' @@ -232,9 +232,9 @@ test_expect_success 'rename pretty print with common prefix and suffix' ' git mv d/e d/f/e && git commit -m "d/e -> d/f/e" && git diff -M --summary HEAD^ HEAD >output && - test_i18ngrep " d/{ => f}/e " output && + test_grep " d/{ => f}/e " output && git diff -M --stat HEAD^ HEAD >output && - test_i18ngrep " d/{ => f}/e " output + test_grep " d/{ => f}/e " output ' test_expect_success 'rename pretty print common prefix and suffix overlap' ' @@ -242,9 +242,9 @@ test_expect_success 'rename pretty print common prefix and suffix overlap' ' git mv d/f/e d/f/f/e && git commit -m "d/f/e d/f/f/e" && git diff -M --summary HEAD^ HEAD >output && - test_i18ngrep " d/f/{ => f}/e " output && + test_grep " d/f/{ => f}/e " output && git diff -M --stat HEAD^ HEAD >output && - test_i18ngrep " d/f/{ => f}/e " output + test_grep " d/f/{ => f}/e " output ' test_expect_success 'diff-tree -l0 defaults to a big rename limit, not zero' ' diff --git a/t/t4002-diff-basic.sh b/t/t4002-diff-basic.sh index ea52e5b91b..7afc883ec3 100755 --- a/t/t4002-diff-basic.sh +++ b/t/t4002-diff-basic.sh @@ -284,132 +284,131 @@ cmp_diff_files_output () { test_cmp "$1" .test-tmp } -test_expect_success \ - 'diff-tree of known trees.' \ - 'git diff-tree $tree_O $tree_A >.test-a && - cmp -s .test-a .test-plain-OA' - -test_expect_success \ - 'diff-tree of known trees.' \ - 'git diff-tree -r $tree_O $tree_A >.test-a && - cmp -s .test-a .test-recursive-OA' - -test_expect_success \ - 'diff-tree of known trees.' \ - 'git diff-tree $tree_O $tree_B >.test-a && - cmp -s .test-a .test-plain-OB' - -test_expect_success \ - 'diff-tree of known trees.' \ - 'git diff-tree -r $tree_O $tree_B >.test-a && - cmp -s .test-a .test-recursive-OB' - -test_expect_success \ - 'diff-tree of known trees.' \ - 'git diff-tree $tree_A $tree_B >.test-a && - cmp -s .test-a .test-plain-AB' - -test_expect_success \ - 'diff-tree of known trees.' \ - 'git diff-tree -r $tree_A $tree_B >.test-a && - cmp -s .test-a .test-recursive-AB' - -test_expect_success \ - 'diff-tree --stdin of known trees.' \ - 'echo $tree_A $tree_B | git diff-tree --stdin > .test-a && - echo $tree_A $tree_B > .test-plain-ABx && - cat .test-plain-AB >> .test-plain-ABx && - cmp -s .test-a .test-plain-ABx' - -test_expect_success \ - 'diff-tree --stdin of known trees.' \ - 'echo $tree_A $tree_B | git diff-tree -r --stdin > .test-a && - echo $tree_A $tree_B > .test-recursive-ABx && - cat .test-recursive-AB >> .test-recursive-ABx && - cmp -s .test-a .test-recursive-ABx' - -test_expect_success \ - 'diff-cache O with A in cache' \ - 'git read-tree $tree_A && - git diff-index --cached $tree_O >.test-a && - cmp -s .test-a .test-recursive-OA' - -test_expect_success \ - 'diff-cache O with B in cache' \ - 'git read-tree $tree_B && - git diff-index --cached $tree_O >.test-a && - cmp -s .test-a .test-recursive-OB' - -test_expect_success \ - 'diff-cache A with B in cache' \ - 'git read-tree $tree_B && - git diff-index --cached $tree_A >.test-a && - cmp -s .test-a .test-recursive-AB' - -test_expect_success \ - 'diff-files with O in cache and A checked out' \ - 'rm -fr Z [A-Z][A-Z] && - git read-tree $tree_A && - git checkout-index -f -a && - git read-tree --reset $tree_O && - test_must_fail git update-index --refresh -q && - git diff-files >.test-a && - cmp_diff_files_output .test-a .test-recursive-OA' - -test_expect_success \ - 'diff-files with O in cache and B checked out' \ - 'rm -fr Z [A-Z][A-Z] && - git read-tree $tree_B && - git checkout-index -f -a && - git read-tree --reset $tree_O && - test_must_fail git update-index --refresh -q && - git diff-files >.test-a && - cmp_diff_files_output .test-a .test-recursive-OB' - -test_expect_success \ - 'diff-files with A in cache and B checked out' \ - 'rm -fr Z [A-Z][A-Z] && - git read-tree $tree_B && - git checkout-index -f -a && - git read-tree --reset $tree_A && - test_must_fail git update-index --refresh -q && - git diff-files >.test-a && - cmp_diff_files_output .test-a .test-recursive-AB' +test_expect_success 'diff-tree of known trees.' ' + git diff-tree $tree_O $tree_A >.test-a && + cmp -s .test-a .test-plain-OA +' + +test_expect_success 'diff-tree of known trees.' ' + git diff-tree -r $tree_O $tree_A >.test-a && + cmp -s .test-a .test-recursive-OA +' + +test_expect_success 'diff-tree of known trees.' ' + git diff-tree $tree_O $tree_B >.test-a && + cmp -s .test-a .test-plain-OB +' + +test_expect_success 'diff-tree of known trees.' ' + git diff-tree -r $tree_O $tree_B >.test-a && + cmp -s .test-a .test-recursive-OB +' + +test_expect_success 'diff-tree of known trees.' ' + git diff-tree $tree_A $tree_B >.test-a && + cmp -s .test-a .test-plain-AB +' + +test_expect_success 'diff-tree of known trees.' ' + git diff-tree -r $tree_A $tree_B >.test-a && + cmp -s .test-a .test-recursive-AB +' + +test_expect_success 'diff-tree --stdin of known trees.' ' + echo $tree_A $tree_B | git diff-tree --stdin > .test-a && + echo $tree_A $tree_B > .test-plain-ABx && + cat .test-plain-AB >> .test-plain-ABx && + cmp -s .test-a .test-plain-ABx +' + +test_expect_success 'diff-tree --stdin of known trees.' ' + echo $tree_A $tree_B | git diff-tree -r --stdin > .test-a && + echo $tree_A $tree_B > .test-recursive-ABx && + cat .test-recursive-AB >> .test-recursive-ABx && + cmp -s .test-a .test-recursive-ABx +' + +test_expect_success 'diff-cache O with A in cache' ' + git read-tree $tree_A && + git diff-index --cached $tree_O >.test-a && + cmp -s .test-a .test-recursive-OA +' + +test_expect_success 'diff-cache O with B in cache' ' + git read-tree $tree_B && + git diff-index --cached $tree_O >.test-a && + cmp -s .test-a .test-recursive-OB +' + +test_expect_success 'diff-cache A with B in cache' ' + git read-tree $tree_B && + git diff-index --cached $tree_A >.test-a && + cmp -s .test-a .test-recursive-AB +' + +test_expect_success 'diff-files with O in cache and A checked out' ' + rm -fr Z [A-Z][A-Z] && + git read-tree $tree_A && + git checkout-index -f -a && + git read-tree --reset $tree_O && + test_must_fail git update-index --refresh -q && + git diff-files >.test-a && + cmp_diff_files_output .test-a .test-recursive-OA +' + +test_expect_success 'diff-files with O in cache and B checked out' ' + rm -fr Z [A-Z][A-Z] && + git read-tree $tree_B && + git checkout-index -f -a && + git read-tree --reset $tree_O && + test_must_fail git update-index --refresh -q && + git diff-files >.test-a && + cmp_diff_files_output .test-a .test-recursive-OB +' + +test_expect_success 'diff-files with A in cache and B checked out' ' + rm -fr Z [A-Z][A-Z] && + git read-tree $tree_B && + git checkout-index -f -a && + git read-tree --reset $tree_A && + test_must_fail git update-index --refresh -q && + git diff-files >.test-a && + cmp_diff_files_output .test-a .test-recursive-AB +' ################################################################ # Now we have established the baseline, we do not have to # rely on individual object ID values that much. -test_expect_success \ - 'diff-tree O A == diff-tree -R A O' \ - 'git diff-tree $tree_O $tree_A >.test-a && - git diff-tree -R $tree_A $tree_O >.test-b && - cmp -s .test-a .test-b' - -test_expect_success \ - 'diff-tree -r O A == diff-tree -r -R A O' \ - 'git diff-tree -r $tree_O $tree_A >.test-a && - git diff-tree -r -R $tree_A $tree_O >.test-b && - cmp -s .test-a .test-b' - -test_expect_success \ - 'diff-tree B A == diff-tree -R A B' \ - 'git diff-tree $tree_B $tree_A >.test-a && - git diff-tree -R $tree_A $tree_B >.test-b && - cmp -s .test-a .test-b' - -test_expect_success \ - 'diff-tree -r B A == diff-tree -r -R A B' \ - 'git diff-tree -r $tree_B $tree_A >.test-a && - git diff-tree -r -R $tree_A $tree_B >.test-b && - cmp -s .test-a .test-b' - -test_expect_success \ - 'diff can read from stdin' \ - 'test_must_fail git diff --no-index -- MN - < NN | - grep -v "^index" | sed "s#/-#/NN#" >.test-a && - test_must_fail git diff --no-index -- MN NN | - grep -v "^index" >.test-b && - test_cmp .test-a .test-b' +test_expect_success 'diff-tree O A == diff-tree -R A O' ' + git diff-tree $tree_O $tree_A >.test-a && + git diff-tree -R $tree_A $tree_O >.test-b && + cmp -s .test-a .test-b +' + +test_expect_success 'diff-tree -r O A == diff-tree -r -R A O' ' + git diff-tree -r $tree_O $tree_A >.test-a && + git diff-tree -r -R $tree_A $tree_O >.test-b && + cmp -s .test-a .test-b +' + +test_expect_success 'diff-tree B A == diff-tree -R A B' ' + git diff-tree $tree_B $tree_A >.test-a && + git diff-tree -R $tree_A $tree_B >.test-b && + cmp -s .test-a .test-b +' + +test_expect_success 'diff-tree -r B A == diff-tree -r -R A B' ' + git diff-tree -r $tree_B $tree_A >.test-a && + git diff-tree -r -R $tree_A $tree_B >.test-b && + cmp -s .test-a .test-b' + +test_expect_success 'diff can read from stdin' ' + test_must_fail git diff --no-index -- MN - < NN | + grep -v "^index" | sed "s#/-#/NN#" >.test-a && + test_must_fail git diff --no-index -- MN NN | + grep -v "^index" >.test-b && + test_cmp .test-a .test-b +' test_done diff --git a/t/t4003-diff-rename-1.sh b/t/t4003-diff-rename-1.sh index 181e9683a7..ebe091828c 100755 --- a/t/t4003-diff-rename-1.sh +++ b/t/t4003-diff-rename-1.sh @@ -11,20 +11,20 @@ TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff.sh ;# test-lib chdir's into trash -test_expect_success \ - 'prepare reference tree' \ - 'COPYING_test_data >COPYING && - echo frotz >rezrov && - git update-index --add COPYING rezrov && - tree=$(git write-tree) && - echo $tree' - -test_expect_success \ - 'prepare work tree' \ - 'sed -e 's/HOWEVER/However/' <COPYING >COPYING.1 && - sed -e 's/GPL/G.P.L/g' <COPYING >COPYING.2 && - rm -f COPYING && - git update-index --add --remove COPYING COPYING.?' +test_expect_success 'prepare reference tree' ' + COPYING_test_data >COPYING && + echo frotz >rezrov && + git update-index --add COPYING rezrov && + tree=$(git write-tree) && + echo $tree +' + +test_expect_success 'prepare work tree' ' + sed -e 's/HOWEVER/However/' <COPYING >COPYING.1 && + sed -e 's/GPL/G.P.L/g' <COPYING >COPYING.2 && + rm -f COPYING && + git update-index --add --remove COPYING COPYING.? +' # tree has COPYING and rezrov. work tree has COPYING.1 and COPYING.2, # both are slightly edited, and unchanged rezrov. So we say you @@ -57,14 +57,14 @@ rename to COPYING.2 + This file is licensed under the G.P.L v2, or a later version EOF -test_expect_success \ - 'validate output from rename/copy detection (#1)' \ - 'compare_diff_patch current expected' +test_expect_success 'validate output from rename/copy detection (#1)' ' + compare_diff_patch current expected +' -test_expect_success \ - 'prepare work tree again' \ - 'mv COPYING.2 COPYING && - git update-index --add --remove COPYING COPYING.1 COPYING.2' +test_expect_success 'prepare work tree again' ' + mv COPYING.2 COPYING && + git update-index --add --remove COPYING COPYING.1 COPYING.2 +' # tree has COPYING and rezrov. work tree has COPYING and COPYING.1, # both are slightly edited, and unchanged rezrov. So we say you @@ -95,14 +95,14 @@ copy to COPYING.1 + However, in order to allow a migration to GPLv3 if that seems like EOF -test_expect_success \ - 'validate output from rename/copy detection (#2)' \ - 'compare_diff_patch current expected' +test_expect_success 'validate output from rename/copy detection (#2)' ' + compare_diff_patch current expected +' -test_expect_success \ - 'prepare work tree once again' \ - 'COPYING_test_data >COPYING && - git update-index --add --remove COPYING COPYING.1' +test_expect_success 'prepare work tree once again' ' + COPYING_test_data >COPYING && + git update-index --add --remove COPYING COPYING.1 +' # tree has COPYING and rezrov. work tree has COPYING and COPYING.1, # but COPYING is not edited. We say you copy-and-edit COPYING.1; this @@ -123,8 +123,8 @@ copy to COPYING.1 + However, in order to allow a migration to GPLv3 if that seems like EOF -test_expect_success \ - 'validate output from rename/copy detection (#3)' \ - 'compare_diff_patch current expected' +test_expect_success 'validate output from rename/copy detection (#3)' ' + compare_diff_patch current expected +' test_done diff --git a/t/t4004-diff-rename-symlink.sh b/t/t4004-diff-rename-symlink.sh index 8def4d4aee..1d70d4d221 100755 --- a/t/t4004-diff-rename-symlink.sh +++ b/t/t4004-diff-rename-symlink.sh @@ -14,21 +14,21 @@ TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff.sh -test_expect_success SYMLINKS \ - 'prepare reference tree' \ - 'echo xyzzy | tr -d '\\\\'012 >yomin && - ln -s xyzzy frotz && - git update-index --add frotz yomin && - tree=$(git write-tree) && - echo $tree' +test_expect_success SYMLINKS 'prepare reference tree' ' + echo xyzzy | tr -d '\\\\'012 >yomin && + ln -s xyzzy frotz && + git update-index --add frotz yomin && + tree=$(git write-tree) && + echo $tree +' -test_expect_success SYMLINKS \ - 'prepare work tree' \ - 'mv frotz rezrov && - rm -f yomin && - ln -s xyzzy nitfol && - ln -s xzzzy bozbar && - git update-index --add --remove frotz rezrov nitfol bozbar yomin' +test_expect_success SYMLINKS 'prepare work tree' ' + mv frotz rezrov && + rm -f yomin && + ln -s xyzzy nitfol && + ln -s xzzzy bozbar && + git update-index --add --remove frotz rezrov nitfol bozbar yomin +' # tree has frotz pointing at xyzzy, and yomin that contains xyzzy to # confuse things. work tree has rezrov (xyzzy) nitfol (xyzzy) and @@ -36,9 +36,9 @@ test_expect_success SYMLINKS \ # rezrov and nitfol are rename/copy of frotz and bozbar should be # a new creation. -test_expect_success SYMLINKS 'setup diff output' " - GIT_DIFF_OPTS=--unified=0 git diff-index -C -p $tree >current && - cat >expected <<\EOF +test_expect_success SYMLINKS 'setup diff output' ' + GIT_DIFF_OPTS=--unified=0 git diff-index -C -p $tree >current && + cat >expected <<\EOF diff --git a/bozbar b/bozbar new file mode 120000 --- /dev/null @@ -62,10 +62,10 @@ deleted file mode 100644 -xyzzy \ No newline at end of file EOF -" +' -test_expect_success SYMLINKS \ - 'validate diff output' \ - 'compare_diff_patch current expected' +test_expect_success SYMLINKS 'validate diff output' ' + compare_diff_patch current expected +' test_done diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index dfcf3a0aaa..cb094241ec 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -178,32 +178,29 @@ process_diffs () { V=$(git version | sed -e 's/^git version //' -e 's/\./\\./g') while read magic cmd do - status=success case "$magic" in '' | '#'*) continue ;; - :*) - magic=${magic#:} + :noellipses) + magic=noellipses label="$magic-$cmd" - case "$magic" in - noellipses) ;; - failure) - status=failure - magic= - label="$cmd" ;; - *) - BUG "unknown magic $magic" ;; - esac ;; + ;; + :*) + BUG "unknown magic $magic" + ;; *) - cmd="$magic $cmd" magic= - label="$cmd" ;; + cmd="$magic $cmd" + magic= + label="$cmd" + ;; esac + test=$(echo "$label" | sed -e 's|[/ ][/ ]*|_|g') pfx=$(printf "%04d" $test_count) expect="$TEST_DIRECTORY/t4013/diff.$test" actual="$pfx-diff.$test" - test_expect_$status "git $cmd # magic is ${magic:-(not used)}" ' + test_expect_success "git $cmd # magic is ${magic:-(not used)}" ' { echo "$ git $cmd" case "$magic" in @@ -473,6 +470,14 @@ test_expect_success 'log --diff-merges=on matches --diff-merges=separate' ' test_cmp expected actual ' +test_expect_success 'log --dd matches --diff-merges=1 -p' ' + git log --diff-merges=1 -p master >result && + process_diffs result >expected && + git log --dd master >result && + process_diffs result >actual && + test_cmp expected actual +' + test_expect_success 'deny wrong log.diffMerges config' ' test_config log.diffMerges wrong-value && test_expect_code 128 git log @@ -514,7 +519,7 @@ test_expect_success 'log -S requires an argument' ' ' test_expect_success 'diff --cached on unborn branch' ' - echo ref: refs/heads/unborn >.git/HEAD && + git symbolic-ref HEAD refs/heads/unborn && git diff --cached >result && process_diffs result >actual && process_diffs "$TEST_DIRECTORY/t4013/diff.diff_--cached" >expected && @@ -613,7 +618,49 @@ test_expect_success 'diff -I<regex> --stat' ' test_expect_success 'diff -I<regex>: detect malformed regex' ' test_expect_code 129 git diff --ignore-matching-lines="^[124-9" 2>error && - test_i18ngrep "invalid regex given to -I: " error + test_grep "invalid regex given to -I: " error +' + +# check_prefix <patch> <src> <dst> +# check only lines with paths to avoid dependency on exact oid/contents +check_prefix () { + grep -E '^(diff|---|\+\+\+) ' "$1" >actual.paths && + cat >expect <<-EOF && + diff --git $2 $3 + --- $2 + +++ $3 + EOF + test_cmp expect actual.paths +} + +test_expect_success 'diff-files does not respect diff.noprefix' ' + git -c diff.noprefix diff-files -p >actual && + check_prefix actual a/file0 b/file0 +' + +test_expect_success 'diff-files respects --no-prefix' ' + git diff-files -p --no-prefix >actual && + check_prefix actual file0 file0 +' + +test_expect_success 'diff respects diff.noprefix' ' + git -c diff.noprefix diff >actual && + check_prefix actual file0 file0 +' + +test_expect_success 'diff --default-prefix overrides diff.noprefix' ' + git -c diff.noprefix diff --default-prefix >actual && + check_prefix actual a/file0 b/file0 +' + +test_expect_success 'diff respects diff.mnemonicprefix' ' + git -c diff.mnemonicprefix diff >actual && + check_prefix actual i/file0 w/file0 +' + +test_expect_success 'diff --default-prefix overrides diff.mnemonicprefix' ' + git -c diff.mnemonicprefix diff --default-prefix >actual && + check_prefix actual a/file0 b/file0 ' test_done diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index f3313b8c58..e37a1411ee 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -59,6 +59,10 @@ test_expect_success setup ' test_tick && git commit -m "patchid 3" && + git checkout -b empty main && + test_tick && + git commit --allow-empty -m "empty commit" && + git checkout main ' @@ -128,6 +132,12 @@ test_expect_success 'replay did not screw up the log message' ' grep "^Side .* with .* backslash-n" actual ' +test_expect_success 'format-patch empty commit' ' + git format-patch --stdout main..empty >empty && + grep "^From " empty >from && + test_line_count = 1 from +' + test_expect_success 'extra headers' ' git config format.headers "To: R E Cipient <rcipient@example.com> " && @@ -445,13 +455,13 @@ test_expect_success 'no threading' ' cat >expect.thread <<EOF --- -Message-Id: <0> +Message-ID: <0> --- -Message-Id: <1> +Message-ID: <1> In-Reply-To: <0> References: <0> --- -Message-Id: <2> +Message-ID: <2> In-Reply-To: <0> References: <0> EOF @@ -460,17 +470,22 @@ test_expect_success 'thread' ' check_threading expect.thread --thread main ' +test_expect_success '--thread overrides format.thread=deep' ' + test_config format.thread deep && + check_threading expect.thread --thread main +' + cat >expect.in-reply-to <<EOF --- -Message-Id: <0> +Message-ID: <0> In-Reply-To: <1> References: <1> --- -Message-Id: <2> +Message-ID: <2> In-Reply-To: <1> References: <1> --- -Message-Id: <3> +Message-ID: <3> In-Reply-To: <1> References: <1> EOF @@ -482,17 +497,17 @@ test_expect_success 'thread in-reply-to' ' cat >expect.cover-letter <<EOF --- -Message-Id: <0> +Message-ID: <0> --- -Message-Id: <1> +Message-ID: <1> In-Reply-To: <0> References: <0> --- -Message-Id: <2> +Message-ID: <2> In-Reply-To: <0> References: <0> --- -Message-Id: <3> +Message-ID: <3> In-Reply-To: <0> References: <0> EOF @@ -503,21 +518,21 @@ test_expect_success 'thread cover-letter' ' cat >expect.cl-irt <<EOF --- -Message-Id: <0> +Message-ID: <0> In-Reply-To: <1> References: <1> --- -Message-Id: <2> +Message-ID: <2> In-Reply-To: <0> References: <1> <0> --- -Message-Id: <3> +Message-ID: <3> In-Reply-To: <0> References: <1> <0> --- -Message-Id: <4> +Message-ID: <4> In-Reply-To: <0> References: <1> <0> @@ -535,13 +550,13 @@ test_expect_success 'thread explicit shallow' ' cat >expect.deep <<EOF --- -Message-Id: <0> +Message-ID: <0> --- -Message-Id: <1> +Message-ID: <1> In-Reply-To: <0> References: <0> --- -Message-Id: <2> +Message-ID: <2> In-Reply-To: <1> References: <0> <1> @@ -553,16 +568,16 @@ test_expect_success 'thread deep' ' cat >expect.deep-irt <<EOF --- -Message-Id: <0> +Message-ID: <0> In-Reply-To: <1> References: <1> --- -Message-Id: <2> +Message-ID: <2> In-Reply-To: <0> References: <1> <0> --- -Message-Id: <3> +Message-ID: <3> In-Reply-To: <2> References: <1> <0> @@ -576,18 +591,18 @@ test_expect_success 'thread deep in-reply-to' ' cat >expect.deep-cl <<EOF --- -Message-Id: <0> +Message-ID: <0> --- -Message-Id: <1> +Message-ID: <1> In-Reply-To: <0> References: <0> --- -Message-Id: <2> +Message-ID: <2> In-Reply-To: <1> References: <0> <1> --- -Message-Id: <3> +Message-ID: <3> In-Reply-To: <2> References: <0> <1> @@ -600,22 +615,22 @@ test_expect_success 'thread deep cover-letter' ' cat >expect.deep-cl-irt <<EOF --- -Message-Id: <0> +Message-ID: <0> In-Reply-To: <1> References: <1> --- -Message-Id: <2> +Message-ID: <2> In-Reply-To: <0> References: <1> <0> --- -Message-Id: <3> +Message-ID: <3> In-Reply-To: <2> References: <1> <0> <2> --- -Message-Id: <4> +Message-ID: <4> In-Reply-To: <3> References: <1> <0> @@ -1358,7 +1373,27 @@ test_expect_success '--rfc' ' Subject: [RFC PATCH 1/1] header with . in it EOF git format-patch -n -1 --stdout --rfc >patch && - grep ^Subject: patch >actual && + grep "^Subject:" patch >actual && + test_cmp expect actual +' + +test_expect_success '--rfc does not overwrite prefix' ' + cat >expect <<-\EOF && + Subject: [RFC PATCH foobar 1/1] header with . in it + EOF + git -c format.subjectPrefix="PATCH foobar" \ + format-patch -n -1 --stdout --rfc >patch && + grep "^Subject:" patch >actual && + test_cmp expect actual +' + +test_expect_success '--rfc is argument order independent' ' + cat >expect <<-\EOF && + Subject: [RFC PATCH foobar 1/1] header with . in it + EOF + git format-patch -n -1 --stdout --rfc \ + --subject-prefix="PATCH foobar" >patch && + grep "^Subject:" patch >actual && test_cmp expect actual ' @@ -1871,6 +1906,16 @@ body" && grep "^body$" actual ' +test_expect_success 'cover letter with --cover-from-description subject (UTF-8 subject line)' ' + test_config branch.rebuild-1.description "Café? + +body" && + git checkout rebuild-1 && + git format-patch --stdout --cover-letter --cover-from-description subject --encode-email-headers main >actual && + grep "^Subject: \[PATCH 0/2\] =?UTF-8?q?Caf=C3=A9=3F?=$" actual && + ! grep "Café" actual +' + test_expect_success 'cover letter with format.coverFromDescription = auto (short subject line)' ' test_config branch.rebuild-1.description "config subject @@ -1976,6 +2021,20 @@ test_expect_success 'cover letter using branch description (6)' ' grep hello actual ' +test_expect_success 'cover letter with --description-file' ' + test_when_finished "rm -f description.txt" && + cat >description.txt <<-\EOF && + subject from file + + body from file + EOF + git checkout rebuild-1 && + git format-patch --stdout --cover-letter --cover-from-description auto \ + --description-file description.txt main >actual && + grep "^Subject: \[PATCH 0/2\] subject from file$" actual && + grep "^body from file$" actual +' + test_expect_success 'cover letter with nothing' ' git format-patch --stdout --cover-letter >actual && test_line_count = 0 actual @@ -2354,25 +2413,25 @@ test_expect_success 'interdiff: cover-letter' ' --q EOF git format-patch --cover-letter --interdiff=boop~2 -1 boop && - test_i18ngrep "^Interdiff:$" 0000-cover-letter.patch && - test_i18ngrep ! "^Interdiff:$" 0001-fleep.patch && + test_grep "^Interdiff:$" 0000-cover-letter.patch && + test_grep ! "^Interdiff:$" 0001-fleep.patch && sed "1,/^@@ /d; /^-- $/q" 0000-cover-letter.patch >actual && test_cmp expect actual ' test_expect_success 'interdiff: reroll-count' ' git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop && - test_i18ngrep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch + test_grep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch ' test_expect_success 'interdiff: reroll-count with a non-integer' ' git format-patch --cover-letter --interdiff=boop~2 -v2.2 -1 boop && - test_i18ngrep "^Interdiff:$" v2.2-0000-cover-letter.patch + test_grep "^Interdiff:$" v2.2-0000-cover-letter.patch ' test_expect_success 'interdiff: reroll-count with a integer' ' git format-patch --cover-letter --interdiff=boop~2 -v2 -1 boop && - test_i18ngrep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch + test_grep "^Interdiff ..* v1:$" v2-0000-cover-letter.patch ' test_expect_success 'interdiff: solo-patch' ' @@ -2381,9 +2440,25 @@ test_expect_success 'interdiff: solo-patch' ' EOF git format-patch --interdiff=boop~2 -1 boop && - test_i18ngrep "^Interdiff:$" 0001-fleep.patch && + test_grep "^Interdiff:$" 0001-fleep.patch && sed "1,/^ @@ /d; /^$/q" 0001-fleep.patch >actual && test_cmp expect actual ' +test_expect_success 'format-patch does not respect diff.noprefix' ' + git -c diff.noprefix format-patch -1 --stdout >actual && + grep "^--- a/blorp" actual +' + +test_expect_success 'format-patch respects format.noprefix' ' + git -c format.noprefix format-patch -1 --stdout >actual && + grep "^--- blorp" actual +' + +test_expect_success 'format-patch --default-prefix overrides format.noprefix' ' + git -c format.noprefix \ + format-patch -1 --default-prefix --stdout >actual && + grep "^--- a/blorp" actual +' + test_done diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index b298f220e0..b443626afd 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -1,7 +1,7 @@ #!/bin/sh # # Copyright (c) 2006 Johannes E. Schindelin -# +# Copyright (c) 2023 Google LLC test_description='Test special whitespace in diff engine. @@ -11,6 +11,43 @@ TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff.sh +for opt_res in --patch --quiet -s --stat --shortstat --dirstat=lines \ + --raw! --name-only! --name-status! +do + opts=${opt_res%!} expect_failure= + test "$opts" = "$opt_res" || + expect_failure="test_expect_code 1" + + test_expect_success "status with $opts (different)" ' + echo foo >x && + git add x && + echo bar >x && + test_expect_code 1 git diff -w $opts --exit-code x + ' + + test_expect_success POSIXPERM "status with $opts (mode differs)" ' + test_when_finished "git update-index --chmod=-x x" && + echo foo >x && + git add x && + git update-index --chmod=+x x && + test_expect_code 1 git diff -w $opts --exit-code x + ' + + test_expect_success "status with $opts (removing an empty file)" ' + : >x && + git add x && + rm x && + test_expect_code 1 git diff -w $opts --exit-code -- x + ' + + test_expect_success "status with $opts (different but equivalent)" ' + echo foo >x && + git add x && + echo " foo" >x && + $expect_failure git diff -w $opts --exit-code x + ' +done + test_expect_success "Ray Lehtiniemi's example" ' cat <<-\EOF >x && do { @@ -909,7 +946,7 @@ test_expect_success 'combined diff with autocrlf conversion' ' git commit -m "the other side" x && git config core.autocrlf true && test_must_fail git merge one-side >actual && - test_i18ngrep "Automatic merge failed" actual && + test_grep "Automatic merge failed" actual && git diff >actual.raw && sed -e "1,/^@@@/d" actual.raw >actual && @@ -2187,27 +2224,27 @@ test_expect_success 'compare whitespace delta across moved blocks' ' test_expect_success 'bogus settings in move detection erroring out' ' test_must_fail git diff --color-moved=bogus 2>err && - test_i18ngrep "must be one of" err && - test_i18ngrep bogus err && + test_grep "must be one of" err && + test_grep bogus err && test_must_fail git -c diff.colormoved=bogus diff 2>err && - test_i18ngrep "must be one of" err && - test_i18ngrep "from command-line config" err && + test_grep "must be one of" err && + test_grep "from command-line config" err && test_must_fail git diff --color-moved-ws=bogus 2>err && - test_i18ngrep "possible values" err && - test_i18ngrep bogus err && + test_grep "possible values" err && + test_grep bogus err && test_must_fail git -c diff.colormovedws=bogus diff 2>err && - test_i18ngrep "possible values" err && - test_i18ngrep "from command-line config" err + test_grep "possible values" err && + test_grep "from command-line config" err ' test_expect_success 'compare whitespace delta incompatible with other space options' ' test_must_fail git diff \ --color-moved-ws=allow-indentation-change,ignore-all-space \ 2>err && - test_i18ngrep allow-indentation-change err + test_grep allow-indentation-change err ' EMPTY='' diff --git a/t/t4017-diff-retval.sh b/t/t4017-diff-retval.sh index 5bc28ad9f0..f439f469bd 100755 --- a/t/t4017-diff-retval.sh +++ b/t/t4017-diff-retval.sh @@ -138,4 +138,9 @@ test_expect_success 'check honors conflict marker length' ' git reset --hard ' +test_expect_success 'option errors are not confused by --exit-code' ' + test_must_fail git diff --exit-code --nonsense 2>err && + grep '^usage:' err +' + test_done diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh index 42a2b9a13b..e026fac1f4 100755 --- a/t/t4018-diff-funcname.sh +++ b/t/t4018-diff-funcname.sh @@ -53,15 +53,34 @@ do echo "*.java diff=$p" >.gitattributes && test_expect_code 1 git diff --no-index \ A.java B.java 2>msg && - test_i18ngrep ! fatal msg && - test_i18ngrep ! error msg + test_grep ! fatal msg && + test_grep ! error msg ' test_expect_success "builtin $p wordRegex pattern compiles" ' echo "*.java diff=$p" >.gitattributes && test_expect_code 1 git diff --no-index --word-diff \ A.java B.java 2>msg && - test_i18ngrep ! fatal msg && - test_i18ngrep ! error msg + test_grep ! fatal msg && + test_grep ! error msg + ' + + test_expect_success "builtin $p pattern compiles on bare repo with --attr-source" ' + test_when_finished "rm -rf bare.git" && + git checkout -B master && + git add . && + echo "*.java diff=notexist" >.gitattributes && + git add .gitattributes && + git commit -am "changing gitattributes" && + git checkout -B branchA && + echo "*.java diff=$p" >.gitattributes && + git add .gitattributes && + git commit -am "changing gitattributes" && + git clone --bare --no-local . bare.git && + git -C bare.git symbolic-ref HEAD refs/heads/master && + test_expect_code 1 git -C bare.git --attr-source=branchA \ + diff --exit-code HEAD:A.java HEAD:B.java 2>msg && + test_grep ! fatal msg && + test_grep ! error msg ' done @@ -69,7 +88,7 @@ test_expect_success 'last regexp must not be negated' ' echo "*.java diff=java" >.gitattributes && test_config diff.java.funcname "!static" && test_expect_code 128 git diff --no-index A.java B.java 2>msg && - test_i18ngrep ": Last expression must not be negated:" msg + test_grep ": Last expression must not be negated:" msg ' test_expect_success 'setup hunk header tests' ' diff --git a/t/t4022-diff-rewrite.sh b/t/t4022-diff-rewrite.sh index 1c89050a97..6fed993ea0 100755 --- a/t/t4022-diff-rewrite.sh +++ b/t/t4022-diff-rewrite.sh @@ -24,7 +24,7 @@ test_expect_success setup ' test_expect_success 'detect rewrite' ' actual=$(git diff-files -B --summary test) && - verbose expr "$actual" : " rewrite test ([0-9]*%)$" + expr "$actual" : " rewrite test ([0-9]*%)$" ' diff --git a/t/t4031-diff-rewrite-binary.sh b/t/t4031-diff-rewrite-binary.sh index eacc6694f7..c4394a27b5 100755 --- a/t/t4031-diff-rewrite-binary.sh +++ b/t/t4031-diff-rewrite-binary.sh @@ -53,7 +53,7 @@ test_expect_success 'rewrite diff --numstat shows binary changes' ' test_expect_success 'diff --stat counts binary rewrite as 0 lines' ' git diff -B --stat --summary >diff && grep "Bin" diff && - test_i18ngrep "0 insertions.*0 deletions" diff && + test_grep "0 insertions.*0 deletions" diff && grep " rewrite file" diff ' diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh index 15764ee9ac..74586f3813 100755 --- a/t/t4034-diff-words.sh +++ b/t/t4034-diff-words.sh @@ -69,6 +69,10 @@ test_language_driver () { echo "* diff='"$lang"'" >.gitattributes && word_diff --color-words ' + test_expect_success "diff driver '$lang' in Islandic" ' + LANG=is_IS.UTF-8 LANGUAGE=is LC_ALL="$is_IS_locale" \ + word_diff --color-words + ' } test_expect_success setup ' diff --git a/t/t4040-whitespace-status.sh b/t/t4040-whitespace-status.sh index e70e020ae9..eec3d73dc2 100755 --- a/t/t4040-whitespace-status.sh +++ b/t/t4040-whitespace-status.sh @@ -28,8 +28,7 @@ test_expect_success 'diff-tree --exit-code' ' test_expect_success 'diff-tree -b --exit-code' ' git diff -b --exit-code HEAD^ HEAD && - git diff-tree -b -p --exit-code HEAD^ HEAD && - git diff-tree -b --exit-code HEAD^ HEAD + git diff-tree -b -p --exit-code HEAD^ HEAD ' test_expect_success 'diff-index --cached --exit-code' ' diff --git a/t/t4047-diff-dirstat.sh b/t/t4047-diff-dirstat.sh index 7fec2cb9cd..7b73462d53 100755 --- a/t/t4047-diff-dirstat.sh +++ b/t/t4047-diff-dirstat.sh @@ -1,6 +1,8 @@ #!/bin/sh test_description='diff --dirstat tests' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # set up two commits where the second commit has these files @@ -941,37 +943,37 @@ test_expect_success '--dirstat=future_param,lines,0 should fail loudly' ' test_must_fail git diff --dirstat=future_param,lines,0 HEAD^..HEAD >actual_diff_dirstat 2>actual_error && test_debug "cat actual_error" && test_must_be_empty actual_diff_dirstat && - test_i18ngrep -q "future_param" actual_error && - test_i18ngrep -q "\--dirstat" actual_error + test_grep -q "future_param" actual_error && + test_grep -q "\--dirstat" actual_error ' test_expect_success '--dirstat=dummy1,cumulative,2dummy should report both unrecognized parameters' ' test_must_fail git diff --dirstat=dummy1,cumulative,2dummy HEAD^..HEAD >actual_diff_dirstat 2>actual_error && test_debug "cat actual_error" && test_must_be_empty actual_diff_dirstat && - test_i18ngrep -q "dummy1" actual_error && - test_i18ngrep -q "2dummy" actual_error && - test_i18ngrep -q "\--dirstat" actual_error + test_grep -q "dummy1" actual_error && + test_grep -q "2dummy" actual_error && + test_grep -q "\--dirstat" actual_error ' test_expect_success 'diff.dirstat=future_param,0,lines should warn, but still work' ' git -c diff.dirstat=future_param,0,lines diff --dirstat HEAD^..HEAD >actual_diff_dirstat 2>actual_error && test_debug "cat actual_error" && test_cmp expect_diff_dirstat actual_diff_dirstat && - test_i18ngrep -q "future_param" actual_error && - test_i18ngrep -q "diff\\.dirstat" actual_error && + test_grep -q "future_param" actual_error && + test_grep -q "diff\\.dirstat" actual_error && git -c diff.dirstat=future_param,0,lines diff --dirstat -M HEAD^..HEAD >actual_diff_dirstat_M 2>actual_error && test_debug "cat actual_error" && test_cmp expect_diff_dirstat_M actual_diff_dirstat_M && - test_i18ngrep -q "future_param" actual_error && - test_i18ngrep -q "diff\\.dirstat" actual_error && + test_grep -q "future_param" actual_error && + test_grep -q "diff\\.dirstat" actual_error && git -c diff.dirstat=future_param,0,lines diff --dirstat -C -C HEAD^..HEAD >actual_diff_dirstat_CC 2>actual_error && test_debug "cat actual_error" && test_cmp expect_diff_dirstat_CC actual_diff_dirstat_CC && - test_i18ngrep -q "future_param" actual_error && - test_i18ngrep -q "diff\\.dirstat" actual_error + test_grep -q "future_param" actual_error && + test_grep -q "diff\\.dirstat" actual_error ' test_expect_success '--shortstat --dirstat should output only one dirstat' ' diff --git a/t/t4052-stat-output.sh b/t/t4052-stat-output.sh index 3ee27e277d..7badd72488 100755 --- a/t/t4052-stat-output.sh +++ b/t/t4052-stat-output.sh @@ -12,7 +12,7 @@ TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-terminal.sh -# 120 character name +# 120-character name name=aaaaaaaaaa name=$name$name$name$name$name$name$name$name$name$name$name$name test_expect_success 'preparation' ' @@ -49,12 +49,41 @@ log -1 --stat EOF cat >expect.60 <<-'EOF' - ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + EOF cat >expect.6030 <<-'EOF' ...aaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + EOF -cat >expect2.60 <<-'EOF' +while read verb expect cmd args +do + # No width limit applied when statNameWidth is ignored + case "$expect" in expect72|expect.6030) + test_expect_success "$cmd $verb diff.statNameWidth with long name" ' + git -c diff.statNameWidth=30 $cmd $args >output && + grep " | " output >actual && + test_cmp $expect actual + ';; + esac + # Maximum width limit still applied when statNameWidth is ignored + case "$expect" in expect.60|expect.6030) + test_expect_success "$cmd --stat=width $verb diff.statNameWidth with long name" ' + git -c diff.statNameWidth=30 $cmd $args --stat=60 >output && + grep " | " output >actual && + test_cmp $expect actual + ';; + esac +done <<\EOF +ignores expect72 format-patch -1 --stdout +ignores expect.60 format-patch -1 --stdout +respects expect.6030 diff HEAD^ HEAD --stat +respects expect.6030 show --stat +respects expect.6030 log -1 --stat +EOF + +cat >expect.40 <<-'EOF' + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + +EOF +cat >expect2.40 <<-'EOF' ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + EOF @@ -67,22 +96,22 @@ do test_expect_success "$cmd --stat=width: a long name is given more room when the bar is short" ' git $cmd $args --stat=40 >output && grep " | " output >actual && - test_cmp $expect.60 actual + test_cmp $expect.40 actual ' test_expect_success "$cmd --stat-width=width with long name" ' git $cmd $args --stat-width=40 >output && grep " | " output >actual && - test_cmp $expect.60 actual + test_cmp $expect.40 actual ' - test_expect_success "$cmd --stat=...,name-width with long name" ' + test_expect_success "$cmd --stat=width,name-width with long name" ' git $cmd $args --stat=60,30 >output && grep " | " output >actual && test_cmp $expect.6030 actual ' - test_expect_success "$cmd --stat-name-width with long name" ' + test_expect_success "$cmd --stat-name-width=width with long name" ' git $cmd $args --stat-name-width=30 >output && grep " | " output >actual && test_cmp $expect.6030 actual @@ -94,8 +123,7 @@ expect show --stat expect log -1 --stat EOF - -test_expect_success 'preparation for big change tests' ' +test_expect_success 'preparation for big-change tests' ' >abcd && git add abcd && git commit -m message && @@ -111,7 +139,7 @@ cat >expect72 <<'EOF' abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ EOF -test_expect_success "format-patch --cover-letter ignores COLUMNS (big change)" ' +test_expect_success "format-patch --cover-letter ignores COLUMNS with big change" ' COLUMNS=200 git format-patch -1 --stdout --cover-letter >output && grep " | " output >actual && test_cmp expect72 actual @@ -131,7 +159,7 @@ cat >expect200-graph <<'EOF' EOF while read verb expect cmd args do - test_expect_success "$cmd $verb COLUMNS (big change)" ' + test_expect_success "$cmd $verb COLUMNS with big change" ' COLUMNS=200 git $cmd $args >output && grep " | " output >actual && test_cmp "$expect" actual @@ -139,7 +167,7 @@ do case "$cmd" in diff|show) continue;; esac - test_expect_success "$cmd --graph $verb COLUMNS (big change)" ' + test_expect_success "$cmd --graph $verb COLUMNS with big change" ' COLUMNS=200 git $cmd $args --graph >output && grep " | " output >actual && test_cmp "$expect-graph" actual @@ -159,7 +187,7 @@ cat >expect40-graph <<'EOF' EOF while read verb expect cmd args do - test_expect_success "$cmd $verb not enough COLUMNS (big change)" ' + test_expect_success "$cmd $verb not enough COLUMNS with big change" ' COLUMNS=40 git $cmd $args >output && grep " | " output >actual && test_cmp "$expect" actual @@ -167,7 +195,7 @@ do case "$cmd" in diff|show) continue;; esac - test_expect_success "$cmd --graph $verb not enough COLUMNS (big change)" ' + test_expect_success "$cmd --graph $verb not enough COLUMNS with big change" ' COLUMNS=40 git $cmd $args --graph >output && grep " | " output >actual && test_cmp "$expect-graph" actual @@ -187,7 +215,7 @@ cat >expect40-graph <<'EOF' EOF while read verb expect cmd args do - test_expect_success "$cmd $verb statGraphWidth config" ' + test_expect_success "$cmd $verb diff.statGraphWidth" ' git -c diff.statGraphWidth=26 $cmd $args >output && grep " | " output >actual && test_cmp "$expect" actual @@ -195,7 +223,7 @@ do case "$cmd" in diff|show) continue;; esac - test_expect_success "$cmd --graph $verb statGraphWidth config" ' + test_expect_success "$cmd --graph $verb diff.statGraphWidth" ' git -c diff.statGraphWidth=26 $cmd $args --graph >output && grep " | " output >actual && test_cmp "$expect-graph" actual @@ -207,7 +235,6 @@ respects expect40 show --stat respects expect40 log -1 --stat EOF - cat >expect <<'EOF' abcd | 1000 ++++++++++++++++++++++++++ EOF @@ -228,7 +255,7 @@ do test_cmp expect actual ' - test_expect_success "$cmd --stat-graph-width with big change" ' + test_expect_success "$cmd --stat-graph-width=width with big change" ' git $cmd $args --stat-graph-width=26 >output && grep " | " output >actual && test_cmp expect actual @@ -242,7 +269,7 @@ do test_cmp expect-graph actual ' - test_expect_success "$cmd --stat-graph-width --graph with big change" ' + test_expect_success "$cmd --stat-graph-width=width --graph with big change" ' git $cmd $args --stat-graph-width=26 --graph >output && grep " | " output >actual && test_cmp expect-graph actual @@ -254,7 +281,7 @@ show --stat log -1 --stat EOF -test_expect_success 'preparation for long filename tests' ' +test_expect_success 'preparation for long-name tests' ' cp abcd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && git add aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && git commit -m message @@ -302,7 +329,7 @@ cat >expect200-graph <<'EOF' EOF while read verb expect cmd args do - test_expect_success "$cmd $verb COLUMNS (long filename)" ' + test_expect_success "$cmd $verb COLUMNS with long name" ' COLUMNS=200 git $cmd $args >output && grep " | " output >actual && test_cmp "$expect" actual @@ -310,7 +337,7 @@ do case "$cmd" in diff|show) continue;; esac - test_expect_success "$cmd --graph $verb COLUMNS (long filename)" ' + test_expect_success "$cmd --graph $verb COLUMNS with long name" ' COLUMNS=200 git $cmd $args --graph >output && grep " | " output >actual && test_cmp "$expect-graph" actual @@ -331,7 +358,7 @@ EOF while read verb expect cmd args do test_expect_success COLUMNS_CAN_BE_1 \ - "$cmd $verb prefix greater than COLUMNS (big change)" ' + "$cmd $verb prefix greater than COLUMNS with big change" ' COLUMNS=1 git $cmd $args >output && grep " | " output >actual && test_cmp "$expect" actual @@ -340,7 +367,7 @@ do case "$cmd" in diff|show) continue;; esac test_expect_success COLUMNS_CAN_BE_1 \ - "$cmd --graph $verb prefix greater than COLUMNS (big change)" ' + "$cmd --graph $verb prefix greater than COLUMNS with big change" ' COLUMNS=1 git $cmd $args --graph >output && grep " | " output >actual && test_cmp "$expect-graph" actual @@ -355,8 +382,14 @@ EOF cat >expect <<'EOF' abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ EOF -test_expect_success 'merge --stat respects COLUMNS (big change)' ' - git checkout -b branch HEAD^^ && +test_expect_success 'merge --stat respects diff.statGraphWidth with big change' ' + git checkout -b branch1 HEAD^^ && + git -c diff.statGraphWidth=26 merge --stat --no-ff main^ >output && + grep " | " output >actual && + test_cmp expect40 actual +' +test_expect_success 'merge --stat respects COLUMNS with big change' ' + git checkout -b branch2 HEAD^^ && COLUMNS=100 git merge --stat --no-ff main^ >output && grep " | " output >actual && test_cmp expect actual @@ -365,7 +398,17 @@ test_expect_success 'merge --stat respects COLUMNS (big change)' ' cat >expect <<'EOF' aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 +++++++++++++++++++++++++++++++++++++++ EOF -test_expect_success 'merge --stat respects COLUMNS (long filename)' ' +cat >expect.30 <<'EOF' + ...aaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++++++++++++++++++++++ +EOF +test_expect_success 'merge --stat respects diff.statNameWidth with long name' ' + git switch branch1 && + git -c diff.statNameWidth=30 merge --stat --no-ff main >output && + grep " | " output >actual && + test_cmp expect.30 actual +' +test_expect_success 'merge --stat respects COLUMNS with long name' ' + git switch branch2 && COLUMNS=100 git merge --stat --no-ff main >output && grep " | " output >actual && test_cmp expect actual diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh index 4e9fa0403d..5ce345d309 100755 --- a/t/t4053-diff-no-index.sh +++ b/t/t4053-diff-no-index.sh @@ -56,7 +56,7 @@ test_expect_success 'git diff --no-index executed outside repo gives correct err export GIT_CEILING_DIRECTORIES && cd non/git && test_must_fail git diff --no-index a 2>actual.err && - test_i18ngrep "usage: git diff --no-index" actual.err + test_grep "usage: git diff --no-index" actual.err ) ' @@ -205,4 +205,83 @@ test_expect_success POSIXPERM,SYMLINKS 'diff --no-index normalizes: mode not lik test_cmp expected actual ' +test_expect_success "diff --no-index treats '-' as stdin" ' + cat >expect <<-EOF && + diff --git a/- b/a/1 + index $ZERO_OID..$(git hash-object --stdin <a/1) 100644 + --- a/- + +++ b/a/1 + @@ -1 +1 @@ + -x + +1 + EOF + + test_write_lines x | test_expect_code 1 \ + git -c core.abbrev=no diff --no-index -- - a/1 >actual && + test_cmp expect actual && + + test_write_lines 1 | git diff --no-index -- a/1 - >actual && + test_must_be_empty actual +' + +test_expect_success "diff --no-index -R treats '-' as stdin" ' + cat >expect <<-EOF && + diff --git b/a/1 a/- + index $(git hash-object --stdin <a/1)..$ZERO_OID 100644 + --- b/a/1 + +++ a/- + @@ -1 +1 @@ + -1 + +x + EOF + + test_write_lines x | test_expect_code 1 \ + git -c core.abbrev=no diff --no-index -R -- - a/1 >actual && + test_cmp expect actual && + + test_write_lines 1 | git diff --no-index -R -- a/1 - >actual && + test_must_be_empty actual +' + +test_expect_success 'diff --no-index refuses to diff stdin and a directory' ' + test_must_fail git diff --no-index -- - a </dev/null 2>err && + grep "fatal: cannot compare stdin to a directory" err +' + +test_expect_success PIPE 'diff --no-index refuses to diff a named pipe and a directory' ' + test_when_finished "rm -f pipe" && + mkfifo pipe && + test_must_fail git diff --no-index -- pipe a 2>err && + grep "fatal: cannot compare a named pipe to a directory" err +' + +test_expect_success PIPE,SYMLINKS 'diff --no-index reads from pipes' ' + test_when_finished "rm -f old new new-link" && + mkfifo old && + mkfifo new && + ln -s new new-link && + { + (test_write_lines a b c >old) & + } && + test_when_finished "kill $! || :" && + { + (test_write_lines a x c >new) & + } && + test_when_finished "kill $! || :" && + + cat >expect <<-EOF && + diff --git a/old b/new-link + --- a/old + +++ b/new-link + @@ -1,3 +1,3 @@ + a + -b + +x + c + EOF + + test_expect_code 1 git diff --no-index old new-link >actual && + test_cmp expect actual +' + test_done diff --git a/t/t4055-diff-context.sh b/t/t4055-diff-context.sh index 73048d0a52..3ea9ae99e0 100755 --- a/t/t4055-diff-context.sh +++ b/t/t4055-diff-context.sh @@ -74,13 +74,13 @@ test_expect_success 'plumbing not affected' ' test_expect_success 'non-integer config parsing' ' git config diff.context no && test_must_fail git diff 2>output && - test_i18ngrep "bad numeric config value" output + test_grep "bad numeric config value" output ' test_expect_success 'negative integer config parsing' ' git config diff.context -1 && test_must_fail git diff 2>output && - test_i18ngrep "bad config variable" output + test_grep "bad config variable" output ' test_expect_success '-U0 is valid, so is diff.context=0' ' diff --git a/t/t4062-diff-pickaxe.sh b/t/t4062-diff-pickaxe.sh index 9aaa068ed9..a90b46b678 100755 --- a/t/t4062-diff-pickaxe.sh +++ b/t/t4062-diff-pickaxe.sh @@ -24,7 +24,7 @@ test_expect_success '-G matches' ' test_expect_success '-S --pickaxe-regex' ' git diff --name-only -S0 --pickaxe-regex HEAD^ >out && - verbose test 4096-zeroes.txt = "$(cat out)" + test 4096-zeroes.txt = "$(cat out)" ' test_done diff --git a/t/t4067-diff-partial-clone.sh b/t/t4067-diff-partial-clone.sh index f60f5cbd65..7af3a08862 100755 --- a/t/t4067-diff-partial-clone.sh +++ b/t/t4067-diff-partial-clone.sh @@ -151,7 +151,7 @@ test_expect_success 'diff does not fetch anything if inexact rename detection is # Ensure no fetches. GIT_TRACE_PACKET="$(pwd)/trace" git -C client diff --raw -M HEAD^ HEAD && - ! test_path_exists trace + test_path_is_missing trace ' test_expect_success 'diff --break-rewrites fetches only if necessary, and batches blobs if it does' ' @@ -171,7 +171,7 @@ test_expect_success 'diff --break-rewrites fetches only if necessary, and batche # Ensure no fetches. GIT_TRACE_PACKET="$(pwd)/trace" git -C client diff --raw -M HEAD^ HEAD && - ! test_path_exists trace && + test_path_is_missing 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 diff --git a/t/t4068-diff-symmetric-merge-base.sh b/t/t4068-diff-symmetric-merge-base.sh index 2d650d8f10..eff63c16b0 100755 --- a/t/t4068-diff-symmetric-merge-base.sh +++ b/t/t4068-diff-symmetric-merge-base.sh @@ -34,7 +34,7 @@ test_expect_success setup ' echo c >c && git add c && git commit -m C && - git tag commit-C && + git tag -m commit-C commit-C && git merge -m D main && git tag commit-D && git checkout main && @@ -68,27 +68,27 @@ test_expect_success 'diff with two merge bases' ' test_expect_success 'diff with no merge bases' ' test_must_fail git diff br2...br3 2>err && - test_i18ngrep "fatal: br2...br3: no merge base" err + test_grep "fatal: br2...br3: no merge base" err ' test_expect_success 'diff with too many symmetric differences' ' test_must_fail git diff br1...main br2...br3 2>err && - test_i18ngrep "usage" err + test_grep "usage" err ' test_expect_success 'diff with symmetric difference and extraneous arg' ' test_must_fail git diff main br1...main 2>err && - test_i18ngrep "usage" err + test_grep "usage" err ' test_expect_success 'diff with two ranges' ' test_must_fail git diff main br1..main br2..br3 2>err && - test_i18ngrep "usage" err + test_grep "usage" err ' test_expect_success 'diff with ranges and extra arg' ' test_must_fail git diff main br1..main commit-D 2>err && - test_i18ngrep "usage" err + test_grep "usage" err ' test_expect_success 'diff --merge-base with no commits' ' @@ -97,7 +97,7 @@ test_expect_success 'diff --merge-base with no commits' ' test_expect_success 'diff --merge-base with three commits' ' test_must_fail git diff --merge-base br1 br2 main 2>err && - test_i18ngrep "usage" err + test_grep "usage" err ' for cmd in diff-index diff @@ -109,6 +109,13 @@ do test_cmp expect actual ' + test_expect_success "$cmd --merge-base with annotated tag" ' + git checkout main && + git $cmd commit-C >expect && + git $cmd --merge-base commit-C >actual && + test_cmp expect actual + ' + test_expect_success "$cmd --merge-base with one commit and unstaged changes" ' git checkout main && test_when_finished git reset --hard && @@ -143,19 +150,19 @@ do test_expect_success "$cmd --merge-base with non-commit" ' git checkout main && test_must_fail git $cmd --merge-base main^{tree} 2>err && - test_i18ngrep "fatal: --merge-base only works with commits" err + test_grep "is a tree, not a commit" err ' test_expect_success "$cmd --merge-base with no merge bases and one commit" ' git checkout main && test_must_fail git $cmd --merge-base br3 2>err && - test_i18ngrep "fatal: no merge base found" err + test_grep "fatal: no merge base found" err ' test_expect_success "$cmd --merge-base with multiple merge bases and one commit" ' git checkout main && test_must_fail git $cmd --merge-base br1 2>err && - test_i18ngrep "fatal: multiple merge bases found" err + test_grep "fatal: multiple merge bases found" err ' done @@ -169,28 +176,28 @@ do test_expect_success "$cmd --merge-base commit and non-commit" ' test_must_fail git $cmd --merge-base br2 main^{tree} 2>err && - test_i18ngrep "fatal: --merge-base only works with commits" err + test_grep "is a tree, not a commit" err ' test_expect_success "$cmd --merge-base with no merge bases and two commits" ' test_must_fail git $cmd --merge-base br2 br3 2>err && - test_i18ngrep "fatal: no merge base found" err + test_grep "fatal: no merge base found" err ' test_expect_success "$cmd --merge-base with multiple merge bases and two commits" ' test_must_fail git $cmd --merge-base main br1 2>err && - test_i18ngrep "fatal: multiple merge bases found" err + test_grep "fatal: multiple merge bases found" err ' done test_expect_success 'diff-tree --merge-base with one commit' ' test_must_fail git diff-tree --merge-base main 2>err && - test_i18ngrep "fatal: --merge-base only works with two commits" err + test_grep "fatal: --merge-base only works with two commits" err ' test_expect_success 'diff --merge-base with range' ' test_must_fail git diff --merge-base br2..br3 2>err && - test_i18ngrep "fatal: --merge-base does not work with ranges" err + test_grep "fatal: --merge-base does not work with ranges" err ' test_done diff --git a/t/t4115-apply-symlink.sh b/t/t4115-apply-symlink.sh index e95e6d4e7d..cbef0a593f 100755 --- a/t/t4115-apply-symlink.sh +++ b/t/t4115-apply-symlink.sh @@ -74,7 +74,7 @@ test_expect_success SYMLINKS 'symlink escape when creating new files' ' error: affected file ${SQ}renamed-symlink/create-me${SQ} is beyond a symbolic link EOF test_cmp expected_stderr stderr && - ! test_path_exists .git/create-me + test_path_is_missing .git/create-me ' test_expect_success SYMLINKS 'symlink escape when modifying file' ' @@ -136,7 +136,7 @@ test_expect_success SYMLINKS '--reject removes .rej symlink if it exists' ' ln -s foo file.t.rej && test_must_fail git apply patch --reject 2>err && - test_i18ngrep "Rejected hunk" err && + test_grep "Rejected hunk" err && test_path_is_missing foo && test_path_is_file file.t.rej ' diff --git a/t/t4120-apply-popt.sh b/t/t4120-apply-popt.sh index 497b62868d..697e86c0ff 100755 --- a/t/t4120-apply-popt.sh +++ b/t/t4120-apply-popt.sh @@ -31,7 +31,7 @@ test_expect_success 'apply git diff with -p2' ' test_expect_success 'apply with too large -p' ' cp file1.saved file1 && test_must_fail git apply --stat -p3 patch.file 2>err && - test_i18ngrep "removing 3 leading" err + test_grep "removing 3 leading" err ' test_expect_success 'apply (-p2) traditional diff with funny filenames' ' @@ -53,7 +53,7 @@ test_expect_success 'apply (-p2) traditional diff with funny filenames' ' test_expect_success 'apply with too large -p and fancy filename' ' cp file1.saved file1 && test_must_fail git apply --stat -p3 patch.escaped 2>err && - test_i18ngrep "removing 3 leading" err + test_grep "removing 3 leading" err ' test_expect_success 'apply (-p2) diff, mode change only' ' diff --git a/t/t4122-apply-symlink-inside.sh b/t/t4122-apply-symlink-inside.sh index 9696537303..2089d84f64 100755 --- a/t/t4122-apply-symlink-inside.sh +++ b/t/t4122-apply-symlink-inside.sh @@ -95,19 +95,19 @@ test_expect_success SYMLINKS 'do not follow symbolic link (same input)' ' # same input creates a confusing symbolic link test_must_fail git apply patch 2>error-wt && - test_i18ngrep "beyond a symbolic link" error-wt && + test_grep "beyond a symbolic link" error-wt && test_path_is_missing arch/x86_64/dir && test_path_is_missing arch/i386/dir/file && test_must_fail git apply --index patch 2>error-ix && - test_i18ngrep "beyond a symbolic link" error-ix && + test_grep "beyond a symbolic link" error-ix && test_path_is_missing arch/x86_64/dir && test_path_is_missing arch/i386/dir/file && test_must_fail git ls-files --error-unmatch arch/x86_64/dir && test_must_fail git ls-files --error-unmatch arch/i386/dir && test_must_fail git apply --cached patch 2>error-ct && - test_i18ngrep "beyond a symbolic link" error-ct && + test_grep "beyond a symbolic link" error-ct && test_must_fail git ls-files --error-unmatch arch/x86_64/dir && test_must_fail git ls-files --error-unmatch arch/i386/dir && @@ -135,23 +135,23 @@ test_expect_success SYMLINKS 'do not follow symbolic link (existing)' ' git add arch/x86_64/dir && test_must_fail git apply add_file.patch 2>error-wt-add && - test_i18ngrep "beyond a symbolic link" error-wt-add && + test_grep "beyond a symbolic link" error-wt-add && test_path_is_missing arch/i386/dir/file && mkdir arch/i386/dir && >arch/i386/dir/file && test_must_fail git apply del_file.patch 2>error-wt-del && - test_i18ngrep "beyond a symbolic link" error-wt-del && + test_grep "beyond a symbolic link" error-wt-del && test_path_is_file arch/i386/dir/file && rm arch/i386/dir/file && test_must_fail git apply --index add_file.patch 2>error-ix-add && - test_i18ngrep "beyond a symbolic link" error-ix-add && + test_grep "beyond a symbolic link" error-ix-add && test_path_is_missing arch/i386/dir/file && test_must_fail git ls-files --error-unmatch arch/i386/dir && test_must_fail git apply --cached add_file.patch 2>error-ct-file && - test_i18ngrep "beyond a symbolic link" error-ct-file && + test_grep "beyond a symbolic link" error-ct-file && test_must_fail git ls-files --error-unmatch arch/i386/dir ' diff --git a/t/t4129-apply-samemode.sh b/t/t4129-apply-samemode.sh index a1c7686519..e7a7295f1b 100755 --- a/t/t4129-apply-samemode.sh +++ b/t/t4129-apply-samemode.sh @@ -66,13 +66,13 @@ test_expect_success FILEMODE 'mode update (index only)' ' test_expect_success FILEMODE 'empty mode is rejected' ' git reset --hard && test_must_fail git apply patch-empty-mode.txt 2>err && - test_i18ngrep "invalid mode" err + test_grep "invalid mode" err ' test_expect_success FILEMODE 'bogus mode is rejected' ' git reset --hard && test_must_fail git apply patch-bogus-mode.txt 2>err && - test_i18ngrep "invalid mode" err + test_grep "invalid mode" err ' test_expect_success POSIXPERM 'do not use core.sharedRepository for working tree files' ' diff --git a/t/t4133-apply-filenames.sh b/t/t4133-apply-filenames.sh index 35f1060bc8..c21ddb2946 100755 --- a/t/t4133-apply-filenames.sh +++ b/t/t4133-apply-filenames.sh @@ -32,9 +32,9 @@ EOF test_expect_success 'apply diff with inconsistent filenames in headers' ' test_must_fail git apply bad1.patch 2>err && - test_i18ngrep "inconsistent new filename" err && + test_grep "inconsistent new filename" err && test_must_fail git apply bad2.patch 2>err && - test_i18ngrep "inconsistent old filename" err + test_grep "inconsistent old filename" err ' test_expect_success 'apply diff with new filename missing from headers' ' @@ -46,7 +46,7 @@ test_expect_success 'apply diff with new filename missing from headers' ' +1 EOF test_must_fail git apply missing_new_filename.diff 2>err && - test_i18ngrep "lacks filename information" err + test_grep "lacks filename information" err ' test_expect_success 'apply diff with old filename missing from headers' ' @@ -58,7 +58,7 @@ test_expect_success 'apply diff with old filename missing from headers' ' -1 EOF test_must_fail git apply missing_old_filename.diff 2>err && - test_i18ngrep "lacks filename information" err + test_grep "lacks filename information" err ' test_done diff --git a/t/t4141-apply-too-large.sh b/t/t4141-apply-too-large.sh index 58742d4fc5..20cc1209f6 100755 --- a/t/t4141-apply-too-large.sh +++ b/t/t4141-apply-too-large.sh @@ -17,7 +17,7 @@ test_expect_success EXPENSIVE 'git apply rejects patches that are too large' ' EOF test-tool genzeros } | test_copy_bytes $sz | test_must_fail git apply 2>err && - grep "git apply: failed to read" err + grep "patch too large" err ' test_done diff --git a/t/t4150-am.sh b/t/t4150-am.sh index 78cf1c880e..3b12576269 100755 --- a/t/t4150-am.sh +++ b/t/t4150-am.sh @@ -103,7 +103,7 @@ test_expect_success setup ' git format-patch --stdout first >patch1 && { - echo "Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>" && + echo "Message-ID: <1226501681-24923-1-git-send-email-bda@mnsspb.ru>" && echo "X-Fake-Field: Line One" && echo "X-Fake-Field: Line Two" && echo "X-Fake-Field: Line Three" && @@ -779,7 +779,7 @@ test_expect_success 'am --resolved fails if index has unmerged entries' ' test_must_fail git am --resolved >err && test_path_is_dir .git/rebase-apply && test_cmp_rev second HEAD && - test_i18ngrep "still have unmerged paths" err + test_grep "still have unmerged paths" err ' test_expect_success 'am takes patches from a Pine mailbox' ' @@ -913,7 +913,7 @@ test_expect_success 'am newline in subject' ' test_tick && sed -e "s/second/second \\\n foo/" patch1 >patchnl && git am <patchnl >output.out 2>&1 && - test_i18ngrep "^Applying: second \\\n foo$" output.out + test_grep "^Applying: second \\\n foo$" output.out ' test_expect_success 'am -q is quiet' ' @@ -942,7 +942,7 @@ test_expect_success 'am --message-id really adds the message id' ' git am --message-id patch1.eml && test_path_is_missing .git/rebase-apply && git cat-file commit HEAD | tail -n1 >actual && - grep Message-Id patch1.eml >expected && + grep Message-ID patch1.eml >expected && test_cmp expected actual ' @@ -954,7 +954,7 @@ test_expect_success 'am.messageid really adds the message id' ' git am patch1.eml && test_path_is_missing .git/rebase-apply && git cat-file commit HEAD | tail -n1 >actual && - grep Message-Id patch1.eml >expected && + grep Message-ID patch1.eml >expected && test_cmp expected actual ' @@ -965,7 +965,7 @@ test_expect_success 'am --message-id -s signs off after the message id' ' git am -s --message-id patch1.eml && test_path_is_missing .git/rebase-apply && git cat-file commit HEAD | tail -n2 | head -n1 >actual && - grep Message-Id patch1.eml >expected && + grep Message-ID patch1.eml >expected && test_cmp expected actual ' diff --git a/t/t4151-am-abort.sh b/t/t4151-am-abort.sh index 5ed7e22827..edb38da701 100755 --- a/t/t4151-am-abort.sh +++ b/t/t4151-am-abort.sh @@ -46,7 +46,7 @@ do test_expect_success "am$with3 --skip continue after failed am$with3" ' test_must_fail git am$with3 --skip >output && - test_i18ngrep "^Applying: 6$" output && + test_grep "^Applying: 6$" output && test_cmp file-2-expect file-2 && test ! -f .git/MERGE_RR ' diff --git a/t/t4153-am-resume-override-opts.sh b/t/t4153-am-resume-override-opts.sh index b7c3861407..4add7c7757 100755 --- a/t/t4153-am-resume-override-opts.sh +++ b/t/t4153-am-resume-override-opts.sh @@ -53,7 +53,7 @@ test_expect_success '--no-quiet overrides --quiet' ' # Applying side1 will be quiet. test_must_fail git am --quiet side[123].eml >out && test_path_is_dir .git/rebase-apply && - test_i18ngrep ! "^Applying: " out && + test_grep ! "^Applying: " out && echo side1 >file && git add file && diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh index 7025cfdae5..fb53dddf79 100755 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@ -433,13 +433,13 @@ test_expect_success 'rerere --no-no-rerere-autoupdate' ' git update-index --index-info <failedmerge && cp file3.conflict file3 && test_must_fail git rerere --no-no-rerere-autoupdate 2>err && - test_i18ngrep [Uu]sage err && + test_grep [Uu]sage err && test_must_fail git update-index --refresh ' test_expect_success 'rerere -h' ' test_must_fail git rerere -h >help && - test_i18ngrep [Uu]sage help + test_grep [Uu]sage help ' concat_insert () { diff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh index 8e4effebdb..d7382709fc 100755 --- a/t/t4201-shortlog.sh +++ b/t/t4201-shortlog.sh @@ -139,7 +139,7 @@ test_expect_success !MINGW 'shortlog can read --format=raw output' ' test_expect_success 'shortlog from non-git directory refuses extra arguments' ' test_must_fail env GIT_DIR=non-existing git shortlog foo 2>out && - test_i18ngrep "too many arguments" out + test_grep "too many arguments" out ' test_expect_success 'shortlog should add newline when input line matches wraplen' ' diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 2ce2b41174..ddd205f98a 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -187,6 +187,21 @@ test_expect_success 'git config log.follow does not die with no paths' ' git log -- ' +test_expect_success 'git log --follow rejects unsupported pathspec magic' ' + test_must_fail git log --follow ":(top,glob,icase)ichi" 2>stderr && + # check full error message; we want to be sure we mention both + # of the rejected types (glob,icase), but not the allowed one (top) + echo "fatal: pathspec magic not supported by --follow: ${SQ}glob${SQ}, ${SQ}icase${SQ}" >expect && + test_cmp expect stderr +' + +test_expect_success 'log.follow disabled with unsupported pathspec magic' ' + test_config log.follow true && + git log --format=%s ":(glob,icase)ichi" >actual && + echo third >expect && + test_cmp expect actual +' + test_expect_success 'git config log.follow is overridden by --no-follow' ' test_config log.follow true && git log --no-follow --pretty="format:%s" ichi >actual && @@ -835,6 +850,21 @@ test_expect_success 'log.decorate configuration' ' ' +test_expect_success 'parse log.excludeDecoration with no value' ' + cp .git/config .git/config.orig && + test_when_finished mv .git/config.orig .git/config && + + cat >>.git/config <<-\EOF && + [log] + excludeDecoration + EOF + cat >expect <<-\EOF && + error: missing value for '\''log.excludeDecoration'\'' + EOF + git log --decorate=short 2>actual && + test_cmp expect actual +' + test_expect_success 'decorate-refs with glob' ' cat >expect.decorate <<-\EOF && Merge-tag-reach @@ -1854,7 +1884,7 @@ test_expect_success '--no-graph does not unset --parents' ' test_expect_success '--reverse and --graph conflict' ' test_must_fail git log --reverse --graph 2>stderr && - test_i18ngrep "cannot be used together" stderr + test_grep "cannot be used together" stderr ' test_expect_success '--reverse --graph --no-graph works' ' @@ -1865,7 +1895,7 @@ test_expect_success '--reverse --graph --no-graph works' ' test_expect_success '--show-linear-break and --graph conflict' ' test_must_fail git log --show-linear-break --graph 2>stderr && - test_i18ngrep "cannot be used together" stderr + test_grep "cannot be used together" stderr ' test_expect_success '--show-linear-break --graph --no-graph works' ' @@ -1876,7 +1906,7 @@ test_expect_success '--show-linear-break --graph --no-graph works' ' test_expect_success '--no-walk and --graph conflict' ' test_must_fail git log --no-walk --graph 2>stderr && - test_i18ngrep "cannot be used together" stderr + test_grep "cannot be used together" stderr ' test_expect_success '--no-walk --graph --no-graph works' ' @@ -1887,8 +1917,8 @@ test_expect_success '--no-walk --graph --no-graph works' ' test_expect_success '--walk-reflogs and --graph conflict' ' test_must_fail git log --walk-reflogs --graph 2>stderr && - (test_i18ngrep "cannot combine" stderr || - test_i18ngrep "cannot be used together" stderr) + (test_grep "cannot combine" stderr || + test_grep "cannot be used together" stderr) ' test_expect_success '--walk-reflogs --graph --no-graph works' ' @@ -2222,7 +2252,7 @@ test_expect_success 'log on empty repo fails' ' git init empty && test_when_finished "rm -rf empty" && test_must_fail git -C empty log 2>stderr && - test_i18ngrep does.not.have.any.commits stderr + test_grep does.not.have.any.commits stderr ' test_expect_success REFFILES 'log diagnoses bogus HEAD hash' ' @@ -2230,16 +2260,16 @@ test_expect_success REFFILES 'log diagnoses bogus HEAD hash' ' test_when_finished "rm -rf empty" && echo 1234abcd >empty/.git/refs/heads/main && test_must_fail git -C empty log 2>stderr && - test_i18ngrep broken stderr + test_grep broken stderr ' test_expect_success REFFILES 'log diagnoses bogus HEAD symref' ' git init empty && - echo "ref: refs/heads/invalid.lock" > empty/.git/HEAD && + test-tool -C empty ref-store main create-symref HEAD refs/heads/invalid.lock && test_must_fail git -C empty log 2>stderr && - test_i18ngrep broken stderr && + test_grep broken stderr && test_must_fail git -C empty log --default totally-bogus 2>stderr && - test_i18ngrep broken stderr + test_grep broken stderr ' test_expect_success 'log does not default to HEAD when rev input is given' ' @@ -2328,10 +2358,10 @@ test_expect_success 'log --decorate does not include things outside filter' ' ' test_expect_success 'log --end-of-options' ' - git update-ref refs/heads/--source HEAD && - git log --end-of-options --source >actual && - git log >expect && - test_cmp expect actual + git update-ref refs/heads/--source HEAD && + git log --end-of-options --source >actual && + git log >expect && + test_cmp expect actual ' test_expect_success 'set up commits with different authors' ' diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh index fa7f987284..8a88dd7900 100755 --- a/t/t4203-mailmap.sh +++ b/t/t4203-mailmap.sh @@ -360,7 +360,7 @@ test_expect_success 'mailmap.blob might be the wrong type' ' cp default.map .mailmap && git -c mailmap.blob=HEAD: shortlog HEAD >actual 2>err && - test_i18ngrep "mailmap is not a blob" err && + test_grep "mailmap is not a blob" err && test_cmp expect actual ' @@ -466,7 +466,7 @@ test_expect_success 'gitmailmap(5) example output: example #1' ' Author Jane Doe <jane@laptop.(none)> maps to Jane Doe <jane@laptop.(none)> Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com> - Author Jane D <jane@desktop.(none)> maps to Jane Doe <jane@desktop.(none)> + Author Jane D. <jane@desktop.(none)> maps to Jane Doe <jane@desktop.(none)> Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com> EOF git -C doc log --reverse --pretty=format:"Author %an <%ae> maps to %aN <%aE>%nCommitter %cn <%ce> maps to %cN <%cE>%n" >actual && @@ -494,7 +494,7 @@ test_expect_success 'gitmailmap(5) example output: example #2' ' Author Jane Doe <jane@laptop.(none)> maps to Jane Doe <jane@example.com> Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com> - Author Jane D <jane@desktop.(none)> maps to Jane Doe <jane@example.com> + Author Jane D. <jane@desktop.(none)> maps to Jane Doe <jane@example.com> Committer C O Mitter <committer@example.com> maps to C O Mitter <committer@example.com> EOF git -C doc log --reverse --pretty=format:"Author %an <%ae> maps to %aN <%aE>%nCommitter %cn <%ce> maps to %cN <%cE>%n" >actual && diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh index 4cf8a77667..e3d655e6b8 100755 --- a/t/t4205-log-pretty-formats.sh +++ b/t/t4205-log-pretty-formats.sh @@ -576,6 +576,38 @@ test_expect_success 'clean log decoration' ' test_cmp expected actual1 ' +test_expect_success 'pretty format %decorate' ' + git checkout -b foo && + git commit --allow-empty -m "new commit" && + git tag bar && + git branch qux && + + echo " (HEAD -> foo, tag: bar, qux)" >expect1 && + git log --format="%(decorate)" -1 >actual1 && + test_cmp expect1 actual1 && + + echo "HEAD -> foo, tag: bar, qux" >expect2 && + git log --format="%(decorate:prefix=,suffix=)" -1 >actual2 && + test_cmp expect2 actual2 && + + echo "[ bar; qux; foo ]" >expect3 && + git log --format="%(decorate:prefix=[ ,suffix= ],separator=%x3B ,tag=)" \ + --decorate-refs=refs/ -1 >actual3 && + test_cmp expect3 actual3 && + + # Try with a typo (in "separator"), in which case the placeholder should + # not be replaced. + echo "%(decorate:prefix=[ ,suffix= ],separater=; )" >expect4 && + git log --format="%(decorate:prefix=[ ,suffix= ],separater=%x3B )" \ + -1 >actual4 && + test_cmp expect4 actual4 && + + echo "HEAD->foo bar qux" >expect5 && + git log --format="%(decorate:prefix=,suffix=,separator= ,tag=,pointer=->)" \ + -1 >actual5 && + test_cmp expect5 actual5 +' + cat >trailers <<EOF Signed-off-by: A U Thor <author@example.com> Acked-by: A U Thor <author@example.com> @@ -924,6 +956,36 @@ test_expect_success '%S in git log --format works with other placeholders (part test_cmp expect actual ' +test_expect_success 'setup more commits for %S with --bisect' ' + test_commit four && + test_commit five && + + head1=$(git rev-parse --verify HEAD~0) && + head2=$(git rev-parse --verify HEAD~1) && + head3=$(git rev-parse --verify HEAD~2) && + head4=$(git rev-parse --verify HEAD~3) +' + +test_expect_success '%S with --bisect labels commits with refs/bisect/bad ref' ' + git update-ref refs/bisect/bad-$head1 $head1 && + git update-ref refs/bisect/go $head1 && + git update-ref refs/bisect/bad-$head2 $head2 && + git update-ref refs/bisect/b $head3 && + git update-ref refs/bisect/bad-$head4 $head4 && + git update-ref refs/bisect/good-$head4 $head4 && + + # We expect to see the range of commits betwee refs/bisect/good-$head4 + # and refs/bisect/bad-$head1. The "source" ref is the nearest bisect ref + # from which the commit is reachable. + cat >expect <<-EOF && + $head1 refs/bisect/bad-$head1 + $head2 refs/bisect/bad-$head2 + $head3 refs/bisect/bad-$head2 + EOF + git log --bisect --format="%H %S" >actual && + test_cmp expect actual +' + test_expect_success 'log --pretty=reference' ' git log --pretty="tformat:%h (%s, %as)" >expect && git log --pretty=reference >actual && @@ -1012,10 +1074,25 @@ test_expect_success '%(describe:tags) vs git describe --tags' ' test_expect_success '%(describe:abbrev=...) vs git describe --abbrev=...' ' test_when_finished "git tag -d tagname" && + + # Case 1: We have commits between HEAD and the most recent tag + # reachable from it + test_commit --no-tag file && + git describe --abbrev=15 >expect && + git log -1 --format="%(describe:abbrev=15)" >actual && + test_cmp expect actual && + + # Make sure the hash used is at least 15 digits long + sed -e "s/^.*-g\([0-9a-f]*\)$/\1/" <actual >hexpart && + test 16 -le $(wc -c <hexpart) && + + # Case 2: We have a tag at HEAD, describe directly gives the + # name of the tag git tag -a -m tagged tagname && git describe --abbrev=15 >expect && git log -1 --format="%(describe:abbrev=15)" >actual && - test_cmp expect actual + test_cmp expect actual && + test tagname = $(cat actual) ' test_expect_success 'log --pretty with space stealing' ' diff --git a/t/t4206-log-follow-harder-copies.sh b/t/t4206-log-follow-harder-copies.sh index 33ecf82c7f..9167b0351f 100755 --- a/t/t4206-log-follow-harder-copies.sh +++ b/t/t4206-log-follow-harder-copies.sh @@ -16,29 +16,29 @@ Line 2 Line 3 ' -test_expect_success \ - 'add a file path0 and commit.' \ - 'git add path0 && - git commit -m "Add path0"' +test_expect_success 'add a file path0 and commit.' ' + git add path0 && + git commit -m "Add path0" +' echo >path0 'New line 1 New line 2 New line 3 ' -test_expect_success \ - 'Change path0.' \ - 'git add path0 && - git commit -m "Change path0"' +test_expect_success 'Change path0.' ' + git add path0 && + git commit -m "Change path0" +' cat <path0 >path1 -test_expect_success \ - 'copy path0 to path1.' \ - 'git add path1 && - git commit -m "Copy path1 from path0"' +test_expect_success 'copy path0 to path1.' ' + git add path1 && + git commit -m "Copy path1 from path0" +' -test_expect_success \ - 'find the copy path0 -> path1 harder' \ - 'git log --follow --name-status --pretty="format:%s" path1 > current' +test_expect_success 'find the copy path0 -> path1 harder' ' + git log --follow --name-status --pretty="format:%s" path1 > current +' cat >expected <<\EOF Copy path1 from path0 @@ -51,8 +51,8 @@ Add path0 A path0 EOF -test_expect_success \ - 'validate the output.' \ - 'compare_diff_patch current expected' +test_expect_success 'validate the output.' ' + compare_diff_patch current expected +' test_done diff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh index ded33a82e2..73ea9e5155 100755 --- a/t/t4207-log-decoration-colors.sh +++ b/t/t4207-log-decoration-colors.sh @@ -53,35 +53,45 @@ cmp_filtered_decorations () { # to this test since it does not contain any decoration, hence --first-parent test_expect_success 'commit decorations colored correctly' ' cat >expect <<-EOF && - ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD -> \ -${c_reset}${c_branch}main${c_reset}${c_commit}, \ -${c_reset}${c_tag}tag: v1.0${c_reset}${c_commit}, \ -${c_reset}${c_tag}tag: B${c_reset}${c_commit})${c_reset} B -${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A1${c_reset}${c_commit}, \ + ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD${c_reset}\ +${c_commit} -> ${c_reset}${c_branch}main${c_reset}${c_commit}, \ +${c_reset}${c_tag}tag: ${c_reset}${c_tag}v1.0${c_reset}${c_commit}, \ +${c_reset}${c_tag}tag: ${c_reset}${c_tag}B${c_reset}${c_commit})${c_reset} B +${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\ +${c_tag}tag: ${c_reset}${c_tag}A1${c_reset}${c_commit}, \ ${c_reset}${c_remoteBranch}other/main${c_reset}${c_commit})${c_reset} A1 - ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_stash}refs/stash${c_reset}${c_commit})${c_reset} \ -On main: Changes to A.t - ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A + ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\ +${c_stash}refs/stash${c_reset}${c_commit})${c_reset} On main: Changes to A.t + ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\ +${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_commit})${c_reset} A EOF git log --first-parent --no-abbrev --decorate --oneline --color=always --all >actual && cmp_filtered_decorations ' +remove_replace_refs () { + git for-each-ref 'refs/replace*/**' --format='delete %(refname)' >in && + git update-ref --stdin <in && + rm in +} + test_expect_success 'test coloring with replace-objects' ' - test_when_finished rm -rf .git/refs/replace* && + test_when_finished remove_replace_refs && test_commit C && test_commit D && git replace HEAD~1 HEAD~2 && cat >expect <<-EOF && - ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD -> \ -${c_reset}${c_branch}main${c_reset}${c_commit}, \ -${c_reset}${c_tag}tag: D${c_reset}${c_commit})${c_reset} D - ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: C${c_reset}${c_commit}, \ + ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD${c_reset}\ +${c_commit} -> ${c_reset}${c_branch}main${c_reset}${c_commit}, \ +${c_reset}${c_tag}tag: ${c_reset}${c_tag}D${c_reset}${c_commit})${c_reset} D + ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\ +${c_tag}tag: ${c_reset}${c_tag}C${c_reset}${c_commit}, \ ${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} B - ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A + ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\ +${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_commit})${c_reset} A EOF git log --first-parent --no-abbrev --decorate --oneline --color=always HEAD >actual && @@ -95,18 +105,20 @@ EOF ' test_expect_success 'test coloring with grafted commit' ' - test_when_finished rm -rf .git/refs/replace* && + test_when_finished remove_replace_refs && git replace --graft HEAD HEAD~2 && cat >expect <<-EOF && - ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD -> \ -${c_reset}${c_branch}main${c_reset}${c_commit}, \ -${c_reset}${c_tag}tag: D${c_reset}${c_commit}, \ + ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD${c_reset}\ +${c_commit} -> ${c_reset}${c_branch}main${c_reset}${c_commit}, \ +${c_reset}${c_tag}tag: ${c_reset}${c_tag}D${c_reset}${c_commit}, \ ${c_reset}${c_grafted}replaced${c_reset}${c_commit})${c_reset} D - ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: v1.0${c_reset}${c_commit}, \ -${c_reset}${c_tag}tag: B${c_reset}${c_commit})${c_reset} B - ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A + ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\ +${c_tag}tag: ${c_reset}${c_tag}v1.0${c_reset}${c_commit}, \ +${c_reset}${c_tag}tag: ${c_reset}${c_tag}B${c_reset}${c_commit})${c_reset} B + ${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}\ +${c_tag}tag: ${c_reset}${c_tag}A${c_reset}${c_commit})${c_reset} A EOF git log --first-parent --no-abbrev --decorate --oneline --color=always HEAD >actual && diff --git a/t/t4208-log-magic-pathspec.sh b/t/t4208-log-magic-pathspec.sh index 2e8f5ad7b8..806b2809d4 100755 --- a/t/t4208-log-magic-pathspec.sh +++ b/t/t4208-log-magic-pathspec.sh @@ -21,7 +21,7 @@ test_expect_success '"git log :/" should not be ambiguous' ' test_expect_success '"git log :/a" should be ambiguous (applied both rev and worktree)' ' : >a && test_must_fail git log :/a 2>error && - test_i18ngrep ambiguous error + test_grep ambiguous error ' test_expect_success '"git log :/a -- " should not be ambiguous' ' @@ -65,7 +65,7 @@ test_expect_success '"git log :/in" should not be ambiguous' ' test_expect_success '"git log :" should be ambiguous' ' test_must_fail git log : 2>error && - test_i18ngrep ambiguous error + test_grep ambiguous error ' test_expect_success 'git log -- :' ' @@ -104,7 +104,7 @@ test_expect_success '"git log :(exclude)sub --" must resolve as an object' ' test_expect_success '"git log :(unknown-magic) complains of bogus magic' ' test_must_fail git log ":(unknown-magic)" 2>error && - test_i18ngrep pathspec.magic error + test_grep pathspec.magic error ' test_expect_success 'command line pathspec parsing for "git log"' ' diff --git a/t/t4209-log-pickaxe.sh b/t/t4209-log-pickaxe.sh index 7f6bb27f14..64e1623733 100755 --- a/t/t4209-log-pickaxe.sh +++ b/t/t4209-log-pickaxe.sh @@ -57,10 +57,10 @@ test_expect_success setup ' test_expect_success 'usage' ' test_expect_code 129 git log -S 2>err && - test_i18ngrep "switch.*requires a value" err && + test_grep "switch.*requires a value" err && test_expect_code 129 git log -G 2>err && - test_i18ngrep "switch.*requires a value" err && + test_grep "switch.*requires a value" err && test_expect_code 128 git log -Gregex -Sstring 2>err && grep "cannot be used together" err && diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh index c6540e822f..02d76dca28 100755 --- a/t/t4211-line-log.sh +++ b/t/t4211-line-log.sh @@ -19,7 +19,7 @@ test_expect_success 'basic command line parsing' ' # -L requires there is no pathspec test_must_fail git log -L1,1:b.c -- b.c 2>error && - test_i18ngrep "cannot be used with pathspec" error && + test_grep "cannot be used with pathspec" error && # This would fail because --follow wants a single path, but # we may fail due to incompatibility between -L/--follow in @@ -50,7 +50,7 @@ canned_test_failure () { test_bad_opts () { test_expect_success "invalid args: $1" " test_must_fail git log $1 2>errors && - test_i18ngrep '$2' errors + test_grep '$2' errors " } diff --git a/t/t4212-log-corrupt.sh b/t/t4212-log-corrupt.sh index e89e1f54b6..e6b59123a3 100755 --- a/t/t4212-log-corrupt.sh +++ b/t/t4212-log-corrupt.sh @@ -8,15 +8,16 @@ TEST_PASSES_SANITIZE_LEAK=true test_expect_success 'setup' ' test_commit foo && - git cat-file commit HEAD | - sed "/^author /s/>/>-<>/" >broken_email.commit && + git cat-file commit HEAD >ok.commit && + sed "s/>/>-<>/" <ok.commit >broken_email.commit && + git hash-object --literally -w -t commit broken_email.commit >broken_email.hash && git update-ref refs/heads/broken_email $(cat broken_email.hash) ' test_expect_success 'fsck notices broken commit' ' test_must_fail git fsck 2>actual && - test_i18ngrep invalid.author actual + test_grep invalid.author actual ' test_expect_success 'git log with broken author email' ' @@ -43,6 +44,11 @@ test_expect_success 'git log --format with broken author email' ' test_must_be_empty actual.err ' +test_expect_success '--until handles broken email' ' + git rev-list --until=1980-01-01 broken_email >actual && + test_must_be_empty actual +' + munge_author_date () { git cat-file commit "$1" >commit.orig && sed "s/^\(author .*>\) [0-9]*/\1 $2/" <commit.orig >commit.munge && @@ -86,4 +92,45 @@ test_expect_success 'absurdly far-in-future date' ' git log -1 --format=%ad $commit ' +test_expect_success 'create commits with whitespace committer dates' ' + # It is important that this subject line is numeric, since we want to + # be sure we are not confused by skipping whitespace and accidentally + # parsing the subject as a timestamp. + # + # Do not use munge_author_date here. Besides not hitting the committer + # line, it leaves the timezone intact, and we want nothing but + # whitespace. + # + # We will make two munged commits here. The first, ws_commit, will + # be purely spaces. The second contains a vertical tab, which is + # considered a space by strtoumax(), but not by our isspace(). + test_commit 1234567890 && + git cat-file commit HEAD >commit.orig && + sed "s/>.*/> /" <commit.orig >commit.munge && + ws_commit=$(git hash-object --literally -w -t commit commit.munge) && + sed "s/>.*/> $(printf "\013")/" <commit.orig >commit.munge && + vt_commit=$(git hash-object --literally -w -t commit commit.munge) +' + +test_expect_success '--until treats whitespace date as sentinel' ' + echo $ws_commit >expect && + git rev-list --until=1980-01-01 $ws_commit >actual && + test_cmp expect actual && + + echo $vt_commit >expect && + git rev-list --until=1980-01-01 $vt_commit >actual && + test_cmp expect actual +' + +test_expect_success 'pretty-printer handles whitespace date' ' + # as with the %ad test above, we will show these as the empty string, + # not the 1970 epoch date. This is intentional; see 7d9a281941 (t4212: + # test bogus timestamps with git-log, 2014-02-24) for more discussion. + echo : >expect && + git log -1 --format="%at:%ct" $ws_commit >actual && + test_cmp expect actual && + git log -1 --format="%at:%ct" $vt_commit >actual && + test_cmp expect actual +' + test_done diff --git a/t/t4214-log-graph-octopus.sh b/t/t4214-log-graph-octopus.sh index f70c46bbbf..7905597869 100755 --- a/t/t4214-log-graph-octopus.sh +++ b/t/t4214-log-graph-octopus.sh @@ -5,6 +5,7 @@ test_description='git log --graph of skewed left octopus merge.' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-log-graph.sh diff --git a/t/t4215-log-skewed-merges.sh b/t/t4215-log-skewed-merges.sh index 28d0779a8c..b877ac7235 100755 --- a/t/t4215-log-skewed-merges.sh +++ b/t/t4215-log-skewed-merges.sh @@ -2,6 +2,7 @@ test_description='git log --graph of skewed merges' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-log-graph.sh diff --git a/t/t4216-log-bloom.sh b/t/t4216-log-bloom.sh index fa9d32facf..2ba0324a69 100755 --- a/t/t4216-log-bloom.sh +++ b/t/t4216-log-bloom.sh @@ -5,6 +5,7 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-chunk.sh GIT_TEST_COMMIT_GRAPH=0 GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0 @@ -404,4 +405,53 @@ test_expect_success 'Bloom generation backfills empty commits' ' ) ' +corrupt_graph () { + graph=.git/objects/info/commit-graph && + test_when_finished "rm -rf $graph" && + git commit-graph write --reachable --changed-paths && + corrupt_chunk_file $graph "$@" +} + +check_corrupt_graph () { + corrupt_graph "$@" && + git -c core.commitGraph=false log -- A/B/file2 >expect.out && + git -c core.commitGraph=true log -- A/B/file2 >out 2>err && + test_cmp expect.out out +} + +test_expect_success 'Bloom reader notices too-small data chunk' ' + check_corrupt_graph BDAT clear 00000000 && + echo "warning: ignoring too-small changed-path chunk" \ + "(4 < 12) in commit-graph file" >expect.err && + test_cmp expect.err err +' + +test_expect_success 'Bloom reader notices out-of-bounds filter offsets' ' + check_corrupt_graph BIDX 12 FFFFFFFF && + # use grep to avoid depending on exact chunk size + grep "warning: ignoring out-of-range offset (4294967295) for changed-path filter at pos 3 of .git/objects/info/commit-graph" err +' + +test_expect_success 'Bloom reader notices too-small index chunk' ' + # replace the index with a single entry, making most + # lookups out-of-bounds + check_corrupt_graph BIDX clear 00000000 && + echo "warning: commit-graph changed-path index chunk" \ + "is too small" >expect.err && + test_cmp expect.err err +' + +test_expect_success 'Bloom reader notices out-of-order index offsets' ' + # we do not know any real offsets, but we can pick + # something plausible; we should not get to the point of + # actually reading from the bogus offsets anyway. + corrupt_graph BIDX 4 0000000c00000005 && + echo "warning: ignoring decreasing changed-path index offsets" \ + "(12 > 5) for positions 1 and 2 of .git/objects/info/commit-graph" >expect.err && + git -c core.commitGraph=false log -- A/B/file2 >expect.out && + git -c core.commitGraph=true log -- A/B/file2 >out 2>err && + test_cmp expect.out out && + test_cmp expect.err err +' + test_done diff --git a/t/t4217-log-limit.sh b/t/t4217-log-limit.sh index 6e01e2629c..613f0710e9 100755 --- a/t/t4217-log-limit.sh +++ b/t/t4217-log-limit.sh @@ -2,6 +2,7 @@ test_description='git log with filter options limiting the output' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup test' ' diff --git a/t/t4256-am-format-flowed.sh b/t/t4256-am-format-flowed.sh index 1015273bc8..92d8c8b651 100755 --- a/t/t4256-am-format-flowed.sh +++ b/t/t4256-am-format-flowed.sh @@ -13,7 +13,7 @@ test_expect_success 'setup' ' test_expect_success 'am with format=flowed' ' git am <"$TEST_DIRECTORY/t4256/1/patch" 2>stderr && - test_i18ngrep "warning: Patch sent with format=flowed" stderr && + test_grep "warning: Patch sent with format=flowed" stderr && test_cmp "$TEST_DIRECTORY/t4256/1/mailinfo.c" mailinfo.c ' diff --git a/t/t4258/mbox b/t/t4258/mbox index c62819f3d2..1ae528ba78 100644 --- a/t/t4258/mbox +++ b/t/t4258/mbox @@ -2,7 +2,7 @@ From: A U Thor <mail@example.com> To: list@example.org Subject: [PATCH v2] sample Date: Mon, 3 Aug 2020 22:40:55 +0700 -Message-Id: <msg-id@example.com> +Message-ID: <msg-id@example.com> Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 diff --git a/t/t4300-merge-tree.sh b/t/t4300-merge-tree.sh index c52c8a21fa..9c197260d5 100755 --- a/t/t4300-merge-tree.sh +++ b/t/t4300-merge-tree.sh @@ -86,6 +86,33 @@ EXPECTED test_cmp expected actual ' +test_expect_success '3-way merge with --attr-source' ' + test_when_finished rm -rf 3-way && + git init 3-way && + ( + cd 3-way && + test_commit initial file1 foo && + base=$(git rev-parse HEAD) && + git checkout -b brancha && + echo bar >>file1 && + git commit -am "adding bar" && + source=$(git rev-parse HEAD) && + git checkout @{-1} && + git checkout -b branchb && + echo baz >>file1 && + git commit -am "adding baz" && + merge=$(git rev-parse HEAD) && + git checkout -b gitattributes && + test_commit "gitattributes" .gitattributes "file1 merge=union" && + git checkout @{-1} && + tree=$(git --attr-source=gitattributes merge-tree --write-tree \ + --merge-base "$base" --end-of-options "$source" "$merge") && + test_write_lines foo bar baz >expect && + git cat-file -p "$tree:file1" >actual && + test_cmp expect actual + ) +' + test_expect_success 'file change A, B (same)' ' git reset --hard initial && test_commit "change-a-b-same-A" "initial-file" "AAA" && @@ -334,4 +361,22 @@ test_expect_success 'turn tree to file' ' test_cmp expect actual ' +test_expect_success 'merge-tree respects core.useReplaceRefs=false' ' + test_commit merge-to && + test_commit valid base && + git reset --hard HEAD^ && + test_commit malicious base && + + test_when_finished "git replace -d $(git rev-parse valid^0)" && + git replace valid^0 malicious^0 && + + tree=$(git -c core.useReplaceRefs=true merge-tree --write-tree merge-to valid) && + merged=$(git cat-file -p $tree:base) && + test malicious = $merged && + + tree=$(git -c core.useReplaceRefs=false merge-tree --write-tree merge-to valid) && + merged=$(git cat-file -p $tree:base) && + test valid = $merged +' + test_done diff --git a/t/t4301-merge-tree-write-tree.sh b/t/t4301-merge-tree-write-tree.sh index 250f721795..12ac436873 100755 --- a/t/t4301-merge-tree-write-tree.sh +++ b/t/t4301-merge-tree-write-tree.sh @@ -22,6 +22,7 @@ test_expect_success setup ' git branch side1 && git branch side2 && git branch side3 && + git branch side4 && git checkout side1 && test_write_lines 1 2 3 4 5 6 >numbers && @@ -46,6 +47,13 @@ test_expect_success setup ' test_tick && git commit -m rename-numbers && + git checkout side4 && + test_write_lines 0 1 2 3 4 5 >numbers && + echo yo >greeting && + git add numbers greeting && + test_tick && + git commit -m other-content-modifications && + git switch --orphan unrelated && >something-else && git add something-else && @@ -97,6 +105,21 @@ test_expect_success 'Content merge and a few conflicts' ' test_cmp expect actual ' +test_expect_success 'Auto resolve conflicts by "ours" strategy option' ' + git checkout side1^0 && + + # make sure merge conflict exists + test_must_fail git merge side4 && + git merge --abort && + + git merge -X ours side4 && + git rev-parse HEAD^{tree} >expected && + + git merge-tree -X ours side1 side4 >actual && + + test_cmp expected actual +' + test_expect_success 'Barf on misspelled option, with exit code other than 0 or 1' ' # Mis-spell with single "s" instead of double "s" test_expect_code 129 git merge-tree --write-tree --mesages FOOBAR side1 side2 2>expect && @@ -864,7 +887,7 @@ test_expect_success '--stdin with both a successful and a conflicted merge' ' test_expect_success '--merge-base is incompatible with --stdin' ' test_must_fail git merge-tree --merge-base=side1 --stdin 2>expect && - grep "^fatal: --merge-base is incompatible with --stdin" expect + grep "^fatal: .*merge-base.*stdin.* cannot be used together" expect ' # specify merge-base as parent of branch2 diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh index 918a2fc7c6..4b4c3315d8 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -185,6 +185,7 @@ test_expect_success 'git archive' ' ' check_tar b +check_mtime b a/a 1117231200 test_expect_success 'git archive --mtime' ' git archive --mtime=2002-02-02T02:02:02-0200 HEAD >with_mtime.tar @@ -257,14 +258,6 @@ test_expect_success 'git archive --remote with configured remote' ' test_cmp_bin b.tar b5-nick.tar ' -test_expect_success 'validate file modification time' ' - mkdir extract && - "$TAR" xf b.tar -C extract a/a && - test-tool chmtime --get extract/a/a >b.mtime && - echo "1117231200" >expected.mtime && - test_cmp expected.mtime b.mtime -' - test_expect_success 'git get-tar-commit-id' ' git get-tar-commit-id <b.tar >actual && git rev-parse HEAD >expect && @@ -433,6 +426,19 @@ test_expect_success 'catch non-matching pathspec' ' test_must_fail git archive -v HEAD -- "*.abc" >/dev/null ' +test_expect_success 'reject paths outside the current directory' ' + test_must_fail git -C a/bin archive HEAD .. >/dev/null 2>err && + grep "outside the current directory" err +' + +test_expect_success 'allow pathspecs that resolve to the current directory' ' + git -C a/bin archive -v HEAD ../bin >/dev/null 2>actual && + cat >expect <<-\EOF && + sh + EOF + test_cmp expect actual +' + # Pull the size and date of each entry in a tarfile using the system tar. # # We'll pull out only the year from the date; that avoids any question of diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh index 04d300eeda..eaf959d8f6 100755 --- a/t/t5001-archive-attr.sh +++ b/t/t5001-archive-attr.sh @@ -33,6 +33,13 @@ test_expect_success 'setup' ' echo ignored-by-tree.d export-ignore >>.gitattributes && git add ignored-by-tree ignored-by-tree.d .gitattributes && + mkdir subdir && + >subdir/included && + >subdir/ignored-by-subtree && + >subdir/ignored-by-tree && + echo ignored-by-subtree export-ignore >subdir/.gitattributes && + git add subdir && + echo ignored by worktree >ignored-by-worktree && echo ignored-by-worktree export-ignore >.gitattributes && git add ignored-by-worktree && @@ -93,6 +100,15 @@ test_expect_exists archive-pathspec-wildcard/ignored-by-worktree test_expect_missing archive-pathspec-wildcard/excluded-by-pathspec.d test_expect_missing archive-pathspec-wildcard/excluded-by-pathspec.d/file +test_expect_success 'git -C subdir archive' ' + git -C subdir archive HEAD >archive-subdir.tar && + extract_tar_to_dir archive-subdir +' + +test_expect_exists archive-subdir/included +test_expect_missing archive-subdir/ignored-by-subtree +test_expect_missing archive-subdir/ignored-by-tree + test_expect_success 'git archive with worktree attributes' ' git archive --worktree-attributes HEAD >worktree.tar && (mkdir worktree && cd worktree && "$TAR" xf -) <worktree.tar @@ -122,7 +138,7 @@ test_expect_success 'git archive with worktree attributes, bare' ' ' test_expect_missing bare-worktree/ignored -test_expect_exists bare-worktree/ignored-by-tree +test_expect_missing bare-worktree/ignored-by-tree test_expect_exists bare-worktree/ignored-by-worktree test_expect_success 'export-subst' ' diff --git a/t/t5100/msg0002 b/t/t5100/msg0002 index e2546ec733..1089382425 100644 --- a/t/t5100/msg0002 +++ b/t/t5100/msg0002 @@ -3,7 +3,7 @@ message: From: Nit Picker <nit.picker@example.net> Subject: foo is too old -Message-Id: <nitpicker.12121212@example.net> +Message-ID: <nitpicker.12121212@example.net> Hopefully this would fix the problem stated there. diff --git a/t/t5100/msg0003 b/t/t5100/msg0003 index 1ac68101b1..3402b534a6 100644 --- a/t/t5100/msg0003 +++ b/t/t5100/msg0003 @@ -3,7 +3,7 @@ message: From: Nit Picker <nit.picker@example.net> Subject: foo is too old -Message-Id: <nitpicker.12121212@example.net> +Message-ID: <nitpicker.12121212@example.net> Hopefully this would fix the problem stated there. diff --git a/t/t5100/msg0012--message-id b/t/t5100/msg0012--message-id index 376e26e9ae..44482958ce 100644 --- a/t/t5100/msg0012--message-id +++ b/t/t5100/msg0012--message-id @@ -5,4 +5,4 @@ docutils заменён на python-docutils python-docutils. В то время как сам rest2web не нужен. Signed-off-by: Dmitriy Blinov <bda@mnsspb.ru> -Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru> +Message-ID: <1226501681-24923-1-git-send-email-bda@mnsspb.ru> diff --git a/t/t5100/quoted-cr.mbox b/t/t5100/quoted-cr.mbox index 909021bb7a..a529d4de08 100644 --- a/t/t5100/quoted-cr.mbox +++ b/t/t5100/quoted-cr.mbox @@ -3,7 +3,7 @@ From: A U Thor <mail@example.com> To: list@example.org Subject: [PATCH v2] sample Date: Mon, 3 Aug 2020 22:40:55 +0700 -Message-Id: <msg-id@example.com> +Message-ID: <msg-id@example.com> Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 @@ -27,7 +27,7 @@ From: A U Thor <mail@example.com> To: list@example.org Subject: [PATCH v2] sample Date: Mon, 3 Aug 2020 22:40:55 +0700 -Message-Id: <msg-id2@example.com> +Message-ID: <msg-id2@example.com> Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 diff --git a/t/t5100/sample.mbox b/t/t5100/sample.mbox index 6d4d0e4474..4a54ee5171 100644 --- a/t/t5100/sample.mbox +++ b/t/t5100/sample.mbox @@ -35,7 +35,7 @@ message: From: Nit Picker <nit.picker@example.net> Subject: foo is too old -Message-Id: <nitpicker.12121212@example.net> +Message-ID: <nitpicker.12121212@example.net> Hopefully this would fix the problem stated there. @@ -78,7 +78,7 @@ message: From: Nit Picker <nit.picker@example.net> Subject: foo is too old -Message-Id: <nitpicker.12121212@example.net> +Message-ID: <nitpicker.12121212@example.net> Hopefully this would fix the problem stated there. @@ -508,7 +508,7 @@ From bda@mnsspb.ru Wed Nov 12 17:54:41 2008 From: Dmitriy Blinov <bda@mnsspb.ru> To: navy-patches@dinar.mns.mnsspb.ru Date: Wed, 12 Nov 2008 17:54:41 +0300 -Message-Id: <1226501681-24923-1-git-send-email-bda@mnsspb.ru> +Message-ID: <1226501681-24923-1-git-send-email-bda@mnsspb.ru> X-Mailer: git-send-email 1.5.6.5 MIME-Version: 1.0 Content-Type: text/plain; diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh index f8a0f309e2..d402ec18b7 100755 --- a/t/t5300-pack-object.sh +++ b/t/t5300-pack-object.sh @@ -208,7 +208,7 @@ test_expect_success 'unpack with OFS_DELTA' ' ' test_expect_success 'unpack with OFS_DELTA (core.fsyncmethod=batch)' ' - check_unpack test-3-${packname_3} obj-list "$BATCH_CONFIGURATION" + check_unpack test-3-${packname_3} obj-list "$BATCH_CONFIGURATION" ' test_expect_success 'compare delta flavors' ' @@ -263,97 +263,97 @@ test_expect_success 'survive missing objects/pack directory' ' ) ' -test_expect_success \ - 'verify pack' \ - 'git verify-pack test-1-${packname_1}.idx \ - test-2-${packname_2}.idx \ - test-3-${packname_3}.idx' - -test_expect_success \ - 'verify pack -v' \ - 'git verify-pack -v test-1-${packname_1}.idx \ - test-2-${packname_2}.idx \ - test-3-${packname_3}.idx' - -test_expect_success \ - 'verify-pack catches mismatched .idx and .pack files' \ - 'cat test-1-${packname_1}.idx >test-3.idx && - cat test-2-${packname_2}.pack >test-3.pack && - if git verify-pack test-3.idx - then false - else :; - fi' - -test_expect_success \ - 'verify-pack catches a corrupted pack signature' \ - 'cat test-1-${packname_1}.pack >test-3.pack && - echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=2 && - if git verify-pack test-3.idx - then false - else :; - fi' - -test_expect_success \ - 'verify-pack catches a corrupted pack version' \ - 'cat test-1-${packname_1}.pack >test-3.pack && - echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=7 && - if git verify-pack test-3.idx - then false - else :; - fi' - -test_expect_success \ - 'verify-pack catches a corrupted type/size of the 1st packed object data' \ - 'cat test-1-${packname_1}.pack >test-3.pack && - echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=12 && - if git verify-pack test-3.idx - then false - else :; - fi' - -test_expect_success \ - 'verify-pack catches a corrupted sum of the index file itself' \ - 'l=$(wc -c <test-3.idx) && - l=$(expr $l - 20) && - cat test-1-${packname_1}.pack >test-3.pack && - printf "%20s" "" | dd of=test-3.idx count=20 bs=1 conv=notrunc seek=$l && - if git verify-pack test-3.pack - then false - else :; - fi' - -test_expect_success \ - 'build pack index for an existing pack' \ - 'cat test-1-${packname_1}.pack >test-3.pack && - git index-pack -o tmp.idx test-3.pack && - cmp tmp.idx test-1-${packname_1}.idx && - - git index-pack --promisor=message test-3.pack && - cmp test-3.idx test-1-${packname_1}.idx && - echo message >expect && - test_cmp expect test-3.promisor && - - cat test-2-${packname_2}.pack >test-3.pack && - git index-pack -o tmp.idx test-2-${packname_2}.pack && - cmp tmp.idx test-2-${packname_2}.idx && - - git index-pack test-3.pack && - cmp test-3.idx test-2-${packname_2}.idx && - - cat test-3-${packname_3}.pack >test-3.pack && - git index-pack -o tmp.idx test-3-${packname_3}.pack && - cmp tmp.idx test-3-${packname_3}.idx && - - git index-pack test-3.pack && - cmp test-3.idx test-3-${packname_3}.idx && - - cat test-1-${packname_1}.pack >test-4.pack && - rm -f test-4.keep && - git index-pack --keep=why test-4.pack && - cmp test-1-${packname_1}.idx test-4.idx && - test -f test-4.keep && - - :' +test_expect_success 'verify pack' ' + git verify-pack test-1-${packname_1}.idx \ + test-2-${packname_2}.idx \ + test-3-${packname_3}.idx +' + +test_expect_success 'verify pack -v' ' + git verify-pack -v test-1-${packname_1}.idx \ + test-2-${packname_2}.idx \ + test-3-${packname_3}.idx +' + +test_expect_success 'verify-pack catches mismatched .idx and .pack files' ' + cat test-1-${packname_1}.idx >test-3.idx && + cat test-2-${packname_2}.pack >test-3.pack && + if git verify-pack test-3.idx + then false + else :; + fi +' + +test_expect_success 'verify-pack catches a corrupted pack signature' ' + cat test-1-${packname_1}.pack >test-3.pack && + echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=2 && + if git verify-pack test-3.idx + then false + else :; + fi +' + +test_expect_success 'verify-pack catches a corrupted pack version' ' + cat test-1-${packname_1}.pack >test-3.pack && + echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=7 && + if git verify-pack test-3.idx + then false + else :; + fi +' + +test_expect_success 'verify-pack catches a corrupted type/size of the 1st packed object data' ' + cat test-1-${packname_1}.pack >test-3.pack && + echo | dd of=test-3.pack count=1 bs=1 conv=notrunc seek=12 && + if git verify-pack test-3.idx + then false + else :; + fi +' + +test_expect_success 'verify-pack catches a corrupted sum of the index file itself' ' + l=$(wc -c <test-3.idx) && + l=$(expr $l - 20) && + cat test-1-${packname_1}.pack >test-3.pack && + printf "%20s" "" | dd of=test-3.idx count=20 bs=1 conv=notrunc seek=$l && + if git verify-pack test-3.pack + then false + else :; + fi +' + +test_expect_success 'build pack index for an existing pack' ' + cat test-1-${packname_1}.pack >test-3.pack && + git index-pack -o tmp.idx test-3.pack && + cmp tmp.idx test-1-${packname_1}.idx && + + git index-pack --promisor=message test-3.pack && + cmp test-3.idx test-1-${packname_1}.idx && + echo message >expect && + test_cmp expect test-3.promisor && + + cat test-2-${packname_2}.pack >test-3.pack && + git index-pack -o tmp.idx test-2-${packname_2}.pack && + cmp tmp.idx test-2-${packname_2}.idx && + + git index-pack test-3.pack && + cmp test-3.idx test-2-${packname_2}.idx && + + cat test-3-${packname_3}.pack >test-3.pack && + git index-pack -o tmp.idx test-3-${packname_3}.pack && + cmp tmp.idx test-3-${packname_3}.idx && + + git index-pack test-3.pack && + cmp test-3.idx test-3-${packname_3}.idx && + + cat test-1-${packname_1}.pack >test-4.pack && + rm -f test-4.keep && + git index-pack --keep=why test-4.pack && + cmp test-1-${packname_1}.idx test-4.idx && + test -f test-4.keep && + + : +' test_expect_success 'unpacking with --strict' ' @@ -541,7 +541,7 @@ test_expect_success 'make sure index-pack detects the SHA1 collision' ' ( cd corrupt && test_must_fail git index-pack -o ../bad.idx ../test-3.pack 2>msg && - test_i18ngrep "SHA1 COLLISION FOUND" msg + test_grep "SHA1 COLLISION FOUND" msg ) ' @@ -549,7 +549,7 @@ test_expect_success 'make sure index-pack detects the SHA1 collision (large blob ( cd corrupt && test_must_fail git -c core.bigfilethreshold=1 index-pack -o ../bad.idx ../test-3.pack 2>msg && - test_i18ngrep "SHA1 COLLISION FOUND" msg + test_grep "SHA1 COLLISION FOUND" msg ) ' @@ -589,141 +589,6 @@ test_expect_success 'prefetch objects' ' test_line_count = 1 donelines ' -test_expect_success 'setup for --stdin-packs tests' ' - git init stdin-packs && - ( - cd stdin-packs && - - test_commit A && - test_commit B && - test_commit C && - - for id in A B C - do - git pack-objects .git/objects/pack/pack-$id \ - --incremental --revs <<-EOF || exit 1 - refs/tags/$id - EOF - done && - - ls -la .git/objects/pack - ) -' - -test_expect_success '--stdin-packs with excluded packs' ' - ( - cd stdin-packs && - - PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" && - PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" && - PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" && - - git pack-objects test --stdin-packs <<-EOF && - $PACK_A - ^$PACK_B - $PACK_C - EOF - - ( - git show-index <$(ls .git/objects/pack/pack-A-*.idx) && - git show-index <$(ls .git/objects/pack/pack-C-*.idx) - ) >expect.raw && - git show-index <$(ls test-*.idx) >actual.raw && - - cut -d" " -f2 <expect.raw | sort >expect && - cut -d" " -f2 <actual.raw | sort >actual && - test_cmp expect actual - ) -' - -test_expect_success '--stdin-packs is incompatible with --filter' ' - ( - cd stdin-packs && - test_must_fail git pack-objects --stdin-packs --stdout \ - --filter=blob:none </dev/null 2>err && - test_i18ngrep "cannot use --filter with --stdin-packs" err - ) -' - -test_expect_success '--stdin-packs is incompatible with --revs' ' - ( - cd stdin-packs && - test_must_fail git pack-objects --stdin-packs --revs out \ - </dev/null 2>err && - test_i18ngrep "cannot use internal rev list with --stdin-packs" err - ) -' - -test_expect_success '--stdin-packs with loose objects' ' - ( - cd stdin-packs && - - PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" && - PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" && - PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" && - - test_commit D && # loose - - git pack-objects test2 --stdin-packs --unpacked <<-EOF && - $PACK_A - ^$PACK_B - $PACK_C - EOF - - ( - git show-index <$(ls .git/objects/pack/pack-A-*.idx) && - git show-index <$(ls .git/objects/pack/pack-C-*.idx) && - git rev-list --objects --no-object-names \ - refs/tags/C..refs/tags/D - - ) >expect.raw && - ls -la . && - git show-index <$(ls test2-*.idx) >actual.raw && - - cut -d" " -f2 <expect.raw | sort >expect && - cut -d" " -f2 <actual.raw | sort >actual && - test_cmp expect actual - ) -' - -test_expect_success '--stdin-packs with broken links' ' - ( - cd stdin-packs && - - # make an unreachable object with a bogus parent - git cat-file -p HEAD >commit && - sed "s/$(git rev-parse HEAD^)/$(test_oid zero)/" <commit | - git hash-object -w -t commit --stdin >in && - - git pack-objects .git/objects/pack/pack-D <in && - - PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" && - PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" && - PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" && - PACK_D="$(basename .git/objects/pack/pack-D-*.pack)" && - - git pack-objects test3 --stdin-packs --unpacked <<-EOF && - $PACK_A - ^$PACK_B - $PACK_C - $PACK_D - EOF - - ( - git show-index <$(ls .git/objects/pack/pack-A-*.idx) && - git show-index <$(ls .git/objects/pack/pack-C-*.idx) && - git show-index <$(ls .git/objects/pack/pack-D-*.idx) && - git rev-list --objects --no-object-names \ - refs/tags/C..refs/tags/D - ) >expect.raw && - git show-index <$(ls test3-*.idx) >actual.raw && - - cut -d" " -f2 <expect.raw | sort >expect && - cut -d" " -f2 <actual.raw | sort >actual && - test_cmp expect actual - ) -' - test_expect_success 'negative window clamps to 0' ' git pack-objects --progress --window=-1 neg-window <obj-list 2>stderr && check_deltas stderr = 0 diff --git a/t/t5301-sliding-window.sh b/t/t5301-sliding-window.sh index 3ccaaeb397..226490d60d 100755 --- a/t/t5301-sliding-window.sh +++ b/t/t5301-sliding-window.sh @@ -8,55 +8,55 @@ test_description='mmap sliding window tests' TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh -test_expect_success \ - 'setup' \ - 'rm -f .git/index* && - for i in a b c - do - echo $i >$i && - test-tool genrandom "$i" 32768 >>$i && - git update-index --add $i || return 1 - done && - echo d >d && cat c >>d && git update-index --add d && - tree=$(git write-tree) && - commit1=$(git commit-tree $tree </dev/null) && - git update-ref HEAD $commit1 && - git repack -a -d && - test "$(git count-objects)" = "0 objects, 0 kilobytes" && - pack1=$(ls .git/objects/pack/*.pack) && - test -f "$pack1"' - -test_expect_success \ - 'verify-pack -v, defaults' \ - 'git verify-pack -v "$pack1"' - -test_expect_success \ - 'verify-pack -v, packedGitWindowSize == 1 page' \ - 'git config core.packedGitWindowSize 512 && - git verify-pack -v "$pack1"' - -test_expect_success \ - 'verify-pack -v, packedGit{WindowSize,Limit} == 1 page' \ - 'git config core.packedGitWindowSize 512 && - git config core.packedGitLimit 512 && - git verify-pack -v "$pack1"' - -test_expect_success \ - 'repack -a -d, packedGit{WindowSize,Limit} == 1 page' \ - 'git config core.packedGitWindowSize 512 && - git config core.packedGitLimit 512 && - commit2=$(git commit-tree $tree -p $commit1 </dev/null) && - git update-ref HEAD $commit2 && - git repack -a -d && - test "$(git count-objects)" = "0 objects, 0 kilobytes" && - pack2=$(ls .git/objects/pack/*.pack) && - test -f "$pack2" && - test "$pack1" \!= "$pack2"' - -test_expect_success \ - 'verify-pack -v, defaults' \ - 'git config --unset core.packedGitWindowSize && - git config --unset core.packedGitLimit && - git verify-pack -v "$pack2"' +test_expect_success 'setup' ' + rm -f .git/index* && + for i in a b c + do + echo $i >$i && + test-tool genrandom "$i" 32768 >>$i && + git update-index --add $i || return 1 + done && + echo d >d && cat c >>d && git update-index --add d && + tree=$(git write-tree) && + commit1=$(git commit-tree $tree </dev/null) && + git update-ref HEAD $commit1 && + git repack -a -d && + test "$(git count-objects)" = "0 objects, 0 kilobytes" && + pack1=$(ls .git/objects/pack/*.pack) && + test -f "$pack1" +' + +test_expect_success 'verify-pack -v, defaults' ' + git verify-pack -v "$pack1" +' + +test_expect_success 'verify-pack -v, packedGitWindowSize == 1 page' ' + git config core.packedGitWindowSize 512 && + git verify-pack -v "$pack1" +' + +test_expect_success 'verify-pack -v, packedGit{WindowSize,Limit} == 1 page' ' + git config core.packedGitWindowSize 512 && + git config core.packedGitLimit 512 && + git verify-pack -v "$pack1" +' + +test_expect_success 'repack -a -d, packedGit{WindowSize,Limit} == 1 page' ' + git config core.packedGitWindowSize 512 && + git config core.packedGitLimit 512 && + commit2=$(git commit-tree $tree -p $commit1 </dev/null) && + git update-ref HEAD $commit2 && + git repack -a -d && + test "$(git count-objects)" = "0 objects, 0 kilobytes" && + pack2=$(ls .git/objects/pack/*.pack) && + test -f "$pack2" && + test "$pack1" \!= "$pack2" +' + +test_expect_success 'verify-pack -v, defaults' ' + git config --unset core.packedGitWindowSize && + git config --unset core.packedGitLimit && + git verify-pack -v "$pack2" +' test_done diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh index f89809be53..d88e6f1691 100755 --- a/t/t5302-pack-index.sh +++ b/t/t5302-pack-index.sh @@ -282,8 +282,8 @@ test_expect_success 'index-pack --fsck-objects also warns upon missing tagger in test_expect_success 'index-pack -v --stdin produces progress for both phases' ' pack=$(git pack-objects --all pack </dev/null) && GIT_PROGRESS_DELAY=0 git index-pack -v --stdin <pack-$pack.pack 2>err && - test_i18ngrep "Receiving objects" err && - test_i18ngrep "Resolving deltas" err + test_grep "Receiving objects" err && + test_grep "Resolving deltas" err ' test_expect_success 'too-large packs report the breach' ' diff --git a/t/t5303-pack-corruption-resilience.sh b/t/t5303-pack-corruption-resilience.sh index 2926e8dfc4..61469ef4a6 100755 --- a/t/t5303-pack-corruption-resilience.sh +++ b/t/t5303-pack-corruption-resilience.sh @@ -59,304 +59,304 @@ do_corrupt_object() { printf '\0' > zero -test_expect_success \ - 'initial setup validation' \ - 'create_test_files && - create_new_pack && - git prune-packed && - git cat-file blob $blob_1 > /dev/null && - git cat-file blob $blob_2 > /dev/null && - git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - 'create corruption in header of first object' \ - 'do_corrupt_object $blob_1 0 < zero && - test_must_fail git cat-file blob $blob_1 > /dev/null && - test_must_fail git cat-file blob $blob_2 > /dev/null && - test_must_fail git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - '... but having a loose copy allows for full recovery' \ - 'mv ${pack}.idx tmp && - git hash-object -t blob -w file_1 && - mv tmp ${pack}.idx && - git cat-file blob $blob_1 > /dev/null && - git cat-file blob $blob_2 > /dev/null && - git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - '... and loose copy of first delta allows for partial recovery' \ - 'git prune-packed && - test_must_fail git cat-file blob $blob_2 > /dev/null && - mv ${pack}.idx tmp && - git hash-object -t blob -w file_2 && - mv tmp ${pack}.idx && - test_must_fail git cat-file blob $blob_1 > /dev/null && - git cat-file blob $blob_2 > /dev/null && - git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - 'create corruption in data of first object' \ - 'create_new_pack && - git prune-packed && - chmod +w ${pack}.pack && - perl -i.bak -pe "s/ base /abcdef/" ${pack}.pack && - test_must_fail git cat-file blob $blob_1 > /dev/null && - test_must_fail git cat-file blob $blob_2 > /dev/null && - test_must_fail git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - '... but having a loose copy allows for full recovery' \ - 'mv ${pack}.idx tmp && - git hash-object -t blob -w file_1 && - mv tmp ${pack}.idx && - git cat-file blob $blob_1 > /dev/null && - git cat-file blob $blob_2 > /dev/null && - git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - '... and loose copy of second object allows for partial recovery' \ - 'git prune-packed && - test_must_fail git cat-file blob $blob_2 > /dev/null && - mv ${pack}.idx tmp && - git hash-object -t blob -w file_2 && - mv tmp ${pack}.idx && - test_must_fail git cat-file blob $blob_1 > /dev/null && - git cat-file blob $blob_2 > /dev/null && - git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - 'create corruption in header of first delta' \ - 'create_new_pack && - git prune-packed && - do_corrupt_object $blob_2 0 < zero && - git cat-file blob $blob_1 > /dev/null && - test_must_fail git cat-file blob $blob_2 > /dev/null && - test_must_fail git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - '... but having a loose copy allows for full recovery' \ - 'mv ${pack}.idx tmp && - git hash-object -t blob -w file_2 && - mv tmp ${pack}.idx && - git cat-file blob $blob_1 > /dev/null && - git cat-file blob $blob_2 > /dev/null && - git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - '... and then a repack "clears" the corruption' \ - 'do_repack && - git prune-packed && - git verify-pack ${pack}.pack && - git cat-file blob $blob_1 > /dev/null && - git cat-file blob $blob_2 > /dev/null && - git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - 'create corruption in data of first delta' \ - 'create_new_pack && - git prune-packed && - chmod +w ${pack}.pack && - perl -i.bak -pe "s/ delta1 /abcdefgh/" ${pack}.pack && - git cat-file blob $blob_1 > /dev/null && - test_must_fail git cat-file blob $blob_2 > /dev/null && - test_must_fail git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - '... but having a loose copy allows for full recovery' \ - 'mv ${pack}.idx tmp && - git hash-object -t blob -w file_2 && - mv tmp ${pack}.idx && - git cat-file blob $blob_1 > /dev/null && - git cat-file blob $blob_2 > /dev/null && - git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - '... and then a repack "clears" the corruption' \ - 'do_repack && - git prune-packed && - git verify-pack ${pack}.pack && - git cat-file blob $blob_1 > /dev/null && - git cat-file blob $blob_2 > /dev/null && - git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - 'corruption in delta base reference of first delta (OBJ_REF_DELTA)' \ - 'create_new_pack && - git prune-packed && - do_corrupt_object $blob_2 2 < zero && - git cat-file blob $blob_1 > /dev/null && - test_must_fail git cat-file blob $blob_2 > /dev/null && - test_must_fail git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - '... but having a loose copy allows for full recovery' \ - 'mv ${pack}.idx tmp && - git hash-object -t blob -w file_2 && - mv tmp ${pack}.idx && - git cat-file blob $blob_1 > /dev/null && - git cat-file blob $blob_2 > /dev/null && - git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - '... and then a repack "clears" the corruption' \ - 'do_repack && - git prune-packed && - git verify-pack ${pack}.pack && - git cat-file blob $blob_1 > /dev/null && - git cat-file blob $blob_2 > /dev/null && - git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - 'corruption #0 in delta base reference of first delta (OBJ_OFS_DELTA)' \ - 'create_new_pack --delta-base-offset && - git prune-packed && - do_corrupt_object $blob_2 2 < zero && - git cat-file blob $blob_1 > /dev/null && - test_must_fail git cat-file blob $blob_2 > /dev/null && - test_must_fail git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - '... but having a loose copy allows for full recovery' \ - 'mv ${pack}.idx tmp && - git hash-object -t blob -w file_2 && - mv tmp ${pack}.idx && - git cat-file blob $blob_1 > /dev/null && - git cat-file blob $blob_2 > /dev/null && - git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - '... and then a repack "clears" the corruption' \ - 'do_repack --delta-base-offset && - git prune-packed && - git verify-pack ${pack}.pack && - git cat-file blob $blob_1 > /dev/null && - git cat-file blob $blob_2 > /dev/null && - git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - 'corruption #1 in delta base reference of first delta (OBJ_OFS_DELTA)' \ - 'create_new_pack --delta-base-offset && - git prune-packed && - printf "\001" | do_corrupt_object $blob_2 2 && - git cat-file blob $blob_1 > /dev/null && - test_must_fail git cat-file blob $blob_2 > /dev/null && - test_must_fail git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - '... but having a loose copy allows for full recovery' \ - 'mv ${pack}.idx tmp && - git hash-object -t blob -w file_2 && - mv tmp ${pack}.idx && - git cat-file blob $blob_1 > /dev/null && - git cat-file blob $blob_2 > /dev/null && - git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - '... and then a repack "clears" the corruption' \ - 'do_repack --delta-base-offset && - git prune-packed && - git verify-pack ${pack}.pack && - git cat-file blob $blob_1 > /dev/null && - git cat-file blob $blob_2 > /dev/null && - git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - '... and a redundant pack allows for full recovery too' \ - 'do_corrupt_object $blob_2 2 < zero && - git cat-file blob $blob_1 > /dev/null && - test_must_fail git cat-file blob $blob_2 > /dev/null && - test_must_fail git cat-file blob $blob_3 > /dev/null && - mv ${pack}.idx tmp && - git hash-object -t blob -w file_1 && - git hash-object -t blob -w file_2 && - printf "$blob_1\n$blob_2\n" | git pack-objects .git/objects/pack/pack && - git prune-packed && - mv tmp ${pack}.idx && - git cat-file blob $blob_1 > /dev/null && - git cat-file blob $blob_2 > /dev/null && - git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - 'corruption of delta base reference pointing to wrong object' \ - 'create_new_pack --delta-base-offset && - git prune-packed && - printf "\220\033" | do_corrupt_object $blob_3 2 && - git cat-file blob $blob_1 >/dev/null && - git cat-file blob $blob_2 >/dev/null && - test_must_fail git cat-file blob $blob_3 >/dev/null' - -test_expect_success \ - '... but having a loose copy allows for full recovery' \ - 'mv ${pack}.idx tmp && - git hash-object -t blob -w file_3 && - mv tmp ${pack}.idx && - git cat-file blob $blob_1 > /dev/null && - git cat-file blob $blob_2 > /dev/null && - git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - '... and then a repack "clears" the corruption' \ - 'do_repack --delta-base-offset --no-reuse-delta && - git prune-packed && - git verify-pack ${pack}.pack && - git cat-file blob $blob_1 > /dev/null && - git cat-file blob $blob_2 > /dev/null && - git cat-file blob $blob_3 > /dev/null' - -test_expect_success \ - 'corrupting header to have too small output buffer fails unpack' \ - 'create_new_pack && - git prune-packed && - printf "\262\001" | do_corrupt_object $blob_1 0 && - test_must_fail git cat-file blob $blob_1 > /dev/null && - test_must_fail git cat-file blob $blob_2 > /dev/null && - test_must_fail git cat-file blob $blob_3 > /dev/null' +test_expect_success 'initial setup validation' ' + create_test_files && + create_new_pack && + git prune-packed && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null +' + +test_expect_success 'create corruption in header of first object' ' + do_corrupt_object $blob_1 0 < zero && + test_must_fail git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null +' + +test_expect_success '... but having a loose copy allows for full recovery' ' + mv ${pack}.idx tmp && + git hash-object -t blob -w file_1 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null +' + +test_expect_success '... and loose copy of first delta allows for partial recovery' ' + git prune-packed && + test_must_fail git cat-file blob $blob_2 > /dev/null && + mv ${pack}.idx tmp && + git hash-object -t blob -w file_2 && + mv tmp ${pack}.idx && + test_must_fail git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null +' + +test_expect_success 'create corruption in data of first object' ' + create_new_pack && + git prune-packed && + chmod +w ${pack}.pack && + perl -i.bak -pe "s/ base /abcdef/" ${pack}.pack && + test_must_fail git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null +' + +test_expect_success '... but having a loose copy allows for full recovery' ' + mv ${pack}.idx tmp && + git hash-object -t blob -w file_1 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null +' + +test_expect_success '... and loose copy of second object allows for partial recovery' ' + git prune-packed && + test_must_fail git cat-file blob $blob_2 > /dev/null && + mv ${pack}.idx tmp && + git hash-object -t blob -w file_2 && + mv tmp ${pack}.idx && + test_must_fail git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null +' + +test_expect_success 'create corruption in header of first delta' ' + create_new_pack && + git prune-packed && + do_corrupt_object $blob_2 0 < zero && + git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null +' + +test_expect_success '... but having a loose copy allows for full recovery' ' + mv ${pack}.idx tmp && + git hash-object -t blob -w file_2 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null +' + +test_expect_success '... and then a repack "clears" the corruption' ' + do_repack && + git prune-packed && + git verify-pack ${pack}.pack && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null +' + +test_expect_success 'create corruption in data of first delta' ' + create_new_pack && + git prune-packed && + chmod +w ${pack}.pack && + perl -i.bak -pe "s/ delta1 /abcdefgh/" ${pack}.pack && + git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null +' + +test_expect_success '... but having a loose copy allows for full recovery' ' + mv ${pack}.idx tmp && + git hash-object -t blob -w file_2 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null +' + +test_expect_success '... and then a repack "clears" the corruption' ' + do_repack && + git prune-packed && + git verify-pack ${pack}.pack && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null +' + +test_expect_success 'corruption in delta base reference of first delta (OBJ_REF_DELTA)' ' + create_new_pack && + git prune-packed && + do_corrupt_object $blob_2 2 < zero && + git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null +' + +test_expect_success '... but having a loose copy allows for full recovery' ' + mv ${pack}.idx tmp && + git hash-object -t blob -w file_2 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null +' + +test_expect_success '... and then a repack "clears" the corruption' ' + do_repack && + git prune-packed && + git verify-pack ${pack}.pack && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null +' + +test_expect_success 'corruption #0 in delta base reference of first delta (OBJ_OFS_DELTA)' ' + create_new_pack --delta-base-offset && + git prune-packed && + do_corrupt_object $blob_2 2 < zero && + git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null +' + +test_expect_success '... but having a loose copy allows for full recovery' ' + mv ${pack}.idx tmp && + git hash-object -t blob -w file_2 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null +' + +test_expect_success '... and then a repack "clears" the corruption' ' + do_repack --delta-base-offset && + git prune-packed && + git verify-pack ${pack}.pack && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null +' + +test_expect_success 'corruption #1 in delta base reference of first delta (OBJ_OFS_DELTA)' ' + create_new_pack --delta-base-offset && + git prune-packed && + printf "\001" | do_corrupt_object $blob_2 2 && + git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null +' + +test_expect_success '... but having a loose copy allows for full recovery' ' + mv ${pack}.idx tmp && + git hash-object -t blob -w file_2 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null +' + +test_expect_success '... and then a repack "clears" the corruption' ' + do_repack --delta-base-offset && + git prune-packed && + git verify-pack ${pack}.pack && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null +' + +test_expect_success '... and a redundant pack allows for full recovery too' ' + do_corrupt_object $blob_2 2 < zero && + git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null && + mv ${pack}.idx tmp && + git hash-object -t blob -w file_1 && + git hash-object -t blob -w file_2 && + printf "$blob_1\n$blob_2\n" | git pack-objects .git/objects/pack/pack && + git prune-packed && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null +' + +test_expect_success 'corruption of delta base reference pointing to wrong object' ' + create_new_pack --delta-base-offset && + git prune-packed && + printf "\220\033" | do_corrupt_object $blob_3 2 && + git cat-file blob $blob_1 >/dev/null && + git cat-file blob $blob_2 >/dev/null && + test_must_fail git cat-file blob $blob_3 >/dev/null +' + +test_expect_success '... but having a loose copy allows for full recovery' ' + mv ${pack}.idx tmp && + git hash-object -t blob -w file_3 && + mv tmp ${pack}.idx && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null +' + +test_expect_success '... and then a repack "clears" the corruption' ' + do_repack --delta-base-offset --no-reuse-delta && + git prune-packed && + git verify-pack ${pack}.pack && + git cat-file blob $blob_1 > /dev/null && + git cat-file blob $blob_2 > /dev/null && + git cat-file blob $blob_3 > /dev/null +' + +test_expect_success 'corrupting header to have too small output buffer fails unpack' ' + create_new_pack && + git prune-packed && + printf "\262\001" | do_corrupt_object $blob_1 0 && + test_must_fail git cat-file blob $blob_1 > /dev/null && + test_must_fail git cat-file blob $blob_2 > /dev/null && + test_must_fail git cat-file blob $blob_3 > /dev/null +' # \0 - empty base # \1 - one byte in result # \1 - one literal byte (X) -test_expect_success \ - 'apply good minimal delta' \ - 'printf "\0\1\1X" > minimal_delta && - test-tool delta -p /dev/null minimal_delta /dev/null' +test_expect_success 'apply good minimal delta' ' + printf "\0\1\1X" > minimal_delta && + test-tool delta -p /dev/null minimal_delta /dev/null +' # \0 - empty base # \1 - 1 byte in result # \2 - two literal bytes (one too many) -test_expect_success \ - 'apply delta with too many literal bytes' \ - 'printf "\0\1\2XX" > too_big_literal && - test_must_fail test-tool delta -p /dev/null too_big_literal /dev/null' +test_expect_success 'apply delta with too many literal bytes' ' + printf "\0\1\2XX" > too_big_literal && + test_must_fail test-tool delta -p /dev/null too_big_literal /dev/null +' # \4 - four bytes in base # \1 - one byte in result # \221 - copy, one byte offset, one byte size # \0 - copy from offset 0 # \2 - copy two bytes (one too many) -test_expect_success \ - 'apply delta with too many copied bytes' \ - 'printf "\4\1\221\0\2" > too_big_copy && - printf base >base && - test_must_fail test-tool delta -p base too_big_copy /dev/null' +test_expect_success 'apply delta with too many copied bytes' ' + printf "\4\1\221\0\2" > too_big_copy && + printf base >base && + test_must_fail test-tool delta -p base too_big_copy /dev/null +' # \0 - empty base # \2 - two bytes in result # \2 - two literal bytes (we are short one) -test_expect_success \ - 'apply delta with too few literal bytes' \ - 'printf "\0\2\2X" > truncated_delta && - test_must_fail test-tool delta -p /dev/null truncated_delta /dev/null' +test_expect_success 'apply delta with too few literal bytes' ' + printf "\0\2\2X" > truncated_delta && + test_must_fail test-tool delta -p /dev/null truncated_delta /dev/null +' # \0 - empty base # \1 - one byte in result # \221 - copy, one byte offset, one byte size # \0 - copy from offset 0 # \1 - copy one byte (we are short one) -test_expect_success \ - 'apply delta with too few bytes in base' \ - 'printf "\0\1\221\0\1" > truncated_base && - test_must_fail test-tool delta -p /dev/null truncated_base /dev/null' +test_expect_success 'apply delta with too few bytes in base' ' + printf "\0\1\221\0\1" > truncated_base && + test_must_fail test-tool delta -p /dev/null truncated_base /dev/null +' # \4 - four bytes in base # \2 - two bytes in result @@ -366,20 +366,20 @@ test_expect_success \ # # Note that the literal byte is necessary to get past the uninteresting minimum # delta size check. -test_expect_success \ - 'apply delta with truncated copy parameters' \ - 'printf "\4\2\1X\221" > truncated_copy_delta && - printf base >base && - test_must_fail test-tool delta -p base truncated_copy_delta /dev/null' +test_expect_success 'apply delta with truncated copy parameters' ' + printf "\4\2\1X\221" > truncated_copy_delta && + printf base >base && + test_must_fail test-tool delta -p base truncated_copy_delta /dev/null +' # \0 - empty base # \1 - one byte in result # \1 - one literal byte (X) # \1 - trailing garbage command -test_expect_success \ - 'apply delta with trailing garbage literal' \ - 'printf "\0\1\1X\1" > tail_garbage_literal && - test_must_fail test-tool delta -p /dev/null tail_garbage_literal /dev/null' +test_expect_success 'apply delta with trailing garbage literal' ' + printf "\0\1\1X\1" > tail_garbage_literal && + test_must_fail test-tool delta -p /dev/null tail_garbage_literal /dev/null +' # \4 - four bytes in base # \1 - one byte in result @@ -387,19 +387,19 @@ test_expect_success \ # \221 - copy, one byte offset, one byte size # \0 - copy from offset 0 # \1 - copy 1 byte -test_expect_success \ - 'apply delta with trailing garbage copy' \ - 'printf "\4\1\1X\221\0\1" > tail_garbage_copy && - printf base >base && - test_must_fail test-tool delta -p /dev/null tail_garbage_copy /dev/null' +test_expect_success 'apply delta with trailing garbage copy' ' + printf "\4\1\1X\221\0\1" > tail_garbage_copy && + printf base >base && + test_must_fail test-tool delta -p /dev/null tail_garbage_copy /dev/null +' # \0 - empty base # \1 - one byte in result # \1 - one literal byte (X) # \0 - bogus opcode -test_expect_success \ - 'apply delta with trailing garbage opcode' \ - 'printf "\0\1\1X\0" > tail_garbage_opcode && - test_must_fail test-tool delta -p /dev/null tail_garbage_opcode /dev/null' +test_expect_success 'apply delta with trailing garbage opcode' ' + printf "\0\1\1X\0" > tail_garbage_opcode && + test_must_fail test-tool delta -p /dev/null tail_garbage_opcode /dev/null +' test_done diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh index d65a5f94b4..1f1f664871 100755 --- a/t/t5304-prune.sh +++ b/t/t5304-prune.sh @@ -16,7 +16,7 @@ add_blob() { before=$(git count-objects | sed "s/ .*//") && BLOB=$(echo aleph_0 | git hash-object -w --stdin) && BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") && - verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && + test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && test_path_is_file $BLOB_FILE && test-tool chmtime =+0 $BLOB_FILE } @@ -51,34 +51,42 @@ test_expect_success 'prune stale packs' ' test_expect_success 'prune --expire' ' add_blob && git prune --expire=1.hour.ago && - verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && + test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && test_path_is_file $BLOB_FILE && test-tool chmtime =-86500 $BLOB_FILE && git prune --expire 1.day && - verbose test $before = $(git count-objects | sed "s/ .*//") && + test $before = $(git count-objects | sed "s/ .*//") && test_path_is_missing $BLOB_FILE ' test_expect_success 'gc: implicit prune --expire' ' add_blob && test-tool chmtime =-$((2*$week-30)) $BLOB_FILE && - git gc && - verbose test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && + git gc --no-cruft && + test $((1 + $before)) = $(git count-objects | sed "s/ .*//") && test_path_is_file $BLOB_FILE && test-tool chmtime =-$((2*$week+1)) $BLOB_FILE && - git gc && - verbose test $before = $(git count-objects | sed "s/ .*//") && + git gc --no-cruft && + test $before = $(git count-objects | sed "s/ .*//") && test_path_is_missing $BLOB_FILE ' test_expect_success 'gc: refuse to start with invalid gc.pruneExpire' ' - git config gc.pruneExpire invalid && - test_must_fail git gc + test_when_finished "rm -rf repo" && + git init repo && + >repo/.git/config && + git -C repo config gc.pruneExpire invalid && + cat >expect <<-\EOF && + error: Invalid gc.pruneexpire: '\''invalid'\'' + fatal: bad config variable '\''gc.pruneexpire'\'' in file '\''.git/config'\'' at line 2 + EOF + test_must_fail git -C repo gc 2>actual && + test_cmp expect actual ' test_expect_success 'gc: start with ok gc.pruneExpire' ' git config gc.pruneExpire 2.days.ago && - git gc + git gc --no-cruft ' test_expect_success 'prune: prune nonsense parameters' ' @@ -129,44 +137,44 @@ test_expect_success 'gc --no-prune' ' add_blob && test-tool chmtime =-$((5001*$day)) $BLOB_FILE && git config gc.pruneExpire 2.days.ago && - git gc --no-prune && - verbose test 1 = $(git count-objects | sed "s/ .*//") && + git gc --no-prune --no-cruft && + test 1 = $(git count-objects | sed "s/ .*//") && test_path_is_file $BLOB_FILE ' test_expect_success 'gc respects gc.pruneExpire' ' git config gc.pruneExpire 5002.days.ago && - git gc && + git gc --no-cruft && test_path_is_file $BLOB_FILE && git config gc.pruneExpire 5000.days.ago && - git gc && + git gc --no-cruft && test_path_is_missing $BLOB_FILE ' test_expect_success 'gc --prune=<date>' ' add_blob && test-tool chmtime =-$((5001*$day)) $BLOB_FILE && - git gc --prune=5002.days.ago && + git gc --prune=5002.days.ago --no-cruft && test_path_is_file $BLOB_FILE && - git gc --prune=5000.days.ago && + git gc --prune=5000.days.ago --no-cruft && test_path_is_missing $BLOB_FILE ' test_expect_success 'gc --prune=never' ' add_blob && - git gc --prune=never && + git gc --prune=never --no-cruft && test_path_is_file $BLOB_FILE && - git gc --prune=now && + git gc --prune=now --no-cruft && test_path_is_missing $BLOB_FILE ' test_expect_success 'gc respects gc.pruneExpire=never' ' git config gc.pruneExpire never && add_blob && - git gc && + git gc --no-cruft && test_path_is_file $BLOB_FILE && git config gc.pruneExpire now && - git gc && + git gc --no-cruft && test_path_is_missing $BLOB_FILE ' @@ -184,10 +192,10 @@ test_expect_success 'gc: prune old objects after local clone' ' git clone --no-hardlinks . aclone && ( cd aclone && - verbose test 1 = $(git count-objects | sed "s/ .*//") && + test 1 = $(git count-objects | sed "s/ .*//") && test_path_is_file $BLOB_FILE && - git gc --prune && - verbose test 0 = $(git count-objects | sed "s/ .*//") && + git gc --prune --no-cruft && + test 0 = $(git count-objects | sed "s/ .*//") && test_path_is_missing $BLOB_FILE ) ' @@ -229,7 +237,7 @@ test_expect_success 'clean pack garbage with gc' ' >.git/objects/pack/fake2.keep && >.git/objects/pack/fake2.idx && >.git/objects/pack/fake3.keep && - git gc && + git gc --no-cruft && git count-objects -v 2>stderr && grep "^warning:" stderr | sort >actual && cat >expected <<\EOF && @@ -310,10 +318,10 @@ test_expect_success 'prune: handle HEAD reflog in multiple worktrees' ' test_expect_success 'prune: handle expire option correctly' ' test_must_fail git prune --expire 2>error && - test_i18ngrep "requires a value" error && + test_grep "requires a value" error && test_must_fail git prune --expire=nyah 2>error && - test_i18ngrep "malformed expiration" error && + test_grep "malformed expiration" error && git prune --no-expire ' @@ -342,4 +350,18 @@ test_expect_success 'old reachable-from-recent retained with bitmaps' ' test_must_fail git cat-file -e $to_drop ' +test_expect_success 'gc.recentObjectsHook' ' + add_blob && + test-tool chmtime =-86500 $BLOB_FILE && + + write_script precious-objects <<-EOF && + echo $BLOB + EOF + test_config gc.recentObjectsHook ./precious-objects && + + git prune --expire=now && + + git cat-file -p $BLOB +' + test_done diff --git a/t/t5306-pack-nobase.sh b/t/t5306-pack-nobase.sh index 846c5ca7d3..0d50c6b4bc 100755 --- a/t/t5306-pack-nobase.sh +++ b/t/t5306-pack-nobase.sh @@ -12,18 +12,17 @@ TEST_PASSES_SANITIZE_LEAK=true # Create A-B chain # -test_expect_success \ - 'setup base' \ - 'test_write_lines a b c d e f g h i >text && - echo side >side && - git update-index --add text side && - A=$(echo A | git commit-tree $(git write-tree)) && +test_expect_success 'setup base' ' + test_write_lines a b c d e f g h i >text && + echo side >side && + git update-index --add text side && + A=$(echo A | git commit-tree $(git write-tree)) && - echo m >>text && - git update-index text && - B=$(echo B | git commit-tree $(git write-tree) -p $A) && - git update-ref HEAD $B - ' + echo m >>text && + git update-index text && + B=$(echo B | git commit-tree $(git write-tree) -p $A) && + git update-ref HEAD $B +' # Create repository with C whose parent is B. # Repository contains C, C^{tree}, C:text, B, B^{tree}. @@ -31,52 +30,49 @@ test_expect_success \ # Repository is missing A (parent of B). # Repository is missing A:side. # -test_expect_success \ - 'setup patch_clone' \ - 'base_objects=$(pwd)/.git/objects && - (mkdir patch_clone && - cd patch_clone && - git init && - echo "$base_objects" >.git/objects/info/alternates && - echo q >>text && - git read-tree $B && - git update-index text && - git update-ref HEAD $(echo C | git commit-tree $(git write-tree) -p $B) && - rm .git/objects/info/alternates && +test_expect_success 'setup patch_clone' ' + base_objects=$(pwd)/.git/objects && + (mkdir patch_clone && + cd patch_clone && + git init && + echo "$base_objects" >.git/objects/info/alternates && + echo q >>text && + git read-tree $B && + git update-index text && + git update-ref HEAD $(echo C | git commit-tree $(git write-tree) -p $B) && + rm .git/objects/info/alternates && - git --git-dir=../.git cat-file commit $B | - git hash-object -t commit -w --stdin && + git --git-dir=../.git cat-file commit $B | + git hash-object -t commit -w --stdin && - git --git-dir=../.git cat-file tree "$B^{tree}" | - git hash-object -t tree -w --stdin - ) && - C=$(git --git-dir=patch_clone/.git rev-parse HEAD) - ' + git --git-dir=../.git cat-file tree "$B^{tree}" | + git hash-object -t tree -w --stdin + ) && + C=$(git --git-dir=patch_clone/.git rev-parse HEAD) +' # Clone patch_clone indirectly by cloning base and fetching. # -test_expect_success \ - 'indirectly clone patch_clone' \ - '(mkdir user_clone && - cd user_clone && - git init && - git pull ../.git && - test $(git rev-parse HEAD) = $B && +test_expect_success 'indirectly clone patch_clone' ' + (mkdir user_clone && + cd user_clone && + git init && + git pull ../.git && + test $(git rev-parse HEAD) = $B && - git pull ../patch_clone/.git && - test $(git rev-parse HEAD) = $C - ) - ' + git pull ../patch_clone/.git && + test $(git rev-parse HEAD) = $C + ) +' # Cloning the patch_clone directly should fail. # -test_expect_success \ - 'clone of patch_clone is incomplete' \ - '(mkdir user_direct && - cd user_direct && - git init && - test_must_fail git fetch ../patch_clone/.git - ) - ' +test_expect_success 'clone of patch_clone is incomplete' ' + (mkdir user_direct && + cd user_direct && + git init && + test_must_fail git fetch ../patch_clone/.git + ) +' test_done diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh index 7d8dee41b0..d7fd71360e 100755 --- a/t/t5310-pack-bitmaps.sh +++ b/t/t5310-pack-bitmaps.sh @@ -9,6 +9,10 @@ test_description='exercise basic bitmap functionality' # their place. GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 +# Likewise, allow individual tests to control whether or not they use +# the boundary-based traversal. +sane_unset GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL + objpath () { echo ".git/objects/$(echo "$1" | sed -e 's|\(..\)|\1/|')" } @@ -267,7 +271,7 @@ test_bitmap_cases () { mv -f $bitmap.tmp $bitmap && git rev-list --use-bitmap-index --count --all >actual 2>stderr && test_cmp expect actual && - test_i18ngrep corrupt.ewah.bitmap stderr + test_grep corrupt.ewah.bitmap stderr ' test_expect_success 'truncated bitmap fails gracefully (cache)' ' @@ -280,7 +284,7 @@ test_bitmap_cases () { mv -f $bitmap.tmp $bitmap && git rev-list --use-bitmap-index --count --all >actual 2>stderr && test_cmp expect actual && - test_i18ngrep corrupted.bitmap.index stderr + test_grep corrupted.bitmap.index stderr ' # Create a state of history with these properties: @@ -404,6 +408,26 @@ test_bitmap_cases () { ) ' + test_expect_success 'pack.preferBitmapTips' ' + git init repo && + test_when_finished "rm -rf repo" && + ( + cd repo && + git config pack.writeBitmapLookupTable '"$writeLookupTable"' && + test_commit_bulk --message="%s" 103 && + + cat >>.git/config <<-\EOF && + [pack] + preferBitmapTips + EOF + cat >expect <<-\EOF && + error: missing value for '\''pack.preferbitmaptips'\'' + EOF + git repack -adb 2>actual && + test_cmp expect actual + ) + ' + test_expect_success 'complains about multiple pack bitmaps' ' rm -fr repo && git init repo && @@ -437,10 +461,17 @@ test_bitmap_cases () { test_bitmap_cases +GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL=1 +export GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL + +test_bitmap_cases + +sane_unset GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL + test_expect_success 'incremental repack fails when bitmaps are requested' ' test_commit more-1 && test_must_fail git repack -d 2>err && - test_i18ngrep "Incremental repacks are incompatible with bitmap" err + test_grep "Incremental repacks are incompatible with bitmap" err ' test_expect_success 'incremental repack can disable bitmaps' ' @@ -448,6 +479,33 @@ test_expect_success 'incremental repack can disable bitmaps' ' git repack -d --no-write-bitmap-index ' +test_expect_success 'boundary-based traversal is used when requested' ' + git repack -a -d --write-bitmap-index && + + for argv in \ + "git -c pack.useBitmapBoundaryTraversal=true" \ + "git -c feature.experimental=true" \ + "GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL=1 git" + do + eval "GIT_TRACE2_EVENT=1 $argv rev-list --objects \ + --use-bitmap-index second..other 2>perf" && + grep "\"region_enter\".*\"label\":\"haves/boundary\"" perf || + return 1 + done && + + for argv in \ + "git -c pack.useBitmapBoundaryTraversal=false" \ + "git -c feature.experimental=true -c pack.useBitmapBoundaryTraversal=false" \ + "GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL=0 git -c pack.useBitmapBoundaryTraversal=true" \ + "GIT_TEST_PACK_USE_BITMAP_BOUNDARY_TRAVERSAL=0 git -c feature.experimental=true" + do + eval "GIT_TRACE2_EVENT=1 $argv rev-list --objects \ + --use-bitmap-index second..other 2>perf" && + grep "\"region_enter\".*\"label\":\"haves/classic\"" perf || + return 1 + done +' + test_bitmap_cases "pack.writeBitmapLookupTable" test_expect_success 'verify writing bitmap lookup table when enabled' ' @@ -466,7 +524,7 @@ test_expect_success 'truncated bitmap fails gracefully (lookup table)' ' mv -f $bitmap.tmp $bitmap && git rev-list --use-bitmap-index --count --all >actual 2>stderr && test_cmp expect actual && - test_i18ngrep corrupted.bitmap.index stderr + test_grep corrupted.bitmap.index stderr ' test_done diff --git a/t/t5311-pack-bitmaps-shallow.sh b/t/t5311-pack-bitmaps-shallow.sh index 9dae60f73e..4fe71fe8cd 100755 --- a/t/t5311-pack-bitmaps-shallow.sh +++ b/t/t5311-pack-bitmaps-shallow.sh @@ -1,6 +1,8 @@ #!/bin/sh test_description='check bitmap operation with shallow repositories' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # We want to create a situation where the shallow, grafted diff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh index b26d476c64..2ff3eef9a3 100755 --- a/t/t5317-pack-objects-filter-objects.sh +++ b/t/t5317-pack-objects-filter-objects.sh @@ -53,6 +53,14 @@ test_expect_success 'verify blob:none packfile has no blobs' ' ! grep blob verify_result ' +test_expect_success 'verify blob:none packfile without --stdout' ' + git -C r1 pack-objects --revs --filter=blob:none mypackname >packhash <<-EOF && + HEAD + EOF + git -C r1 verify-pack -v "mypackname-$(cat packhash).pack" >verify_result && + ! grep blob verify_result +' + test_expect_success 'verify normal and blob:none packfiles have same commits/trees' ' git -C r1 verify-pack -v ../all.pack >verify_result && grep -E "commit|tree" verify_result | diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh index 049c5fc8ea..a2b4442660 100755 --- a/t/t5318-commit-graph.sh +++ b/t/t5318-commit-graph.sh @@ -2,6 +2,7 @@ test_description='commit graph' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-chunk.sh GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0 @@ -24,12 +25,10 @@ test_expect_success 'usage shown with an error on unknown sub-command' ' test_cmp expect actual ' +objdir=".git/objects" + test_expect_success 'setup full repo' ' - mkdir full && - cd "$TRASH_DIRECTORY/full" && - git init && - git config core.commitGraph true && - objdir=".git/objects" + git init full ' test_expect_success POSIXPERM 'tweak umask for modebit tests' ' @@ -37,31 +36,28 @@ test_expect_success POSIXPERM 'tweak umask for modebit tests' ' ' test_expect_success 'verify graph with no graph file' ' - cd "$TRASH_DIRECTORY/full" && - git commit-graph verify + git -C full commit-graph verify ' test_expect_success 'write graph with no packs' ' - cd "$TRASH_DIRECTORY/full" && - git commit-graph write --object-dir $objdir && - test_path_is_missing $objdir/info/commit-graph + git -C full commit-graph write --object-dir $objdir && + test_path_is_missing full/$objdir/info/commit-graph ' test_expect_success 'exit with correct error on bad input to --stdin-packs' ' - cd "$TRASH_DIRECTORY/full" && echo doesnotexist >in && - test_expect_code 1 git commit-graph write --stdin-packs <in 2>stderr && - test_i18ngrep "error adding pack" stderr + test_expect_code 1 git -C full commit-graph write --stdin-packs \ + <in 2>stderr && + test_grep "error adding pack" stderr ' test_expect_success 'create commits and repack' ' - cd "$TRASH_DIRECTORY/full" && for i in $(test_seq 3) do - test_commit $i && - git branch commits/$i || return 1 + test_commit -C full $i && + git -C full branch commits/$i || return 1 done && - git repack + git -C full repack ' . "$TEST_DIRECTORY"/lib-commit-graph.sh @@ -69,117 +65,106 @@ test_expect_success 'create commits and repack' ' graph_git_behavior 'no graph' full commits/3 commits/1 test_expect_success 'exit with correct error on bad input to --stdin-commits' ' - cd "$TRASH_DIRECTORY/full" && # invalid, non-hex OID - echo HEAD >in && - test_expect_code 1 git commit-graph write --stdin-commits <in 2>stderr && - test_i18ngrep "unexpected non-hex object ID: HEAD" stderr && + echo HEAD | test_expect_code 1 git -C full commit-graph write \ + --stdin-commits 2>stderr && + test_grep "unexpected non-hex object ID: HEAD" stderr && # non-existent OID - echo $ZERO_OID >in && - test_expect_code 1 git commit-graph write --stdin-commits <in 2>stderr && - test_i18ngrep "invalid object" stderr && + echo $ZERO_OID | test_expect_code 1 git -C full commit-graph write \ + --stdin-commits 2>stderr && + test_grep "invalid object" stderr && # valid commit and tree OID - git rev-parse HEAD HEAD^{tree} >in && - git commit-graph write --stdin-commits <in && - graph_read_expect 3 generation_data + git -C full rev-parse HEAD HEAD^{tree} >in && + git -C full commit-graph write --stdin-commits <in && + graph_read_expect -C full 3 generation_data ' test_expect_success 'write graph' ' - cd "$TRASH_DIRECTORY/full" && - git commit-graph write && - test_path_is_file $objdir/info/commit-graph && - graph_read_expect "3" generation_data + git -C full commit-graph write && + test_path_is_file full/$objdir/info/commit-graph && + graph_read_expect -C full 3 generation_data ' test_expect_success POSIXPERM 'write graph has correct permissions' ' - test_path_is_file $objdir/info/commit-graph && + test_path_is_file full/$objdir/info/commit-graph && echo "-r--r--r--" >expect && - test_modebits $objdir/info/commit-graph >actual && + test_modebits full/$objdir/info/commit-graph >actual && test_cmp expect actual ' graph_git_behavior 'graph exists' full commits/3 commits/1 test_expect_success 'Add more commits' ' - cd "$TRASH_DIRECTORY/full" && - git reset --hard commits/1 && + git -C full reset --hard commits/1 && for i in $(test_seq 4 5) do - test_commit $i && - git branch commits/$i || return 1 + test_commit -C full $i && + git -C full branch commits/$i || return 1 done && - git reset --hard commits/2 && + git -C full reset --hard commits/2 && for i in $(test_seq 6 7) do - test_commit $i && - git branch commits/$i || return 1 + test_commit -C full $i && + git -C full branch commits/$i || return 1 done && - git reset --hard commits/2 && - git merge commits/4 && - git branch merge/1 && - git reset --hard commits/4 && - git merge commits/6 && - git branch merge/2 && - git reset --hard commits/3 && - git merge commits/5 commits/7 && - git branch merge/3 && - git repack + git -C full reset --hard commits/2 && + git -C full merge commits/4 && + git -C full branch merge/1 && + git -C full reset --hard commits/4 && + git -C full merge commits/6 && + git -C full branch merge/2 && + git -C full reset --hard commits/3 && + git -C full merge commits/5 commits/7 && + git -C full branch merge/3 && + git -C full repack ' test_expect_success 'commit-graph write progress off for redirected stderr' ' - cd "$TRASH_DIRECTORY/full" && - git commit-graph write 2>err && + git -C full commit-graph write 2>err && test_must_be_empty err ' test_expect_success 'commit-graph write force progress on for stderr' ' - cd "$TRASH_DIRECTORY/full" && - GIT_PROGRESS_DELAY=0 git commit-graph write --progress 2>err && + GIT_PROGRESS_DELAY=0 git -C full commit-graph write --progress 2>err && test_file_not_empty err ' test_expect_success 'commit-graph write with the --no-progress option' ' - cd "$TRASH_DIRECTORY/full" && - git commit-graph write --no-progress 2>err && + git -C full commit-graph write --no-progress 2>err && test_must_be_empty err ' test_expect_success 'commit-graph write --stdin-commits progress off for redirected stderr' ' - cd "$TRASH_DIRECTORY/full" && - git rev-parse commits/5 >in && - git commit-graph write --stdin-commits <in 2>err && + git -C full rev-parse commits/5 >in && + git -C full commit-graph write --stdin-commits <in 2>err && test_must_be_empty err ' test_expect_success 'commit-graph write --stdin-commits force progress on for stderr' ' - cd "$TRASH_DIRECTORY/full" && - git rev-parse commits/5 >in && - GIT_PROGRESS_DELAY=0 git commit-graph write --stdin-commits --progress <in 2>err && - test_i18ngrep "Collecting commits from input" err + git -C full rev-parse commits/5 >in && + GIT_PROGRESS_DELAY=0 git -C full commit-graph write --stdin-commits \ + --progress <in 2>err && + test_grep "Collecting commits from input" err ' test_expect_success 'commit-graph write --stdin-commits with the --no-progress option' ' - cd "$TRASH_DIRECTORY/full" && - git rev-parse commits/5 >in && - git commit-graph write --stdin-commits --no-progress <in 2>err && + git -C full rev-parse commits/5 >in && + git -C full commit-graph write --stdin-commits --no-progress <in 2>err && test_must_be_empty err ' test_expect_success 'commit-graph verify progress off for redirected stderr' ' - cd "$TRASH_DIRECTORY/full" && - git commit-graph verify 2>err && + git -C full commit-graph verify 2>err && test_must_be_empty err ' test_expect_success 'commit-graph verify force progress on for stderr' ' - cd "$TRASH_DIRECTORY/full" && - GIT_PROGRESS_DELAY=0 git commit-graph verify --progress 2>err && + GIT_PROGRESS_DELAY=0 git -C full commit-graph verify --progress 2>err && test_file_not_empty err ' test_expect_success 'commit-graph verify with the --no-progress option' ' - cd "$TRASH_DIRECTORY/full" && - git commit-graph verify --no-progress 2>err && + git -C full commit-graph verify --no-progress 2>err && test_must_be_empty err ' @@ -194,10 +179,9 @@ test_expect_success 'commit-graph verify with the --no-progress option' ' # 1 test_expect_success 'write graph with merges' ' - cd "$TRASH_DIRECTORY/full" && - git commit-graph write && - test_path_is_file $objdir/info/commit-graph && - graph_read_expect "10" "generation_data extra_edges" + git -C full commit-graph write && + test_path_is_file full/$objdir/info/commit-graph && + graph_read_expect -C full 10 "generation_data extra_edges" ' graph_git_behavior 'merge 1 vs 2' full merge/1 merge/2 @@ -205,12 +189,11 @@ graph_git_behavior 'merge 1 vs 3' full merge/1 merge/3 graph_git_behavior 'merge 2 vs 3' full merge/2 merge/3 test_expect_success 'Add one more commit' ' - cd "$TRASH_DIRECTORY/full" && - test_commit 8 && - git branch commits/8 && - ls $objdir/pack | grep idx >existing-idx && - git repack && - ls $objdir/pack| grep idx | grep -v -f existing-idx >new-idx + test_commit -C full 8 && + git -C full branch commits/8 && + ls full/$objdir/pack | grep idx >existing-idx && + git -C full repack && + ls full/$objdir/pack| grep idx | grep -v -f existing-idx >new-idx ' # Current graph structure: @@ -229,114 +212,101 @@ graph_git_behavior 'mixed mode, commit 8 vs merge 1' full commits/8 merge/1 graph_git_behavior 'mixed mode, commit 8 vs merge 2' full commits/8 merge/2 test_expect_success 'write graph with new commit' ' - cd "$TRASH_DIRECTORY/full" && - git commit-graph write && - test_path_is_file $objdir/info/commit-graph && - graph_read_expect "11" "generation_data extra_edges" + git -C full commit-graph write && + test_path_is_file full/$objdir/info/commit-graph && + graph_read_expect -C full 11 "generation_data extra_edges" ' graph_git_behavior 'full graph, commit 8 vs merge 1' full commits/8 merge/1 graph_git_behavior 'full graph, commit 8 vs merge 2' full commits/8 merge/2 test_expect_success 'write graph with nothing new' ' - cd "$TRASH_DIRECTORY/full" && - git commit-graph write && - test_path_is_file $objdir/info/commit-graph && - graph_read_expect "11" "generation_data extra_edges" + git -C full commit-graph write && + test_path_is_file full/$objdir/info/commit-graph && + graph_read_expect -C full 11 "generation_data extra_edges" ' graph_git_behavior 'cleared graph, commit 8 vs merge 1' full commits/8 merge/1 graph_git_behavior 'cleared graph, commit 8 vs merge 2' full commits/8 merge/2 test_expect_success 'build graph from latest pack with closure' ' - cd "$TRASH_DIRECTORY/full" && - cat new-idx | git commit-graph write --stdin-packs && - test_path_is_file $objdir/info/commit-graph && - graph_read_expect "9" "generation_data extra_edges" + git -C full commit-graph write --stdin-packs <new-idx && + test_path_is_file full/$objdir/info/commit-graph && + graph_read_expect -C full 9 "generation_data extra_edges" ' graph_git_behavior 'graph from pack, commit 8 vs merge 1' full commits/8 merge/1 graph_git_behavior 'graph from pack, commit 8 vs merge 2' full commits/8 merge/2 test_expect_success 'build graph from commits with closure' ' - cd "$TRASH_DIRECTORY/full" && - git tag -a -m "merge" tag/merge merge/2 && - git rev-parse tag/merge >commits-in && - git rev-parse merge/1 >>commits-in && - cat commits-in | git commit-graph write --stdin-commits && - test_path_is_file $objdir/info/commit-graph && - graph_read_expect "6" "generation_data" + git -C full tag -a -m "merge" tag/merge merge/2 && + git -C full rev-parse tag/merge >commits-in && + git -C full rev-parse merge/1 >>commits-in && + git -C full commit-graph write --stdin-commits <commits-in && + test_path_is_file full/$objdir/info/commit-graph && + graph_read_expect -C full 6 "generation_data" ' graph_git_behavior 'graph from commits, commit 8 vs merge 1' full commits/8 merge/1 graph_git_behavior 'graph from commits, commit 8 vs merge 2' full commits/8 merge/2 test_expect_success 'build graph from commits with append' ' - cd "$TRASH_DIRECTORY/full" && - git rev-parse merge/3 | git commit-graph write --stdin-commits --append && - test_path_is_file $objdir/info/commit-graph && - graph_read_expect "10" "generation_data extra_edges" + git -C full rev-parse merge/3 >in && + git -C full commit-graph write --stdin-commits --append <in && + test_path_is_file full/$objdir/info/commit-graph && + graph_read_expect -C full 10 "generation_data extra_edges" ' graph_git_behavior 'append graph, commit 8 vs merge 1' full commits/8 merge/1 graph_git_behavior 'append graph, commit 8 vs merge 2' full commits/8 merge/2 test_expect_success 'build graph using --reachable' ' - cd "$TRASH_DIRECTORY/full" && - git commit-graph write --reachable && - test_path_is_file $objdir/info/commit-graph && - graph_read_expect "11" "generation_data extra_edges" + git -C full commit-graph write --reachable && + test_path_is_file full/$objdir/info/commit-graph && + graph_read_expect -C full 11 "generation_data extra_edges" ' graph_git_behavior 'append graph, commit 8 vs merge 1' full commits/8 merge/1 graph_git_behavior 'append graph, commit 8 vs merge 2' full commits/8 merge/2 test_expect_success 'setup bare repo' ' - cd "$TRASH_DIRECTORY" && - git clone --bare --no-local full bare && - cd bare && - git config core.commitGraph true && - baredir="./objects" + git clone --bare --no-local full bare ' graph_git_behavior 'bare repo, commit 8 vs merge 1' bare commits/8 merge/1 graph_git_behavior 'bare repo, commit 8 vs merge 2' bare commits/8 merge/2 test_expect_success 'write graph in bare repo' ' - cd "$TRASH_DIRECTORY/bare" && - git commit-graph write && - test_path_is_file $baredir/info/commit-graph && - graph_read_expect "11" "generation_data extra_edges" + git -C bare commit-graph write && + test_path_is_file bare/objects/info/commit-graph && + graph_read_expect -C bare 11 "generation_data extra_edges" ' graph_git_behavior 'bare repo with graph, commit 8 vs merge 1' bare commits/8 merge/1 graph_git_behavior 'bare repo with graph, commit 8 vs merge 2' bare commits/8 merge/2 test_expect_success 'perform fast-forward merge in full repo' ' - cd "$TRASH_DIRECTORY/full" && - git checkout -b merge-5-to-8 commits/5 && - git merge commits/8 && - git show-ref -s merge-5-to-8 >output && - git show-ref -s commits/8 >expect && + git -C full checkout -b merge-5-to-8 commits/5 && + git -C full merge commits/8 && + git -C full show-ref -s merge-5-to-8 >output && + git -C full show-ref -s commits/8 >expect && test_cmp expect output ' test_expect_success 'check that gc computes commit-graph' ' - cd "$TRASH_DIRECTORY/full" && - git commit --allow-empty -m "blank" && - git commit-graph write --reachable && - cp $objdir/info/commit-graph commit-graph-before-gc && - git reset --hard HEAD~1 && - git config gc.writeCommitGraph true && - git gc && - cp $objdir/info/commit-graph commit-graph-after-gc && + test_commit -C full --no-tag blank && + git -C full commit-graph write --reachable && + cp full/$objdir/info/commit-graph commit-graph-before-gc && + git -C full reset --hard HEAD~1 && + test_config -C full gc.writeCommitGraph true && + git -C full gc && + cp full/$objdir/info/commit-graph commit-graph-after-gc && ! test_cmp_bin commit-graph-before-gc commit-graph-after-gc && - git commit-graph write --reachable && - test_cmp_bin commit-graph-after-gc $objdir/info/commit-graph + git -C full commit-graph write --reachable && + test_cmp_bin commit-graph-after-gc full/$objdir/info/commit-graph ' test_expect_success 'replace-objects invalidates commit-graph' ' - cd "$TRASH_DIRECTORY" && test_when_finished rm -rf replace && git clone full replace && ( @@ -359,7 +329,6 @@ test_expect_success 'replace-objects invalidates commit-graph' ' ' test_expect_success 'commit grafts invalidate commit-graph' ' - cd "$TRASH_DIRECTORY" && test_when_finished rm -rf graft && git clone --template= full graft && ( @@ -384,7 +353,6 @@ test_expect_success 'commit grafts invalidate commit-graph' ' ' test_expect_success 'replace-objects invalidates commit-graph' ' - cd "$TRASH_DIRECTORY" && test_when_finished rm -rf shallow && git clone --depth 2 "file://$TRASH_DIRECTORY/full" shallow && ( @@ -416,35 +384,36 @@ test_expect_success 'warn on improper hash version' ' cd sha1 && mv ../cg-sha256 .git/objects/info/commit-graph && git log -1 2>err && - test_i18ngrep "commit-graph hash version 2 does not match version 1" err + test_grep "commit-graph hash version 2 does not match version 1" err ) && ( cd sha256 && mv ../cg-sha1 .git/objects/info/commit-graph && git log -1 2>err && - test_i18ngrep "commit-graph hash version 1 does not match version 2" err + test_grep "commit-graph hash version 1 does not match version 2" err ) ' test_expect_success TIME_IS_64BIT,TIME_T_IS_64BIT 'lower layers have overflow chunk' ' - cd "$TRASH_DIRECTORY/full" && UNIX_EPOCH_ZERO="@0 +0000" && FUTURE_DATE="@4147483646 +0000" && - rm -f .git/objects/info/commit-graph && - test_commit --date "$FUTURE_DATE" future-1 && - test_commit --date "$UNIX_EPOCH_ZERO" old-1 && - git commit-graph write --reachable && - test_commit --date "$FUTURE_DATE" future-2 && - test_commit --date "$UNIX_EPOCH_ZERO" old-2 && - git commit-graph write --reachable --split=no-merge && - test_commit extra && - git commit-graph write --reachable --split=no-merge && - git commit-graph write --reachable && - graph_read_expect 16 "generation_data generation_data_overflow extra_edges" && - mv .git/objects/info/commit-graph commit-graph-upgraded && - git commit-graph write --reachable && - graph_read_expect 16 "generation_data generation_data_overflow extra_edges" && - test_cmp .git/objects/info/commit-graph commit-graph-upgraded + rm -f full/.git/objects/info/commit-graph && + test_commit -C full --date "$FUTURE_DATE" future-1 && + test_commit -C full --date "$UNIX_EPOCH_ZERO" old-1 && + git -C full commit-graph write --reachable && + test_commit -C full --date "$FUTURE_DATE" future-2 && + test_commit -C full --date "$UNIX_EPOCH_ZERO" old-2 && + git -C full commit-graph write --reachable --split=no-merge && + test_commit -C full extra && + git -C full commit-graph write --reachable --split=no-merge && + git -C full commit-graph write --reachable && + graph_read_expect -C full 16 \ + "generation_data generation_data_overflow extra_edges" && + mv full/.git/objects/info/commit-graph commit-graph-upgraded && + git -C full commit-graph write --reachable && + graph_read_expect -C full 16 \ + "generation_data generation_data_overflow extra_edges" && + test_cmp full/.git/objects/info/commit-graph commit-graph-upgraded ' # the verify tests below expect the commit-graph to contain @@ -454,10 +423,11 @@ test_expect_success TIME_IS_64BIT,TIME_T_IS_64BIT 'lower layers have overflow ch # and the tests will likely break. test_expect_success 'git commit-graph verify' ' - cd "$TRASH_DIRECTORY/full" && - git rev-parse commits/8 | git -c commitGraph.generationVersion=1 commit-graph write --stdin-commits && - git commit-graph verify >output && - graph_read_expect 9 extra_edges 1 + git -C full rev-parse commits/8 >in && + git -C full -c commitGraph.generationVersion=1 commit-graph write \ + --stdin-commits <in && + git -C full commit-graph verify >output && + graph_read_expect -C full 9 extra_edges 1 ' NUM_COMMITS=9 @@ -481,39 +451,39 @@ GRAPH_BYTE_FANOUT2=$(($GRAPH_FANOUT_OFFSET + 4 * 255)) GRAPH_OID_LOOKUP_OFFSET=$(($GRAPH_FANOUT_OFFSET + 4 * 256)) GRAPH_BYTE_OID_LOOKUP_ORDER=$(($GRAPH_OID_LOOKUP_OFFSET + $HASH_LEN * 8)) GRAPH_BYTE_OID_LOOKUP_MISSING=$(($GRAPH_OID_LOOKUP_OFFSET + $HASH_LEN * 4 + 10)) +GRAPH_COMMIT_DATA_WIDTH=$(($HASH_LEN + 16)) GRAPH_COMMIT_DATA_OFFSET=$(($GRAPH_OID_LOOKUP_OFFSET + $HASH_LEN * $NUM_COMMITS)) GRAPH_BYTE_COMMIT_TREE=$GRAPH_COMMIT_DATA_OFFSET GRAPH_BYTE_COMMIT_PARENT=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN)) GRAPH_BYTE_COMMIT_EXTRA_PARENT=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN + 4)) GRAPH_BYTE_COMMIT_WRONG_PARENT=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN + 3)) GRAPH_BYTE_COMMIT_GENERATION=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN + 11)) +GRAPH_BYTE_COMMIT_GENERATION_LAST=$(($GRAPH_BYTE_COMMIT_GENERATION + $(($NUM_COMMITS - 1)) * $GRAPH_COMMIT_DATA_WIDTH)) GRAPH_BYTE_COMMIT_DATE=$(($GRAPH_COMMIT_DATA_OFFSET + $HASH_LEN + 12)) -GRAPH_COMMIT_DATA_WIDTH=$(($HASH_LEN + 16)) GRAPH_OCTOPUS_DATA_OFFSET=$(($GRAPH_COMMIT_DATA_OFFSET + \ $GRAPH_COMMIT_DATA_WIDTH * $NUM_COMMITS)) GRAPH_BYTE_OCTOPUS=$(($GRAPH_OCTOPUS_DATA_OFFSET + 4)) GRAPH_BYTE_FOOTER=$(($GRAPH_OCTOPUS_DATA_OFFSET + 4 * $NUM_OCTOPUS_EDGES)) corrupt_graph_setup() { - cd "$TRASH_DIRECTORY/full" && - test_when_finished mv commit-graph-backup $objdir/info/commit-graph && - cp $objdir/info/commit-graph commit-graph-backup && - chmod u+w $objdir/info/commit-graph + test_when_finished mv commit-graph-backup full/$objdir/info/commit-graph && + cp full/$objdir/info/commit-graph commit-graph-backup && + chmod u+w full/$objdir/info/commit-graph } corrupt_graph_verify() { grepstr=$1 - test_must_fail git commit-graph verify 2>test_err && + test_must_fail git -C full commit-graph verify 2>test_err && grep -v "^+" test_err >err && - test_i18ngrep "$grepstr" err && + test_grep "$grepstr" err && if test "$2" != "no-copy" then - cp $objdir/info/commit-graph commit-graph-pre-write-test + cp full/$objdir/info/commit-graph commit-graph-pre-write-test fi && - git status --short && - GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE=true git commit-graph write && - chmod u+w $objdir/info/commit-graph && - git commit-graph verify + git -C full status --short && + GIT_TEST_COMMIT_GRAPH_DIE_ON_PARSE=true git -C full commit-graph write && + chmod u+w full/$objdir/info/commit-graph && + git -C full commit-graph verify } # usage: corrupt_graph_and_verify <position> <data> <string> [<zero_pos>] @@ -527,24 +497,24 @@ corrupt_graph_and_verify() { data="${2:-\0}" grepstr=$3 corrupt_graph_setup && - orig_size=$(wc -c < $objdir/info/commit-graph) && + orig_size=$(wc -c <full/$objdir/info/commit-graph) && zero_pos=${4:-${orig_size}} && - printf "$data" | dd of="$objdir/info/commit-graph" bs=1 seek="$pos" conv=notrunc && - dd of="$objdir/info/commit-graph" bs=1 seek="$zero_pos" if=/dev/null && - test-tool genzeros $(($orig_size - $zero_pos)) >>"$objdir/info/commit-graph" && + printf "$data" | dd of="full/$objdir/info/commit-graph" bs=1 seek="$pos" conv=notrunc && + dd of="full/$objdir/info/commit-graph" bs=1 seek="$zero_pos" if=/dev/null && + test-tool genzeros $(($orig_size - $zero_pos)) >>"full/$objdir/info/commit-graph" && corrupt_graph_verify "$grepstr" } test_expect_success POSIXPERM,SANITY 'detect permission problem' ' corrupt_graph_setup && - chmod 000 $objdir/info/commit-graph && + chmod 000 full/$objdir/info/commit-graph && corrupt_graph_verify "Could not open" "no-copy" ' test_expect_success 'detect too small' ' corrupt_graph_setup && - echo "a small graph" >$objdir/info/commit-graph && + echo "a small graph" >full/$objdir/info/commit-graph && corrupt_graph_verify "too small" ' @@ -570,17 +540,17 @@ test_expect_success 'detect low chunk count' ' test_expect_success 'detect missing OID fanout chunk' ' corrupt_graph_and_verify $GRAPH_BYTE_OID_FANOUT_ID "\0" \ - "missing the OID Fanout chunk" + "commit-graph required OID fanout chunk missing or corrupted" ' test_expect_success 'detect missing OID lookup chunk' ' corrupt_graph_and_verify $GRAPH_BYTE_OID_LOOKUP_ID "\0" \ - "missing the OID Lookup chunk" + "commit-graph required OID lookup chunk missing or corrupted" ' test_expect_success 'detect missing commit data chunk' ' corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_DATA_ID "\0" \ - "missing the Commit Data chunk" + "commit-graph required commit data chunk missing or corrupted" ' test_expect_success 'detect incorrect fanout' ' @@ -590,7 +560,7 @@ test_expect_success 'detect incorrect fanout' ' test_expect_success 'detect incorrect fanout final value' ' corrupt_graph_and_verify $GRAPH_BYTE_FANOUT2 "\01" \ - "fanout value" + "OID lookup chunk is the wrong size" ' test_expect_success 'detect incorrect OID order' ' @@ -628,11 +598,6 @@ test_expect_success 'detect incorrect generation number' ' "generation for commit" ' -test_expect_success 'detect incorrect generation number' ' - corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_GENERATION "\01" \ - "non-zero generation number" -' - test_expect_success 'detect incorrect commit date' ' corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_DATE "\01" \ "commit date" @@ -654,34 +619,51 @@ test_expect_success 'detect incorrect chunk count' ' $GRAPH_CHUNK_LOOKUP_OFFSET ' +test_expect_success 'detect mixed generation numbers (non-zero to zero)' ' + corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_GENERATION_LAST "\0\0\0\0" \ + "both zero and non-zero generations" +' + +test_expect_success 'detect mixed generation numbers (zero to non-zero)' ' + corrupt_graph_and_verify $GRAPH_BYTE_COMMIT_GENERATION "\0\0\0\0" \ + "both zero and non-zero generations" +' + test_expect_success 'git fsck (checks commit-graph when config set to true)' ' - cd "$TRASH_DIRECTORY/full" && - git fsck && + git -C full fsck && corrupt_graph_and_verify $GRAPH_BYTE_FOOTER "\00" \ "incorrect checksum" && - cp commit-graph-pre-write-test $objdir/info/commit-graph && - test_must_fail git -c core.commitGraph=true fsck + cp commit-graph-pre-write-test full/$objdir/info/commit-graph && + test_must_fail git -C full -c core.commitGraph=true fsck ' test_expect_success 'git fsck (ignores commit-graph when config set to false)' ' - cd "$TRASH_DIRECTORY/full" && - git fsck && + git -C full fsck && corrupt_graph_and_verify $GRAPH_BYTE_FOOTER "\00" \ "incorrect checksum" && - cp commit-graph-pre-write-test $objdir/info/commit-graph && - git -c core.commitGraph=false fsck + cp commit-graph-pre-write-test full/$objdir/info/commit-graph && + git -C full -c core.commitGraph=false fsck ' test_expect_success 'git fsck (checks commit-graph when config unset)' ' - cd "$TRASH_DIRECTORY/full" && - test_when_finished "git config core.commitGraph true" && + test_when_finished "git -C full config core.commitGraph true" && - git fsck && + git -C full fsck && corrupt_graph_and_verify $GRAPH_BYTE_FOOTER "\00" \ "incorrect checksum" && - test_unconfig core.commitGraph && - cp commit-graph-pre-write-test $objdir/info/commit-graph && - test_must_fail git fsck + test_unconfig -C full core.commitGraph && + cp commit-graph-pre-write-test full/$objdir/info/commit-graph && + test_must_fail git -C full fsck +' + +test_expect_success 'git fsck shows commit-graph output with --progress' ' + git -C "$TRASH_DIRECTORY/full" fsck --progress 2>err && + grep "Verifying commits in commit graph" err +' + +test_expect_success 'git fsck suppresses commit-graph output with --no-progress' ' + git -C "$TRASH_DIRECTORY/full" fsck --no-progress 2>err && + ! grep "Verifying commits in commit graph" err ' test_expect_success 'setup non-the_repository tests' ' @@ -739,7 +721,7 @@ test_expect_success 'corrupt commit-graph write (broken parent)' ' git commit-tree -p "$broken" -m "good commit" "$empty" >good && test_must_fail git commit-graph write --stdin-commits \ <good 2>test_err && - test_i18ngrep "unable to parse commit" test_err + test_grep "unable to parse commit" test_err ) ' @@ -760,7 +742,7 @@ test_expect_success 'corrupt commit-graph write (missing tree)' ' git commit-tree -p "$broken" -m "good" "$tree" >good && test_must_fail git commit-graph write --stdin-commits \ <good 2>test_err && - test_i18ngrep "unable to parse commit" test_err + test_grep "unable to parse commit" test_err ) ' @@ -782,32 +764,33 @@ test_expect_success 'corrupt commit-graph write (missing tree)' ' # test_expect_success 'set up and verify repo with generation data overflow chunk' ' - objdir=".git/objects" && UNIX_EPOCH_ZERO="@0 +0000" && FUTURE_DATE="@2147483646 +0000" && - cd "$TRASH_DIRECTORY" && - mkdir repo && - cd repo && - git init && - test_commit --date "$UNIX_EPOCH_ZERO" 1 && - test_commit 2 && - test_commit --date "$UNIX_EPOCH_ZERO" 3 && - git commit-graph write --reachable && - graph_read_expect 3 generation_data && - test_commit --date "$FUTURE_DATE" 4 && - test_commit 5 && - test_commit --date "$UNIX_EPOCH_ZERO" 6 && - git branch left && - git reset --hard 3 && - test_commit 7 && - test_commit --date "$FUTURE_DATE" 8 && - test_commit 9 && - git branch right && - git reset --hard 3 && - test_merge M left right && - git commit-graph write --reachable && - graph_read_expect 10 "generation_data generation_data_overflow" && - git commit-graph verify + + git init repo && + ( + cd repo && + + test_commit --date "$UNIX_EPOCH_ZERO" 1 && + test_commit 2 && + test_commit --date "$UNIX_EPOCH_ZERO" 3 && + git commit-graph write --reachable && + graph_read_expect 3 generation_data && + test_commit --date "$FUTURE_DATE" 4 && + test_commit 5 && + test_commit --date "$UNIX_EPOCH_ZERO" 6 && + git branch left && + git reset --hard 3 && + test_commit 7 && + test_commit --date "$FUTURE_DATE" 8 && + test_commit 9 && + git branch right && + git reset --hard 3 && + test_merge M left right && + git commit-graph write --reachable && + graph_read_expect 10 "generation_data generation_data_overflow" && + git commit-graph verify + ) ' graph_git_behavior 'generation data overflow chunk repo' repo left right @@ -839,4 +822,127 @@ test_expect_success 'overflow during generation version upgrade' ' ) ' +corrupt_chunk () { + graph=full/.git/objects/info/commit-graph && + test_when_finished "rm -rf $graph" && + git -C full commit-graph write --reachable && + corrupt_chunk_file $graph "$@" +} + +check_corrupt_chunk () { + corrupt_chunk "$@" && + git -C full -c core.commitGraph=false log >expect.out && + git -C full -c core.commitGraph=true log >out 2>err && + test_cmp expect.out out +} + +test_expect_success 'reader notices too-small oid fanout chunk' ' + # make it big enough that the graph file is plausible, + # otherwise we hit an earlier check + check_corrupt_chunk OIDF clear $(printf "000000%02x" $(test_seq 250)) && + cat >expect.err <<-\EOF && + error: commit-graph oid fanout chunk is wrong size + error: commit-graph required OID fanout chunk missing or corrupted + EOF + test_cmp expect.err err +' + +test_expect_success 'reader notices fanout/lookup table mismatch' ' + check_corrupt_chunk OIDF 1020 "FFFFFFFF" && + cat >expect.err <<-\EOF && + error: commit-graph OID lookup chunk is the wrong size + error: commit-graph required OID lookup chunk missing or corrupted + EOF + test_cmp expect.err err +' + +test_expect_success 'reader notices out-of-bounds fanout' ' + # Rather than try to corrupt a specific hash, we will just + # wreck them all. But we cannot just set them all to 0xFFFFFFFF or + # similar, as they are used for hi/lo starts in a binary search (so if + # they are identical, that indicates that the search should abort + # immediately). Instead, we will give them high values that differ by + # 2^24, ensuring that any that are used would cause an out-of-bounds + # read. + check_corrupt_chunk OIDF 0 $(printf "%02x000000" $(test_seq 0 254)) && + cat >expect.err <<-\EOF && + error: commit-graph fanout values out of order + error: commit-graph required OID fanout chunk missing or corrupted + EOF + test_cmp expect.err err +' + +test_expect_success 'reader notices too-small commit data chunk' ' + check_corrupt_chunk CDAT clear 00000000 && + cat >expect.err <<-\EOF && + error: commit-graph commit data chunk is wrong size + error: commit-graph required commit data chunk missing or corrupted + EOF + test_cmp expect.err err +' + +test_expect_success 'reader notices out-of-bounds extra edge' ' + check_corrupt_chunk EDGE clear && + cat >expect.err <<-\EOF && + error: commit-graph extra-edges pointer out of bounds + EOF + test_cmp expect.err err +' + +test_expect_success 'reader notices too-small generations chunk' ' + check_corrupt_chunk GDA2 clear 00000000 && + cat >expect.err <<-\EOF && + error: commit-graph generations chunk is wrong size + EOF + test_cmp expect.err err +' + +test_expect_success 'stale commit cannot be parsed when given directly' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + test_commit A && + test_commit B && + git commit-graph write --reachable && + + oid=$(git rev-parse B) && + rm .git/objects/"$(test_oid_to_path "$oid")" && + + # Verify that it is possible to read the commit from the + # commit graph when not being paranoid, ... + git rev-list B && + # ... but parsing the commit when double checking that + # it actually exists in the object database should fail. + test_must_fail env GIT_COMMIT_GRAPH_PARANOIA=true git rev-list -1 B + ) +' + +test_expect_success 'stale commit cannot be parsed when traversing graph' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + + test_commit A && + test_commit B && + test_commit C && + git commit-graph write --reachable && + + # Corrupt the repository by deleting the intermediate commit + # object. Commands should notice that this object is absent and + # thus that the repository is corrupt even if the commit graph + # exists. + oid=$(git rev-parse B) && + rm .git/objects/"$(test_oid_to_path "$oid")" && + + # Again, we should be able to parse the commit when not + # being paranoid about commit graph staleness... + git rev-parse HEAD~2 && + # ... but fail when we are paranoid. + test_must_fail env GIT_COMMIT_GRAPH_PARANOIA=true git rev-parse HEAD~2 2>error && + grep "error: commit $oid exists in commit-graph but not in the object database" error + ) +' + test_done diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh index 499d5d4c78..c20aafe99a 100755 --- a/t/t5319-multi-pack-index.sh +++ b/t/t5319-multi-pack-index.sh @@ -2,6 +2,7 @@ test_description='multi-pack-indexes' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-chunk.sh GIT_TEST_MULTI_PACK_INDEX=0 objdir=.git/objects @@ -183,6 +184,18 @@ test_expect_success 'write midx with --stdin-packs' ' compare_results_with_midx "mixed mode (one pack + extra)" +test_expect_success 'write with no objects and preferred pack' ' + test_when_finished "rm -rf empty" && + git init empty && + test_must_fail git -C empty multi-pack-index write \ + --stdin-packs --preferred-pack=does-not-exist </dev/null 2>err && + cat >expect <<-EOF && + warning: unknown preferred pack: ${SQ}does-not-exist${SQ} + error: no pack files to index. + EOF + test_cmp expect err +' + test_expect_success 'write progress off for redirected stderr' ' git multi-pack-index --object-dir=$objdir write 2>err && test_line_count = 0 err @@ -267,13 +280,13 @@ test_expect_success 'warn on improper hash version' ' cd sha1 && mv ../mpi-sha256 .git/objects/pack/multi-pack-index && git log -1 2>err && - test_i18ngrep "multi-pack-index hash version 2 does not match version 1" err + test_grep "multi-pack-index hash version 2 does not match version 1" err ) && ( cd sha256 && mv ../mpi-sha1 .git/objects/pack/multi-pack-index && git log -1 2>err && - test_i18ngrep "multi-pack-index hash version 1 does not match version 2" err + test_grep "multi-pack-index hash version 1 does not match version 2" err ) ' @@ -374,7 +387,7 @@ corrupt_midx_and_verify() { printf "$DATA" | dd of="$FILE" bs=1 seek="$POS" conv=notrunc && test_must_fail $COMMAND 2>test_err && grep -v "^+" test_err >err && - test_i18ngrep "$GREPSTR" err + test_grep "$GREPSTR" err } test_expect_success 'verify bad signature' ' @@ -426,7 +439,7 @@ test_expect_success 'verify extended chunk count' ' test_expect_success 'verify missing required chunk' ' corrupt_midx_and_verify $MIDX_BYTE_CHUNK_ID "\01" $objdir \ - "missing required" + "required pack-name chunk missing" ' test_expect_success 'verify invalid chunk offset' ' @@ -473,11 +486,23 @@ test_expect_success 'git-fsck incorrect offset' ' git -c core.multiPackIndex=false fsck ' +test_expect_success 'git fsck shows MIDX output with --progress' ' + git fsck --progress 2>err && + grep "Verifying OID order in multi-pack-index" err && + grep "Verifying object offsets" err +' + +test_expect_success 'git fsck suppresses MIDX output with --no-progress' ' + git fsck --no-progress 2>err && + ! grep "Verifying OID order in multi-pack-index" err && + ! grep "Verifying object offsets" err +' + test_expect_success 'corrupt MIDX is not reused' ' corrupt_midx_and_verify $MIDX_BYTE_OFFSET "\377" $objdir \ "incorrect object offset" && git multi-pack-index write 2>err && - test_i18ngrep checksum.mismatch err && + test_grep checksum.mismatch err && git multi-pack-index verify ' @@ -1007,7 +1032,7 @@ test_expect_success 'load reverse index when missing .idx, .pack' ' test_expect_success 'usage shown without sub-command' ' test_expect_code 129 git multi-pack-index 2>err && - ! test_i18ngrep "unrecognized subcommand" err + ! test_grep "unrecognized subcommand" err ' test_expect_success 'complains when run outside of a repository' ' @@ -1031,4 +1056,119 @@ test_expect_success 'repack with delta islands' ' ) ' +corrupt_chunk () { + midx=.git/objects/pack/multi-pack-index && + test_when_finished "rm -rf $midx" && + git repack -ad --write-midx && + corrupt_chunk_file $midx "$@" +} + +test_expect_success 'reader notices too-small oid fanout chunk' ' + corrupt_chunk OIDF clear 00000000 && + test_must_fail git log 2>err && + cat >expect <<-\EOF && + error: multi-pack-index OID fanout is of the wrong size + fatal: multi-pack-index required OID fanout chunk missing or corrupted + EOF + test_cmp expect err +' + +test_expect_success 'reader notices too-small oid lookup chunk' ' + corrupt_chunk OIDL clear 00000000 && + test_must_fail git log 2>err && + cat >expect <<-\EOF && + error: multi-pack-index OID lookup chunk is the wrong size + fatal: multi-pack-index required OID lookup chunk missing or corrupted + EOF + test_cmp expect err +' + +test_expect_success 'reader notices too-small pack names chunk' ' + # There is no NUL to terminate the name here, so the + # chunk is too short. + corrupt_chunk PNAM clear 70656666 && + test_must_fail git log 2>err && + cat >expect <<-\EOF && + fatal: multi-pack-index pack-name chunk is too short + EOF + test_cmp expect err +' + +test_expect_success 'reader handles unaligned chunks' ' + # A 9-byte PNAM means all of the subsequent chunks + # will no longer be 4-byte aligned, but it is still + # a valid one-pack chunk on its own (it is "foo.pack\0"). + corrupt_chunk PNAM clear 666f6f2e7061636b00 && + git -c core.multipackindex=false log >expect.out && + git -c core.multipackindex=true log >out 2>err && + test_cmp expect.out out && + cat >expect.err <<-\EOF && + error: chunk id 4f494446 not 4-byte aligned + EOF + test_cmp expect.err err +' + +test_expect_success 'reader notices too-small object offset chunk' ' + corrupt_chunk OOFF clear 00000000 && + test_must_fail git log 2>err && + cat >expect <<-\EOF && + error: multi-pack-index object offset chunk is the wrong size + fatal: multi-pack-index required object offsets chunk missing or corrupted + EOF + test_cmp expect err +' + +test_expect_success 'reader bounds-checks large offset table' ' + # re-use the objects64 dir here to cheaply get access to a midx + # with large offsets. + git init repo && + test_when_finished "rm -rf repo" && + ( + cd repo && + (cd ../objects64 && pwd) >.git/objects/info/alternates && + git multi-pack-index --object-dir=../objects64 write && + midx=../objects64/pack/multi-pack-index && + corrupt_chunk_file $midx LOFF clear && + # using only %(objectsize) is important here; see the commit + # message for more details + test_must_fail git cat-file --batch-all-objects \ + --batch-check="%(objectsize)" 2>err && + cat >expect <<-\EOF && + fatal: multi-pack-index large offset out of bounds + EOF + test_cmp expect err + ) +' + +test_expect_success 'reader notices too-small revindex chunk' ' + # We only get a revindex with bitmaps (and likewise only + # load it when they are asked for). + test_config repack.writeBitmaps true && + corrupt_chunk RIDX clear 00000000 && + git -c core.multipackIndex=false rev-list \ + --all --use-bitmap-index >expect.out && + git -c core.multipackIndex=true rev-list \ + --all --use-bitmap-index >out 2>err && + test_cmp expect.out out && + cat >expect.err <<-\EOF && + error: multi-pack-index reverse-index chunk is the wrong size + warning: multi-pack bitmap is missing required reverse index + EOF + test_cmp expect.err err +' + +test_expect_success 'reader notices out-of-bounds fanout' ' + # This is similar to the out-of-bounds fanout test in t5318. The values + # in adjacent entries should be large but not identical (they + # are used as hi/lo starts for a binary search, which would then abort + # immediately). + corrupt_chunk OIDF 0 $(printf "%02x000000" $(test_seq 0 254)) && + test_must_fail git log 2>err && + cat >expect <<-\EOF && + error: oid fanout out of order: fanout[254] = fe000000 > 5c = fanout[255] + fatal: multi-pack-index required OID fanout chunk missing or corrupted + EOF + test_cmp expect err +' + test_done diff --git a/t/t5324-split-commit-graph.sh b/t/t5324-split-commit-graph.sh index 669ddc645f..281266f788 100755 --- a/t/t5324-split-commit-graph.sh +++ b/t/t5324-split-commit-graph.sh @@ -1,7 +1,10 @@ #!/bin/sh test_description='split commit graph' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-chunk.sh GIT_TEST_COMMIT_GRAPH=0 GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0 @@ -281,7 +284,33 @@ test_expect_success 'verify hashes along chain, even in shallow' ' corrupt_file "$base_file" $(test_oid shallow) "\01" && test_must_fail git commit-graph verify --shallow 2>test_err && grep -v "^+" test_err >err && - test_i18ngrep "incorrect checksum" err + test_grep "incorrect checksum" err + ) +' + +test_expect_success 'verify notices chain slice which is bogus (base)' ' + git clone --no-hardlinks . verify-chain-bogus-base && + ( + cd verify-chain-bogus-base && + git commit-graph verify && + base_file=$graphdir/graph-$(sed -n 1p $graphdir/commit-graph-chain).graph && + echo "garbage" >$base_file && + test_must_fail git commit-graph verify 2>test_err && + grep -v "^+" test_err >err && + grep "commit-graph file is too small" err + ) +' + +test_expect_success 'verify notices chain slice which is bogus (tip)' ' + git clone --no-hardlinks . verify-chain-bogus-tip && + ( + cd verify-chain-bogus-tip && + git commit-graph verify && + tip_file=$graphdir/graph-$(sed -n 2p $graphdir/commit-graph-chain).graph && + echo "garbage" >$tip_file && + test_must_fail git commit-graph verify 2>test_err && + grep -v "^+" test_err >err && + grep "commit-graph file is too small" err ) ' @@ -291,11 +320,11 @@ test_expect_success 'verify --shallow does not check base contents' ' cd verify-shallow && git commit-graph verify && base_file=$graphdir/graph-$(head -n 1 $graphdir/commit-graph-chain).graph && - corrupt_file "$base_file" 1000 "\01" && + corrupt_file "$base_file" 1500 "\01" && git commit-graph verify --shallow && test_must_fail git commit-graph verify 2>test_err && grep -v "^+" test_err >err && - test_i18ngrep "incorrect checksum" err + test_grep "incorrect checksum" err ) ' @@ -306,24 +335,51 @@ test_expect_success 'warn on base graph chunk incorrect' ' git commit-graph verify && base_file=$graphdir/graph-$(tail -n 1 $graphdir/commit-graph-chain).graph && corrupt_file "$base_file" $(test_oid base) "\01" && - git commit-graph verify --shallow 2>test_err && + test_must_fail git commit-graph verify --shallow 2>test_err && + grep -v "^+" test_err >err && + test_grep "commit-graph chain does not match" err + ) +' + +test_expect_success 'verify after commit-graph-chain corruption (base)' ' + git clone --no-hardlinks . verify-chain-base && + ( + cd verify-chain-base && + corrupt_file "$graphdir/commit-graph-chain" 30 "G" && + test_must_fail git commit-graph verify 2>test_err && + grep -v "^+" test_err >err && + test_grep "invalid commit-graph chain" err && + corrupt_file "$graphdir/commit-graph-chain" 30 "A" && + test_must_fail git commit-graph verify 2>test_err && grep -v "^+" test_err >err && - test_i18ngrep "commit-graph chain does not match" err + test_grep "unable to find all commit-graph files" err ) ' -test_expect_success 'verify after commit-graph-chain corruption' ' - git clone --no-hardlinks . verify-chain && +test_expect_success 'verify after commit-graph-chain corruption (tip)' ' + git clone --no-hardlinks . verify-chain-tip && ( - cd verify-chain && - corrupt_file "$graphdir/commit-graph-chain" 60 "G" && - git commit-graph verify 2>test_err && + cd verify-chain-tip && + corrupt_file "$graphdir/commit-graph-chain" 70 "G" && + test_must_fail git commit-graph verify 2>test_err && grep -v "^+" test_err >err && - test_i18ngrep "invalid commit-graph chain" err && - corrupt_file "$graphdir/commit-graph-chain" 60 "A" && - git commit-graph verify 2>test_err && + test_grep "invalid commit-graph chain" err && + corrupt_file "$graphdir/commit-graph-chain" 70 "A" && + test_must_fail git commit-graph verify 2>test_err && grep -v "^+" test_err >err && - test_i18ngrep "unable to find all commit-graph files" err + test_grep "unable to find all commit-graph files" err + ) +' + +test_expect_success 'verify notices too-short chain file' ' + git clone --no-hardlinks . verify-chain-short && + ( + cd verify-chain-short && + git commit-graph verify && + echo "garbage" >$graphdir/commit-graph-chain && + test_must_fail git commit-graph verify 2>test_err && + grep -v "^+" test_err >err && + grep "commit-graph chain file too small" err ) ' @@ -338,10 +394,23 @@ test_expect_success 'verify across alternates' ' test_commit extra && git commit-graph write --reachable --split && tip_file=$graphdir/graph-$(tail -n 1 $graphdir/commit-graph-chain).graph && - corrupt_file "$tip_file" 100 "\01" && + corrupt_file "$tip_file" 1500 "\01" && test_must_fail git commit-graph verify --shallow 2>test_err && grep -v "^+" test_err >err && - test_i18ngrep "commit-graph has incorrect fanout value" err + test_grep "incorrect checksum" err + ) +' + +test_expect_success 'reader bounds-checks base-graph chunk' ' + git clone --no-hardlinks . corrupt-base-chunk && + ( + cd corrupt-base-chunk && + tip_file=$graphdir/graph-$(tail -n 1 $graphdir/commit-graph-chain).graph && + corrupt_chunk_file "$tip_file" BASE clear 01020304 && + git -c core.commitGraph=false log >expect.out && + git -c core.commitGraph=true log >out 2>err && + test_cmp expect.out out && + grep "commit-graph base graphs chunk is too small" err ) ' @@ -351,8 +420,9 @@ test_expect_success 'add octopus merge' ' git branch merge/octopus && git commit-graph write --reachable --split && git commit-graph verify --progress 2>err && - test_line_count = 3 err && - test_i18ngrep ! warning err && + test_line_count = 1 err && + grep "Verifying commits in commit graph: 100% (18/18)" err && + test_grep ! warning err && test_line_count = 3 $graphdir/commit-graph-chain ' @@ -454,7 +524,7 @@ test_expect_success 'prevent regression for duplicate commits across layers' ' git init dup && git -C dup commit --allow-empty -m one && git -C dup -c core.commitGraph=false commit-graph write --split=no-merge --reachable 2>err && - test_i18ngrep "attempting to write a commit-graph" err && + test_grep "attempting to write a commit-graph" err && git -C dup commit-graph write --split=no-merge --reachable && git -C dup commit --allow-empty -m two && git -C dup commit-graph write --split=no-merge --reachable && diff --git a/t/t5325-reverse-index.sh b/t/t5325-reverse-index.sh index d042d26f2b..431a603ca0 100755 --- a/t/t5325-reverse-index.sh +++ b/t/t5325-reverse-index.sh @@ -1,17 +1,20 @@ #!/bin/sh test_description='on-disk reverse index' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # The below tests want control over the 'pack.writeReverseIndex' setting # themselves to assert various combinations of it with other options. -sane_unset GIT_TEST_WRITE_REV_INDEX +sane_unset GIT_TEST_NO_WRITE_REV_INDEX packdir=.git/objects/pack test_expect_success 'setup' ' test_commit base && + test_config pack.writeReverseIndex false && pack=$(git pack-objects --all $packdir/pack) && rev=$packdir/pack-$pack.rev && @@ -94,6 +97,17 @@ test_expect_success 'reverse index is not generated when available on disk' ' --batch-check="%(objectsize:disk)" <tip ' +test_expect_success 'reverse index is ignored when pack.readReverseIndex is false' ' + test_index_pack true && + test_path_is_file $rev && + + test_config pack.readReverseIndex false && + + git rev-parse HEAD >tip && + GIT_TEST_REV_INDEX_DIE_ON_DISK=1 git cat-file \ + --batch-check="%(objectsize:disk)" <tip +' + test_expect_success 'revindex in-memory vs on-disk' ' git init repo && test_when_finished "rm -fr repo" && @@ -117,4 +131,78 @@ test_expect_success 'revindex in-memory vs on-disk' ' test_cmp on-disk in-core ) ' + +test_expect_success 'fsck succeeds on good rev-index' ' + test_when_finished rm -fr repo && + git init repo && + ( + cd repo && + + test_commit commit && + git -c pack.writeReverseIndex=true repack -ad && + git fsck 2>err && + test_must_be_empty err + ) +' + +test_expect_success 'set up rev-index corruption tests' ' + git init corrupt && + ( + cd corrupt && + + test_commit commit && + git -c pack.writeReverseIndex=true repack -ad && + + revfile=$(ls .git/objects/pack/pack-*.rev) && + chmod a+w $revfile && + cp $revfile $revfile.bak + ) +' + +corrupt_rev_and_verify () { + ( + pos="$1" && + value="$2" && + error="$3" && + + cd corrupt && + revfile=$(ls .git/objects/pack/pack-*.rev) && + + # Reset to original rev-file. + cp $revfile.bak $revfile && + + printf "$value" | dd of=$revfile bs=1 seek="$pos" conv=notrunc && + test_must_fail git fsck 2>err && + grep "$error" err + ) +} + +test_expect_success 'fsck catches invalid checksum' ' + revfile=$(ls corrupt/.git/objects/pack/pack-*.rev) && + orig_size=$(wc -c <$revfile) && + hashpos=$((orig_size - 10)) && + corrupt_rev_and_verify $hashpos bogus \ + "invalid checksum" +' + +test_expect_success 'fsck catches invalid row position' ' + corrupt_rev_and_verify 14 "\07" \ + "invalid rev-index position" +' + +test_expect_success 'fsck catches invalid header: magic number' ' + corrupt_rev_and_verify 1 "\07" \ + "reverse-index file .* has unknown signature" +' + +test_expect_success 'fsck catches invalid header: version' ' + corrupt_rev_and_verify 7 "\02" \ + "reverse-index file .* has unsupported version" +' + +test_expect_success 'fsck catches invalid header: hash function' ' + corrupt_rev_and_verify 11 "\03" \ + "reverse-index file .* has unsupported hash id" +' + test_done diff --git a/t/t5326-multi-pack-bitmaps.sh b/t/t5326-multi-pack-bitmaps.sh index 0882cbb6e4..70d1b58709 100755 --- a/t/t5326-multi-pack-bitmaps.sh +++ b/t/t5326-multi-pack-bitmaps.sh @@ -434,4 +434,83 @@ test_expect_success 'tagged commits are selected for bitmapping' ' ) ' +corrupt_file () { + chmod a+w "$1" && + printf "bogus" | dd of="$1" bs=1 seek="12" conv=notrunc +} + +test_expect_success 'git fsck correctly identifies good and bad bitmaps' ' + git init valid && + test_when_finished rm -rf valid && + + test_commit_bulk 20 && + git repack -adbf && + + # Move pack-bitmap aside so it is not deleted + # in next repack. + packbitmap=$(ls .git/objects/pack/pack-*.bitmap) && + mv "$packbitmap" "$packbitmap.bak" && + + test_commit_bulk 10 && + git repack -b --write-midx && + midxbitmap=$(ls .git/objects/pack/multi-pack-index-*.bitmap) && + + # Copy MIDX bitmap to backup. Copy pack bitmap from backup. + cp "$midxbitmap" "$midxbitmap.bak" && + cp "$packbitmap.bak" "$packbitmap" && + + # fsck works at first + git fsck 2>err && + test_must_be_empty err && + + corrupt_file "$packbitmap" && + test_must_fail git fsck 2>err && + grep "bitmap file '\''$packbitmap'\'' has invalid checksum" err && + + cp "$packbitmap.bak" "$packbitmap" && + corrupt_file "$midxbitmap" && + test_must_fail git fsck 2>err && + grep "bitmap file '\''$midxbitmap'\'' has invalid checksum" err && + + corrupt_file "$packbitmap" && + test_must_fail git fsck 2>err && + grep "bitmap file '\''$midxbitmap'\'' has invalid checksum" err && + grep "bitmap file '\''$packbitmap'\'' has invalid checksum" err +' + +test_expect_success 'corrupt MIDX with bitmap causes fallback' ' + git init corrupt-midx-bitmap && + ( + cd corrupt-midx-bitmap && + + test_commit first && + git repack -d && + test_commit second && + git repack -d && + + git multi-pack-index write --bitmap && + checksum=$(midx_checksum $objdir) && + for f in $midx $midx-$checksum.bitmap + do + mv $f $f.bak || return 1 + done && + + # pack everything together, invalidating the MIDX + git repack -ad && + # then restore the now-stale MIDX + for f in $midx $midx-$checksum.bitmap + do + mv $f.bak $f || return 1 + done && + + git rev-list --count --objects --use-bitmap-index HEAD >out 2>err && + # should attempt opening the broken pack twice (once + # from the attempt to load it via the stale bitmap, and + # again when attempting to load it from the stale MIDX) + # before falling back to the non-MIDX case + test 2 -eq $(grep -c "could not open pack" err) && + test 6 -eq $(cat out) + ) +' + test_done diff --git a/t/t5328-commit-graph-64bit-time.sh b/t/t5328-commit-graph-64bit-time.sh index 093f0c067a..fc6a242b56 100755 --- a/t/t5328-commit-graph-64bit-time.sh +++ b/t/t5328-commit-graph-64bit-time.sh @@ -1,6 +1,8 @@ #!/bin/sh test_description='commit graph with 64-bit timestamps' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh if ! test_have_prereq TIME_IS_64BIT || ! test_have_prereq TIME_T_IS_64BIT @@ -10,6 +12,7 @@ then fi . "$TEST_DIRECTORY"/lib-commit-graph.sh +. "$TEST_DIRECTORY/lib-chunk.sh" UNIX_EPOCH_ZERO="@0 +0000" FUTURE_DATE="@4147483646 +0000" @@ -37,30 +40,48 @@ test_expect_success 'lower layers have overflow chunk' ' graph_git_behavior 'overflow' '' HEAD~2 HEAD test_expect_success 'set up and verify repo with generation data overflow chunk' ' - mkdir repo && - cd repo && - git init && - test_commit --date "$UNIX_EPOCH_ZERO" 1 && - test_commit 2 && - test_commit --date "$UNIX_EPOCH_ZERO" 3 && - git commit-graph write --reachable && - graph_read_expect 3 generation_data && - test_commit --date "$FUTURE_DATE" 4 && - test_commit 5 && - test_commit --date "$UNIX_EPOCH_ZERO" 6 && - git branch left && - git reset --hard 3 && - test_commit 7 && - test_commit --date "$FUTURE_DATE" 8 && - test_commit 9 && - git branch right && - git reset --hard 3 && - test_merge M left right && - git commit-graph write --reachable && - graph_read_expect 10 "generation_data generation_data_overflow" && - git commit-graph verify + git init repo && + ( + cd repo && + test_commit --date "$UNIX_EPOCH_ZERO" 1 && + test_commit 2 && + test_commit --date "$UNIX_EPOCH_ZERO" 3 && + git commit-graph write --reachable && + graph_read_expect 3 generation_data && + test_commit --date "$FUTURE_DATE" 4 && + test_commit 5 && + test_commit --date "$UNIX_EPOCH_ZERO" 6 && + git branch left && + git reset --hard 3 && + test_commit 7 && + test_commit --date "$FUTURE_DATE" 8 && + test_commit 9 && + git branch right && + git reset --hard 3 && + test_merge M left right && + git commit-graph write --reachable && + graph_read_expect 10 "generation_data generation_data_overflow" && + git commit-graph verify + ) ' graph_git_behavior 'overflow 2' repo left right +test_expect_success 'single commit with generation data exceeding UINT32_MAX' ' + git init repo-uint32-max && + test_commit -C repo-uint32-max --date "@4294967297 +0000" 1 && + git -C repo-uint32-max commit-graph write --reachable && + graph_read_expect -C repo-uint32-max 1 "generation_data" && + git -C repo-uint32-max commit-graph verify +' + +test_expect_success 'reader notices out-of-bounds generation overflow' ' + graph=.git/objects/info/commit-graph && + test_when_finished "rm -rf $graph" && + git commit-graph write --reachable && + corrupt_chunk_file $graph GDO2 clear && + test_must_fail git log 2>err && + grep "commit-graph overflow generation data is too small" err +' + test_done diff --git a/t/t5329-pack-objects-cruft.sh b/t/t5329-pack-objects-cruft.sh index 303f7a5d84..fc5fedbe9b 100755 --- a/t/t5329-pack-objects-cruft.sh +++ b/t/t5329-pack-objects-cruft.sh @@ -573,23 +573,54 @@ test_expect_success 'cruft repack with no reachable objects' ' ) ' -test_expect_success 'cruft repack ignores --max-pack-size' ' +write_blob () { + test-tool genrandom "$@" >in && + git hash-object -w -t blob in +} + +find_pack () { + for idx in $(ls $packdir/pack-*.idx) + do + git show-index <$idx >out && + if grep -q "$1" out + then + echo $idx + fi || return 1 + done +} + +test_expect_success 'cruft repack with --max-pack-size' ' git init max-pack-size && ( cd max-pack-size && test_commit base && + # two cruft objects which exceed the maximum pack size - test-tool genrandom foo 1048576 | git hash-object --stdin -w && - test-tool genrandom bar 1048576 | git hash-object --stdin -w && + foo=$(write_blob foo 1048576) && + bar=$(write_blob bar 1048576) && + test-tool chmtime --get -1000 \ + "$objdir/$(test_oid_to_path $foo)" >foo.mtime && + test-tool chmtime --get -2000 \ + "$objdir/$(test_oid_to_path $bar)" >bar.mtime && git repack --cruft --max-pack-size=1M && find $packdir -name "*.mtimes" >cruft && - test_line_count = 1 cruft && - test-tool pack-mtimes "$(basename "$(cat cruft)")" >objects && - test_line_count = 2 objects + test_line_count = 2 cruft && + + foo_mtimes="$(basename $(find_pack $foo) .idx).mtimes" && + bar_mtimes="$(basename $(find_pack $bar) .idx).mtimes" && + test-tool pack-mtimes $foo_mtimes >foo.actual && + test-tool pack-mtimes $bar_mtimes >bar.actual && + + echo "$foo $(cat foo.mtime)" >foo.expect && + echo "$bar $(cat bar.mtime)" >bar.expect && + + test_cmp foo.expect foo.actual && + test_cmp bar.expect bar.actual && + test "$foo_mtimes" != "$bar_mtimes" ) ' -test_expect_success 'cruft repack ignores pack.packSizeLimit' ' +test_expect_success 'cruft repack with pack.packSizeLimit' ' ( cd max-pack-size && # repack everything back together to remove the existing cruft @@ -599,9 +630,12 @@ test_expect_success 'cruft repack ignores pack.packSizeLimit' ' # ensure the same post condition is met when --max-pack-size # would otherwise be inferred from the configuration find $packdir -name "*.mtimes" >cruft && - test_line_count = 1 cruft && - test-tool pack-mtimes "$(basename "$(cat cruft)")" >objects && - test_line_count = 2 objects + test_line_count = 2 cruft && + for pack in $(cat cruft) + do + test-tool pack-mtimes "$(basename $pack)" >objects && + test_line_count = 1 objects || return 1 + done ) ' @@ -739,4 +773,175 @@ test_expect_success 'cruft objects are freshend via loose' ' ) ' +test_expect_success 'gc.recentObjectsHook' ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + + # Create a handful of objects. + # + # - one reachable commit, "base", designated for the reachable + # pack + # - one unreachable commit, "cruft.discard", which is marked + # for deletion + # - one unreachable commit, "cruft.old", which would be marked + # for deletion, but is rescued as an extra cruft tip + # - one unreachable commit, "cruft.new", which is not marked + # for deletion + test_commit base && + git branch -M main && + + git checkout --orphan discard && + git rm -fr . && + test_commit --no-tag cruft.discard && + + git checkout --orphan old && + git rm -fr . && + test_commit --no-tag cruft.old && + cruft_old="$(git rev-parse HEAD)" && + + git checkout --orphan new && + git rm -fr . && + test_commit --no-tag cruft.new && + cruft_new="$(git rev-parse HEAD)" && + + git checkout main && + git branch -D discard old new && + git reflog expire --all --expire=all && + + # mark cruft.old with an mtime that is many minutes + # older than the expiration period, and mark cruft.new + # with an mtime that is in the future (and thus not + # eligible for pruning). + test-tool chmtime -2000 "$objdir/$(test_oid_to_path $cruft_old)" && + test-tool chmtime +1000 "$objdir/$(test_oid_to_path $cruft_new)" && + + # Write the list of cruft objects we expect to + # accumulate, which is comprised of everything reachable + # from cruft.old and cruft.new, but not cruft.discard. + git rev-list --objects --no-object-names \ + $cruft_old $cruft_new >cruft.raw && + sort cruft.raw >cruft.expect && + + # Write the script to list extra tips, which are limited + # to cruft.old, in this case. + write_script extra-tips <<-EOF && + echo $cruft_old + EOF + git config gc.recentObjectsHook ./extra-tips && + + git repack --cruft --cruft-expiration=now -d && + + mtimes="$(ls .git/objects/pack/pack-*.mtimes)" && + git show-index <${mtimes%.mtimes}.idx >cruft && + cut -d" " -f2 cruft | sort >cruft.actual && + test_cmp cruft.expect cruft.actual && + + # Ensure that the "old" objects are removed after + # dropping the gc.recentObjectsHook hook. + git config --unset gc.recentObjectsHook && + git repack --cruft --cruft-expiration=now -d && + + mtimes="$(ls .git/objects/pack/pack-*.mtimes)" && + git show-index <${mtimes%.mtimes}.idx >cruft && + cut -d" " -f2 cruft | sort >cruft.actual && + + git rev-list --objects --no-object-names $cruft_new >cruft.raw && + cp cruft.expect cruft.old && + sort cruft.raw >cruft.expect && + test_cmp cruft.expect cruft.actual && + + # ensure objects which are no longer in the cruft pack were + # removed from the repository + for object in $(comm -13 cruft.expect cruft.old) + do + test_must_fail git cat-file -t $object || return 1 + done + ) +' + +test_expect_success 'multi-valued gc.recentObjectsHook' ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + + test_commit base && + git branch -M main && + + git checkout --orphan cruft.a && + git rm -fr . && + test_commit --no-tag cruft.a && + cruft_a="$(git rev-parse HEAD)" && + + git checkout --orphan cruft.b && + git rm -fr . && + test_commit --no-tag cruft.b && + cruft_b="$(git rev-parse HEAD)" && + + git checkout main && + git branch -D cruft.a cruft.b && + git reflog expire --all --expire=all && + + echo "echo $cruft_a" | write_script extra-tips.a && + echo "echo $cruft_b" | write_script extra-tips.b && + echo "false" | write_script extra-tips.c && + + git rev-list --objects --no-object-names $cruft_a $cruft_b \ + >cruft.raw && + sort cruft.raw >cruft.expect && + + # ensure that each extra cruft tip is saved by its + # respective hook + git config --add gc.recentObjectsHook ./extra-tips.a && + git config --add gc.recentObjectsHook ./extra-tips.b && + git repack --cruft --cruft-expiration=now -d && + + mtimes="$(ls .git/objects/pack/pack-*.mtimes)" && + git show-index <${mtimes%.mtimes}.idx >cruft && + cut -d" " -f2 cruft | sort >cruft.actual && + test_cmp cruft.expect cruft.actual && + + # ensure that a dirty exit halts cruft pack generation + git config --add gc.recentObjectsHook ./extra-tips.c && + test_must_fail git repack --cruft --cruft-expiration=now -d 2>err && + grep "unable to enumerate additional recent objects" err && + + # and that the existing cruft pack is left alone + test_path_is_file "$mtimes" + ) +' + +test_expect_success 'additional cruft blobs via gc.recentObjectsHook' ' + git init repo && + test_when_finished "rm -fr repo" && + ( + cd repo && + + test_commit base && + + blob=$(echo "unreachable" | git hash-object -w --stdin) && + + # mark the unreachable blob we wrote above as having + # aged out of the retention period + test-tool chmtime -2000 "$objdir/$(test_oid_to_path $blob)" && + + # Write the script to list extra tips, which is just the + # extra blob as above. + write_script extra-tips <<-EOF && + echo $blob + EOF + git config gc.recentObjectsHook ./extra-tips && + + git repack --cruft --cruft-expiration=now -d && + + mtimes="$(ls .git/objects/pack/pack-*.mtimes)" && + git show-index <${mtimes%.mtimes}.idx >cruft && + cut -d" " -f2 cruft >actual && + echo $blob >expect && + test_cmp expect actual + ) +' + test_done diff --git a/t/t5331-pack-objects-stdin.sh b/t/t5331-pack-objects-stdin.sh new file mode 100755 index 0000000000..2dcf1eecee --- /dev/null +++ b/t/t5331-pack-objects-stdin.sh @@ -0,0 +1,240 @@ +#!/bin/sh + +test_description='pack-objects --stdin' +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh + +packed_objects () { + git show-index <"$1" >tmp-object-list && + cut -d' ' -f2 tmp-object-list | sort && + rm tmp-object-list + } + +test_expect_success 'setup for --stdin-packs tests' ' + git init stdin-packs && + ( + cd stdin-packs && + + test_commit A && + test_commit B && + test_commit C && + + for id in A B C + do + git pack-objects .git/objects/pack/pack-$id \ + --incremental --revs <<-EOF || exit 1 + refs/tags/$id + EOF + done && + + ls -la .git/objects/pack + ) +' + +test_expect_success '--stdin-packs with excluded packs' ' + ( + cd stdin-packs && + + PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" && + PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" && + PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" && + + git pack-objects test --stdin-packs <<-EOF && + $PACK_A + ^$PACK_B + $PACK_C + EOF + + ( + git show-index <$(ls .git/objects/pack/pack-A-*.idx) && + git show-index <$(ls .git/objects/pack/pack-C-*.idx) + ) >expect.raw && + git show-index <$(ls test-*.idx) >actual.raw && + + cut -d" " -f2 <expect.raw | sort >expect && + cut -d" " -f2 <actual.raw | sort >actual && + test_cmp expect actual + ) +' + +test_expect_success '--stdin-packs is incompatible with --filter' ' + ( + cd stdin-packs && + test_must_fail git pack-objects --stdin-packs --stdout \ + --filter=blob:none </dev/null 2>err && + test_grep "cannot use --filter with --stdin-packs" err + ) +' + +test_expect_success '--stdin-packs is incompatible with --revs' ' + ( + cd stdin-packs && + test_must_fail git pack-objects --stdin-packs --revs out \ + </dev/null 2>err && + test_grep "cannot use internal rev list with --stdin-packs" err + ) +' + +test_expect_success '--stdin-packs with loose objects' ' + ( + cd stdin-packs && + + PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" && + PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" && + PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" && + + test_commit D && # loose + + git pack-objects test2 --stdin-packs --unpacked <<-EOF && + $PACK_A + ^$PACK_B + $PACK_C + EOF + + ( + git show-index <$(ls .git/objects/pack/pack-A-*.idx) && + git show-index <$(ls .git/objects/pack/pack-C-*.idx) && + git rev-list --objects --no-object-names \ + refs/tags/C..refs/tags/D + + ) >expect.raw && + ls -la . && + git show-index <$(ls test2-*.idx) >actual.raw && + + cut -d" " -f2 <expect.raw | sort >expect && + cut -d" " -f2 <actual.raw | sort >actual && + test_cmp expect actual + ) +' + +test_expect_success '--stdin-packs with broken links' ' + ( + cd stdin-packs && + + # make an unreachable object with a bogus parent + git cat-file -p HEAD >commit && + sed "s/$(git rev-parse HEAD^)/$(test_oid zero)/" <commit | + git hash-object -w -t commit --stdin >in && + + git pack-objects .git/objects/pack/pack-D <in && + + PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" && + PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" && + PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" && + PACK_D="$(basename .git/objects/pack/pack-D-*.pack)" && + + git pack-objects test3 --stdin-packs --unpacked <<-EOF && + $PACK_A + ^$PACK_B + $PACK_C + $PACK_D + EOF + + ( + git show-index <$(ls .git/objects/pack/pack-A-*.idx) && + git show-index <$(ls .git/objects/pack/pack-C-*.idx) && + git show-index <$(ls .git/objects/pack/pack-D-*.idx) && + git rev-list --objects --no-object-names \ + refs/tags/C..refs/tags/D + ) >expect.raw && + git show-index <$(ls test3-*.idx) >actual.raw && + + cut -d" " -f2 <expect.raw | sort >expect && + cut -d" " -f2 <actual.raw | sort >actual && + test_cmp expect actual + ) +' + +test_expect_success 'pack-objects --stdin with duplicate packfile' ' + test_when_finished "rm -fr repo" && + + git init repo && + ( + cd repo && + test_commit "commit" && + git repack -ad && + + { + basename .git/objects/pack/pack-*.pack && + basename .git/objects/pack/pack-*.pack + } >packfiles && + + git pack-objects --stdin-packs generated-pack <packfiles && + packed_objects .git/objects/pack/pack-*.idx >expect && + packed_objects generated-pack-*.idx >actual && + test_cmp expect actual + ) +' + +test_expect_success 'pack-objects --stdin with same packfile excluded and included' ' + test_when_finished "rm -fr repo" && + + git init repo && + ( + cd repo && + test_commit "commit" && + git repack -ad && + + { + basename .git/objects/pack/pack-*.pack && + printf "^%s\n" "$(basename .git/objects/pack/pack-*.pack)" + } >packfiles && + + git pack-objects --stdin-packs generated-pack <packfiles && + packed_objects generated-pack-*.idx >packed-objects && + test_must_be_empty packed-objects + ) +' + +test_expect_success 'pack-objects --stdin with packfiles from alternate object database' ' + test_when_finished "rm -fr shared member" && + + # Set up a shared repository with a single packfile. + git init shared && + test_commit -C shared "shared-objects" && + git -C shared repack -ad && + basename shared/.git/objects/pack/pack-*.pack >packfile && + + # Set up a repository that is connected to the shared repository. This + # repository has no objects on its own, but we still expect to be able + # to pack objects from its alternate. + git clone --shared shared member && + git -C member pack-objects --stdin-packs generated-pack <packfile && + test_cmp shared/.git/objects/pack/pack-*.pack member/generated-pack-*.pack +' + +test_expect_success 'pack-objects --stdin with packfiles from main and alternate object database' ' + test_when_finished "rm -fr shared member" && + + # Set up a shared repository with a single packfile. + git init shared && + test_commit -C shared "shared-commit" && + git -C shared repack -ad && + + # Set up a repository that is connected to the shared repository. This + # repository has a second packfile so that we can verify that it is + # possible to write packs that include packfiles from different object + # databases. + git clone --shared shared member && + test_commit -C member "local-commit" && + git -C member repack -dl && + + { + basename shared/.git/objects/pack/pack-*.pack && + basename member/.git/objects/pack/pack-*.pack + } >packfiles && + + { + packed_objects shared/.git/objects/pack/pack-*.idx && + packed_objects member/.git/objects/pack/pack-*.idx + } | sort >expected-objects && + + git -C member pack-objects --stdin-packs generated-pack <packfiles && + packed_objects member/generated-pack-*.idx >actual-objects && + test_cmp expected-objects actual-objects +' + +test_done diff --git a/t/t5351-unpack-large-objects.sh b/t/t5351-unpack-large-objects.sh index 8c8af99b84..43cbcd5d49 100755 --- a/t/t5351-unpack-large-objects.sh +++ b/t/t5351-unpack-large-objects.sh @@ -55,7 +55,7 @@ check_fsync_events () { cat >expect && sed -n \ - -e '/^{"event":"data",.*"category":"fsync",/ { + -e '/^{"event":"counter",.*"category":"fsync",/ { s/.*"category":"fsync",//; s/}$//; p; @@ -78,8 +78,8 @@ test_expect_success 'unpack big object in stream (core.fsyncmethod=batch)' ' flush_count=1 fi && check_fsync_events trace2.txt <<-EOF && - "key":"fsync/writeout-only","value":"6" - "key":"fsync/hardware-flush","value":"$flush_count" + "name":"writeout-only","count":6 + "name":"hardware-flush","count":$flush_count EOF test_dir_is_empty dest.git/objects/pack && diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh index 001b7a17ad..8b8bc47dc0 100755 --- a/t/t5401-update-hooks.sh +++ b/t/t5401-update-hooks.sh @@ -133,10 +133,8 @@ test_expect_success 'pre-receive hook that forgets to read its input' ' EOF rm -f victim.git/hooks/update victim.git/hooks/post-update && - for v in $(test_seq 100 999) - do - git branch branch_$v main || return - done && + printf "create refs/heads/branch_%d main\n" $(test_seq 100 999) >input && + git update-ref --stdin <input && git push ./victim.git "+refs/heads/*:refs/heads/*" ' diff --git a/t/t5404-tracking-branches.sh b/t/t5404-tracking-branches.sh index cc07889667..51737eeafe 100755 --- a/t/t5404-tracking-branches.sh +++ b/t/t5404-tracking-branches.sh @@ -5,6 +5,7 @@ test_description='tracking branch update checks for git push' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t5407-post-rewrite-hook.sh b/t/t5407-post-rewrite-hook.sh index 5f3ff051ca..ad7f8c6f00 100755 --- a/t/t5407-post-rewrite-hook.sh +++ b/t/t5407-post-rewrite-hook.sh @@ -17,6 +17,12 @@ test_expect_success 'setup' ' git checkout A^0 && test_commit E bar E && test_commit F foo F && + git checkout B && + git merge E && + git tag merge-E && + test_commit G G && + test_commit H H && + test_commit I I && git checkout main && test_hook --setup post-rewrite <<-EOF @@ -173,6 +179,48 @@ test_fail_interactive_rebase () { ) } +test_expect_success 'git rebase with failed pick' ' + clear_hook_input && + cat >todo <<-\EOF && + exec >bar + merge -C merge-E E + exec >G + pick G + exec >H 2>I + pick H + fixup I + EOF + + ( + set_replace_editor todo && + test_must_fail git rebase -i D D 2>err + ) && + grep "would be overwritten" err && + rm bar && + + test_must_fail git rebase --continue 2>err && + grep "would be overwritten" err && + rm G && + + test_must_fail git rebase --continue 2>err && + grep "would be overwritten" err && + rm H && + + test_must_fail git rebase --continue 2>err && + grep "would be overwritten" err && + rm I && + + git rebase --continue && + echo rebase >expected.args && + cat >expected.data <<-EOF && + $(git rev-parse merge-E) $(git rev-parse HEAD~2) + $(git rev-parse G) $(git rev-parse HEAD~1) + $(git rev-parse H) $(git rev-parse HEAD) + $(git rev-parse I) $(git rev-parse HEAD) + EOF + verify_hook_input +' + test_expect_success 'git rebase -i (unchanged)' ' git reset --hard D && clear_hook_input && diff --git a/t/t5411/test-0026-push-options.sh b/t/t5411/test-0026-push-options.sh index 6dfc7b1c0d..510fff38da 100644 --- a/t/t5411/test-0026-push-options.sh +++ b/t/t5411/test-0026-push-options.sh @@ -18,7 +18,7 @@ test_expect_success "proc-receive: not support push options ($PROTOCOL)" ' HEAD:refs/for/main/topic \ >out-$test_count 2>&1 && make_user_friendly_and_stable_output <out-$test_count >actual && - test_i18ngrep "fatal: the receiving end does not support push options" \ + test_grep "fatal: the receiving end does not support push options" \ actual && test_cmp_refs -C "$upstream" <<-EOF diff --git a/t/t5411/test-0027-push-options--porcelain.sh b/t/t5411/test-0027-push-options--porcelain.sh index 768880b40f..9435457de0 100644 --- a/t/t5411/test-0027-push-options--porcelain.sh +++ b/t/t5411/test-0027-push-options--porcelain.sh @@ -19,7 +19,7 @@ test_expect_success "proc-receive: not support push options ($PROTOCOL/porcelain HEAD:refs/for/main/topic \ >out-$test_count 2>&1 && make_user_friendly_and_stable_output <out-$test_count >actual && - test_i18ngrep "fatal: the receiving end does not support push options" \ + test_grep "fatal: the receiving end does not support push options" \ actual && test_cmp_refs -C "$upstream" <<-EOF diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh index d18f2823d8..1bc15a3f08 100755 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@ -132,13 +132,18 @@ test_expect_success 'single branch object count' ' ' test_expect_success 'single given branch clone' ' - git clone --single-branch --branch A "file://$(pwd)/." branch-a && - test_must_fail git --git-dir=branch-a/.git rev-parse origin/B + GIT_TRACE2_EVENT="$(pwd)/branch-a/trace2_event" \ + git clone --single-branch --branch A "file://$(pwd)/." branch-a && + test_must_fail git --git-dir=branch-a/.git rev-parse origin/B && + grep \"fetch-info\".*\"haves\":0 branch-a/trace2_event && + grep \"fetch-info\".*\"wants\":1 branch-a/trace2_event ' test_expect_success 'clone shallow depth 1' ' - git clone --no-single-branch --depth 1 "file://$(pwd)/." shallow0 && - test "$(git --git-dir=shallow0/.git rev-list --count HEAD)" = 1 + GIT_TRACE2_EVENT="$(pwd)/shallow0/trace2_event" \ + git clone --no-single-branch --depth 1 "file://$(pwd)/." shallow0 && + test "$(git --git-dir=shallow0/.git rev-list --count HEAD)" = 1 && + grep \"fetch-info\".*\"depth\":1 shallow0/trace2_event ' test_expect_success 'clone shallow depth 1 with fsck' ' @@ -235,7 +240,10 @@ test_expect_success 'add two more (part 2)' ' test_expect_success 'deepening pull in shallow repo' ' ( cd shallow && - git pull --depth 4 .. B + GIT_TRACE2_EVENT="$(pwd)/trace2_event" \ + git pull --depth 4 .. B && + grep \"fetch-info\".*\"depth\":4 trace2_event && + grep \"fetch-info\".*\"shallows\":2 trace2_event ) ' @@ -306,9 +314,12 @@ test_expect_success 'fetch --depth --no-shallow' ' test_expect_success 'turn shallow to complete repository' ' ( cd shallow && - git fetch --unshallow && + GIT_TRACE2_EVENT="$(pwd)/trace2_event" \ + git fetch --unshallow && ! test -f .git/shallow && - git fsck --full + git fsck --full && + grep \"fetch-info\".*\"shallows\":2 trace2_event && + grep \"fetch-info\".*\"depth\":2147483647 trace2_event ) ' @@ -403,7 +414,7 @@ test_expect_success 'in_vain not triggered before first ACK' ' test_commit -C myserver bar && git -C myclient fetch --progress origin 2>log && - test_i18ngrep "remote: Total 3 " log + test_grep "remote: Total 3 " log ' test_expect_success 'in_vain resetted upon ACK' ' @@ -435,7 +446,7 @@ test_expect_success 'in_vain resetted upon ACK' ' # the client reports that first_anotherbranch_commit is common. GIT_TRACE2_EVENT="$(pwd)/trace2" git -C myclient fetch --progress origin main 2>log && grep \"key\":\"total_rounds\",\"value\":\"6\" trace2 && - test_i18ngrep "Total 3 " log + test_grep "Total 3 " log ' test_expect_success 'fetch in shallow repo unreachable shallow objects' ' @@ -459,7 +470,7 @@ test_expect_success 'fetch creating new shallow root' ' git fetch --depth=1 --progress 2>actual && # This should fetch only the empty commit, no tree or # blob objects - test_i18ngrep "remote: Total 1" actual + test_grep "remote: Total 1" actual ) ' @@ -694,7 +705,7 @@ test_expect_success 'fetch-pack cannot fetch a raw sha1 that is not advertised a # unadvertised objects, so restrict this test to v0. test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 git -C client fetch-pack ../server \ $(git -C server rev-parse refs/heads/main^) 2>err && - test_i18ngrep "Server does not allow request for unadvertised object" err + test_grep "Server does not allow request for unadvertised object" err ' check_prot_path () { @@ -826,13 +837,15 @@ test_expect_success 'clone shallow since ...' ' ' test_expect_success 'fetch shallow since ...' ' - git -C shallow11 fetch --shallow-since "200000000 +0700" origin && + GIT_TRACE2_EVENT=$(pwd)/shallow11/trace2_event \ + git -C shallow11 fetch --shallow-since "200000000 +0700" origin && git -C shallow11 log --pretty=tformat:%s origin/main >actual && cat >expected <<-\EOF && three two EOF - test_cmp expected actual + test_cmp expected actual && + grep \"fetch-info\".*\"deepen-since\":true shallow11/trace2_event ' test_expect_success 'clone shallow since selects no commits' ' @@ -987,13 +1000,16 @@ test_expect_success 'filtering by size' ' test_config -C server uploadpack.allowfilter 1 && test_create_repo client && - git -C client fetch-pack --filter=blob:limit=0 ../server HEAD && + GIT_TRACE2_EVENT=$(pwd)/client/trace2_event \ + git -C client fetch-pack --filter=blob:limit=0 ../server HEAD && # Ensure that object is not inadvertently fetched commit=$(git -C server rev-parse HEAD) && blob=$(git hash-object server/one.t) && git -C client rev-list --objects --missing=allow-any "$commit" >oids && - ! grep "$blob" oids + ! grep "$blob" oids && + + grep \"fetch-info\".*\"filter\":\"blob:limit\" client/trace2_event ' test_expect_success 'filtering by size has no effect if support for it is not advertised' ' @@ -1010,7 +1026,7 @@ test_expect_success 'filtering by size has no effect if support for it is not ad git -C client rev-list --objects --missing=allow-any "$commit" >oids && grep "$blob" oids && - test_i18ngrep "filtering not recognized by server" err + test_grep "filtering not recognized by server" err ' fetch_filter_blob_limit_zero () { diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh index 0b8ab4afdb..138e6778a4 100755 --- a/t/t5504-fetch-receive-strict.sh +++ b/t/t5504-fetch-receive-strict.sh @@ -144,7 +144,7 @@ test_expect_success 'setup bogus commit' ' test_expect_success 'fsck with no skipList input' ' test_must_fail git fsck 2>err && - test_i18ngrep "missingEmail" err + test_grep "missingEmail" err ' test_expect_success 'setup sorted and unsorted skipLists' ' @@ -169,9 +169,9 @@ test_expect_success 'fsck with unsorted skipList' ' test_expect_success 'fsck with invalid or bogus skipList input' ' git -c fsck.skipList=/dev/null -c fsck.missingEmail=ignore fsck && test_must_fail git -c fsck.skipList=does-not-exist -c fsck.missingEmail=ignore fsck 2>err && - test_i18ngrep "could not open.*: does-not-exist" err && + test_grep "could not open.*: does-not-exist" err && test_must_fail git -c fsck.skipList=.git/config -c fsck.missingEmail=ignore fsck 2>err && - test_i18ngrep "invalid object name: \[core\]" err + test_grep "invalid object name: \[core\]" err ' test_expect_success 'fsck with other accepted skipList input (comments & empty lines)' ' @@ -180,14 +180,14 @@ test_expect_success 'fsck with other accepted skipList input (comments & empty l $(test_oid 001) EOF test_must_fail git -c fsck.skipList=SKIP.with-comment fsck 2>err-with-comment && - test_i18ngrep "missingEmail" err-with-comment && + test_grep "missingEmail" err-with-comment && cat >SKIP.with-empty-line <<-EOF && $(test_oid 001) $(test_oid 002) EOF test_must_fail git -c fsck.skipList=SKIP.with-empty-line fsck 2>err-with-empty-line && - test_i18ngrep "missingEmail" err-with-empty-line + test_grep "missingEmail" err-with-empty-line ' test_expect_success 'fsck no garbage output from comments & empty lines errors' ' @@ -198,7 +198,7 @@ test_expect_success 'fsck no garbage output from comments & empty lines errors' test_expect_success 'fsck with invalid abbreviated skipList input' ' echo $commit | test_copy_bytes 20 >SKIP.abbreviated && test_must_fail git -c fsck.skipList=SKIP.abbreviated fsck 2>err-abbreviated && - test_i18ngrep "^fatal: invalid object name: " err-abbreviated + test_grep "^fatal: invalid object name: " err-abbreviated ' test_expect_success 'fsck with exhaustive accepted skipList input (various types of comments etc.)' ' @@ -231,10 +231,10 @@ test_expect_success 'push with receive.fsck.skipList' ' test_must_fail git push --porcelain dst bogus && git --git-dir=dst/.git config receive.fsck.skipList does-not-exist && test_must_fail git push --porcelain dst bogus 2>err && - test_i18ngrep "could not open.*: does-not-exist" err && + test_grep "could not open.*: does-not-exist" err && git --git-dir=dst/.git config receive.fsck.skipList config && test_must_fail git push --porcelain dst bogus 2>err && - test_i18ngrep "invalid object name: \[core\]" err && + test_grep "invalid object name: \[core\]" err && git --git-dir=dst/.git config receive.fsck.skipList SKIP && git push --porcelain dst bogus @@ -260,10 +260,10 @@ test_expect_success 'fetch with fetch.fsck.skipList' ' test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec && git --git-dir=dst/.git config fetch.fsck.skipList does-not-exist && test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec 2>err && - test_i18ngrep "could not open.*: does-not-exist" err && + test_grep "could not open.*: does-not-exist" err && git --git-dir=dst/.git config fetch.fsck.skipList dst/.git/config && test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec 2>err && - test_i18ngrep "invalid object name: \[core\]" err && + test_grep "invalid object name: \[core\]" err && git --git-dir=dst/.git config fetch.fsck.skipList dst/.git/SKIP && git --git-dir=dst/.git fetch "file://$(pwd)" $refspec @@ -271,7 +271,7 @@ test_expect_success 'fetch with fetch.fsck.skipList' ' test_expect_success 'fsck.<unknownmsg-id> dies' ' test_must_fail git -c fsck.whatEver=ignore fsck 2>err && - test_i18ngrep "Unhandled message id: whatever" err + test_grep "Unhandled message id: whatever" err ' test_expect_success 'push with receive.fsck.missingEmail=warn' ' @@ -293,7 +293,7 @@ test_expect_success 'push with receive.fsck.missingEmail=warn' ' receive.fsck.missingEmail warn && git push --porcelain dst bogus >act 2>&1 && grep "missingEmail" act && - test_i18ngrep "skipping unknown msg id.*whatever" act && + test_grep "skipping unknown msg id.*whatever" act && git --git-dir=dst/.git branch -D bogus && git --git-dir=dst/.git config --add \ receive.fsck.missingEmail ignore && @@ -321,7 +321,7 @@ test_expect_success 'fetch with fetch.fsck.missingEmail=warn' ' fetch.fsck.missingEmail warn && git --git-dir=dst/.git fetch "file://$(pwd)" $refspec >act 2>&1 && grep "missingEmail" act && - test_i18ngrep "Skipping unknown msg id.*whatever" act && + test_grep "Skipping unknown msg id.*whatever" act && rm -rf dst && git init dst && git --git-dir=dst/.git config fetch.fsckobjects true && diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index 43b7bcd715..7789ff12c4 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -1075,7 +1075,7 @@ test_expect_success 'remote prune to cause a dangling symref' ' cd eight && git remote prune origin ) >err 2>&1 && - test_i18ngrep "has become dangling" err && + test_grep "has become dangling" err && : And the dangling symref will not cause other annoying errors && ( @@ -1087,7 +1087,7 @@ test_expect_success 'remote prune to cause a dangling symref' ' cd eight && test_must_fail git branch nomore origin ) 2>err && - test_i18ngrep "dangling symref" err + test_grep "dangling symref" err ' test_expect_success 'show empty remote' ' @@ -1419,7 +1419,7 @@ test_expect_success 'extra args: setup' ' test_extra_arg () { test_expect_success "extra args: $*" " test_must_fail git remote $* bogus_extra_arg 2>actual && - test_i18ngrep '^usage:' actual + test_grep '^usage:' actual " } @@ -1453,12 +1453,12 @@ test_expect_success 'unqualified <dst> refspec DWIM and advice' ' oid=$(git rev-parse some-tag^{$type}) fi && test_must_fail git push origin $oid:dst 2>err && - test_i18ngrep "error: The destination you" err && - test_i18ngrep "hint: Did you mean" err && + test_grep "error: The destination you" err && + test_grep "hint: Did you mean" err && test_must_fail git -c advice.pushUnqualifiedRefName=false \ push origin $oid:dst 2>err && - test_i18ngrep "error: The destination you" err && - test_i18ngrep ! "hint: Did you mean" err || + test_grep "error: The destination you" err && + test_grep ! "hint: Did you mean" err || exit 1 done ) @@ -1479,16 +1479,16 @@ test_expect_success 'refs/remotes/* <src> refspec and unqualified <dst> DWIM and git fetch --no-tags two && test_must_fail git push origin refs/remotes/two/another:dst 2>err && - test_i18ngrep "error: The destination you" err && + test_grep "error: The destination you" err && test_must_fail git push origin refs/remotes/tags-from-two/my-tag:dst-tag 2>err && - test_i18ngrep "error: The destination you" err && + test_grep "error: The destination you" err && test_must_fail git push origin refs/remotes/trees-from-two/my-head-tree:dst-tree 2>err && - test_i18ngrep "error: The destination you" err && + test_grep "error: The destination you" err && test_must_fail git push origin refs/remotes/blobs-from-two/my-file-blob:dst-blob 2>err && - test_i18ngrep "error: The destination you" err + test_grep "error: The destination you" err ) ' diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 34a1261520..79592a3b0a 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -169,6 +169,7 @@ test_expect_success REFFILES 'fetch --prune fails to delete branches' ' git clone . prune-fail && cd prune-fail && git update-ref refs/remotes/origin/extrabranch main && + git pack-refs --all && : this will prevent --prune from locking packed-refs for deleting refs, but adding loose refs still succeeds && >.git/packed-refs.new && @@ -415,9 +416,9 @@ test_expect_success 'fetch uses remote ref names to describe new refs' ' ( cd descriptive && git fetch o 2>actual && - test_i18ngrep "new branch.* -> refs/crazyheads/descriptive-branch$" actual && - test_i18ngrep "new tag.* -> descriptive-tag$" actual && - test_i18ngrep "new ref.* -> crazy$" actual + test_grep "new branch.* -> refs/crazyheads/descriptive-branch$" actual && + test_grep "new tag.* -> descriptive-tag$" actual && + test_grep "new ref.* -> crazy$" actual ) && git checkout main ' @@ -1113,63 +1114,65 @@ test_expect_success 'fetching with auto-gc does not lock up' ' git config gc.autoPackLimit 1 && git config gc.autoDetach false && GIT_ASK_YESNO="$D/askyesno" git fetch --verbose >fetch.out 2>&1 && - test_i18ngrep "Auto packing the repository" fetch.out && + test_grep "Auto packing the repository" fetch.out && ! grep "Should I try again" fetch.out ) ' -test_expect_success 'fetch aligned output' ' - git clone . full-output && - test_commit looooooooooooong-tag && - ( - cd full-output && - git -c fetch.output=full fetch origin >actual 2>&1 && - grep -e "->" actual | cut -c 22- >../actual - ) && - cat >expect <<-\EOF && - main -> origin/main - looooooooooooong-tag -> looooooooooooong-tag - EOF - test_cmp expect actual -' +for section in fetch transfer +do + test_expect_success "$section.hideRefs affects connectivity check" ' + GIT_TRACE="$PWD"/trace git -c $section.hideRefs=refs -c \ + $section.hideRefs="!refs/tags/" fetch && + grep "git rev-list .*--exclude-hidden=fetch" trace + ' +done + +test_expect_success 'prepare source branch' ' + echo one >onebranch && + git checkout --orphan onebranch && + git rm --cached -r . && + git add onebranch && + git commit -m onebranch && + git rev-list --objects onebranch -- >actual && + # 3 objects should be created, at least ... + test 3 -le $(wc -l <actual) +' + +validate_store_type () { + git -C dest count-objects -v >actual && + case "$store_type" in + packed) + grep "^count: 0$" actual ;; + loose) + grep "^packs: 0$" actual ;; + esac || { + echo "store_type is $store_type" + cat actual + false + } +} -test_expect_success 'fetch compact output' ' - git clone . compact && - test_commit extraaa && - ( - cd compact && - git -c fetch.output=compact fetch origin >actual 2>&1 && - grep -e "->" actual | cut -c 22- >../actual - ) && - cat >expect <<-\EOF && - main -> origin/* - extraaa -> * - EOF - test_cmp expect actual -' +test_unpack_limit () { + store_type=$1 -test_expect_success '--no-show-forced-updates' ' - mkdir forced-updates && - ( - cd forced-updates && - git init && - test_commit 1 && - test_commit 2 - ) && - git clone forced-updates forced-update-clone && - git clone forced-updates no-forced-update-clone && - git -C forced-updates reset --hard HEAD~1 && - ( - cd forced-update-clone && - git fetch --show-forced-updates origin 2>output && - test_i18ngrep "(forced update)" output - ) && - ( - cd no-forced-update-clone && - git fetch --no-show-forced-updates origin 2>output && - test_i18ngrep ! "(forced update)" output - ) -' + case "$store_type" in + packed) fetch_limit=1 transfer_limit=10000 ;; + loose) fetch_limit=10000 transfer_limit=1 ;; + esac + + test_expect_success "fetch trumps transfer limit" ' + rm -fr dest && + git --bare init dest && + git -C dest config fetch.unpacklimit $fetch_limit && + git -C dest config transfer.unpacklimit $transfer_limit && + git -C dest fetch .. onebranch && + validate_store_type + ' +} + +test_unpack_limit packed +test_unpack_limit loose setup_negotiation_tip () { SERVER="$1" diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh index 20d063fb9a..5dbe107ce8 100755 --- a/t/t5512-ls-remote.sh +++ b/t/t5512-ls-remote.sh @@ -15,6 +15,19 @@ generate_references () { done } +test_expect_success 'set up fake upload-pack' ' + # This can be used to simulate an upload-pack that just shows the + # contents of the "input" file (prepared with the test-tool pkt-line + # helper), and does not do any negotiation (since ls-remote does not + # need it). + write_script cat-input <<-\EOF + # send our initial advertisement/response + cat input + # soak up the flush packet from the client + cat + EOF +' + test_expect_success 'dies when no remote found' ' test_must_fail git ls-remote ' @@ -231,22 +244,25 @@ test_expect_success 'protocol v2 supports hiderefs' ' test_expect_success 'ls-remote --symref' ' git fetch origin && - echo "ref: refs/heads/main HEAD" >expect && + echo "ref: refs/heads/main HEAD" >expect.v2 && generate_references \ HEAD \ - refs/heads/main >>expect && + refs/heads/main >>expect.v2 && + echo "ref: refs/remotes/origin/main refs/remotes/origin/HEAD" >>expect.v2 && oid=$(git rev-parse HEAD) && - echo "$oid refs/remotes/origin/HEAD" >>expect && + echo "$oid refs/remotes/origin/HEAD" >>expect.v2 && generate_references \ refs/remotes/origin/main \ refs/tags/mark \ refs/tags/mark1.1 \ refs/tags/mark1.10 \ - refs/tags/mark1.2 >>expect && - # Protocol v2 supports sending symrefs for refs other than HEAD, so use - # protocol v0 here. - GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref >actual && - test_cmp expect actual + refs/tags/mark1.2 >>expect.v2 && + # v0 does not show non-HEAD symrefs + grep -v "ref: refs/remotes" <expect.v2 >expect.v0 && + git -c protocol.version=0 ls-remote --symref >actual.v0 && + test_cmp expect.v0 actual.v0 && + git -c protocol.version=2 ls-remote --symref >actual.v2 && + test_cmp expect.v2 actual.v2 ' test_expect_success 'ls-remote with filtered symref (refname)' ' @@ -255,76 +271,41 @@ test_expect_success 'ls-remote with filtered symref (refname)' ' ref: refs/heads/main HEAD $rev HEAD EOF - # Protocol v2 supports sending symrefs for refs other than HEAD, so use - # protocol v0 here. - GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref . HEAD >actual && + git ls-remote --symref . HEAD >actual && test_cmp expect actual ' -test_expect_failure 'ls-remote with filtered symref (--heads)' ' +test_expect_success 'ls-remote with filtered symref (--heads)' ' git symbolic-ref refs/heads/foo refs/tags/mark && - cat >expect <<-EOF && + cat >expect.v2 <<-EOF && ref: refs/tags/mark refs/heads/foo $rev refs/heads/foo $rev refs/heads/main EOF - # Protocol v2 supports sending symrefs for refs other than HEAD, so use - # protocol v0 here. - GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref --heads . >actual && - test_cmp expect actual + grep -v "^ref: refs/tags/" <expect.v2 >expect.v0 && + git -c protocol.version=0 ls-remote --symref --heads . >actual.v0 && + test_cmp expect.v0 actual.v0 && + git -c protocol.version=2 ls-remote --symref --heads . >actual.v2 && + test_cmp expect.v2 actual.v2 ' -test_expect_success 'ls-remote --symref omits filtered-out matches' ' - cat >expect <<-EOF && - $rev refs/heads/foo - $rev refs/heads/main +test_expect_success 'indicate no refs in v0 standards-compliant empty remote' ' + # Git does not produce an output like this, but it does match the + # standard and is produced by other implementations like JGit. So + # hard-code the case we care about. + # + # The actual capabilities do not matter; there are none that would + # change how ls-remote behaves. + oid=0000000000000000000000000000000000000000 && + test-tool pkt-line pack >input.q <<-EOF && + $oid capabilities^{}Qcaps-go-here + 0000 EOF - # Protocol v2 supports sending symrefs for refs other than HEAD, so use - # protocol v0 here. - GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref --heads . >actual && - test_cmp expect actual && - GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref . "refs/heads/*" >actual && - test_cmp expect actual -' - -test_lazy_prereq GIT_DAEMON ' - test_bool_env GIT_TEST_GIT_DAEMON true -' + q_to_nul <input.q >input && -# This test spawns a daemon, so run it only if the user would be OK with -# testing with git-daemon. -test_expect_success PIPE,JGIT,GIT_DAEMON 'indicate no refs in standards-compliant empty remote' ' - test_set_port JGIT_DAEMON_PORT && - JGIT_DAEMON_PID= && - git init --bare empty.git && - >empty.git/git-daemon-export-ok && - mkfifo jgit_daemon_output && - { - jgit daemon --port="$JGIT_DAEMON_PORT" . >jgit_daemon_output & - JGIT_DAEMON_PID=$! - } && - test_when_finished kill "$JGIT_DAEMON_PID" && - { - read line && - case $line in - Exporting*) - ;; - *) - echo "Expected: Exporting" && - false;; - esac && - read line && - case $line in - "Listening on"*) - ;; - *) - echo "Expected: Listening on" && - false;; - esac - } <jgit_daemon_output && # --exit-code asks the command to exit with 2 when no # matching refs are found. - test_expect_code 2 git ls-remote --exit-code git://localhost:$JGIT_DAEMON_PORT/empty.git + test_expect_code 2 git ls-remote --exit-code --upload-pack=./cat-input . ' test_expect_success 'ls-remote works outside repository' ' @@ -339,14 +320,14 @@ test_expect_success 'ls-remote works outside repository' ' test_expect_success 'ls-remote --sort fails gracefully outside repository' ' # Use a sort key that requires access to the referenced objects. nongit test_must_fail git ls-remote --sort=authordate "$TRASH_DIRECTORY" 2>err && - test_i18ngrep "^fatal: not a git repository, but the field '\''authordate'\'' requires access to object data" err + test_grep "^fatal: not a git repository, but the field '\''authordate'\'' requires access to object data" err ' test_expect_success 'ls-remote patterns work with all protocol versions' ' git for-each-ref --format="%(objectname) %(refname)" \ refs/heads/main refs/remotes/origin/main >expect && - git -c protocol.version=1 ls-remote . main >actual.v1 && - test_cmp expect actual.v1 && + git -c protocol.version=0 ls-remote . main >actual.v0 && + test_cmp expect actual.v0 && git -c protocol.version=2 ls-remote . main >actual.v2 && test_cmp expect actual.v2 ' @@ -354,10 +335,49 @@ test_expect_success 'ls-remote patterns work with all protocol versions' ' test_expect_success 'ls-remote prefixes work with all protocol versions' ' git for-each-ref --format="%(objectname) %(refname)" \ refs/heads/ refs/tags/ >expect && - git -c protocol.version=1 ls-remote --heads --tags . >actual.v1 && - test_cmp expect actual.v1 && + git -c protocol.version=0 ls-remote --heads --tags . >actual.v0 && + test_cmp expect actual.v0 && git -c protocol.version=2 ls-remote --heads --tags . >actual.v2 && test_cmp expect actual.v2 ' +test_expect_success 'v0 clients can handle multiple symrefs' ' + # Modern versions of Git will not return multiple symref capabilities + # for v0, so we have to hard-code the response. Note that we will + # always use both v0 and object-format=sha1 here, as the hard-coded + # response reflects a server that only supports those. + oid=1234567890123456789012345678901234567890 && + symrefs="symref=refs/remotes/origin/HEAD:refs/remotes/origin/main" && + symrefs="$symrefs symref=HEAD:refs/heads/main" && + + # Likewise we want to make sure our parser is not fooled by the string + # "symref" appearing as part of an earlier cap. But there is no way to + # do that via upload-pack, as arbitrary strings can appear only in a + # "symref" value itself (where we skip past the values as a whole) + # and "agent" (which always appears after "symref", so putting our + # parser in a confused state is less interesting). + caps="some other caps including a-fake-symref-cap" && + + test-tool pkt-line pack >input.q <<-EOF && + $oid HEADQ$caps $symrefs + $oid refs/heads/main + $oid refs/remotes/origin/HEAD + $oid refs/remotes/origin/main + 0000 + EOF + q_to_nul <input.q >input && + + cat >expect <<-EOF && + ref: refs/heads/main HEAD + $oid HEAD + $oid refs/heads/main + ref: refs/remotes/origin/main refs/remotes/origin/HEAD + $oid refs/remotes/origin/HEAD + $oid refs/remotes/origin/main + EOF + + git ls-remote --symref --upload-pack=./cat-input . >actual && + test_cmp expect actual +' + test_done diff --git a/t/t5514-fetch-multiple.sh b/t/t5514-fetch-multiple.sh index 54f422ced3..a95841dc36 100755 --- a/t/t5514-fetch-multiple.sh +++ b/t/t5514-fetch-multiple.sh @@ -58,6 +58,13 @@ test_expect_success 'git fetch --all' ' test_cmp expect output) ' +test_expect_success 'git fetch --all --no-write-fetch-head' ' + (cd test && + rm -f .git/FETCH_HEAD && + git fetch --all --no-write-fetch-head && + test_path_is_missing .git/FETCH_HEAD) +' + test_expect_success 'git fetch --all should continue if a remote has errors' ' (git clone one test2 && cd test2 && @@ -193,8 +200,8 @@ test_expect_success 'parallel' ' test_must_fail env GIT_TRACE="$PWD/trace" \ git fetch --jobs=2 --multiple one two 2>err && grep "preparing to run up to 2 tasks" trace && - test_i18ngrep "could not fetch .one.*128" err && - test_i18ngrep "could not fetch .two.*128" err + test_grep "could not fetch .one.*128" err && + test_grep "could not fetch .two.*128" err ' test_expect_success 'git fetch --multiple --jobs=0 picks a default' ' diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 98a27a2948..2e7c0e1648 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -120,6 +120,17 @@ test_expect_success setup ' ' +for cmd in push fetch +do + for opt in ipv4 ipv6 + do + test_expect_success "reject 'git $cmd --no-$opt'" ' + test_must_fail git $cmd --no-$opt 2>err && + grep "unknown option .no-$opt" err + ' + done +done + test_expect_success 'fetch without wildcard' ' mk_empty testrepo && ( @@ -216,7 +227,7 @@ test_expect_success 'push with negotiation proceeds anyway even if negotiation f GIT_TEST_PROTOCOL_VERSION=0 GIT_TRACE2_EVENT="$(pwd)/event" \ git -c push.negotiate=1 push testrepo refs/heads/main:refs/remotes/origin/main 2>err && grep_wrote 5 event && # 2 commits, 2 trees, 1 blob - test_i18ngrep "push negotiation failed" err + test_grep "push negotiation failed" err ' test_expect_success 'push with negotiation does not attempt to fetch submodules' ' @@ -401,6 +412,11 @@ test_expect_success 'push with ambiguity' ' ' +test_expect_success 'push with onelevel ref' ' + mk_test testrepo heads/main && + test_must_fail git push testrepo HEAD:refs/onelevel +' + test_expect_success 'push with colon-less refspec (1)' ' mk_test testrepo heads/frotz tags/frotz && @@ -898,6 +914,13 @@ test_expect_success 'push --delete refuses empty string' ' test_must_fail git push testrepo --delete "" ' +test_expect_success 'push --delete onelevel refspecs' ' + mk_test testrepo heads/main && + git -C testrepo update-ref refs/onelevel refs/heads/main && + git push testrepo --delete refs/onelevel && + test_must_fail git -C testrepo rev-parse --verify refs/onelevel +' + test_expect_success 'warn on push to HEAD of non-bare repository' ' mk_test testrepo heads/main && ( @@ -1244,7 +1267,7 @@ test_expect_success 'fetch exact SHA1' ' # fetching the hidden object should fail by default test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \ git fetch -v ../testrepo $the_commit:refs/heads/copy 2>err && - test_i18ngrep "Server does not allow request for unadvertised object" err && + test_grep "Server does not allow request for unadvertised object" err && test_must_fail git rev-parse --verify refs/heads/copy && # the server side can allow it to succeed @@ -1346,7 +1369,7 @@ do git fetch ../testrepo/.git $SHA1_3 2>err && # ideally we would insist this be on a "remote error:" # line, but it is racy; see the commit message - test_i18ngrep "not our ref.*$SHA1_3\$" err + test_grep "not our ref.*$SHA1_3\$" err ) ' done @@ -1384,7 +1407,7 @@ test_expect_success 'peeled advertisements are not considered ref tips' ' oid=$(git -C testrepo rev-parse mytag^{commit}) && test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \ git fetch testrepo $oid 2>err && - test_i18ngrep "Server does not allow request for unadvertised object" err + test_grep "Server does not allow request for unadvertised object" err ' test_expect_success 'pushing a specific ref applies remote.$name.push as refmap' ' diff --git a/t/t5517-push-mirror.sh b/t/t5517-push-mirror.sh index a448e169bd..6d4944a728 100755 --- a/t/t5517-push-mirror.sh +++ b/t/t5517-push-mirror.sh @@ -5,6 +5,7 @@ test_description='pushing to a mirror repository' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh D=$(pwd) diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index 0b72112fb1..47534f1062 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -31,7 +31,7 @@ test_pull_autostash_fail () { echo dirty >new_file && git add new_file && test_must_fail git pull "$@" . copy 2>err && - test_i18ngrep -E "uncommitted changes.|overwritten by merge:" err + test_grep -E "uncommitted changes.|overwritten by merge:" err } test_expect_success setup ' @@ -151,7 +151,7 @@ test_expect_success 'fail if wildcard spec does not match any refs' ' echo file >expect && test_cmp expect file && test_must_fail git pull . "refs/nonexisting1/*:refs/nonexisting2/*" 2>err && - test_i18ngrep "no candidates for merging" err && + test_grep "no candidates for merging" err && test_cmp expect file ' @@ -164,7 +164,7 @@ test_expect_success 'fail if no branches specified with non-default remote' ' test_cmp expect file && test_config branch.test.remote origin && test_must_fail git pull test_remote 2>err && - test_i18ngrep "specify a branch on the command line" err && + test_grep "specify a branch on the command line" err && test_cmp expect file ' @@ -176,7 +176,7 @@ test_expect_success 'fail if not on a branch' ' echo file >expect && test_cmp expect file && test_must_fail git pull 2>err && - test_i18ngrep "not currently on a branch" err && + test_grep "not currently on a branch" err && test_cmp expect file ' @@ -189,7 +189,7 @@ test_expect_success 'fail if no configuration for current branch' ' echo file >expect && test_cmp expect file && test_must_fail git pull 2>err && - test_i18ngrep "no tracking information" err && + test_grep "no tracking information" err && test_cmp expect file ' @@ -202,7 +202,7 @@ test_expect_success 'pull --all: fail if no configuration for current branch' ' echo file >expect && test_cmp expect file && test_must_fail git pull --all 2>err && - test_i18ngrep "There is no tracking information" err && + test_grep "There is no tracking information" err && test_cmp expect file ' @@ -214,7 +214,7 @@ test_expect_success 'fail if upstream branch does not exist' ' echo file >expect && test_cmp expect file && test_must_fail git pull 2>err && - test_i18ngrep "no such ref was fetched" err && + test_grep "no such ref was fetched" err && test_cmp expect file ' @@ -248,13 +248,13 @@ test_expect_success 'fail if the index has unresolved entries' ' test_file_not_empty unmerged && cp file expected && test_must_fail git pull . second 2>err && - test_i18ngrep "Pulling is not possible because you have unmerged files." err && + test_grep "Pulling is not possible because you have unmerged files." err && test_cmp expected file && git add file && git ls-files -u >unmerged && test_must_be_empty unmerged && test_must_fail git pull . second 2>err && - test_i18ngrep "You have not concluded your merge" err && + test_grep "You have not concluded your merge" err && test_cmp expected file ' @@ -264,7 +264,7 @@ test_expect_success 'fast-forwards working tree if branch head is updated' ' echo file >expect && test_cmp expect file && git pull . second:third 2>err && - test_i18ngrep "fetch updated the current branch head" err && + test_grep "fetch updated the current branch head" err && echo modified >expect && test_cmp expect file && test_cmp_rev third second @@ -277,7 +277,7 @@ test_expect_success 'fast-forward fails with conflicting work tree' ' test_cmp expect file && echo conflict >file && test_must_fail git pull . second:third 2>err && - test_i18ngrep "Cannot fast-forward your working tree" err && + test_grep "Cannot fast-forward your working tree" err && echo conflict >expect && test_cmp expect file && test_cmp_rev third second @@ -375,7 +375,7 @@ test_expect_success '--rebase with conflicts shows advice' ' test_tick && git commit -m "Create conflict" seq.txt && test_must_fail git pull --rebase . seq 2>err >out && - test_i18ngrep "Resolve all conflicts manually" err + test_grep "Resolve all conflicts manually" err ' test_expect_success 'failed --rebase shows advice' ' @@ -389,14 +389,14 @@ test_expect_success 'failed --rebase shows advice' ' git checkout -f -b fails-to-rebase HEAD^ && test_commit v2-without-cr file "2" file2-lf && test_must_fail git pull --rebase . diverging 2>err >out && - test_i18ngrep "Resolve all conflicts manually" err + test_grep "Resolve all conflicts manually" err ' test_expect_success '--rebase fails with multiple branches' ' git reset --hard before-rebase && test_must_fail git pull --rebase . copy main 2>err && test_cmp_rev HEAD before-rebase && - test_i18ngrep "Cannot rebase onto multiple branches" err && + test_grep "Cannot rebase onto multiple branches" err && echo modified >expect && git show HEAD:file >actual && test_cmp expect actual @@ -520,7 +520,7 @@ test_expect_success 'pull --rebase warns on --verify-signatures' ' echo new >expect && git show HEAD:file2 >actual && test_cmp expect actual && - test_i18ngrep "ignoring --verify-signatures for rebase" err + test_grep "ignoring --verify-signatures for rebase" err ' test_expect_success 'pull --rebase does not warn on --no-verify-signatures' ' @@ -530,7 +530,7 @@ test_expect_success 'pull --rebase does not warn on --no-verify-signatures' ' echo new >expect && git show HEAD:file2 >actual && test_cmp expect actual && - test_i18ngrep ! "verify-signatures" err + test_grep ! "verify-signatures" err ' # add a feature branch, keep-merge, that is merged into main, so the @@ -740,7 +740,7 @@ test_expect_success 'pull --rebase fails on unborn branch with staged changes' ' test_cmp expect actual && git show :staged-file >actual && test_cmp expect actual && - test_i18ngrep "unborn branch with changes added to the index" err + test_grep "unborn branch with changes added to the index" err ) ' diff --git a/t/t5521-pull-options.sh b/t/t5521-pull-options.sh index 264de29c35..db00c4336b 100755 --- a/t/t5521-pull-options.sh +++ b/t/t5521-pull-options.sh @@ -5,6 +5,7 @@ test_description='pull options' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' @@ -93,7 +94,7 @@ test_expect_success 'git pull --no-write-fetch-head fails' ' (cd clonedwfh && git init && test_expect_code 129 git pull --no-write-fetch-head "../parent" >out 2>err && test_must_be_empty out && - test_i18ngrep "no-write-fetch-head" err) + test_grep "no-write-fetch-head" err) ' test_expect_success 'git pull --force' ' @@ -142,7 +143,7 @@ test_expect_success 'git pull --dry-run' ' cd clonedry && git pull --dry-run ../parent && test_path_is_missing .git/FETCH_HEAD && - test_path_is_missing .git/refs/heads/main && + test_ref_missing refs/heads/main && test_path_is_missing .git/index && test_path_is_missing file ) @@ -156,7 +157,7 @@ test_expect_success 'git pull --all --dry-run' ' git remote add origin ../parent && git pull --all --dry-run && test_path_is_missing .git/FETCH_HEAD && - test_path_is_missing .git/refs/remotes/origin/main && + test_ref_missing refs/remotes/origin/main && test_path_is_missing .git/index && test_path_is_missing file ) diff --git a/t/t5522-pull-symlink.sh b/t/t5522-pull-symlink.sh index 394bc60cb8..cc5496e28f 100755 --- a/t/t5522-pull-symlink.sh +++ b/t/t5522-pull-symlink.sh @@ -79,7 +79,9 @@ test_expect_success SYMLINKS 'pushing from symlinked subdir' ' git commit -m push ./file && git push ) && - test push = $(git show HEAD:subdir/file) + echo push >expect && + git show HEAD:subdir/file >actual && + test_cmp expect actual ' test_done diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh index c9acc07635..1f859ade16 100755 --- a/t/t5523-push-upstream.sh +++ b/t/t5523-push-upstream.sh @@ -61,12 +61,20 @@ test_expect_success 'push -u :topic_2' ' check_config topic_2 upstream refs/heads/other2 ' -test_expect_success 'push -u --all' ' +test_expect_success 'push -u --all(the same behavior with--branches)' ' git branch all1 && git branch all2 && git push -u --all && check_config all1 upstream refs/heads/all1 && - check_config all2 upstream refs/heads/all2 + check_config all2 upstream refs/heads/all2 && + git config --get-regexp branch.all* > expect && + git config --remove-section branch.all1 && + git config --remove-section branch.all2 && + git push -u --branches && + check_config all1 upstream refs/heads/all1 && + check_config all2 upstream refs/heads/all2 && + git config --get-regexp branch.all* > actual && + test_cmp expect actual ' test_expect_success 'push -u HEAD' ' @@ -79,7 +87,7 @@ test_expect_success TTY 'progress messages go to tty' ' ensure_fresh_upstream && test_terminal git push -u upstream main >out 2>err && - test_i18ngrep "Writing objects" err + test_grep "Writing objects" err ' test_expect_success 'progress messages do not go to non-tty' ' @@ -87,7 +95,7 @@ test_expect_success 'progress messages do not go to non-tty' ' # skip progress messages, since stderr is non-tty git push -u upstream main >out 2>err && - test_i18ngrep ! "Writing objects" err + test_grep ! "Writing objects" err ' test_expect_success 'progress messages go to non-tty (forced)' ' @@ -95,22 +103,22 @@ test_expect_success 'progress messages go to non-tty (forced)' ' # force progress messages to stderr, even though it is non-tty git push -u --progress upstream main >out 2>err && - test_i18ngrep "Writing objects" err + test_grep "Writing objects" err ' test_expect_success TTY 'push -q suppresses progress' ' ensure_fresh_upstream && test_terminal git push -u -q upstream main >out 2>err && - test_i18ngrep ! "Writing objects" err + test_grep ! "Writing objects" err ' test_expect_success TTY 'push --no-progress suppresses progress' ' ensure_fresh_upstream && test_terminal git push -u --no-progress upstream main >out 2>err && - test_i18ngrep ! "Unpacking objects" err && - test_i18ngrep ! "Writing objects" err + test_grep ! "Unpacking objects" err && + test_grep ! "Writing objects" err ' test_expect_success TTY 'quiet push' ' diff --git a/t/t5525-fetch-tagopt.sh b/t/t5525-fetch-tagopt.sh index 45815f7378..3a28f1ded5 100755 --- a/t/t5525-fetch-tagopt.sh +++ b/t/t5525-fetch-tagopt.sh @@ -2,6 +2,7 @@ test_description='tagopt variable affects "git fetch" and is overridden by commandline.' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh setup_clone () { diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh index b9546ef8e5..7ab220fa31 100755 --- a/t/t5526-fetch-submodules.sh +++ b/t/t5526-fetch-submodules.sh @@ -167,6 +167,19 @@ test_expect_success "fetch --recurse-submodules recurses into submodules" ' verify_fetch_result actual.err ' +test_expect_success "fetch --recurse-submodules honors --no-write-fetch-head" ' + ( + cd downstream && + git submodule foreach --recursive \ + sh -c "cd \"\$(git rev-parse --git-dir)\" && rm -f FETCH_HEAD" && + + git fetch --recurse-submodules --no-write-fetch-head && + + git submodule foreach --recursive \ + sh -c "cd \"\$(git rev-parse --git-dir)\" && ! test -f FETCH_HEAD" + ) +' + test_expect_success "submodule.recurse option triggers recursive fetch" ' add_submodule_commits && ( @@ -758,7 +771,7 @@ test_expect_success 'fetching submodule into a broken repository' ' git -C dst fetch --recurse-submodules && # Break the receiving submodule - rm -f dst/sub/.git/HEAD && + test-tool -C dst/sub ref-store main delete-refs REF_NO_DEREF msg HEAD && # NOTE: without the fix the following tests will recurse forever! # They should terminate with an error. @@ -1167,4 +1180,17 @@ test_expect_success 'fetch --all with --recurse-submodules with multiple' ' test_line_count = 2 fetch-subs ' +test_expect_success "fetch --all with --no-recurse-submodules only fetches superproject" ' + test_when_finished "rm -rf src_clone" && + + git clone --recurse-submodules src src_clone && + ( + cd src_clone && + git remote add secondary ../src && + git config submodule.recurse true && + git fetch --all --no-recurse-submodules 2>../fetch-log + ) && + ! grep "Fetching submodule" fetch-log +' + test_done diff --git a/t/t5528-push-default.sh b/t/t5528-push-default.sh index 284e20fefd..14f7eced9a 100755 --- a/t/t5528-push-default.sh +++ b/t/t5528-push-default.sh @@ -179,7 +179,7 @@ test_expect_success 'push from/to new branch succeeds with simple if push.autoSe test_expect_success '"matching" fails if none match' ' git init --bare empty && test_must_fail git push empty : 2>actual && - test_i18ngrep "Perhaps you should specify a branch" actual + test_grep "Perhaps you should specify a branch" actual ' test_expect_success 'push ambiguously named branch with upstream, matching and simple' ' diff --git a/t/t5530-upload-pack-error.sh b/t/t5530-upload-pack-error.sh index 7c1460eaa9..7172780d55 100755 --- a/t/t5530-upload-pack-error.sh +++ b/t/t5530-upload-pack-error.sh @@ -2,6 +2,7 @@ test_description='errors in upload-pack' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh D=$(pwd) @@ -35,8 +36,8 @@ test_expect_success 'upload-pack fails due to error in pack-objects packing' ' printf "%04xwant %s\n00000009done\n0000" \ $(($hexsz + 10)) $head >input && test_must_fail git upload-pack . <input >/dev/null 2>output.err && - test_i18ngrep "unable to read" output.err && - test_i18ngrep "pack-objects died" output.err + test_grep "unable to read" output.err && + test_grep "pack-objects died" output.err ' test_expect_success 'corrupt repo differently' ' diff --git a/t/t5531-deep-submodule-push.sh b/t/t5531-deep-submodule-push.sh index 302e4cbdba..f3fff55744 100755 --- a/t/t5531-deep-submodule-push.sh +++ b/t/t5531-deep-submodule-push.sh @@ -311,7 +311,7 @@ test_expect_success 'submodule entry pointing at a tag is error' ' git -C work commit -m "bad commit" && test_when_finished "git -C work reset --hard HEAD^" && test_must_fail git -C work push --recurse-submodules=on-demand ../pub.git main 2>err && - test_i18ngrep "is a tag, not a commit" err + test_grep "is a tag, not a commit" err ' test_expect_success 'push fails if recurse submodules option passed as yes' ' diff --git a/t/t5534-push-signed.sh b/t/t5534-push-signed.sh index 7c0a148e73..b4bc24691c 100755 --- a/t/t5534-push-signed.sh +++ b/t/t5534-push-signed.sh @@ -68,13 +68,13 @@ test_expect_success 'talking with a receiver without push certificate support' ' test_expect_success 'push --signed fails with a receiver without push certificate support' ' prepare_dst && test_must_fail git push --signed dst noop ff +noff 2>err && - test_i18ngrep "the receiving end does not support" err + test_grep "the receiving end does not support" err ' test_expect_success 'push --signed=1 is accepted' ' prepare_dst && test_must_fail git push --signed=1 dst noop ff +noff 2>err && - test_i18ngrep "the receiving end does not support" err + test_grep "the receiving end does not support" err ' test_expect_success GPG 'no certificate for a signed push with no update' ' @@ -378,7 +378,7 @@ test_expect_success GPG 'failed atomic push does not execute GPG' ' --signed --atomic --porcelain \ dst noop ff noff >out 2>err && - test_i18ngrep ! "gpg failed to sign" err && + test_grep ! "gpg failed to sign" err && cat >expect <<-EOF && To dst = refs/heads/noop:refs/heads/noop [up to date] diff --git a/t/t5536-fetch-conflicts.sh b/t/t5536-fetch-conflicts.sh index 91f28c2f78..23bf696170 100755 --- a/t/t5536-fetch-conflicts.sh +++ b/t/t5536-fetch-conflicts.sh @@ -40,7 +40,7 @@ test_expect_success 'fetch conflict: config vs. config' ' "+refs/heads/branch2:refs/remotes/origin/branch1" && ( cd ccc && test_must_fail git fetch origin 2>error && - test_i18ngrep "fatal: Cannot fetch both refs/heads/branch1 and refs/heads/branch2 to refs/remotes/origin/branch1" error + test_grep "fatal: Cannot fetch both refs/heads/branch1 and refs/heads/branch2 to refs/remotes/origin/branch1" error ) ' @@ -67,7 +67,7 @@ test_expect_success 'fetch conflict: arg vs. arg' ' test_must_fail git fetch origin \ refs/heads/*:refs/remotes/origin/* \ refs/heads/branch2:refs/remotes/origin/branch1 2>error && - test_i18ngrep "fatal: Cannot fetch both refs/heads/branch1 and refs/heads/branch2 to refs/remotes/origin/branch1" error + test_grep "fatal: Cannot fetch both refs/heads/branch1 and refs/heads/branch2 to refs/remotes/origin/branch1" error ) ' @@ -78,8 +78,8 @@ test_expect_success 'fetch conflict: criss-cross args' ' git fetch origin \ refs/heads/branch1:refs/remotes/origin/branch2 \ refs/heads/branch2:refs/remotes/origin/branch1 2>error && - test_i18ngrep "warning: refs/remotes/origin/branch1 usually tracks refs/heads/branch1, not refs/heads/branch2" error && - test_i18ngrep "warning: refs/remotes/origin/branch2 usually tracks refs/heads/branch2, not refs/heads/branch1" error + test_grep "warning: refs/remotes/origin/branch1 usually tracks refs/heads/branch1, not refs/heads/branch2" error && + test_grep "warning: refs/remotes/origin/branch2 usually tracks refs/heads/branch2, not refs/heads/branch1" error ) ' diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh index d0211cd8be..df758e187d 100755 --- a/t/t5541-http-push-smart.sh +++ b/t/t5541-http-push-smart.sh @@ -153,7 +153,7 @@ test_expect_success 'push fails for non-fast-forward refs unmatched by remote he ' test_expect_success 'push fails for non-fast-forward refs unmatched by remote helper: our output' ' - test_i18ngrep "Updates were rejected because" \ + test_grep "Updates were rejected because" \ output ' @@ -297,7 +297,7 @@ test_expect_success TTY 'push shows progress when stderr is a tty' ' cd "$ROOT_PATH"/test_repo_clone && test_commit noisy && test_terminal git push >output 2>&1 && - test_i18ngrep "^Writing objects" output + test_grep "^Writing objects" output ' test_expect_success TTY 'push --quiet silences status and progress' ' @@ -311,16 +311,16 @@ test_expect_success TTY 'push --no-progress silences progress but not status' ' cd "$ROOT_PATH"/test_repo_clone && test_commit no-progress && test_terminal git push --no-progress >output 2>&1 && - test_i18ngrep "^To http" output && - test_i18ngrep ! "^Writing objects" output + test_grep "^To http" output && + test_grep ! "^Writing objects" output ' test_expect_success 'push --progress shows progress to non-tty' ' cd "$ROOT_PATH"/test_repo_clone && test_commit progress && git push --progress >output 2>&1 && - test_i18ngrep "^To http" output && - test_i18ngrep "^Writing objects" output + test_grep "^To http" output && + test_grep "^Writing objects" output ' test_expect_success 'http push gives sane defaults to reflog' ' @@ -489,10 +489,10 @@ test_expect_success 'colorize errors/hints' ' -c color.push=always \ push origin origin/main^:main 2>act && test_decode_color <act >decoded && - test_i18ngrep "<RED>.*rejected.*<RESET>" decoded && - test_i18ngrep "<RED>error: failed to push some refs" decoded && - test_i18ngrep "<YELLOW>hint: " decoded && - test_i18ngrep ! "^hint: " decoded + test_grep "<RED>.*rejected.*<RESET>" decoded && + test_grep "<RED>error: failed to push some refs" decoded && + test_grep "<YELLOW>hint: " decoded && + test_grep ! "^hint: " decoded ' test_expect_success 'report error server does not provide ref status' ' diff --git a/t/t5543-atomic-push.sh b/t/t5543-atomic-push.sh index 70431122a4..04b47ad84a 100755 --- a/t/t5543-atomic-push.sh +++ b/t/t5543-atomic-push.sh @@ -117,7 +117,10 @@ test_expect_success 'atomic push fails if one branch fails' ' test_commit five && git checkout main && test_commit six && - test_must_fail git push --atomic --all up + test_must_fail git push --atomic --all up >output-all 2>&1 && + # --all and --branches have the same behavior when be combined with --atomic + test_must_fail git push --atomic --branches up >output-branches 2>&1 && + test_cmp output-all output-branches ) && test_refs main HEAD@{7} && test_refs second HEAD@{4} diff --git a/t/t5545-push-options.sh b/t/t5545-push-options.sh index a158e7d2c0..fb13549da7 100755 --- a/t/t5545-push-options.sh +++ b/t/t5545-push-options.sh @@ -252,7 +252,7 @@ test_expect_success 'push option denied properly by http server' ' mk_http_pair false && test_commit -C test_http_clone one && test_must_fail git -C test_http_clone push --push-option=asdf origin main 2>actual && - test_i18ngrep "the receiving end does not support push options" actual && + test_grep "the receiving end does not support push options" actual && git -C test_http_clone push origin main ' diff --git a/t/t5546-receive-limits.sh b/t/t5546-receive-limits.sh index eed3c9d81a..9fc9ba552f 100755 --- a/t/t5546-receive-limits.sh +++ b/t/t5546-receive-limits.sh @@ -9,10 +9,26 @@ TEST_PASSES_SANITIZE_LEAK=true # When the limit is 1, `git receive-pack` will call `git index-pack`. # When the limit is 10000, `git receive-pack` will call `git unpack-objects`. +validate_store_type () { + git -C dest count-objects -v >actual && + case "$store_type" in + index) + grep "^count: 0$" actual ;; + unpack) + grep "^packs: 0$" actual ;; + esac || { + echo "store_type is $store_type" + cat actual + false; + } +} + test_pack_input_limit () { - case "$1" in - index) unpack_limit=1 ;; - unpack) unpack_limit=10000 ;; + store_type=$1 + + case "$store_type" in + index) unpack_limit=1 other_limit=10000 ;; + unpack) unpack_limit=10000 other_limit=1 ;; esac test_expect_success 'prepare destination repository' ' @@ -43,6 +59,19 @@ test_pack_input_limit () { git --git-dir=dest config receive.maxInputSize 0 && git push dest HEAD ' + + test_expect_success 'prepare destination repository (once more)' ' + rm -fr dest && + git --bare init dest + ' + + test_expect_success 'receive trumps transfer' ' + git --git-dir=dest config receive.unpacklimit "$unpack_limit" && + git --git-dir=dest config transfer.unpacklimit "$other_limit" && + git push dest HEAD && + validate_store_type + ' + } test_expect_success "create known-size (1024 bytes) commit" ' diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh index 8f182a3cbf..e444b30bf6 100755 --- a/t/t5550-http-fetch-dumb.sh +++ b/t/t5550-http-fetch-dumb.sh @@ -376,7 +376,7 @@ test_expect_success 'git client send an empty Accept-Language' ' test_expect_success 'remote-http complains cleanly about malformed urls' ' test_must_fail git remote-http http::/example.com/repo.git 2>stderr && - test_i18ngrep "url has no scheme" stderr + test_grep "url has no scheme" stderr ' # NEEDSWORK: Writing commands to git-remote-curl can race against the latter @@ -385,7 +385,7 @@ test_expect_success 'remote-http complains cleanly about malformed urls' ' test_expect_success 'remote-http complains cleanly about empty scheme' ' test_must_fail ok=sigpipe git ls-remote \ http::${HTTPD_URL#http}/dumb/repo.git 2>stderr && - test_i18ngrep "url has no scheme" stderr + test_grep "url has no scheme" stderr ' test_expect_success 'redirects can be forbidden/allowed' ' @@ -397,7 +397,7 @@ test_expect_success 'redirects can be forbidden/allowed' ' test_expect_success 'redirects are reported to stderr' ' # just look for a snippet of the redirected-to URL - test_i18ngrep /dumb/ stderr + test_grep /dumb/ stderr ' test_expect_success 'non-initial redirects can be forbidden' ' @@ -466,7 +466,7 @@ test_expect_success 'can redirect through non-"info/refs?service=git-upload-pack test_expect_success 'print HTTP error when any intermediate redirect throws error' ' test_must_fail git clone "$HTTPD_URL/redir-to/502" 2> stderr && - test_i18ngrep "unable to access.*/redir-to/502" stderr + test_grep "unable to access.*/redir-to/502" stderr ' test_expect_success 'fetching via http alternates works' ' diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh index 0908534f25..e069737b80 100755 --- a/t/t5551-http-fetch-smart.sh +++ b/t/t5551-http-fetch-smart.sh @@ -275,7 +275,7 @@ test_expect_success 'GIT_SMART_HTTP can disable smart http' ' test_expect_success 'invalid Content-Type rejected' ' test_must_fail git clone $HTTPD_URL/broken_smart/repo.git 2>actual && - test_i18ngrep "not valid:" actual + test_grep "not valid:" actual ' test_expect_success 'create namespaced refs' ' @@ -359,7 +359,9 @@ create_tags () { # now assign tags to all the dangling commits we created above tag=$(perl -e "print \"bla\" x 30") && - sed -e "s|^:\([^ ]*\) \(.*\)$|\2 refs/tags/$tag-\1|" <marks >>packed-refs + sed -e "s|^:\([^ ]*\) \(.*\)$|create refs/tags/$tag-\1 \2|" <marks >input && + git update-ref --stdin <input && + rm input } test_expect_success 'create 2,000 tags in the repo' ' @@ -558,7 +560,7 @@ test_expect_success 'GIT_TRACE_CURL_NO_DATA prevents data from being traced' ' test_expect_success 'server-side error detected' ' test_must_fail git clone $HTTPD_URL/error_smart/repo.git 2>actual && - test_i18ngrep "server-side error" actual + test_grep "server-side error" actual ' test_expect_success 'http auth remembers successful credentials' ' @@ -611,6 +613,33 @@ test_expect_success 'client falls back from v2 to v0 to match server' ' grep symref=HEAD:refs/heads/ trace ' +test_expect_success 'create empty http-accessible SHA-256 repository' ' + mkdir "$HTTPD_DOCUMENT_ROOT_PATH/sha256.git" && + (cd "$HTTPD_DOCUMENT_ROOT_PATH/sha256.git" && + git --bare init --object-format=sha256 + ) +' + +test_expect_success 'clone empty SHA-256 repository with protocol v2' ' + rm -fr sha256 && + echo sha256 >expected && + git -c protocol.version=2 clone "$HTTPD_URL/smart/sha256.git" && + git -C sha256 rev-parse --show-object-format >actual && + test_cmp actual expected && + git ls-remote "$HTTPD_URL/smart/sha256.git" >actual && + test_must_be_empty actual +' + +test_expect_success 'clone empty SHA-256 repository with protocol v0' ' + rm -fr sha256 && + echo sha256 >expected && + GIT_TRACE=1 GIT_TRACE_PACKET=1 git -c protocol.version=0 clone "$HTTPD_URL/smart/sha256.git" && + git -C sha256 rev-parse --show-object-format >actual && + test_cmp actual expected && + git ls-remote "$HTTPD_URL/smart/sha256.git" >actual && + test_must_be_empty actual +' + test_expect_success 'passing hostname resolution information works' ' BOGUS_HOST=gitbogusexamplehost.invalid && BOGUS_HTTPD_URL=$HTTPD_PROTO://$BOGUS_HOST:$LIB_HTTPD_PORT && diff --git a/t/t5552-skipping-fetch-negotiator.sh b/t/t5552-skipping-fetch-negotiator.sh index 165427d57e..b55a9f65e6 100755 --- a/t/t5552-skipping-fetch-negotiator.sh +++ b/t/t5552-skipping-fetch-negotiator.sh @@ -3,6 +3,22 @@ test_description='test skipping fetch negotiator' . ./test-lib.sh +test_expect_success 'fetch.negotiationalgorithm config' ' + test_when_finished "rm -rf repo" && + git init repo && + cat >repo/.git/config <<-\EOF && + [fetch] + negotiationAlgorithm + EOF + cat >expect <<-\EOF && + error: missing value for '\''fetch.negotiationalgorithm'\'' + fatal: bad config variable '\''fetch.negotiationalgorithm'\'' in file '\''.git/config'\'' at line 2 + EOF + test_expect_code 128 git -C repo fetch >out 2>actual && + test_must_be_empty out && + test_cmp expect actual +' + have_sent () { while test "$#" -ne 0 do diff --git a/t/t5558-clone-bundle-uri.sh b/t/t5558-clone-bundle-uri.sh index afd56926c5..996a08e90c 100755 --- a/t/t5558-clone-bundle-uri.sh +++ b/t/t5558-clone-bundle-uri.sh @@ -1018,6 +1018,40 @@ test_expect_success 'creationToken heuristic with failed downloads (fetch)' ' test_cmp expect refs ' +test_expect_success 'bundles are downloaded once during fetch --all' ' + test_when_finished rm -rf download-* trace*.txt fetch-mult && + + cat >"$HTTPD_DOCUMENT_ROOT_PATH/bundle-list" <<-EOF && + [bundle] + version = 1 + mode = all + heuristic = creationToken + + [bundle "bundle-1"] + uri = bundle-1.bundle + creationToken = 1 + + [bundle "bundle-2"] + uri = bundle-2.bundle + creationToken = 2 + + [bundle "bundle-3"] + uri = bundle-3.bundle + creationToken = 3 + EOF + + git clone --single-branch --branch=left \ + --bundle-uri="$HTTPD_URL/bundle-list" \ + "$HTTPD_URL/smart/fetch.git" fetch-mult && + git -C fetch-mult remote add dup1 "$HTTPD_URL/smart/fetch.git" && + git -C fetch-mult remote add dup2 "$HTTPD_URL/smart/fetch.git" && + + GIT_TRACE2_EVENT="$(pwd)/trace-mult.txt" \ + git -C fetch-mult fetch --all && + grep "\"child_start\".*\"git-remote-https\",\"$HTTPD_URL/bundle-list\"" \ + trace-mult.txt >bundle-fetches && + test_line_count = 1 bundle-fetches +' # Do not add tests here unless they use the HTTP server, as they will # not run unless the HTTP dependencies exist. diff --git a/t/t5562/invoke-with-content-length.pl b/t/t5562/invoke-with-content-length.pl index 718dd9b49d..9babb9a375 100644 --- a/t/t5562/invoke-with-content-length.pl +++ b/t/t5562/invoke-with-content-length.pl @@ -1,4 +1,4 @@ -use 5.008; +use 5.008001; use strict; use warnings; diff --git a/t/t5563-simple-http-auth.sh b/t/t5563-simple-http-auth.sh new file mode 100755 index 0000000000..ab8a721ccc --- /dev/null +++ b/t/t5563-simple-http-auth.sh @@ -0,0 +1,329 @@ +#!/bin/sh + +test_description='test http auth header and credential helper interop' + +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-httpd.sh + +enable_cgipassauth +if ! test_have_prereq CGIPASSAUTH +then + skip_all="no CGIPassAuth support" + test_done +fi +start_httpd + +test_expect_success 'setup_credential_helper' ' + mkdir "$TRASH_DIRECTORY/bin" && + PATH=$PATH:"$TRASH_DIRECTORY/bin" && + export PATH && + + CREDENTIAL_HELPER="$TRASH_DIRECTORY/bin/git-credential-test-helper" && + write_script "$CREDENTIAL_HELPER" <<-\EOF + cmd=$1 + teefile=$cmd-query.cred + catfile=$cmd-reply.cred + sed -n -e "/^$/q" -e "p" >>$teefile + if test "$cmd" = "get" + then + cat $catfile + fi + EOF +' + +set_credential_reply () { + cat >"$TRASH_DIRECTORY/$1-reply.cred" +} + +expect_credential_query () { + cat >"$TRASH_DIRECTORY/$1-expect.cred" && + test_cmp "$TRASH_DIRECTORY/$1-expect.cred" \ + "$TRASH_DIRECTORY/$1-query.cred" +} + +per_test_cleanup () { + rm -f *.cred && + rm -f "$HTTPD_ROOT_PATH"/custom-auth.valid \ + "$HTTPD_ROOT_PATH"/custom-auth.challenge +} + +test_expect_success 'setup repository' ' + test_commit foo && + git init --bare "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + git push --mirror "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" +' + +test_expect_success 'access using basic auth' ' + test_when_finished "per_test_cleanup" && + + set_credential_reply get <<-EOF && + username=alice + password=secret-passwd + EOF + + # Basic base64(alice:secret-passwd) + cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF && + Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== + EOF + + cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF && + WWW-Authenticate: Basic realm="example.com" + EOF + + test_config_global credential.helper test-helper && + git ls-remote "$HTTPD_URL/custom_auth/repo.git" && + + expect_credential_query get <<-EOF && + protocol=http + host=$HTTPD_DEST + wwwauth[]=Basic realm="example.com" + EOF + + expect_credential_query store <<-EOF + protocol=http + host=$HTTPD_DEST + username=alice + password=secret-passwd + EOF +' + +test_expect_success 'access using basic auth invalid credentials' ' + test_when_finished "per_test_cleanup" && + + set_credential_reply get <<-EOF && + username=baduser + password=wrong-passwd + EOF + + # Basic base64(alice:secret-passwd) + cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF && + Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== + EOF + + cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF && + WWW-Authenticate: Basic realm="example.com" + EOF + + test_config_global credential.helper test-helper && + test_must_fail git ls-remote "$HTTPD_URL/custom_auth/repo.git" && + + expect_credential_query get <<-EOF && + protocol=http + host=$HTTPD_DEST + wwwauth[]=Basic realm="example.com" + EOF + + expect_credential_query erase <<-EOF + protocol=http + host=$HTTPD_DEST + username=baduser + password=wrong-passwd + wwwauth[]=Basic realm="example.com" + EOF +' + +test_expect_success 'access using basic auth with extra challenges' ' + test_when_finished "per_test_cleanup" && + + set_credential_reply get <<-EOF && + username=alice + password=secret-passwd + EOF + + # Basic base64(alice:secret-passwd) + cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF && + Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== + EOF + + cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF && + WWW-Authenticate: FooBar param1="value1" param2="value2" + WWW-Authenticate: Bearer authorize_uri="id.example.com" p=1 q=0 + WWW-Authenticate: Basic realm="example.com" + EOF + + test_config_global credential.helper test-helper && + git ls-remote "$HTTPD_URL/custom_auth/repo.git" && + + expect_credential_query get <<-EOF && + protocol=http + host=$HTTPD_DEST + wwwauth[]=FooBar param1="value1" param2="value2" + wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0 + wwwauth[]=Basic realm="example.com" + EOF + + expect_credential_query store <<-EOF + protocol=http + host=$HTTPD_DEST + username=alice + password=secret-passwd + EOF +' + +test_expect_success 'access using basic auth mixed-case wwwauth header name' ' + test_when_finished "per_test_cleanup" && + + set_credential_reply get <<-EOF && + username=alice + password=secret-passwd + EOF + + # Basic base64(alice:secret-passwd) + cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF && + Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== + EOF + + cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF && + www-authenticate: foobar param1="value1" param2="value2" + WWW-AUTHENTICATE: BEARER authorize_uri="id.example.com" p=1 q=0 + WwW-aUtHeNtIcAtE: baSiC realm="example.com" + EOF + + test_config_global credential.helper test-helper && + git ls-remote "$HTTPD_URL/custom_auth/repo.git" && + + expect_credential_query get <<-EOF && + protocol=http + host=$HTTPD_DEST + wwwauth[]=foobar param1="value1" param2="value2" + wwwauth[]=BEARER authorize_uri="id.example.com" p=1 q=0 + wwwauth[]=baSiC realm="example.com" + EOF + + expect_credential_query store <<-EOF + protocol=http + host=$HTTPD_DEST + username=alice + password=secret-passwd + EOF +' + +test_expect_success 'access using basic auth with wwwauth header continuations' ' + test_when_finished "per_test_cleanup" && + + set_credential_reply get <<-EOF && + username=alice + password=secret-passwd + EOF + + # Basic base64(alice:secret-passwd) + cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF && + Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== + EOF + + # Note that leading and trailing whitespace is important to correctly + # simulate a continuation/folded header. + cat >"$HTTPD_ROOT_PATH/custom-auth.challenge" <<-EOF && + WWW-Authenticate: FooBar param1="value1" + param2="value2" + WWW-Authenticate: Bearer authorize_uri="id.example.com" + p=1 + q=0 + WWW-Authenticate: Basic realm="example.com" + EOF + + test_config_global credential.helper test-helper && + git ls-remote "$HTTPD_URL/custom_auth/repo.git" && + + expect_credential_query get <<-EOF && + protocol=http + host=$HTTPD_DEST + wwwauth[]=FooBar param1="value1" param2="value2" + wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0 + wwwauth[]=Basic realm="example.com" + EOF + + expect_credential_query store <<-EOF + protocol=http + host=$HTTPD_DEST + username=alice + password=secret-passwd + EOF +' + +test_expect_success 'access using basic auth with wwwauth header empty continuations' ' + test_when_finished "per_test_cleanup" && + + set_credential_reply get <<-EOF && + username=alice + password=secret-passwd + EOF + + # Basic base64(alice:secret-passwd) + cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF && + Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== + EOF + + CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" && + + # Note that leading and trailing whitespace is important to correctly + # simulate a continuation/folded header. + printf "WWW-Authenticate: FooBar param1=\"value1\"\r\n" >"$CHALLENGE" && + printf " \r\n" >>"$CHALLENGE" && + printf " param2=\"value2\"\r\n" >>"$CHALLENGE" && + printf "WWW-Authenticate: Bearer authorize_uri=\"id.example.com\"\r\n" >>"$CHALLENGE" && + printf " p=1\r\n" >>"$CHALLENGE" && + printf " \r\n" >>"$CHALLENGE" && + printf " q=0\r\n" >>"$CHALLENGE" && + printf "WWW-Authenticate: Basic realm=\"example.com\"\r\n" >>"$CHALLENGE" && + + test_config_global credential.helper test-helper && + git ls-remote "$HTTPD_URL/custom_auth/repo.git" && + + expect_credential_query get <<-EOF && + protocol=http + host=$HTTPD_DEST + wwwauth[]=FooBar param1="value1" param2="value2" + wwwauth[]=Bearer authorize_uri="id.example.com" p=1 q=0 + wwwauth[]=Basic realm="example.com" + EOF + + expect_credential_query store <<-EOF + protocol=http + host=$HTTPD_DEST + username=alice + password=secret-passwd + EOF +' + +test_expect_success 'access using basic auth with wwwauth header mixed line-endings' ' + test_when_finished "per_test_cleanup" && + + set_credential_reply get <<-EOF && + username=alice + password=secret-passwd + EOF + + # Basic base64(alice:secret-passwd) + cat >"$HTTPD_ROOT_PATH/custom-auth.valid" <<-EOF && + Basic YWxpY2U6c2VjcmV0LXBhc3N3ZA== + EOF + + CHALLENGE="$HTTPD_ROOT_PATH/custom-auth.challenge" && + + # Note that leading and trailing whitespace is important to correctly + # simulate a continuation/folded header. + printf "WWW-Authenticate: FooBar param1=\"value1\"\r\n" >"$CHALLENGE" && + printf " \r\n" >>"$CHALLENGE" && + printf "\tparam2=\"value2\"\r\n" >>"$CHALLENGE" && + printf "WWW-Authenticate: Basic realm=\"example.com\"" >>"$CHALLENGE" && + + test_config_global credential.helper test-helper && + git ls-remote "$HTTPD_URL/custom_auth/repo.git" && + + expect_credential_query get <<-EOF && + protocol=http + host=$HTTPD_DEST + wwwauth[]=FooBar param1="value1" param2="value2" + wwwauth[]=Basic realm="example.com" + EOF + + expect_credential_query store <<-EOF + protocol=http + host=$HTTPD_DEST + username=alice + password=secret-passwd + EOF +' + +test_done diff --git a/t/t5570-git-daemon.sh b/t/t5570-git-daemon.sh index 1131503b76..f9a9bf9503 100755 --- a/t/t5570-git-daemon.sh +++ b/t/t5570-git-daemon.sh @@ -10,9 +10,9 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME start_git_daemon check_verbose_connect () { - test_i18ngrep -F "Looking up 127.0.0.1 ..." stderr && - test_i18ngrep -F "Connecting to 127.0.0.1 (port " stderr && - test_i18ngrep -F "done." stderr + test_grep -F "Looking up 127.0.0.1 ..." stderr && + test_grep -F "Connecting to 127.0.0.1 (port " stderr && + test_grep -F "done." stderr } test_expect_success 'setup repository' ' @@ -108,7 +108,7 @@ test_expect_success 'fetch notices corrupt idx' ' test_expect_success 'client refuses to ask for repo with newline' ' test_must_fail git clone "$GIT_DAEMON_URL/repo$LF.git" dst 2>stderr && - test_i18ngrep newline.is.forbidden stderr + test_grep newline.is.forbidden stderr ' test_remote_error() @@ -148,7 +148,7 @@ test_remote_error() fi test_must_fail git "$cmd" "$GIT_DAEMON_URL/$repo" "$@" 2>output && - test_i18ngrep "fatal: remote error: $msg: /$repo" output && + test_grep "fatal: remote error: $msg: /$repo" output && ret=$? chmod +x "$GIT_DAEMON_DOCUMENT_ROOT_PATH/repo.git" (exit $ret) diff --git a/t/t5571-pre-push-hook.sh b/t/t5571-pre-push-hook.sh index a11b20e378..448134c4bf 100755 --- a/t/t5571-pre-push-hook.sh +++ b/t/t5571-pre-push-hook.sh @@ -4,6 +4,7 @@ test_description='check pre-push hooks' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t5572-pull-submodule.sh b/t/t5572-pull-submodule.sh index 09097eff3f..51744521f7 100755 --- a/t/t5572-pull-submodule.sh +++ b/t/t5572-pull-submodule.sh @@ -121,7 +121,7 @@ test_expect_success "fetch.recurseSubmodules option triggers recursive fetch (bu sub_oid=$(git -C child rev-parse HEAD) && git -C super/sub cat-file -e $sub_oid && # Check that the submodule worktree did not update - ! test_path_is_file super/sub/merge_strategy_5.t + test_path_is_missing super/sub/merge_strategy_5.t ' test_expect_success "fetch.recurseSubmodules takes precedence over submodule.recurse" ' @@ -134,7 +134,7 @@ test_expect_success "fetch.recurseSubmodules takes precedence over submodule.rec sub_oid=$(git -C child rev-parse HEAD) && git -C super/sub cat-file -e $sub_oid && # Check that the submodule worktree did not update - ! test_path_is_file super/sub/merge_strategy_6.t + test_path_is_missing super/sub/merge_strategy_6.t ' test_expect_success 'pull --rebase --recurse-submodules (remote superproject submodule changes, local submodule changes)' ' @@ -177,7 +177,7 @@ test_expect_success 'pull --rebase --recurse-submodules fails if both sides reco # submodule itself, but the merge strategy in submodules # does not support rebase: test_must_fail git -C super pull --rebase --recurse-submodules 2>err && - test_i18ngrep "locally recorded submodule modifications" err + test_grep "locally recorded submodule modifications" err ' test_expect_success 'pull --rebase --recurse-submodules (no submodule changes, no fork-point)' ' diff --git a/t/t5573-pull-verify-signatures.sh b/t/t5573-pull-verify-signatures.sh index 1221ac0597..ab05f38a99 100755 --- a/t/t5573-pull-verify-signatures.sh +++ b/t/t5573-pull-verify-signatures.sh @@ -47,46 +47,46 @@ test_expect_success GPG 'create repositories with signed commits' ' test_expect_success GPG 'pull unsigned commit with --verify-signatures' ' test_when_finished "git reset --hard && git checkout initial" && test_must_fail git pull --ff-only --verify-signatures unsigned 2>pullerror && - test_i18ngrep "does not have a GPG signature" pullerror + test_grep "does not have a GPG signature" pullerror ' test_expect_success GPG 'pull commit with bad signature with --verify-signatures' ' test_when_finished "git reset --hard && git checkout initial" && test_must_fail git pull --ff-only --verify-signatures bad 2>pullerror && - test_i18ngrep "has a bad GPG signature" pullerror + test_grep "has a bad GPG signature" pullerror ' test_expect_success GPG 'pull commit with untrusted signature with --verify-signatures' ' test_when_finished "git reset --hard && git checkout initial" && test_must_fail git pull --ff-only --verify-signatures untrusted 2>pullerror && - test_i18ngrep "has an untrusted GPG signature" pullerror + test_grep "has an untrusted GPG signature" pullerror ' test_expect_success GPG 'pull commit with untrusted signature with --verify-signatures and minTrustLevel=ultimate' ' test_when_finished "git reset --hard && git checkout initial" && test_config gpg.minTrustLevel ultimate && test_must_fail git pull --ff-only --verify-signatures untrusted 2>pullerror && - test_i18ngrep "has an untrusted GPG signature" pullerror + test_grep "has an untrusted GPG signature" pullerror ' test_expect_success GPG 'pull commit with untrusted signature with --verify-signatures and minTrustLevel=marginal' ' test_when_finished "git reset --hard && git checkout initial" && test_config gpg.minTrustLevel marginal && test_must_fail git pull --ff-only --verify-signatures untrusted 2>pullerror && - test_i18ngrep "has an untrusted GPG signature" pullerror + test_grep "has an untrusted GPG signature" pullerror ' test_expect_success GPG 'pull commit with untrusted signature with --verify-signatures and minTrustLevel=undefined' ' test_when_finished "git reset --hard && git checkout initial" && test_config gpg.minTrustLevel undefined && git pull --ff-only --verify-signatures untrusted >pulloutput && - test_i18ngrep "has a good GPG signature" pulloutput + test_grep "has a good GPG signature" pulloutput ' test_expect_success GPG 'pull signed commit with --verify-signatures' ' test_when_finished "git reset --hard && git checkout initial" && git pull --verify-signatures signed >pulloutput && - test_i18ngrep "has a good GPG signature" pulloutput + test_grep "has a good GPG signature" pulloutput ' test_expect_success GPG 'pull commit with bad signature without verification' ' @@ -106,7 +106,7 @@ test_expect_success GPG 'pull unsigned commit into unborn branch' ' git init empty-repo && test_must_fail \ git -C empty-repo pull --verify-signatures .. 2>pullerror && - test_i18ngrep "does not have a GPG signature" pullerror + test_grep "does not have a GPG signature" pullerror ' test_expect_success GPG 'pull commit into unborn branch with bad signature and --verify-signatures' ' @@ -114,7 +114,7 @@ test_expect_success GPG 'pull commit into unborn branch with bad signature and - git init empty-repo && test_must_fail \ git -C empty-repo pull --ff-only --verify-signatures ../bad 2>pullerror && - test_i18ngrep "has a bad GPG signature" pullerror + test_grep "has a bad GPG signature" pullerror ' test_expect_success GPG 'pull commit into unborn branch with untrusted signature and --verify-signatures' ' @@ -122,7 +122,7 @@ test_expect_success GPG 'pull commit into unborn branch with untrusted signature git init empty-repo && test_must_fail \ git -C empty-repo pull --ff-only --verify-signatures ../untrusted 2>pullerror && - test_i18ngrep "has an untrusted GPG signature" pullerror + test_grep "has an untrusted GPG signature" pullerror ' test_expect_success GPG 'pull commit into unborn branch with untrusted signature and --verify-signatures and minTrustLevel=ultimate' ' @@ -131,7 +131,7 @@ test_expect_success GPG 'pull commit into unborn branch with untrusted signature test_config_global gpg.minTrustLevel ultimate && test_must_fail \ git -C empty-repo pull --ff-only --verify-signatures ../untrusted 2>pullerror && - test_i18ngrep "has an untrusted GPG signature" pullerror + test_grep "has an untrusted GPG signature" pullerror ' test_expect_success GPG 'pull commit into unborn branch with untrusted signature and --verify-signatures and minTrustLevel=marginal' ' @@ -140,7 +140,7 @@ test_expect_success GPG 'pull commit into unborn branch with untrusted signature test_config_global gpg.minTrustLevel marginal && test_must_fail \ git -C empty-repo pull --ff-only --verify-signatures ../untrusted 2>pullerror && - test_i18ngrep "has an untrusted GPG signature" pullerror + test_grep "has an untrusted GPG signature" pullerror ' test_expect_success GPG 'pull commit into unborn branch with untrusted signature and --verify-signatures and minTrustLevel=undefined' ' @@ -148,7 +148,7 @@ test_expect_success GPG 'pull commit into unborn branch with untrusted signature git init empty-repo && test_config_global gpg.minTrustLevel undefined && git -C empty-repo pull --ff-only --verify-signatures ../untrusted >pulloutput && - test_i18ngrep "has a good GPG signature" pulloutput + test_grep "has a good GPG signature" pulloutput ' test_done diff --git a/t/t5574-fetch-output.sh b/t/t5574-fetch-output.sh new file mode 100755 index 0000000000..a9b06b2251 --- /dev/null +++ b/t/t5574-fetch-output.sh @@ -0,0 +1,293 @@ +#!/bin/sh + +test_description='git fetch output format' + +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + +. ./test-lib.sh + +test_expect_success 'fetch with invalid output format configuration' ' + test_when_finished "rm -rf clone" && + git clone . clone && + + test_must_fail git -C clone -c fetch.output fetch origin 2>actual.err && + cat >expect <<-EOF && + error: missing value for ${SQ}fetch.output${SQ} + fatal: unable to parse ${SQ}fetch.output${SQ} from command-line config + EOF + test_cmp expect actual.err && + + test_must_fail git -C clone -c fetch.output= fetch origin 2>actual.err && + cat >expect <<-EOF && + fatal: invalid value for ${SQ}fetch.output${SQ}: ${SQ}${SQ} + EOF + test_cmp expect actual.err && + + test_must_fail git -C clone -c fetch.output=garbage fetch origin 2>actual.err && + cat >expect <<-EOF && + fatal: invalid value for ${SQ}fetch.output${SQ}: ${SQ}garbage${SQ} + EOF + test_cmp expect actual.err +' + +test_expect_success 'fetch aligned output' ' + git clone . full-output && + test_commit looooooooooooong-tag && + ( + cd full-output && + git -c fetch.output=full fetch origin >actual 2>&1 && + grep -e "->" actual | cut -c 22- >../actual + ) && + cat >expect <<-\EOF && + main -> origin/main + looooooooooooong-tag -> looooooooooooong-tag + EOF + test_cmp expect actual +' + +test_expect_success 'fetch compact output' ' + git clone . compact && + test_commit extraaa && + ( + cd compact && + git -c fetch.output=compact fetch origin >actual 2>&1 && + grep -e "->" actual | cut -c 22- >../actual + ) && + cat >expect <<-\EOF && + main -> origin/* + extraaa -> * + EOF + test_cmp expect actual +' + +test_expect_success 'fetch porcelain output' ' + test_when_finished "rm -rf porcelain" && + + # Set up a bunch of references that we can use to demonstrate different + # kinds of flag symbols in the output format. + MAIN_OLD=$(git rev-parse HEAD) && + git branch "fast-forward" && + git branch "deleted-branch" && + git checkout -b force-updated && + test_commit --no-tag force-update-old && + FORCE_UPDATED_OLD=$(git rev-parse HEAD) && + git checkout main && + + # Clone and pre-seed the repositories. We fetch references into two + # namespaces so that we can test that rejected and force-updated + # references are reported properly. + refspecs="refs/heads/*:refs/unforced/* +refs/heads/*:refs/forced/*" && + git clone . porcelain && + git -C porcelain fetch origin $refspecs && + + # Now that we have set up the client repositories we can change our + # local references. + git branch new-branch && + git branch -d deleted-branch && + git checkout fast-forward && + test_commit --no-tag fast-forward-new && + FAST_FORWARD_NEW=$(git rev-parse HEAD) && + git checkout force-updated && + git reset --hard HEAD~ && + test_commit --no-tag force-update-new && + FORCE_UPDATED_NEW=$(git rev-parse HEAD) && + + cat >expect <<-EOF && + - $MAIN_OLD $ZERO_OID refs/forced/deleted-branch + - $MAIN_OLD $ZERO_OID refs/unforced/deleted-branch + $MAIN_OLD $FAST_FORWARD_NEW refs/unforced/fast-forward + ! $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/unforced/force-updated + * $ZERO_OID $MAIN_OLD refs/unforced/new-branch + $MAIN_OLD $FAST_FORWARD_NEW refs/forced/fast-forward + + $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/forced/force-updated + * $ZERO_OID $MAIN_OLD refs/forced/new-branch + $MAIN_OLD $FAST_FORWARD_NEW refs/remotes/origin/fast-forward + + $FORCE_UPDATED_OLD $FORCE_UPDATED_NEW refs/remotes/origin/force-updated + * $ZERO_OID $MAIN_OLD refs/remotes/origin/new-branch + EOF + + # Execute a dry-run fetch first. We do this to assert that the dry-run + # and non-dry-run fetches produces the same output. Execution of the + # fetch is expected to fail as we have a rejected reference update. + test_must_fail git -C porcelain fetch \ + --porcelain --dry-run --prune origin $refspecs >actual && + test_cmp expect actual && + + # And now we perform a non-dry-run fetch. + test_must_fail git -C porcelain fetch \ + --porcelain --prune origin $refspecs >actual 2>stderr && + test_cmp expect actual && + test_must_be_empty stderr +' + +test_expect_success 'fetch porcelain with multiple remotes' ' + test_when_finished "rm -rf porcelain" && + + git switch --create multiple-remotes && + git clone . porcelain && + git -C porcelain remote add second-remote "$PWD" && + git -C porcelain fetch second-remote && + + test_commit --no-tag multi-commit && + old_commit=$(git rev-parse HEAD~) && + new_commit=$(git rev-parse HEAD) && + + cat >expect <<-EOF && + $old_commit $new_commit refs/remotes/origin/multiple-remotes + $old_commit $new_commit refs/remotes/second-remote/multiple-remotes + EOF + + git -C porcelain fetch --porcelain --all >actual 2>stderr && + test_cmp expect actual && + test_must_be_empty stderr +' + +test_expect_success 'fetch porcelain refuses to work with submodules' ' + test_when_finished "rm -rf porcelain" && + + cat >expect <<-EOF && + fatal: options ${SQ}--porcelain${SQ} and ${SQ}--recurse-submodules${SQ} cannot be used together + EOF + + git init porcelain && + test_must_fail git -C porcelain fetch --porcelain --recurse-submodules=yes 2>stderr && + test_cmp expect stderr && + + test_must_fail git -C porcelain fetch --porcelain --recurse-submodules=on-demand 2>stderr && + test_cmp expect stderr +' + +test_expect_success 'fetch porcelain overrides fetch.output config' ' + test_when_finished "rm -rf porcelain" && + + git switch --create config-override && + git clone . porcelain && + test_commit new-commit && + old_commit=$(git rev-parse HEAD~) && + new_commit=$(git rev-parse HEAD) && + + cat >expect <<-EOF && + $old_commit $new_commit refs/remotes/origin/config-override + * $ZERO_OID $new_commit refs/tags/new-commit + EOF + + git -C porcelain -c fetch.output=compact fetch --porcelain >stdout 2>stderr && + test_must_be_empty stderr && + test_cmp expect stdout +' + +test_expect_success 'fetch --no-porcelain overrides previous --porcelain' ' + test_when_finished "rm -rf no-porcelain" && + + git switch --create no-porcelain && + git clone . no-porcelain && + test_commit --no-tag no-porcelain && + old_commit=$(git rev-parse --short HEAD~) && + new_commit=$(git rev-parse --short HEAD) && + + cat >expect <<-EOF && + From $(test-tool path-utils real_path .)/. + $old_commit..$new_commit no-porcelain -> origin/no-porcelain + EOF + + git -C no-porcelain fetch --porcelain --no-porcelain >stdout 2>stderr && + test_cmp expect stderr && + test_must_be_empty stdout +' + +test_expect_success 'fetch output with HEAD' ' + test_when_finished "rm -rf head" && + git clone . head && + + git -C head fetch --dry-run origin HEAD >actual.out 2>actual.err && + cat >expect <<-EOF && + From $(test-tool path-utils real_path .)/. + * branch HEAD -> FETCH_HEAD + EOF + test_must_be_empty actual.out && + test_cmp expect actual.err && + + git -C head fetch origin HEAD >actual.out 2>actual.err && + test_must_be_empty actual.out && + test_cmp expect actual.err && + + git -C head fetch --dry-run origin HEAD:foo >actual.out 2>actual.err && + cat >expect <<-EOF && + From $(test-tool path-utils real_path .)/. + * [new ref] HEAD -> foo + EOF + test_must_be_empty actual.out && + test_cmp expect actual.err && + + git -C head fetch origin HEAD:foo >actual.out 2>actual.err && + test_must_be_empty actual.out && + test_cmp expect actual.err +' + +test_expect_success 'fetch porcelain output with HEAD' ' + test_when_finished "rm -rf head" && + git clone . head && + COMMIT_ID=$(git rev-parse HEAD) && + + git -C head fetch --porcelain --dry-run origin HEAD >actual && + cat >expect <<-EOF && + * $ZERO_OID $COMMIT_ID FETCH_HEAD + EOF + test_cmp expect actual && + + git -C head fetch --porcelain origin HEAD >actual && + test_cmp expect actual && + + git -C head fetch --porcelain --dry-run origin HEAD:foo >actual && + cat >expect <<-EOF && + * $ZERO_OID $COMMIT_ID refs/heads/foo + EOF + test_cmp expect actual && + + git -C head fetch --porcelain origin HEAD:foo >actual && + test_cmp expect actual +' + +test_expect_success 'fetch output with object ID' ' + test_when_finished "rm -rf object-id" && + git clone . object-id && + commit=$(git rev-parse HEAD) && + + git -C object-id fetch --dry-run origin $commit:object-id >actual.out 2>actual.err && + cat >expect <<-EOF && + From $(test-tool path-utils real_path .)/. + * [new ref] $commit -> object-id + EOF + test_must_be_empty actual.out && + test_cmp expect actual.err && + + git -C object-id fetch origin $commit:object-id >actual.out 2>actual.err && + test_must_be_empty actual.out && + test_cmp expect actual.err +' + +test_expect_success '--no-show-forced-updates' ' + mkdir forced-updates && + ( + cd forced-updates && + git init && + test_commit 1 && + test_commit 2 + ) && + git clone forced-updates forced-update-clone && + git clone forced-updates no-forced-update-clone && + git -C forced-updates reset --hard HEAD~1 && + ( + cd forced-update-clone && + git fetch --show-forced-updates origin 2>output && + test_grep "(forced update)" output + ) && + ( + cd no-forced-update-clone && + git fetch --no-show-forced-updates origin 2>output && + test_grep ! "(forced update)" output + ) +' + +test_done diff --git a/t/t5580-unc-paths.sh b/t/t5580-unc-paths.sh index cd7604fff9..d7537a162b 100755 --- a/t/t5580-unc-paths.sh +++ b/t/t5580-unc-paths.sh @@ -75,7 +75,7 @@ test_expect_success push ' test_expect_success MINGW 'remote nick cannot contain backslashes' ' BACKSLASHED="$(winpwd | tr / \\\\)" && git ls-remote "$BACKSLASHED" 2>err && - test_i18ngrep ! "unable to access" err + test_grep ! "unable to access" err ' test_expect_success 'unc alternates' ' diff --git a/t/t5583-push-branches.sh b/t/t5583-push-branches.sh new file mode 100755 index 0000000000..320f49c753 --- /dev/null +++ b/t/t5583-push-branches.sh @@ -0,0 +1,116 @@ +#!/bin/sh + +test_description='check the consisitency of behavior of --all and --branches' + +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh + +delete_refs() { + dir=$1 + shift + rm -rf deletes + for arg in $* + do + echo "delete ${arg}" >>deletes + done + git -C $dir update-ref --stdin < deletes +} + +test_expect_success 'setup bare remote' ' + git init --bare remote-1 && + git -C remote-1 config gc.auto 0 && + test_commit one && + git push remote-1 HEAD +' + +test_expect_success 'setup different types of references' ' + cat >refs <<-EOF && + update refs/heads/branch-1 HEAD + update refs/heads/branch-2 HEAD + EOF + + git tag -a -m "annotated" annotated-1 HEAD && + git tag -a -m "annotated" annotated-2 HEAD && + git update-ref --stdin < refs +' + +test_expect_success '--all and --branches have the same behavior' ' + test_when_finished "delete_refs remote-1 \ + refs/heads/branch-1 \ + refs/heads/branch-2" && + git push remote-1 --all && + commit=$(git rev-parse HEAD) && + cat >expect <<-EOF && + $commit refs/heads/branch-1 + $commit refs/heads/branch-2 + $commit refs/heads/main + EOF + + git -C remote-1 show-ref --heads >actual.all && + delete_refs remote-1 refs/heads/branch-1 refs/heads/branch-2 && + git push remote-1 --branches && + git -C remote-1 show-ref --heads >actual.branches && + test_cmp actual.all actual.branches && + test_cmp expect actual.all +' + +test_expect_success '--all or --branches can not be combined with refspecs' ' + test_must_fail git push remote-1 --all main >actual.all 2>&1 && + test_must_fail git push remote-1 --branches main >actual.branches 2>&1 && + test_cmp actual.all actual.branches && + grep "be combined with refspecs" actual.all +' + +test_expect_success '--all or --branches can not be combined with --mirror' ' + test_must_fail git push remote-1 --all --mirror >actual.all 2>&1 && + test_must_fail git push remote-1 --branches --mirror >actual.branches 2>&1 && + test_cmp actual.all actual.branches && + grep "cannot be used together" actual.all +' + +test_expect_success '--all or --branches can not be combined with --tags' ' + test_must_fail git push remote-1 --all --tags >actual.all 2>&1 && + test_must_fail git push remote-1 --branches --tags >actual.branches 2>&1 && + test_cmp actual.all actual.branches && + grep "cannot be used together" actual.all +' + + +test_expect_success '--all or --branches can not be combined with --delete' ' + test_must_fail git push remote-1 --all --delete >actual.all 2>&1 && + test_must_fail git push remote-1 --branches --delete >actual.branches 2>&1 && + test_cmp actual.all actual.branches && + grep "cannot be used together" actual.all +' + +test_expect_success '--all or --branches combines with --follow-tags have same behavior' ' + test_when_finished "delete_refs remote-1 \ + refs/heads/branch-1 \ + refs/heads/branch-2 \ + refs/tags/annotated-1 \ + refs/tags/annotated-2" && + git push remote-1 --all --follow-tags && + git -C remote-1 show-ref > actual.all && + cat >expect <<-EOF && + $commit refs/heads/branch-1 + $commit refs/heads/branch-2 + $commit refs/heads/main + $(git rev-parse annotated-1) refs/tags/annotated-1 + $(git rev-parse annotated-2) refs/tags/annotated-2 + EOF + + delete_refs remote-1 \ + refs/heads/branch-1 \ + refs/heads/branch-2 \ + refs/tags/annotated-1 \ + refs/tags/annotated-2 && + git push remote-1 --branches --follow-tags && + git -C remote-1 show-ref >actual.branches && + test_cmp actual.all actual.branches && + test_cmp expect actual.all +' + +test_done diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index b7d5551262..47eae641f0 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -630,7 +630,7 @@ test_expect_success 'clone on case-insensitive fs' ' test_expect_success CASE_INSENSITIVE_FS 'colliding file detection' ' grep X icasefs/warning && grep x icasefs/warning && - test_i18ngrep "the following paths have collided" icasefs/warning + test_grep "the following paths have collided" icasefs/warning ' test_expect_success 'clone with GIT_DEFAULT_HASH' ' @@ -696,7 +696,7 @@ test_expect_success 'partial clone: warn if server does not support object filte git clone --filter=blob:limit=0 "file://$(pwd)/server" client 2> err && - test_i18ngrep "filtering not recognized by server" err + test_grep "filtering not recognized by server" err ' test_expect_success 'batch missing blob request during checkout' ' @@ -767,7 +767,7 @@ test_expect_success 'reject cloning shallow repository using HTTP' ' test_when_finished "rm -rf repo" && git clone --bare --no-local --depth=1 src "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && test_must_fail git -c protocol.version=2 clone --reject-shallow $HTTPD_URL/smart/repo.git repo 2>err && - test_i18ngrep -e "source repository is shallow, reject to clone." err && + test_grep -e "source repository is shallow, reject to clone." err && git clone --no-reject-shallow $HTTPD_URL/smart/repo.git repo ' diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh index 83e3c97861..9b32db8478 100755 --- a/t/t5604-clone-reference.sh +++ b/t/t5604-clone-reference.sh @@ -317,7 +317,7 @@ test_expect_success SYMLINKS 'clone repo with symlinked or unknown files at obje for option in --local --no-hardlinks --dissociate do test_must_fail git clone $option T T$option 2>err || return 1 && - test_i18ngrep "symlink.*exists" err || return 1 + test_grep "symlink.*exists" err || return 1 done && # But `--shared` clones should still work, even when specifying @@ -358,7 +358,7 @@ test_expect_success SYMLINKS 'clone repo with symlinked objects directory' ' test_must_fail git clone --local malicious clone 2>err && test_path_is_missing clone && - grep "failed to start iterator over" err + grep "is a symlink, refusing to clone with --local" err ' test_done diff --git a/t/t5605-clone-local.sh b/t/t5605-clone-local.sh index 38b850c10e..a3055869bc 100755 --- a/t/t5605-clone-local.sh +++ b/t/t5605-clone-local.sh @@ -15,8 +15,12 @@ test_expect_success 'preparing origin repository' ' : >file && git add . && git commit -m1 && git clone --bare . a.git && git clone --bare . x && - test "$(cd a.git && git config --bool core.bare)" = true && - test "$(cd x && git config --bool core.bare)" = true && + echo true >expect && + git -C a.git config --bool core.bare >actual && + test_cmp expect actual && + echo true >expect && + git -C x config --bool core.bare >actual && + test_cmp expect actual && git bundle create b1.bundle --all && git bundle create b2.bundle main && mkdir dir && @@ -29,7 +33,9 @@ test_expect_success 'preparing origin repository' ' test_expect_success 'local clone without .git suffix' ' git clone -l -s a b && (cd b && - test "$(git config --bool core.bare)" = false && + echo false >expect && + git config --bool core.bare >actual && + test_cmp expect actual && git fetch) ' @@ -59,11 +65,11 @@ test_expect_success 'Even without -l, local will make a hardlink' ' ' test_expect_success 'local clone of repo with nonexistent ref in HEAD' ' - echo "ref: refs/heads/nonexistent" > a.git/HEAD && + git -C a.git symbolic-ref HEAD refs/heads/nonexistent && git clone a d && (cd d && git fetch && - test ! -e .git/refs/remotes/origin/HEAD) + test_ref_missing refs/remotes/origin/HEAD) ' test_expect_success 'bundle clone without .bundle suffix' ' @@ -151,7 +157,7 @@ test_expect_success 'cloning locally respects "-u" for fetching refs' ' test_must_fail git clone --bare -u false a should_not_work.git ' -test_expect_success 'local clone from repo with corrupt refs fails gracefully' ' +test_expect_success REFFILES 'local clone from repo with corrupt refs fails gracefully' ' git init corrupt && test_commit -C corrupt one && echo a >corrupt/.git/refs/heads/topic && diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh index 27f9f77638..a400bcca62 100755 --- a/t/t5606-clone-options.sh +++ b/t/t5606-clone-options.sh @@ -39,7 +39,7 @@ test_expect_success 'clone -o' ' test_expect_success 'rejects invalid -o/--origin' ' test_must_fail git clone -o "bad...name" parent clone-bad-name 2>err && - test_i18ngrep "'\''bad...name'\'' is not a valid remote name" err + test_grep "'\''bad...name'\'' is not a valid remote name" err ' @@ -56,7 +56,7 @@ test_expect_success 'disallows --bare with --separate-git-dir' ' test_must_fail git clone --bare --separate-git-dir dot-git-destiation parent clone-bare-sgd 2>err && test_debug "cat err" && - test_i18ngrep -e "options .--bare. and .--separate-git-dir. cannot be used together" err + test_grep -e "options .--bare. and .--separate-git-dir. cannot be used together" err ' @@ -64,14 +64,14 @@ test_expect_success 'disallows --bundle-uri with shallow options' ' for option in --depth=1 --shallow-since=01-01-2000 --shallow-exclude=HEAD do test_must_fail git clone --bundle-uri=bundle $option from to 2>err && - grep "bundle-uri is incompatible" err || return 1 + grep "bundle-uri.* cannot be used together" err || return 1 done ' test_expect_success 'reject cloning shallow repository' ' test_when_finished "rm -rf repo" && test_must_fail git clone --reject-shallow shallow-repo out 2>err && - test_i18ngrep -e "source repository is shallow, reject to clone." err && + test_grep -e "source repository is shallow, reject to clone." err && git clone --no-reject-shallow shallow-repo repo ' @@ -79,7 +79,7 @@ test_expect_success 'reject cloning shallow repository' ' test_expect_success 'reject cloning non-local shallow repository' ' test_when_finished "rm -rf repo" && test_must_fail git clone --reject-shallow --no-local shallow-repo out 2>err && - test_i18ngrep -e "source repository is shallow, reject to clone." err && + test_grep -e "source repository is shallow, reject to clone." err && git clone --no-reject-shallow --no-local shallow-repo repo ' @@ -120,6 +120,16 @@ test_expect_success 'prefers -c config over --template config' ' ' +test_expect_failure 'prefers --template config even for core.bare' ' + + template="$TRASH_DIRECTORY/template-with-bare-config" && + mkdir "$template" && + git config --file "$template/config" core.bare true && + git clone "--template=$template" parent clone-bare-config && + test "$(git -C clone-bare-config config --local core.bare)" = "true" && + test_path_is_file clone-bare-config/HEAD +' + test_expect_success 'prefers config "clone.defaultRemoteName" over default' ' test_config_global clone.defaultRemoteName from_config && @@ -139,7 +149,7 @@ test_expect_success 'redirected clone does not show progress' ' git clone "file://$(pwd)/parent" clone-redirected >out 2>err && ! grep % err && - test_i18ngrep ! "Checking connectivity" err + test_grep ! "Checking connectivity" err ' diff --git a/t/t5607-clone-bundle.sh b/t/t5607-clone-bundle.sh index 51705aa86a..0d1e92d996 100755 --- a/t/t5607-clone-bundle.sh +++ b/t/t5607-clone-bundle.sh @@ -24,7 +24,7 @@ test_expect_success 'setup' ' test_expect_success '"verify" needs a worktree' ' git bundle create tip.bundle -1 main && nongit test_must_fail git bundle verify ../tip.bundle 2>err && - test_i18ngrep "need a repository" err + test_grep "need a repository" err ' test_expect_success 'annotated tags can be excluded by rev-list options' ' @@ -166,7 +166,7 @@ test_expect_success 'git bundle v3 rejects unknown capabilities' ' @unknown=silly EOF test_must_fail git bundle verify new 2>output && - test_i18ngrep "unknown capability .unknown=silly." output + test_grep "unknown capability .unknown=silly." output ' test_done diff --git a/t/t5611-clone-config.sh b/t/t5611-clone-config.sh index 727caff443..298d4befab 100755 --- a/t/t5611-clone-config.sh +++ b/t/t5611-clone-config.sh @@ -103,7 +103,7 @@ test_expect_success 'set up shallow repository' ' test_expect_success 'clone.rejectshallow=true should reject cloning shallow repo' ' test_when_finished "rm -rf out" && test_must_fail git -c clone.rejectshallow=true clone --no-local shallow-repo out 2>err && - test_i18ngrep -e "source repository is shallow, reject to clone." err && + test_grep -e "source repository is shallow, reject to clone." err && git -c clone.rejectshallow=false clone --no-local shallow-repo out ' @@ -111,7 +111,7 @@ test_expect_success 'clone.rejectshallow=true should reject cloning shallow repo test_expect_success 'option --[no-]reject-shallow override clone.rejectshallow config' ' test_when_finished "rm -rf out" && test_must_fail git -c clone.rejectshallow=false clone --reject-shallow --no-local shallow-repo out 2>err && - test_i18ngrep -e "source repository is shallow, reject to clone." err && + test_grep -e "source repository is shallow, reject to clone." err && git -c clone.rejectshallow=true clone --no-reject-shallow --no-local shallow-repo out ' diff --git a/t/t5616-partial-clone.sh b/t/t5616-partial-clone.sh index f519d2a87a..2da7291e37 100755 --- a/t/t5616-partial-clone.sh +++ b/t/t5616-partial-clone.sh @@ -257,8 +257,8 @@ test_expect_success 'partial clone with transfer.fsckobjects=1 works with submod test_commit -C submodule mycommit && test_create_repo src_with_sub && - test_config -C src_with_sub uploadpack.allowfilter 1 && - test_config -C src_with_sub uploadpack.allowanysha1inwant 1 && + git -C src_with_sub config uploadpack.allowfilter 1 && + git -C src_with_sub config uploadpack.allowanysha1inwant 1 && test_config_global protocol.file.allow always && @@ -270,6 +270,12 @@ test_expect_success 'partial clone with transfer.fsckobjects=1 works with submod test_when_finished rm -rf dst ' +test_expect_success 'lazily fetched .gitmodules works' ' + git clone --filter="blob:none" --no-checkout "file://$(pwd)/src_with_sub" dst && + git -C dst fetch && + test_when_finished rm -rf dst +' + test_expect_success 'partial clone with transfer.fsckobjects=1 uses index-pack --fsck-objects' ' git init src && test_commit -C src x && @@ -347,14 +353,14 @@ test_expect_success 'upload-pack complains of bogus filter config' ' test_must_fail git \ -c uploadpackfilter.tree.maxdepth \ upload-pack . >/dev/null 2>err && - test_i18ngrep "unable to parse.*tree.maxdepth" err + test_grep "unable to parse.*tree.maxdepth" err ' test_expect_success 'upload-pack fails banned object filters' ' test_config -C srv.bare uploadpackfilter.blob:none.allow false && test_must_fail ok=sigpipe git clone --no-checkout --filter=blob:none \ "file://$(pwd)/srv.bare" pc3 2>err && - test_i18ngrep "filter '\''blob:none'\'' not supported" err + test_grep "filter '\''blob:none'\'' not supported" err ' test_expect_success 'upload-pack fails banned combine object filters' ' @@ -364,14 +370,14 @@ test_expect_success 'upload-pack fails banned combine object filters' ' test_config -C srv.bare uploadpackfilter.blob:none.allow false && test_must_fail ok=sigpipe git clone --no-checkout --filter=tree:1 \ --filter=blob:none "file://$(pwd)/srv.bare" pc3 2>err && - test_i18ngrep "filter '\''blob:none'\'' not supported" err + test_grep "filter '\''blob:none'\'' not supported" err ' test_expect_success 'upload-pack fails banned object filters with fallback' ' test_config -C srv.bare uploadpackfilter.allow false && test_must_fail ok=sigpipe git clone --no-checkout --filter=blob:none \ "file://$(pwd)/srv.bare" pc3 2>err && - test_i18ngrep "filter '\''blob:none'\'' not supported" err + test_grep "filter '\''blob:none'\'' not supported" err ' test_expect_success 'upload-pack limits tree depth filters' ' @@ -380,7 +386,7 @@ test_expect_success 'upload-pack limits tree depth filters' ' test_config -C srv.bare uploadpackfilter.tree.maxDepth 0 && test_must_fail ok=sigpipe git clone --no-checkout --filter=tree:1 \ "file://$(pwd)/srv.bare" pc3 2>err && - test_i18ngrep "tree filter allows max depth 0, but got 1" err && + test_grep "tree filter allows max depth 0, but got 1" err && git clone --no-checkout --filter=tree:0 "file://$(pwd)/srv.bare" pc4 && @@ -388,7 +394,7 @@ test_expect_success 'upload-pack limits tree depth filters' ' git clone --no-checkout --filter=tree:5 "file://$(pwd)/srv.bare" pc5 && test_must_fail ok=sigpipe git clone --no-checkout --filter=tree:6 \ "file://$(pwd)/srv.bare" pc6 2>err && - test_i18ngrep "tree filter allows max depth 5, but got 6" err + test_grep "tree filter allows max depth 5, but got 6" err ' test_expect_success 'partial clone fetches blobs pointed to by refs even if normally filtered out' ' @@ -453,11 +459,11 @@ test_expect_success 'partial clone with unresolvable sparse filter fails cleanly test_must_fail git clone --no-local --bare \ --filter=sparse:oid=main:no-such-name \ sparse-src dst.git 2>err && - test_i18ngrep "unable to access sparse blob in .main:no-such-name" err && + test_grep "unable to access sparse blob in .main:no-such-name" err && test_must_fail git clone --no-local --bare \ --filter=sparse:oid=main \ sparse-src dst.git 2>err && - test_i18ngrep "unable to parse sparse filter data in" err + test_grep "unable to parse sparse filter data in" err ' setup_triangle () { @@ -487,8 +493,8 @@ setup_triangle () { TREE_HASH=$(git -C server rev-parse HEAD~1^{tree}) && git -C promisor-remote fetch --keep "file://$(pwd)/server" "$TREE_HASH" && git -C promisor-remote count-objects -v >object-count && - test_i18ngrep "count: 0" object-count && - test_i18ngrep "in-pack: 2" object-count && + test_grep "count: 0" object-count && + test_grep "in-pack: 2" object-count && # Set it as the promisor remote of client. Thus, whenever # the client lazy fetches, the lazy fetch will succeed only if it is @@ -742,7 +748,7 @@ test_expect_success 'upon cloning, check that all refs point to objects' ' test_must_fail git -c protocol.version=2 clone \ --filter=blob:none $HTTPD_URL/one_time_perl/server repo 2>err && - test_i18ngrep "did not send all necessary objects" err && + test_grep "did not send all necessary objects" err && # Ensure that the one-time-perl script was used. ! test -e "$HTTPD_ROOT_PATH/one-time-perl" diff --git a/t/t5700-protocol-v1.sh b/t/t5700-protocol-v1.sh index 6c8d4c6cf1..a73b4d4ff6 100755 --- a/t/t5700-protocol-v1.sh +++ b/t/t5700-protocol-v1.sh @@ -244,15 +244,28 @@ test_expect_success 'push with ssh:// using protocol v1' ' grep "push< version 1" log ' +test_expect_success 'clone propagates object-format from empty repo' ' + test_when_finished "rm -fr src256 dst256" && + + echo sha256 >expect && + git init --object-format=sha256 src256 && + git clone --no-local src256 dst256 && + git -C dst256 rev-parse --show-object-format >actual && + + test_cmp expect actual +' + # Test protocol v1 with 'http://' transport # . "$TEST_DIRECTORY"/lib-httpd.sh start_httpd -test_expect_success 'create repo to be served by http:// transport' ' +test_expect_success 'create repos to be served by http:// transport' ' git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && git -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" config http.receivepack true && - test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one + test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one && + git init --object-format=sha256 "$HTTPD_DOCUMENT_ROOT_PATH/sha256" && + git -C "$HTTPD_DOCUMENT_ROOT_PATH/sha256" config http.receivepack true ' test_expect_success 'clone with http:// using protocol v1' ' @@ -269,6 +282,20 @@ test_expect_success 'clone with http:// using protocol v1' ' grep "git< version 1" log ' +test_expect_success 'clone with http:// using protocol v1 with empty SHA-256 repo' ' + GIT_TRACE_PACKET=1 GIT_TRACE_CURL=1 git -c protocol.version=1 \ + clone "$HTTPD_URL/smart/sha256" sha256 2>log && + + echo sha256 >expect && + git -C sha256 rev-parse --show-object-format >actual && + test_cmp expect actual && + + # Client requested to use protocol v1 + grep "Git-Protocol: version=1" log && + # Server responded using protocol v1 + grep "git< version 1" log +' + test_expect_success 'fetch with http:// using protocol v1' ' test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" two && diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh index f21e5e9d33..3591bc2417 100755 --- a/t/t5701-git-serve.sh +++ b/t/t5701-git-serve.sh @@ -52,7 +52,7 @@ test_expect_success 'request invalid capability' ' 0000 EOF test_must_fail test-tool serve-v2 --stateless-rpc 2>err <in && - test_i18ngrep "unknown capability" err + test_grep "unknown capability" err ' test_expect_success 'request with no command' ' @@ -62,7 +62,7 @@ test_expect_success 'request with no command' ' 0000 EOF test_must_fail test-tool serve-v2 --stateless-rpc 2>err <in && - test_i18ngrep "no command requested" err + test_grep "no command requested" err ' test_expect_success 'request invalid command' ' @@ -73,7 +73,7 @@ test_expect_success 'request invalid command' ' 0000 EOF test_must_fail test-tool serve-v2 --stateless-rpc 2>err <in && - test_i18ngrep "invalid command" err + test_grep "invalid command" err ' test_expect_success 'request capability as command' ' @@ -115,7 +115,7 @@ test_expect_success 'wrong object-format' ' 0000 EOF test_must_fail test-tool serve-v2 --stateless-rpc 2>err <in && - test_i18ngrep "mismatched object format" err + test_grep "mismatched object format" err ' # Test the basics of ls-refs diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index e4db7513f4..6ef4971845 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -189,8 +189,8 @@ test_expect_success 'warn if using server-option with ls-remote with legacy prot test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 git -c protocol.version=0 \ ls-remote -o hello -o world "file://$(pwd)/file_parent" main 2>err && - test_i18ngrep "see protocol.version in" err && - test_i18ngrep "server options require protocol version 2 or later" err + test_grep "see protocol.version in" err && + test_grep "server options require protocol version 2 or later" err ' test_expect_success 'clone with file:// using protocol v2' ' @@ -221,7 +221,9 @@ test_expect_success 'clone of empty repo propagates name of default branch' ' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= \ git -c init.defaultBranch=main -c protocol.version=2 \ clone "file://$(pwd)/file_empty_parent" file_empty_child && - grep "refs/heads/mydefaultbranch" file_empty_child/.git/HEAD + echo refs/heads/mydefaultbranch >expect && + git -C file_empty_child symbolic-ref HEAD >actual && + test_cmp expect actual ' test_expect_success '...but not if explicitly forbidden by config' ' @@ -234,7 +236,9 @@ test_expect_success '...but not if explicitly forbidden by config' ' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= \ git -c init.defaultBranch=main -c protocol.version=2 \ clone "file://$(pwd)/file_empty_parent" file_empty_child && - ! grep "refs/heads/mydefaultbranch" file_empty_child/.git/HEAD + echo refs/heads/main >expect && + git -C file_empty_child symbolic-ref HEAD >actual && + test_cmp expect actual ' test_expect_success 'bare clone propagates empty default branch' ' @@ -247,7 +251,9 @@ test_expect_success 'bare clone propagates empty default branch' ' git -c init.defaultBranch=main -c protocol.version=2 \ clone --bare \ "file://$(pwd)/file_empty_parent" file_empty_child.git && - grep "refs/heads/mydefaultbranch" file_empty_child.git/HEAD + echo "refs/heads/mydefaultbranch" >expect && + git -C file_empty_child.git symbolic-ref HEAD >actual && + test_cmp expect actual ' test_expect_success 'clone propagates unborn HEAD from non-empty repo' ' @@ -265,10 +271,23 @@ test_expect_success 'clone propagates unborn HEAD from non-empty repo' ' git -c init.defaultBranch=main -c protocol.version=2 \ clone "file://$(pwd)/file_unborn_parent" \ file_unborn_child 2>stderr && - grep "refs/heads/mydefaultbranch" file_unborn_child/.git/HEAD && + echo "refs/heads/mydefaultbranch" >expect && + git -C file_unborn_child symbolic-ref HEAD >actual && + test_cmp expect actual && grep "warning: remote HEAD refers to nonexistent ref" stderr ' +test_expect_success 'clone propagates object-format from empty repo' ' + test_when_finished "rm -fr src256 dst256" && + + echo sha256 >expect && + git init --object-format=sha256 src256 && + git clone src256 dst256 && + git -C dst256 rev-parse --show-object-format >actual && + + test_cmp expect actual +' + test_expect_success 'bare clone propagates unborn HEAD from non-empty repo' ' test_when_finished "rm -rf file_unborn_parent file_unborn_child.git" && @@ -284,7 +303,9 @@ test_expect_success 'bare clone propagates unborn HEAD from non-empty repo' ' git -c init.defaultBranch=main -c protocol.version=2 \ clone --bare "file://$(pwd)/file_unborn_parent" \ file_unborn_child.git 2>stderr && - grep "refs/heads/mydefaultbranch" file_unborn_child.git/HEAD && + echo "refs/heads/mydefaultbranch" >expect && + git -C file_unborn_child.git symbolic-ref HEAD >actual && + test_cmp expect actual && ! grep "warning:" stderr ' @@ -304,7 +325,9 @@ test_expect_success 'defaulted HEAD uses remote branch if available' ' git -c init.defaultBranch=branchwithstuff -c protocol.version=2 \ clone "file://$(pwd)/file_unborn_parent" \ file_unborn_child 2>stderr && - grep "refs/heads/branchwithstuff" file_unborn_child/.git/HEAD && + echo "refs/heads/branchwithstuff" >expect && + git -C file_unborn_child symbolic-ref HEAD >actual && + test_cmp expect actual && test_path_is_file file_unborn_child/stuff.t && ! grep "warning:" stderr ' @@ -366,8 +389,8 @@ test_expect_success 'warn if using server-option with fetch with legacy protocol test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 git -C temp_child -c protocol.version=0 \ fetch -o hello -o world "file://$(pwd)/file_parent" main 2>err && - test_i18ngrep "see protocol.version in" err && - test_i18ngrep "server options require protocol version 2 or later" err + test_grep "see protocol.version in" err && + test_grep "server options require protocol version 2 or later" err ' test_expect_success 'server-options are sent when cloning' ' @@ -388,8 +411,8 @@ test_expect_success 'warn if using server-option with clone with legacy protocol clone --server-option=hello --server-option=world \ "file://$(pwd)/file_parent" myclone 2>err && - test_i18ngrep "see protocol.version in" err && - test_i18ngrep "server options require protocol version 2 or later" err + test_grep "see protocol.version in" err && + test_grep "server options require protocol version 2 or later" err ' test_expect_success 'upload-pack respects config using protocol v2' ' @@ -484,7 +507,7 @@ test_expect_success 'partial clone warns if filter is not advertised' ' git -C server config uploadpack.allowfilter 0 && git -c protocol.version=2 \ clone --filter=blob:none "file://$(pwd)/server" client 2>err && - test_i18ngrep "filtering not recognized by server, ignoring" err + test_grep "filtering not recognized by server, ignoring" err ' test_expect_success 'even with handcrafted request, filter does not work if not advertised' ' @@ -725,7 +748,34 @@ test_expect_success 'file:// --negotiate-only with protocol v0' ' --negotiate-only \ --negotiation-tip=$(git -C client rev-parse HEAD) \ origin 2>err && - test_i18ngrep "negotiate-only requires protocol v2" err + test_grep "negotiate-only requires protocol v2" err +' + +test_expect_success 'push with custom path does not request v2' ' + rm -f env.trace && + git -C client push \ + --receive-pack="env >../env.trace; git-receive-pack" \ + origin HEAD:refs/heads/custom-push-test && + test_path_is_file env.trace && + ! grep ^GIT_PROTOCOL env.trace +' + +test_expect_success 'fetch with custom path does request v2' ' + rm -f env.trace && + git -C client fetch \ + --upload-pack="env >../env.trace; git-upload-pack" \ + origin HEAD && + grep ^GIT_PROTOCOL=version=2 env.trace +' + +test_expect_success 'archive with custom path does not request v2' ' + rm -f env.trace && + git -C client archive \ + --exec="env >../env.trace; git-upload-archive" \ + --remote=origin \ + HEAD >/dev/null && + test_path_is_file env.trace && + ! grep ^GIT_PROTOCOL env.trace ' # Test protocol v2 with 'http://' transport @@ -771,7 +821,7 @@ test_expect_success 'clone repository with http:// using protocol v2 with incomp # Server responded using protocol v2 grep "git< version 2" log && # Client reported appropriate failure - test_i18ngrep "bytes of length header were received" err + test_grep "bytes of length header were received" err ' test_expect_success 'clone repository with http:// using protocol v2 with incomplete pktline body' ' @@ -788,7 +838,7 @@ test_expect_success 'clone repository with http:// using protocol v2 with incomp # Server responded using protocol v2 grep "git< version 2" log && # Client reported appropriate failure - test_i18ngrep "bytes of body are still expected" err + test_grep "bytes of body are still expected" err ' test_expect_success 'clone with http:// using protocol v2 and invalid parameters' ' @@ -935,7 +985,7 @@ test_expect_success 'when server sends "ready", expect DELIM' ' test_must_fail git -C http_child -c protocol.version=2 \ fetch "$HTTPD_URL/one_time_perl/http_parent" 2> err && - test_i18ngrep "expected packfile to be sent after .ready." err + test_grep "expected packfile to be sent after .ready." err ' test_expect_success 'when server does not send "ready", expect FLUSH' ' @@ -963,7 +1013,7 @@ test_expect_success 'when server does not send "ready", expect FLUSH' ' fetch "$HTTPD_URL/one_time_perl/http_parent" 2> err && grep "fetch< .*acknowledgments" log && ! grep "fetch< .*ready" log && - test_i18ngrep "expected no other sections to be sent after no .ready." err + test_grep "expected no other sections to be sent after no .ready." err ' configure_exclusion () { @@ -1073,7 +1123,7 @@ test_expect_success 'fetching with valid packfile URI but invalid hash fails' ' git -c protocol.version=2 \ -c fetch.uriprotocols=http,https \ clone "$HTTPD_URL/smart/http_parent" http_child 2>err && - test_i18ngrep "pack downloaded from.*does not match expected hash" err + test_grep "pack downloaded from.*does not match expected hash" err ' test_expect_success 'packfile-uri with transfer.fsckobjects' ' @@ -1127,7 +1177,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails on bad object' test_must_fail git -c protocol.version=2 -c transfer.fsckobjects=1 \ -c fetch.uriprotocols=http,https \ clone "$HTTPD_URL/smart/http_parent" http_child 2>error && - test_i18ngrep "invalid author/committer line - missing email" error + test_grep "invalid author/committer line - missing email" error ' test_expect_success 'packfile-uri with transfer.fsckobjects succeeds when .gitmodules is separate from tree' ' @@ -1175,7 +1225,7 @@ test_expect_success 'packfile-uri with transfer.fsckobjects fails when .gitmodul test_must_fail git -c protocol.version=2 -c transfer.fsckobjects=1 \ -c fetch.uriprotocols=http,https \ clone "$HTTPD_URL/smart/http_parent" http_child 2>err && - test_i18ngrep "disallowed submodule name" err + test_grep "disallowed submodule name" err ' test_expect_success 'packfile-uri path redacted in trace' ' @@ -1258,7 +1308,7 @@ test_expect_success 'http:// --negotiate-only without wait-for-done support' ' --negotiate-only \ --negotiation-tip=$(git -C client rev-parse HEAD) \ origin 2>err && - test_i18ngrep "server does not support wait-for-done" err + test_grep "server does not support wait-for-done" err ' test_expect_success 'http:// --negotiate-only with protocol v0' ' @@ -1272,7 +1322,7 @@ test_expect_success 'http:// --negotiate-only with protocol v0' ' --negotiate-only \ --negotiation-tip=$(git -C client rev-parse HEAD) \ origin 2>err && - test_i18ngrep "negotiate-only requires protocol v2" err + test_grep "negotiate-only requires protocol v2" err ' # DO NOT add non-httpd-specific tests here, because the last part of this diff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh index df74f80061..191097171b 100755 --- a/t/t5703-upload-pack-ref-in-want.sh +++ b/t/t5703-upload-pack-ref-in-want.sh @@ -484,7 +484,7 @@ test_expect_success 'server is initially ahead - no ref in want' ' cp -r "$LOCAL_PRISTINE" local && inconsistency main $(test_oid numeric) && test_must_fail git -C local fetch 2>err && - test_i18ngrep "fatal: remote error: upload-pack: not our ref" err + test_grep "fatal: remote error: upload-pack: not our ref" err ' test_expect_success 'server is initially ahead - ref in want' ' @@ -530,7 +530,7 @@ test_expect_success 'server loses a ref - ref in want' ' echo "s/main/rain/" >"$HTTPD_ROOT_PATH/one-time-perl" && test_must_fail git -C local fetch 2>err && - test_i18ngrep "fatal: remote error: unknown ref refs/heads/rain" err + test_grep "fatal: remote error: unknown ref refs/heads/rain" err ' # DO NOT add non-httpd-specific tests here, because the last part of this diff --git a/t/t5704-protocol-violations.sh b/t/t5704-protocol-violations.sh index ae1a00afb0..11be64fc03 100755 --- a/t/t5704-protocol-violations.sh +++ b/t/t5704-protocol-violations.sh @@ -18,7 +18,7 @@ test_expect_success 'extra delim packet in v2 ls-refs args' ' } >input && test_must_fail env GIT_PROTOCOL=version=2 \ git upload-pack . <input 2>err && - test_i18ngrep "expected flush after ls-refs arguments" err + test_grep "expected flush after ls-refs arguments" err ' test_expect_success 'extra delim packet in v2 fetch args' ' @@ -31,7 +31,7 @@ test_expect_success 'extra delim packet in v2 fetch args' ' } >input && test_must_fail env GIT_PROTOCOL=version=2 \ git upload-pack . <input 2>err && - test_i18ngrep "expected flush after fetch arguments" err + test_grep "expected flush after fetch arguments" err ' test_expect_success 'bogus symref in v0 capabilities' ' diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh index d386076dbd..4e0a77f985 100755 --- a/t/t5801-remote-helpers.sh +++ b/t/t5801-remote-helpers.sh @@ -137,7 +137,7 @@ test_expect_success 'forced push' ' test_expect_success 'cloning without refspec' ' GIT_REMOTE_TESTGIT_NOREFSPEC=1 \ git clone "testgit::${PWD}/server" local2 2>error && - test_i18ngrep "this remote helper should implement refspec capability" error && + test_grep "this remote helper should implement refspec capability" error && compare_refs local2 HEAD server HEAD ' @@ -145,7 +145,7 @@ test_expect_success 'pulling without refspecs' ' (cd local2 && git reset --hard && GIT_REMOTE_TESTGIT_NOREFSPEC=1 git pull 2>../error) && - test_i18ngrep "this remote helper should implement refspec capability" error && + test_grep "this remote helper should implement refspec capability" error && compare_refs local2 HEAD server HEAD ' @@ -157,7 +157,7 @@ test_expect_success 'pushing without refspecs' ' GIT_REMOTE_TESTGIT_NOREFSPEC=1 && export GIT_REMOTE_TESTGIT_NOREFSPEC && test_must_fail git push 2>../error) && - test_i18ngrep "remote-helper doesn.t support push; refspec needed" error + test_grep "remote-helper doesn.t support push; refspec needed" error ' test_expect_success 'pulling without marks' ' @@ -256,7 +256,7 @@ clean_mark () { test_expect_success 'proper failure checks for fetching' ' (cd local && test_must_fail env GIT_REMOTE_TESTGIT_FAILURE=1 git fetch 2>error && - test_i18ngrep -q "error while running fast-import" error + test_grep -q "error while running fast-import" error ) ' diff --git a/t/t5811-proto-disable-git.sh b/t/t5811-proto-disable-git.sh index 8ac6b2a1d0..ed773e7432 100755 --- a/t/t5811-proto-disable-git.sh +++ b/t/t5811-proto-disable-git.sh @@ -1,6 +1,8 @@ #!/bin/sh test_description='test disabling of git-over-tcp in clone/fetch' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY/lib-proto-disable.sh" . "$TEST_DIRECTORY/lib-git-daemon.sh" diff --git a/t/t5812-proto-disable-http.sh b/t/t5812-proto-disable-http.sh index d8da5f58d1..769c717e88 100755 --- a/t/t5812-proto-disable-http.sh +++ b/t/t5812-proto-disable-http.sh @@ -20,7 +20,7 @@ test_expect_success 'http(s) transport respects GIT_ALLOW_PROTOCOL' ' test_must_fail env GIT_ALLOW_PROTOCOL=http:https \ GIT_SMART_HTTP=0 \ git clone "$HTTPD_URL/ftp-redir/repo.git" 2>stderr && - test_i18ngrep -E "(ftp.*disabled|your curl version is too old)" stderr + test_grep -E "(ftp.*disabled|your curl version is too old)" stderr ' test_expect_success 'curl limits redirects' ' diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh index 12def7bcbf..6289a2e8b0 100755 --- a/t/t6000-rev-list-misc.sh +++ b/t/t6000-rev-list-misc.sh @@ -169,4 +169,17 @@ test_expect_success 'rev-list --count --objects' ' test_line_count = $count actual ' +test_expect_success 'rev-list --unpacked' ' + git repack -ad && + test_commit unpacked && + + git rev-list --objects --no-object-names unpacked^.. >expect.raw && + sort expect.raw >expect && + + git rev-list --all --objects --unpacked --no-object-names >actual.raw && + sort actual.raw >actual && + + test_cmp expect actual +' + test_done diff --git a/t/t6001-rev-list-graft.sh b/t/t6001-rev-list-graft.sh index 16635ecc33..73a2465aa0 100755 --- a/t/t6001-rev-list-graft.sh +++ b/t/t6001-rev-list-graft.sh @@ -118,10 +118,10 @@ done test_expect_success 'show advice that grafts are deprecated' ' git show HEAD 2>err && - test_i18ngrep "git replace" err && + test_grep "git replace" err && test_config advice.graftFileDeprecated false && git show HEAD 2>err && - test_i18ngrep ! "git replace" err + test_grep ! "git replace" err ' test_done diff --git a/t/t6005-rev-list-count.sh b/t/t6005-rev-list-count.sh index 0729f800c3..ee0306aeec 100755 --- a/t/t6005-rev-list-count.sh +++ b/t/t6005-rev-list-count.sh @@ -18,20 +18,34 @@ test_expect_success 'no options' ' ' test_expect_success '--max-count' ' + test_must_fail git rev-list --max-count=1q HEAD 2>error && + grep "not an integer" error && + test_stdout_line_count = 0 git rev-list HEAD --max-count=0 && test_stdout_line_count = 3 git rev-list HEAD --max-count=3 && test_stdout_line_count = 5 git rev-list HEAD --max-count=5 && - test_stdout_line_count = 5 git rev-list HEAD --max-count=10 + test_stdout_line_count = 5 git rev-list HEAD --max-count=10 && + test_stdout_line_count = 5 git rev-list HEAD --max-count=-1 ' test_expect_success '--max-count all forms' ' + test_must_fail git rev-list -1q HEAD 2>error && + grep "not an integer" error && + test_must_fail git rev-list --1 HEAD && + test_must_fail git rev-list -n 1q HEAD 2>error && + grep "not an integer" error && + test_stdout_line_count = 1 git rev-list HEAD --max-count=1 && test_stdout_line_count = 1 git rev-list HEAD -1 && test_stdout_line_count = 1 git rev-list HEAD -n1 && - test_stdout_line_count = 1 git rev-list HEAD -n 1 + test_stdout_line_count = 1 git rev-list HEAD -n 1 && + test_stdout_line_count = 5 git rev-list HEAD -n -1 ' test_expect_success '--skip' ' + test_must_fail git rev-list --skip 1q HEAD 2>error && + grep "not an integer" error && + test_stdout_line_count = 5 git rev-list HEAD --skip=0 && test_stdout_line_count = 2 git rev-list HEAD --skip=3 && test_stdout_line_count = 0 git rev-list HEAD --skip=5 && diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh index 41d0ca00b1..573eb97a0f 100755 --- a/t/t6006-rev-list-format.sh +++ b/t/t6006-rev-list-format.sh @@ -493,7 +493,7 @@ test_expect_success 'empty email' ' test_tick && C=$(GIT_AUTHOR_EMAIL= git commit-tree HEAD^{tree} </dev/null) && A=$(git show --pretty=format:%an,%ae,%ad%n -s $C) && - verbose test "$A" = "$GIT_AUTHOR_NAME,,Thu Apr 7 15:14:13 2005 -0700" + test "$A" = "$GIT_AUTHOR_NAME,,Thu Apr 7 15:14:13 2005 -0700" ' test_expect_success 'del LF before empty (1)' ' diff --git a/t/t6009-rev-list-parent.sh b/t/t6009-rev-list-parent.sh index 5a67bbc760..91db8fafe8 100755 --- a/t/t6009-rev-list-parent.sh +++ b/t/t6009-rev-list-parent.sh @@ -5,6 +5,7 @@ test_description='ancestor culling and limiting by parent number' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh check_revlist () { @@ -62,6 +63,17 @@ test_expect_success 'setup roots, merges and octopuses' ' git checkout main ' +test_expect_success 'parse --max-parents & --min-parents' ' + test_must_fail git rev-list --max-parents=1q HEAD 2>error && + grep "not an integer" error && + + test_must_fail git rev-list --min-parents=1q HEAD 2>error && + grep "not an integer" error && + + git rev-list --max-parents=1 --min-parents=1 HEAD && + git rev-list --max-parents=-1 --min-parents=-1 HEAD +' + test_expect_success 'rev-list roots' ' check_revlist "--max-parents=0" one five diff --git a/t/t6017-rev-list-stdin.sh b/t/t6017-rev-list-stdin.sh index 05162512a0..4821b90e74 100755 --- a/t/t6017-rev-list-stdin.sh +++ b/t/t6017-rev-list-stdin.sh @@ -48,7 +48,9 @@ test_expect_success setup ' git add file-$i && test_tick && git commit -m side-$i || exit - done + done && + + git update-ref refs/heads/-dashed-branch HEAD ) ' @@ -60,6 +62,13 @@ check side-1 ^side-7 -- file-2 check side-3 ^side-4 -- file-3 check side-3 ^side-2 check side-3 ^side-2 -- file-1 +check --all +check --all --not --branches +check --glob=refs/heads +check --glob=refs/heads -- +check --glob=refs/heads -- file-1 +check --end-of-options -dashed-branch +check --all --not refs/heads/main test_expect_success 'not only --stdin' ' cat >expect <<-EOF && @@ -78,4 +87,65 @@ test_expect_success 'not only --stdin' ' test_cmp expect actual ' +test_expect_success 'pseudo-opt with missing value' ' + cat >input <<-EOF && + --glob + refs/heads + EOF + + cat >expect <<-EOF && + fatal: Option ${SQ}--glob${SQ} requires a value + EOF + + test_must_fail git rev-list --stdin <input 2>error && + test_cmp expect error +' + +test_expect_success 'pseudo-opt with invalid value' ' + cat >input <<-EOF && + --no-walk=garbage + EOF + + cat >expect <<-EOF && + error: invalid argument to --no-walk + fatal: invalid option ${SQ}--no-walk=garbage${SQ} in --stdin mode + EOF + + test_must_fail git rev-list --stdin <input 2>error && + test_cmp expect error +' + +test_expect_success 'unknown option without --end-of-options' ' + cat >input <<-EOF && + -dashed-branch + EOF + + cat >expect <<-EOF && + fatal: invalid option ${SQ}-dashed-branch${SQ} in --stdin mode + EOF + + test_must_fail git rev-list --stdin <input 2>error && + test_cmp expect error +' + +test_expect_success '--not on command line does not influence revisions read via --stdin' ' + cat >input <<-EOF && + refs/heads/main + EOF + git rev-list refs/heads/main >expect && + + git rev-list refs/heads/main --not --stdin <input >actual && + test_cmp expect actual +' + +test_expect_success '--not via stdin does not influence revisions from command line' ' + cat >input <<-EOF && + --not + EOF + git rev-list refs/heads/main >expect && + + git rev-list refs/heads/main --stdin refs/heads/main <input >actual && + test_cmp expect actual +' + test_done diff --git a/t/t6018-rev-list-glob.sh b/t/t6018-rev-list-glob.sh index aabf590dda..3b181f771c 100755 --- a/t/t6018-rev-list-glob.sh +++ b/t/t6018-rev-list-glob.sh @@ -187,7 +187,7 @@ test_expect_success 'rev-parse --exclude=ref with --remotes=glob' ' compare rev-parse "--exclude=upstream/x --remotes=upstream/*" "upstream/one upstream/two" ' -for section in receive uploadpack +for section in fetch receive uploadpack do test_expect_success "rev-parse --exclude-hidden=$section with --all" ' compare "-c transfer.hideRefs=refs/remotes/ rev-parse" "--branches --tags" "--exclude-hidden=$section --all" @@ -214,15 +214,13 @@ do for pseudoopt in branches tags remotes do test_expect_success "rev-parse --exclude-hidden=$section fails with --$pseudoopt" ' - echo "error: --exclude-hidden cannot be used together with --$pseudoopt" >expected && test_must_fail git rev-parse --exclude-hidden=$section --$pseudoopt 2>err && - test_cmp expected err + test_grep "error: options .--exclude-hidden. and .--$pseudoopt. cannot be used together" err ' test_expect_success "rev-parse --exclude-hidden=$section fails with --$pseudoopt=pattern" ' - echo "error: --exclude-hidden cannot be used together with --$pseudoopt" >expected && test_must_fail git rev-parse --exclude-hidden=$section --$pseudoopt=pattern 2>err && - test_cmp expected err + test_grep "error: options .--exclude-hidden. and .--$pseudoopt. cannot be used together" err ' done done diff --git a/t/t6020-bundle-misc.sh b/t/t6020-bundle-misc.sh index 7d40994991..3e6bcbf30c 100755 --- a/t/t6020-bundle-misc.sh +++ b/t/t6020-bundle-misc.sh @@ -10,6 +10,7 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . ./test-lib.sh . "$TEST_DIRECTORY"/lib-bundle.sh +. "$TEST_DIRECTORY"/lib-terminal.sh for cmd in create verify list-heads unbundle do @@ -606,4 +607,48 @@ test_expect_success 'verify catches unreachable, broken prerequisites' ' ) ' +test_expect_success 'bundle progress includes write phase' ' + GIT_PROGRESS_DELAY=0 \ + git bundle create --progress out.bundle --all 2>err && + grep 'Writing' err +' + +test_expect_success TTY 'create --quiet disables all bundle progress' ' + test_terminal env GIT_PROGRESS_DELAY=0 \ + git bundle create --quiet out.bundle --all 2>err && + test_must_be_empty err +' + +test_expect_success 'bundle progress with --no-quiet' ' + GIT_PROGRESS_DELAY=0 \ + git bundle create --no-quiet out.bundle --all 2>err && + grep "%" err +' + +test_expect_success 'read bundle over stdin' ' + git bundle create some.bundle HEAD && + + git bundle verify - <some.bundle 2>err && + grep "<stdin> is okay" err && + + git bundle list-heads some.bundle >expect && + git bundle list-heads - <some.bundle >actual && + test_cmp expect actual && + + git bundle unbundle some.bundle >expect && + git bundle unbundle - <some.bundle >actual && + test_cmp expect actual +' + +test_expect_success 'send a bundle to standard output' ' + git bundle create - --all HEAD >bundle-one && + mkdir -p down && + git -C down bundle create - --all HEAD >bundle-two && + git bundle verify bundle-one && + git bundle verify bundle-two && + git ls-remote bundle-one >expect && + git ls-remote bundle-two >actual && + test_cmp expect actual +' + test_done diff --git a/t/t6021-rev-list-exclude-hidden.sh b/t/t6021-rev-list-exclude-hidden.sh index 11c50b7c0d..51df02105d 100755 --- a/t/t6021-rev-list-exclude-hidden.sh +++ b/t/t6021-rev-list-exclude-hidden.sh @@ -22,7 +22,7 @@ test_expect_success 'invalid section' ' test_cmp expected err ' -for section in receive uploadpack +for section in fetch receive uploadpack do test_expect_success "$section: passed multiple times" ' echo "fatal: --exclude-hidden= passed more than once" >expected && @@ -151,12 +151,12 @@ do do test_expect_success "$section: fails with --$pseudoopt" ' test_must_fail git rev-list --exclude-hidden=$section --$pseudoopt 2>err && - test_i18ngrep "error: --exclude-hidden cannot be used together with --$pseudoopt" err + test_grep "error: options .--exclude-hidden. and .--$pseudoopt. cannot be used together" err ' test_expect_success "$section: fails with --$pseudoopt=pattern" ' test_must_fail git rev-list --exclude-hidden=$section --$pseudoopt=pattern 2>err && - test_i18ngrep "error: --exclude-hidden cannot be used together with --$pseudoopt" err + test_grep "error: options .--exclude-hidden. and .--$pseudoopt. cannot be used together" err ' done done diff --git a/t/t6022-rev-list-missing.sh b/t/t6022-rev-list-missing.sh new file mode 100755 index 0000000000..211672759a --- /dev/null +++ b/t/t6022-rev-list-missing.sh @@ -0,0 +1,80 @@ +#!/bin/sh + +test_description='handling of missing objects in rev-list' + +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh + +# We setup the repository with two commits, this way HEAD is always +# available and we can hide commit 1. +test_expect_success 'create repository and alternate directory' ' + test_commit 1 && + test_commit 2 && + test_commit 3 +' + +# We manually corrupt the repository, which means that the commit-graph may +# contain references to already-deleted objects. We thus need to enable +# commit-graph paranoia to not returned these deleted commits from the graph. +GIT_COMMIT_GRAPH_PARANOIA=true +export GIT_COMMIT_GRAPH_PARANOIA + +for obj in "HEAD~1" "HEAD~1^{tree}" "HEAD:1.t" +do + test_expect_success "rev-list --missing=error fails with missing object $obj" ' + oid="$(git rev-parse $obj)" && + path=".git/objects/$(test_oid_to_path $oid)" && + + mv "$path" "$path.hidden" && + test_when_finished "mv $path.hidden $path" && + + test_must_fail git rev-list --missing=error --objects \ + --no-object-names HEAD + ' +done + +for obj in "HEAD~1" "HEAD~1^{tree}" "HEAD:1.t" +do + for action in "allow-any" "print" + do + test_expect_success "rev-list --missing=$action with missing $obj" ' + oid="$(git rev-parse $obj)" && + path=".git/objects/$(test_oid_to_path $oid)" && + + # Before the object is made missing, we use rev-list to + # get the expected oids. + git rev-list --objects --no-object-names \ + HEAD ^$obj >expect.raw && + + # Blobs are shared by all commits, so evethough a commit/tree + # might be skipped, its blob must be accounted for. + if [ $obj != "HEAD:1.t" ]; then + echo $(git rev-parse HEAD:1.t) >>expect.raw && + echo $(git rev-parse HEAD:2.t) >>expect.raw + fi && + + mv "$path" "$path.hidden" && + test_when_finished "mv $path.hidden $path" && + + git rev-list --missing=$action --objects --no-object-names \ + HEAD >actual.raw && + + # When the action is to print, we should also add the missing + # oid to the expect list. + case $action in + allow-any) + ;; + print) + grep ?$oid actual.raw && + echo ?$oid >>expect.raw + ;; + esac && + + sort actual.raw >actual && + sort expect.raw >expect && + test_cmp expect actual + ' + done +done + +test_done diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index 3ba4fdf615..2a5b7d8379 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -122,6 +122,29 @@ test_expect_success 'bisect start without -- takes unknown arg as pathspec' ' grep bar ".git/BISECT_NAMES" ' +test_expect_success 'bisect reset: back in a branch checked out also elsewhere' ' + echo "shared" > branch.expect && + test_bisect_reset() { + git -C $1 bisect start && + git -C $1 bisect good $HASH1 && + git -C $1 bisect bad $HASH3 && + git -C $1 bisect reset && + git -C $1 branch --show-current > branch.output && + cmp branch.expect branch.output + } && + test_when_finished " + git worktree remove wt1 && + git worktree remove wt2 && + git branch -d shared + " && + git worktree add wt1 -b shared && + git worktree add wt2 -f shared && + # we test in both worktrees to ensure that works + # as expected with "first" and "next" worktrees + test_bisect_reset wt1 && + test_bisect_reset wt2 +' + test_expect_success 'bisect reset: back in the main branch' ' git bisect reset && echo "* main" > branch.expect && @@ -197,7 +220,7 @@ test_expect_success 'bisect start: existing ".git/BISECT_START" not modified if cp .git/BISECT_START saved && test_must_fail git bisect start $HASH4 foo -- && git branch > branch.output && - test_i18ngrep "* (no branch, bisect started on other)" branch.output > /dev/null && + test_grep "* (no branch, bisect started on other)" branch.output > /dev/null && test_cmp saved .git/BISECT_START ' test_expect_success 'bisect start: no ".git/BISECT_START" if mistaken rev' ' @@ -565,7 +588,7 @@ test_expect_success 'bisect starting with a detached HEAD' ' test_expect_success 'bisect errors out if bad and good are mistaken' ' git bisect reset && test_must_fail git bisect start $HASH2 $HASH4 2> rev_list_error && - test_i18ngrep "mistook good and bad" rev_list_error && + test_grep "mistook good and bad" rev_list_error && git bisect reset ' @@ -607,7 +630,7 @@ test_expect_success 'side branch creation' ' test_expect_success 'good merge base when good and bad are siblings' ' git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt && - test_i18ngrep "merge base must be tested" my_bisect_log.txt && + test_grep "merge base must be tested" my_bisect_log.txt && grep $HASH4 my_bisect_log.txt && git bisect good > my_bisect_log.txt && ! grep "merge base must be tested" my_bisect_log.txt && @@ -616,7 +639,7 @@ test_expect_success 'good merge base when good and bad are siblings' ' ' test_expect_success 'skipped merge base when good and bad are siblings' ' git bisect start "$SIDE_HASH7" "$HASH7" > my_bisect_log.txt && - test_i18ngrep "merge base must be tested" my_bisect_log.txt && + test_grep "merge base must be tested" my_bisect_log.txt && grep $HASH4 my_bisect_log.txt && git bisect skip > my_bisect_log.txt 2>&1 && grep "warning" my_bisect_log.txt && @@ -626,11 +649,11 @@ test_expect_success 'skipped merge base when good and bad are siblings' ' test_expect_success 'bad merge base when good and bad are siblings' ' git bisect start "$HASH7" HEAD > my_bisect_log.txt && - test_i18ngrep "merge base must be tested" my_bisect_log.txt && + test_grep "merge base must be tested" my_bisect_log.txt && grep $HASH4 my_bisect_log.txt && test_must_fail git bisect bad > my_bisect_log.txt 2>&1 && - test_i18ngrep "merge base $HASH4 is bad" my_bisect_log.txt && - test_i18ngrep "fixed between $HASH4 and \[$SIDE_HASH7\]" my_bisect_log.txt && + test_grep "merge base $HASH4 is bad" my_bisect_log.txt && + test_grep "fixed between $HASH4 and \[$SIDE_HASH7\]" my_bisect_log.txt && git bisect reset ' @@ -681,9 +704,9 @@ test_expect_success '"git bisect run --first-parent" simple case' ' test_expect_success 'good merge bases when good and bad are siblings' ' git bisect start "$B_HASH" "$A_HASH" > my_bisect_log.txt && - test_i18ngrep "merge base must be tested" my_bisect_log.txt && + test_grep "merge base must be tested" my_bisect_log.txt && git bisect good > my_bisect_log2.txt && - test_i18ngrep "merge base must be tested" my_bisect_log2.txt && + test_grep "merge base must be tested" my_bisect_log2.txt && { { grep "$SIDE_HASH5" my_bisect_log.txt && @@ -698,14 +721,14 @@ test_expect_success 'good merge bases when good and bad are siblings' ' test_expect_success 'optimized merge base checks' ' git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt && - test_i18ngrep "merge base must be tested" my_bisect_log.txt && + test_grep "merge base must be tested" my_bisect_log.txt && grep "$HASH4" my_bisect_log.txt && git bisect good > my_bisect_log2.txt && test -f ".git/BISECT_ANCESTORS_OK" && test "$HASH6" = $(git rev-parse --verify HEAD) && git bisect bad && git bisect good "$A_HASH" > my_bisect_log4.txt && - test_i18ngrep "merge base must be tested" my_bisect_log4.txt && + test_grep "merge base must be tested" my_bisect_log4.txt && test_path_is_missing ".git/BISECT_ANCESTORS_OK" ' @@ -783,7 +806,7 @@ test_expect_success 'skipping away from skipped commit' ' test_expect_success 'erroring out when using bad path arguments' ' test_must_fail git bisect start $PARA_HASH7 $HASH1 -- foobar 2> error.txt && - test_i18ngrep "bad path arguments" error.txt + test_grep "bad path arguments" error.txt ' test_expect_success 'test bisection on bare repo - --no-checkout specified' ' diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh index a313849406..acc281c116 100755 --- a/t/t6040-tracking-info.sh +++ b/t/t6040-tracking-info.sh @@ -5,6 +5,7 @@ test_description='remote tracking stats' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh advance () { @@ -82,13 +83,13 @@ test_expect_success 'checkout (diverged from upstream)' ' ( cd test && git checkout b1 ) >actual && - test_i18ngrep "have 1 and 1 different" actual + test_grep "have 1 and 1 different" actual ' test_expect_success 'checkout with local tracked branch' ' git checkout main && git checkout follower >actual && - test_i18ngrep "is ahead of" actual + test_grep "is ahead of" actual ' test_expect_success 'checkout (upstream is gone)' ' @@ -96,14 +97,14 @@ test_expect_success 'checkout (upstream is gone)' ' cd test && git checkout b5 ) >actual && - test_i18ngrep "is based on .*, but the upstream is gone." actual + test_grep "is based on .*, but the upstream is gone." actual ' test_expect_success 'checkout (up-to-date with upstream)' ' ( cd test && git checkout b6 ) >actual && - test_i18ngrep "Your branch is up to date with .origin/main" actual + test_grep "Your branch is up to date with .origin/main" actual ' test_expect_success 'status (diverged from upstream)' ' @@ -113,7 +114,7 @@ test_expect_success 'status (diverged from upstream)' ' # reports nothing to commit test_must_fail git commit --dry-run ) >actual && - test_i18ngrep "have 1 and 1 different" actual + test_grep "have 1 and 1 different" actual ' test_expect_success 'status (upstream is gone)' ' @@ -123,7 +124,7 @@ test_expect_success 'status (upstream is gone)' ' # reports nothing to commit test_must_fail git commit --dry-run ) >actual && - test_i18ngrep "is based on .*, but the upstream is gone." actual + test_grep "is based on .*, but the upstream is gone." actual ' test_expect_success 'status (up-to-date with upstream)' ' @@ -133,7 +134,7 @@ test_expect_success 'status (up-to-date with upstream)' ' # reports nothing to commit test_must_fail git commit --dry-run ) >actual && - test_i18ngrep "Your branch is up to date with .origin/main" actual + test_grep "Your branch is up to date with .origin/main" actual ' cat >expect <<\EOF @@ -252,7 +253,7 @@ test_expect_success 'fail to track lightweight tags' ' git checkout main && git tag light && test_must_fail git branch --track lighttrack light >actual && - test_i18ngrep ! "set up to track" actual && + test_grep ! "set up to track" actual && test_must_fail git checkout lighttrack ' @@ -260,7 +261,7 @@ test_expect_success 'fail to track annotated tags' ' git checkout main && git tag -m heavy heavy && test_must_fail git branch --track heavytrack heavy >actual && - test_i18ngrep ! "set up to track" actual && + test_grep ! "set up to track" actual && test_must_fail git checkout heavytrack ' diff --git a/t/t6050-replace.sh b/t/t6050-replace.sh index 2500acc2ef..c6e9b33e44 100755 --- a/t/t6050-replace.sh +++ b/t/t6050-replace.sh @@ -44,7 +44,7 @@ commit_peeling_shows_parents () _parent_number=$(( $_parent_number + 1 )) done && test_must_fail git rev-parse --verify $_commit^$_parent_number 2>err && - test_i18ngrep "Needed a single revision" err + test_grep "Needed a single revision" err } commit_has_parents () @@ -62,59 +62,59 @@ HASH6= HASH7= test_expect_success 'set up buggy branch' ' - echo "line 1" >>hello && - echo "line 2" >>hello && - echo "line 3" >>hello && - echo "line 4" >>hello && - add_and_commit_file hello "4 lines" && - HASH1=$(git rev-parse --verify HEAD) && - echo "line BUG" >>hello && - echo "line 6" >>hello && - echo "line 7" >>hello && - echo "line 8" >>hello && - add_and_commit_file hello "4 more lines with a BUG" && - HASH2=$(git rev-parse --verify HEAD) && - echo "line 9" >>hello && - echo "line 10" >>hello && - add_and_commit_file hello "2 more lines" && - HASH3=$(git rev-parse --verify HEAD) && - echo "line 11" >>hello && - add_and_commit_file hello "1 more line" && - HASH4=$(git rev-parse --verify HEAD) && - sed -e "s/BUG/5/" hello >hello.new && - mv hello.new hello && - add_and_commit_file hello "BUG fixed" && - HASH5=$(git rev-parse --verify HEAD) && - echo "line 12" >>hello && - echo "line 13" >>hello && - add_and_commit_file hello "2 more lines" && - HASH6=$(git rev-parse --verify HEAD) && - echo "line 14" >>hello && - echo "line 15" >>hello && - echo "line 16" >>hello && - add_and_commit_file hello "again 3 more lines" && - HASH7=$(git rev-parse --verify HEAD) + echo "line 1" >>hello && + echo "line 2" >>hello && + echo "line 3" >>hello && + echo "line 4" >>hello && + add_and_commit_file hello "4 lines" && + HASH1=$(git rev-parse --verify HEAD) && + echo "line BUG" >>hello && + echo "line 6" >>hello && + echo "line 7" >>hello && + echo "line 8" >>hello && + add_and_commit_file hello "4 more lines with a BUG" && + HASH2=$(git rev-parse --verify HEAD) && + echo "line 9" >>hello && + echo "line 10" >>hello && + add_and_commit_file hello "2 more lines" && + HASH3=$(git rev-parse --verify HEAD) && + echo "line 11" >>hello && + add_and_commit_file hello "1 more line" && + HASH4=$(git rev-parse --verify HEAD) && + sed -e "s/BUG/5/" hello >hello.new && + mv hello.new hello && + add_and_commit_file hello "BUG fixed" && + HASH5=$(git rev-parse --verify HEAD) && + echo "line 12" >>hello && + echo "line 13" >>hello && + add_and_commit_file hello "2 more lines" && + HASH6=$(git rev-parse --verify HEAD) && + echo "line 14" >>hello && + echo "line 15" >>hello && + echo "line 16" >>hello && + add_and_commit_file hello "again 3 more lines" && + HASH7=$(git rev-parse --verify HEAD) ' test_expect_success 'replace the author' ' - git cat-file commit $HASH2 | grep "author A U Thor" && - R=$(git cat-file commit $HASH2 | sed -e "s/A U/O/" | git hash-object -t commit --stdin -w) && - git cat-file commit $R | grep "author O Thor" && - git update-ref refs/replace/$HASH2 $R && - git show HEAD~5 | grep "O Thor" && - git show $HASH2 | grep "O Thor" + git cat-file commit $HASH2 | grep "author A U Thor" && + R=$(git cat-file commit $HASH2 | sed -e "s/A U/O/" | git hash-object -t commit --stdin -w) && + git cat-file commit $R | grep "author O Thor" && + git update-ref refs/replace/$HASH2 $R && + git show HEAD~5 | grep "O Thor" && + git show $HASH2 | grep "O Thor" ' test_expect_success 'test --no-replace-objects option' ' - git cat-file commit $HASH2 | grep "author O Thor" && - git --no-replace-objects cat-file commit $HASH2 | grep "author A U Thor" && - git show $HASH2 | grep "O Thor" && - git --no-replace-objects show $HASH2 | grep "A U Thor" + git cat-file commit $HASH2 | grep "author O Thor" && + git --no-replace-objects cat-file commit $HASH2 | grep "author A U Thor" && + git show $HASH2 | grep "O Thor" && + git --no-replace-objects show $HASH2 | grep "A U Thor" ' test_expect_success 'test GIT_NO_REPLACE_OBJECTS env variable' ' - GIT_NO_REPLACE_OBJECTS=1 git cat-file commit $HASH2 | grep "author A U Thor" && - GIT_NO_REPLACE_OBJECTS=1 git show $HASH2 | grep "A U Thor" + GIT_NO_REPLACE_OBJECTS=1 git cat-file commit $HASH2 | grep "author A U Thor" && + GIT_NO_REPLACE_OBJECTS=1 git show $HASH2 | grep "A U Thor" ' test_expect_success 'test core.usereplacerefs config option' ' @@ -132,64 +132,64 @@ tagger T A Gger <> 0 +0000 EOF test_expect_success 'tag replaced commit' ' - git update-ref refs/tags/mytag $(git mktag <tag.sig) + git update-ref refs/tags/mytag $(git mktag <tag.sig) ' test_expect_success '"git fsck" works' ' - git fsck main >fsck_main.out && - test_i18ngrep "dangling commit $R" fsck_main.out && - test_i18ngrep "dangling tag $(git show-ref -s refs/tags/mytag)" fsck_main.out && - test -z "$(git fsck)" + git fsck main >fsck_main.out && + test_grep "dangling commit $R" fsck_main.out && + test_grep "dangling tag $(git show-ref -s refs/tags/mytag)" fsck_main.out && + test -z "$(git fsck)" ' test_expect_success 'repack, clone and fetch work' ' - git repack -a -d && - git clone --no-hardlinks . clone_dir && - ( - cd clone_dir && - git show HEAD~5 | grep "A U Thor" && - git show $HASH2 | grep "A U Thor" && - git cat-file commit $R && - git repack -a -d && - test_must_fail git cat-file commit $R && - git fetch ../ "refs/replace/*:refs/replace/*" && - git show HEAD~5 | grep "O Thor" && - git show $HASH2 | grep "O Thor" && - git cat-file commit $R - ) + git repack -a -d && + git clone --no-hardlinks . clone_dir && + ( + cd clone_dir && + git show HEAD~5 | grep "A U Thor" && + git show $HASH2 | grep "A U Thor" && + git cat-file commit $R && + git repack -a -d && + test_must_fail git cat-file commit $R && + git fetch ../ "refs/replace/*:refs/replace/*" && + git show HEAD~5 | grep "O Thor" && + git show $HASH2 | grep "O Thor" && + git cat-file commit $R + ) ' test_expect_success '"git replace" listing and deleting' ' - test "$HASH2" = "$(git replace -l)" && - test "$HASH2" = "$(git replace)" && - aa=${HASH2%??????????????????????????????????????} && - test "$HASH2" = "$(git replace --list "$aa*")" && - test_must_fail git replace -d $R && - test_must_fail git replace --delete && - test_must_fail git replace -l -d $HASH2 && - git replace -d $HASH2 && - git show $HASH2 | grep "A U Thor" && - test -z "$(git replace -l)" + test "$HASH2" = "$(git replace -l)" && + test "$HASH2" = "$(git replace)" && + aa=${HASH2%??????????????????????????????????????} && + test "$HASH2" = "$(git replace --list "$aa*")" && + test_must_fail git replace -d $R && + test_must_fail git replace --delete && + test_must_fail git replace -l -d $HASH2 && + git replace -d $HASH2 && + git show $HASH2 | grep "A U Thor" && + test -z "$(git replace -l)" ' test_expect_success '"git replace" replacing' ' - git replace $HASH2 $R && - git show $HASH2 | grep "O Thor" && - test_must_fail git replace $HASH2 $R && - git replace -f $HASH2 $R && - test_must_fail git replace -f && - test "$HASH2" = "$(git replace)" + git replace $HASH2 $R && + git show $HASH2 | grep "O Thor" && + test_must_fail git replace $HASH2 $R && + git replace -f $HASH2 $R && + test_must_fail git replace -f && + test "$HASH2" = "$(git replace)" ' test_expect_success '"git replace" resolves sha1' ' - SHORTHASH2=$(git rev-parse --short=8 $HASH2) && - git replace -d $SHORTHASH2 && - git replace $SHORTHASH2 $R && - git show $HASH2 | grep "O Thor" && - test_must_fail git replace $HASH2 $R && - git replace -f $HASH2 $R && - test_must_fail git replace --force && - test "$HASH2" = "$(git replace)" + SHORTHASH2=$(git rev-parse --short=8 $HASH2) && + git replace -d $SHORTHASH2 && + git replace $SHORTHASH2 $R && + git show $HASH2 | grep "O Thor" && + test_must_fail git replace $HASH2 $R && + git replace -f $HASH2 $R && + test_must_fail git replace --force && + test "$HASH2" = "$(git replace)" ' # This creates a side branch where the bug in H2 @@ -207,79 +207,79 @@ test_expect_success '"git replace" resolves sha1' ' # Then we replace H6 with P6. # test_expect_success 'create parallel branch without the bug' ' - git replace -d $HASH2 && - git show $HASH2 | grep "A U Thor" && - git checkout $HASH1 && - git cherry-pick $HASH2 && - git show $HASH5 | git apply && - git commit --amend -m "hello: 4 more lines WITHOUT the bug" hello && - PARA2=$(git rev-parse --verify HEAD) && - git cherry-pick $HASH3 && - PARA3=$(git rev-parse --verify HEAD) && - git cherry-pick $HASH4 && - PARA4=$(git rev-parse --verify HEAD) && - git cherry-pick $HASH6 && - PARA6=$(git rev-parse --verify HEAD) && - git replace $HASH6 $PARA6 && - git checkout main && - cur=$(git rev-parse --verify HEAD) && - test "$cur" = "$HASH7" && - git log --pretty=oneline | grep $PARA2 && - git remote add cloned ./clone_dir + git replace -d $HASH2 && + git show $HASH2 | grep "A U Thor" && + git checkout $HASH1 && + git cherry-pick $HASH2 && + git show $HASH5 | git apply && + git commit --amend -m "hello: 4 more lines WITHOUT the bug" hello && + PARA2=$(git rev-parse --verify HEAD) && + git cherry-pick $HASH3 && + PARA3=$(git rev-parse --verify HEAD) && + git cherry-pick $HASH4 && + PARA4=$(git rev-parse --verify HEAD) && + git cherry-pick $HASH6 && + PARA6=$(git rev-parse --verify HEAD) && + git replace $HASH6 $PARA6 && + git checkout main && + cur=$(git rev-parse --verify HEAD) && + test "$cur" = "$HASH7" && + git log --pretty=oneline | grep $PARA2 && + git remote add cloned ./clone_dir ' test_expect_success 'push to cloned repo' ' - git push cloned $HASH6^:refs/heads/parallel && - ( - cd clone_dir && - git checkout parallel && - git log --pretty=oneline | grep $PARA2 - ) + git push cloned $HASH6^:refs/heads/parallel && + ( + cd clone_dir && + git checkout parallel && + git log --pretty=oneline | grep $PARA2 + ) ' test_expect_success 'push branch with replacement' ' - git cat-file commit $PARA3 | grep "author A U Thor" && - S=$(git cat-file commit $PARA3 | sed -e "s/A U/O/" | git hash-object -t commit --stdin -w) && - git cat-file commit $S | grep "author O Thor" && - git replace $PARA3 $S && - git show $HASH6~2 | grep "O Thor" && - git show $PARA3 | grep "O Thor" && - git push cloned $HASH6^:refs/heads/parallel2 && - ( - cd clone_dir && - git checkout parallel2 && - git log --pretty=oneline | grep $PARA3 && - git show $PARA3 | grep "A U Thor" - ) + git cat-file commit $PARA3 | grep "author A U Thor" && + S=$(git cat-file commit $PARA3 | sed -e "s/A U/O/" | git hash-object -t commit --stdin -w) && + git cat-file commit $S | grep "author O Thor" && + git replace $PARA3 $S && + git show $HASH6~2 | grep "O Thor" && + git show $PARA3 | grep "O Thor" && + git push cloned $HASH6^:refs/heads/parallel2 && + ( + cd clone_dir && + git checkout parallel2 && + git log --pretty=oneline | grep $PARA3 && + git show $PARA3 | grep "A U Thor" + ) ' test_expect_success 'fetch branch with replacement' ' - git branch tofetch $HASH6 && - ( - cd clone_dir && - git fetch origin refs/heads/tofetch:refs/heads/parallel3 && - git log --pretty=oneline parallel3 >output.txt && - ! grep $PARA3 output.txt && - git show $PARA3 >para3.txt && - grep "A U Thor" para3.txt && - git fetch origin "refs/replace/*:refs/replace/*" && - git log --pretty=oneline parallel3 >output.txt && - grep $PARA3 output.txt && - git show $PARA3 >para3.txt && - grep "O Thor" para3.txt - ) + git branch tofetch $HASH6 && + ( + cd clone_dir && + git fetch origin refs/heads/tofetch:refs/heads/parallel3 && + git log --pretty=oneline parallel3 >output.txt && + ! grep $PARA3 output.txt && + git show $PARA3 >para3.txt && + grep "A U Thor" para3.txt && + git fetch origin "refs/replace/*:refs/replace/*" && + git log --pretty=oneline parallel3 >output.txt && + grep $PARA3 output.txt && + git show $PARA3 >para3.txt && + grep "O Thor" para3.txt + ) ' test_expect_success 'bisect and replacements' ' - git bisect start $HASH7 $HASH1 && - test "$PARA3" = "$(git rev-parse --verify HEAD)" && - git bisect reset && - GIT_NO_REPLACE_OBJECTS=1 git bisect start $HASH7 $HASH1 && - test "$HASH4" = "$(git rev-parse --verify HEAD)" && - git bisect reset && - git --no-replace-objects bisect start $HASH7 $HASH1 && - test "$HASH4" = "$(git rev-parse --verify HEAD)" && - git bisect reset + git bisect start $HASH7 $HASH1 && + test "$PARA3" = "$(git rev-parse --verify HEAD)" && + git bisect reset && + GIT_NO_REPLACE_OBJECTS=1 git bisect start $HASH7 $HASH1 && + test "$HASH4" = "$(git rev-parse --verify HEAD)" && + git bisect reset && + git --no-replace-objects bisect start $HASH7 $HASH1 && + test "$HASH4" = "$(git rev-parse --verify HEAD)" && + git bisect reset ' test_expect_success 'index-pack and replacements' ' @@ -490,9 +490,9 @@ test_expect_success '--convert-graft-file' ' $(git rev-parse HEAD^^ HEAD^ HEAD^^ HEAD^2) \ >.git/info/grafts && git status 2>stderr && - test_i18ngrep "hint:.*grafts is deprecated" stderr && + test_grep "hint:.*grafts is deprecated" stderr && git replace --convert-graft-file 2>stderr && - test_i18ngrep ! "hint:.*grafts is deprecated" stderr && + test_grep ! "hint:.*grafts is deprecated" stderr && test_path_is_missing .git/info/grafts && : verify that the history is now "grafted" && @@ -503,8 +503,8 @@ test_expect_success '--convert-graft-file' ' test_when_finished "rm -f .git/info/grafts" && echo $EMPTY_BLOB $EMPTY_TREE >.git/info/grafts && test_must_fail git replace --convert-graft-file 2>err && - test_i18ngrep "$EMPTY_BLOB $EMPTY_TREE" err && - test_i18ngrep "$EMPTY_BLOB $EMPTY_TREE" .git/info/grafts + test_grep "$EMPTY_BLOB $EMPTY_TREE" err && + test_grep "$EMPTY_BLOB $EMPTY_TREE" .git/info/grafts ' test_done diff --git a/t/t6102-rev-list-unexpected-objects.sh b/t/t6102-rev-list-unexpected-objects.sh index 9350b5fd2c..5d28507efc 100755 --- a/t/t6102-rev-list-unexpected-objects.sh +++ b/t/t6102-rev-list-unexpected-objects.sh @@ -28,7 +28,7 @@ test_expect_success 'TODO (should fail!): traverse unexpected non-blob entry (lo test_expect_success 'traverse unexpected non-blob entry (seen)' ' test_must_fail git rev-list --objects $tree $broken_tree >output 2>&1 && - test_i18ngrep "is not a blob" output + test_grep "is not a blob" output ' test_expect_success 'setup unexpected non-tree entry' ' @@ -42,7 +42,7 @@ test_expect_success 'traverse unexpected non-tree entry (lone)' ' test_expect_success 'traverse unexpected non-tree entry (seen)' ' test_must_fail git rev-list --objects $blob $broken_tree >output 2>&1 && - test_i18ngrep "is not a tree" output + test_grep "is not a tree" output ' test_expect_success 'setup unexpected non-commit parent' ' @@ -54,13 +54,13 @@ test_expect_success 'setup unexpected non-commit parent' ' test_expect_success 'traverse unexpected non-commit parent (lone)' ' test_must_fail git rev-list --objects $broken_commit >output 2>&1 && - test_i18ngrep "not a commit" output + test_grep "not a commit" output ' test_expect_success 'traverse unexpected non-commit parent (seen)' ' test_must_fail git rev-list --objects $blob $broken_commit \ >output 2>&1 && - test_i18ngrep "not a commit" output + test_grep "not a commit" output ' test_expect_success 'setup unexpected non-tree root' ' @@ -76,7 +76,7 @@ test_expect_success 'traverse unexpected non-tree root (lone)' ' test_expect_success 'traverse unexpected non-tree root (seen)' ' test_must_fail git rev-list --objects $blob $broken_commit \ >output 2>&1 && - test_i18ngrep "not a tree" output + test_grep "not a tree" output ' test_expect_success 'setup unexpected non-commit tag' ' @@ -93,7 +93,7 @@ test_expect_success 'traverse unexpected non-commit tag (lone)' ' test_expect_success 'traverse unexpected non-commit tag (seen)' ' test_must_fail git rev-list --objects $blob $tag >output 2>&1 && - test_i18ngrep "not a commit" output + test_grep "not a commit" output ' test_expect_success 'setup unexpected non-tree tag' ' @@ -110,7 +110,7 @@ test_expect_success 'traverse unexpected non-tree tag (lone)' ' test_expect_success 'traverse unexpected non-tree tag (seen)' ' test_must_fail git rev-list --objects $blob $tag >output 2>&1 && - test_i18ngrep "not a tree" output + test_grep "not a tree" output ' test_expect_success 'setup unexpected non-blob tag' ' @@ -127,7 +127,7 @@ test_expect_success 'traverse unexpected non-blob tag (lone)' ' test_expect_success 'traverse unexpected non-blob tag (seen)' ' test_must_fail git rev-list --objects $commit $tag >output 2>&1 && - test_i18ngrep "not a blob" output + test_grep "not a blob" output ' test_done diff --git a/t/t6112-rev-list-filters-objects.sh b/t/t6112-rev-list-filters-objects.sh index 8d9d6604f0..52822b9461 100755 --- a/t/t6112-rev-list-filters-objects.sh +++ b/t/t6112-rev-list-filters-objects.sh @@ -457,7 +457,7 @@ expect_invalid_filter_spec () { test_must_fail git -C r3 rev-list --objects --filter="$spec" HEAD \ >actual 2>actual_stderr && test_must_be_empty actual && - test_i18ngrep "$err" actual_stderr + test_grep "$err" actual_stderr } test_expect_success 'combine:... while URL-encoding things that should not be' ' diff --git a/t/t6113-rev-list-bitmap-filters.sh b/t/t6113-rev-list-bitmap-filters.sh index 4d8e09167e..86c70521f1 100755 --- a/t/t6113-rev-list-bitmap-filters.sh +++ b/t/t6113-rev-list-bitmap-filters.sh @@ -141,4 +141,17 @@ test_expect_success 'combine filter with --filter-provided-objects' ' done <objects ' +test_expect_success 'bitmap traversal with --unpacked' ' + git repack -adb && + test_commit unpacked && + + git rev-list --objects --no-object-names unpacked^.. >expect.raw && + sort expect.raw >expect && + + git rev-list --use-bitmap-index --objects --all --unpacked >actual.raw && + sort actual.raw >actual && + + test_cmp expect actual +' + test_done diff --git a/t/t6115-rev-list-du.sh b/t/t6115-rev-list-du.sh index d59111dede..c0cfda62fa 100755 --- a/t/t6115-rev-list-du.sh +++ b/t/t6115-rev-list-du.sh @@ -48,6 +48,13 @@ check_du HEAD check_du --objects HEAD check_du --objects HEAD^..HEAD +test_expect_success 'setup for --unpacked tests' ' + git repack -adb && + test_commit unpacked +' + +check_du --all --objects --unpacked + # As mentioned above, don't use hardcode sizes as actual size, but use the # output from git cat-file. test_expect_success 'rev-list --disk-usage=human' ' diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh index c9afcef201..e78315d23d 100755 --- a/t/t6120-describe.sh +++ b/t/t6120-describe.sh @@ -85,6 +85,7 @@ check_describe e-1-gHASH --tags HEAD^^ check_describe c-2-gHASH --tags HEAD^^2 check_describe B --tags HEAD^^2^ check_describe e --tags HEAD^^^ +check_describe e --tags --exact-match HEAD^^^ check_describe heads/main --all HEAD check_describe tags/c-6-gHASH --all HEAD^ @@ -96,6 +97,13 @@ check_describe A-3-gHASH --long HEAD^^2 check_describe c-7-gHASH --tags check_describe e-3-gHASH --first-parent --tags +check_describe c-7-gHASH --tags --no-exact-match HEAD +check_describe e-3-gHASH --first-parent --tags --no-exact-match HEAD + +test_expect_success '--exact-match failure' ' + test_must_fail git describe --exact-match HEAD 2>err +' + test_expect_success 'describe --contains defaults to HEAD without commit-ish' ' echo "A^0" >expect && git checkout A && @@ -384,7 +392,7 @@ test_expect_success 'describe directly tagged blob' ' test_expect_success 'describe tag object' ' git tag test-blob-1 -a -m msg unique-file:file && test_must_fail git describe test-blob-1 2>actual && - test_i18ngrep "fatal: test-blob-1 is neither a commit nor blob" actual + test_grep "fatal: test-blob-1 is neither a commit nor blob" actual ' test_expect_success ULIMIT_STACK_SIZE 'name-rev works in a deep repo' ' diff --git a/t/t6134-pathspec-in-submodule.sh b/t/t6134-pathspec-in-submodule.sh index 3214d9db97..16ce4cfcc6 100755 --- a/t/t6134-pathspec-in-submodule.sh +++ b/t/t6134-pathspec-in-submodule.sh @@ -27,7 +27,7 @@ test_expect_success 'error message for path inside submodule' ' test_expect_success 'error message for path inside submodule from within submodule' ' test_must_fail git -C sub add . 2>actual && - test_i18ngrep "in unpopulated submodule" actual + test_grep "in unpopulated submodule" actual ' test_done diff --git a/t/t6135-pathspec-with-attrs.sh b/t/t6135-pathspec-with-attrs.sh index 457cc167c7..00b84ecba6 100755 --- a/t/t6135-pathspec-with-attrs.sh +++ b/t/t6135-pathspec-with-attrs.sh @@ -64,11 +64,24 @@ test_expect_success 'setup .gitattributes' ' fileSetLabel label fileValue label=foo fileWrongLabel label☺ + newFileA* labelA + newFileB* labelB EOF - git add .gitattributes && + echo fileSetLabel label1 >sub/.gitattributes && + git add .gitattributes sub/.gitattributes && git commit -m "add attributes" ' +test_expect_success 'setup .gitignore' ' + cat <<-\EOF >.gitignore && + actual + expect + pathspec_file + EOF + git add .gitignore && + git commit -m "add gitignore" +' + test_expect_success 'check specific set attr' ' cat <<-\EOF >expect && fileSetLabel @@ -78,7 +91,17 @@ test_expect_success 'check specific set attr' ' test_cmp expect actual ' -test_expect_success 'check specific set attr (2)' ' +test_expect_success 'check set attr with pathspec pattern' ' + echo sub/fileSetLabel >expect && + + git ls-files ":(attr:label)sub" >actual && + test_cmp expect actual && + + git ls-files ":(attr:label)sub/" >actual && + test_cmp expect actual +' + +test_expect_success 'check specific set attr in tree-ish' ' cat <<-\EOF >expect && HEAD:fileSetLabel HEAD:sub/fileSetLabel @@ -87,6 +110,16 @@ test_expect_success 'check specific set attr (2)' ' test_cmp expect actual ' +test_expect_success 'check specific set attr with pathspec pattern in tree-ish' ' + echo HEAD:sub/fileSetLabel >expect && + + git grep -l content HEAD ":(attr:label)sub" >actual && + test_cmp expect actual && + + git grep -l content HEAD ":(attr:label)sub/" >actual && + test_cmp expect actual +' + test_expect_success 'check specific unset attr' ' cat <<-\EOF >expect && fileUnsetLabel @@ -129,6 +162,7 @@ test_expect_success 'check specific value attr (2)' ' test_expect_success 'check unspecified attr' ' cat <<-\EOF >expect && .gitattributes + .gitignore fileA fileAB fileAC @@ -137,6 +171,7 @@ test_expect_success 'check unspecified attr' ' fileC fileNoLabel fileWrongLabel + sub/.gitattributes sub/fileA sub/fileAB sub/fileAC @@ -153,6 +188,7 @@ test_expect_success 'check unspecified attr' ' test_expect_success 'check unspecified attr (2)' ' cat <<-\EOF >expect && HEAD:.gitattributes + HEAD:.gitignore HEAD:fileA HEAD:fileAB HEAD:fileAC @@ -161,6 +197,7 @@ test_expect_success 'check unspecified attr (2)' ' HEAD:fileC HEAD:fileNoLabel HEAD:fileWrongLabel + HEAD:sub/.gitattributes HEAD:sub/fileA HEAD:sub/fileAB HEAD:sub/fileAC @@ -177,9 +214,11 @@ test_expect_success 'check unspecified attr (2)' ' test_expect_success 'check multiple unspecified attr' ' cat <<-\EOF >expect && .gitattributes + .gitignore fileC fileNoLabel fileWrongLabel + sub/.gitattributes sub/fileC sub/fileNoLabel sub/fileWrongLabel @@ -212,17 +251,100 @@ test_expect_success 'check label excluding other labels' ' test_expect_success 'fail on multiple attr specifiers in one pathspec item' ' test_must_fail git ls-files . ":(attr:labelB,attr:labelC)" 2>actual && - test_i18ngrep "Only one" actual + test_grep "Only one" actual ' -test_expect_success 'fail if attr magic is used places not implemented' ' +test_expect_success 'fail if attr magic is used in places not implemented' ' # The main purpose of this test is to check that we actually fail # when you attempt to use attr magic in commands that do not implement - # attr magic. This test does not advocate git-add to stay that way, - # though, but git-add is convenient as it has its own internal pathspec - # parsing. - test_must_fail git add ":(attr:labelB)" 2>actual && - test_i18ngrep "magic not supported" actual + # attr magic. This test does not advocate check-ignore to stay that way. + # When you teach the command to grok the pathspec, you need to find + # another command to replace it for the test. + test_must_fail git check-ignore ":(attr:labelB)" 2>actual && + test_grep "magic not supported" actual +' + +test_expect_success 'check that attr magic works for git stash push' ' + cat <<-\EOF >expect && + A sub/newFileA-foo + EOF + >sub/newFileA-foo && + >sub/newFileB-foo && + git stash push --include-untracked -- ":(exclude,attr:labelB)" && + git stash show --include-untracked --name-status >actual && + test_cmp expect actual +' + +test_expect_success 'check that attr magic works for git add --all' ' + cat <<-\EOF >expect && + sub/newFileA-foo + EOF + >sub/newFileA-foo && + >sub/newFileB-foo && + git add --all ":(exclude,attr:labelB)" && + git diff --name-only --cached >actual && + git restore -W -S . && + test_cmp expect actual +' + +test_expect_success 'check that attr magic works for git add -u' ' + cat <<-\EOF >expect && + sub/fileA + EOF + >sub/newFileA-foo && + >sub/newFileB-foo && + >sub/fileA && + >sub/fileB && + git add -u ":(exclude,attr:labelB)" && + git diff --name-only --cached >actual && + git restore -S -W . && rm sub/new* && + test_cmp expect actual +' + +test_expect_success 'check that attr magic works for git add <path>' ' + cat <<-\EOF >expect && + fileA + fileB + sub/fileA + EOF + >fileA && + >fileB && + >sub/fileA && + >sub/fileB && + git add ":(exclude,attr:labelB)sub/*" && + git diff --name-only --cached >actual && + git restore -S -W . && + test_cmp expect actual +' + +test_expect_success 'check that attr magic works for git -add .' ' + cat <<-\EOF >expect && + sub/fileA + EOF + >fileA && + >fileB && + >sub/fileA && + >sub/fileB && + cd sub && + git add . ":(exclude,attr:labelB)" && + cd .. && + git diff --name-only --cached >actual && + git restore -S -W . && + test_cmp expect actual +' + +test_expect_success 'check that attr magic works for git add --pathspec-from-file' ' + cat <<-\EOF >pathspec_file && + :(exclude,attr:labelB) + EOF + cat <<-\EOF >expect && + sub/newFileA-foo + EOF + >sub/newFileA-foo && + >sub/newFileB-foo && + git add --all --pathspec-from-file=pathspec_file && + git diff --name-only --cached >actual && + test_cmp expect actual ' test_expect_success 'abort on giving invalid label on the command line' ' @@ -245,12 +367,30 @@ test_expect_success 'check attribute list' ' test_expect_success 'backslash cannot be the last character' ' test_must_fail git ls-files ":(attr:label=foo\\ labelA=bar)" 2>actual && - test_i18ngrep "not allowed as last character in attr value" actual + test_grep "not allowed as last character in attr value" actual ' test_expect_success 'backslash cannot be used as a value' ' test_must_fail git ls-files ":(attr:label=f\\\oo)" 2>actual && - test_i18ngrep "for value matching" actual + test_grep "for value matching" actual +' + +test_expect_success 'reading from .gitattributes in a subdirectory (1)' ' + git ls-files ":(attr:label1)" >actual && + test_write_lines "sub/fileSetLabel" >expect && + test_cmp expect actual +' + +test_expect_success 'reading from .gitattributes in a subdirectory (2)' ' + git ls-files ":(attr:label1)sub" >actual && + test_write_lines "sub/fileSetLabel" >expect && + test_cmp expect actual +' + +test_expect_success 'reading from .gitattributes in a subdirectory (3)' ' + git ls-files ":(attr:label1)sub/" >actual && + test_write_lines "sub/fileSetLabel" >expect && + test_cmp expect actual ' test_done diff --git a/t/t6136-pathspec-in-bare.sh b/t/t6136-pathspec-in-bare.sh index ae8b5379e2..2db37a6596 100755 --- a/t/t6136-pathspec-in-bare.sh +++ b/t/t6136-pathspec-in-bare.sh @@ -15,11 +15,11 @@ test_expect_success 'log and ls-files in a bare repository' ' cd bare && test_must_fail git log -- .. >out 2>err && test_must_be_empty out && - test_i18ngrep "outside repository" err && + test_grep "outside repository" err && test_must_fail git ls-files -- .. >out 2>err && test_must_be_empty out && - test_i18ngrep "outside repository" err + test_grep "outside repository" err ) ' @@ -28,11 +28,11 @@ test_expect_success 'log and ls-files in .git directory' ' cd .git && test_must_fail git log -- .. >out 2>err && test_must_be_empty out && - test_i18ngrep "outside repository" err && + test_grep "outside repository" err && test_must_fail git ls-files -- .. >out 2>err && test_must_be_empty out && - test_i18ngrep "outside repository" err + test_grep "outside repository" err ) ' diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index c466fd989f..54e2281259 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -6,6 +6,7 @@ test_description='for-each-ref test' . ./test-lib.sh +GNUPGHOME_NOT_USED=$GNUPGHOME . "$TEST_DIRECTORY"/lib-gpg.sh . "$TEST_DIRECTORY"/lib-terminal.sh @@ -24,6 +25,13 @@ test_expect_success setup ' disklen sha1:138 disklen sha256:154 EOF + + # setup .mailmap + cat >.mailmap <<-EOF && + A Thor <athor@example.com> A U Thor <author@example.com> + C Mitter <cmitter@example.com> C O Mitter <committer@example.com> + EOF + setdate_and_increment && echo "Using $datestamp" > one && git add one && @@ -40,25 +48,29 @@ test_expect_success setup ' git config push.default current ' -test_atom() { +test_atom () { case "$1" in head) ref=refs/heads/main ;; tag) ref=refs/tags/testtag ;; sym) ref=refs/heads/sym ;; *) ref=$1 ;; esac + format=$2 + test_do=test_expect_${4:-success} + printf '%s\n' "$3" >expected - test_expect_${4:-success} $PREREQ "basic atom: $1 $2" " - git for-each-ref --format='%($2)' $ref >actual && + $test_do $PREREQ "basic atom: $ref $format" ' + git for-each-ref --format="%($format)" "$ref" >actual && sanitize_pgp <actual >actual.clean && test_cmp expected actual.clean - " + ' + # Automatically test "contents:size" atom after testing "contents" - if test "$2" = "contents" + if test "$format" = "contents" then # for commit leg, $3 is changed there expect=$(printf '%s' "$3" | wc -c) - test_expect_${4:-success} $PREREQ "basic atom: $1 contents:size" ' + $test_do $PREREQ "basic atom: $ref contents:size" ' type=$(git cat-file -t "$ref") && case $type in tag) @@ -140,15 +152,31 @@ test_atom head '*objectname' '' test_atom head '*objecttype' '' test_atom head author 'A U Thor <author@example.com> 1151968724 +0200' test_atom head authorname 'A U Thor' +test_atom head authorname:mailmap 'A Thor' test_atom head authoremail '<author@example.com>' test_atom head authoremail:trim 'author@example.com' test_atom head authoremail:localpart 'author' +test_atom head authoremail:trim,localpart 'author' +test_atom head authoremail:mailmap '<athor@example.com>' +test_atom head authoremail:mailmap,trim 'athor@example.com' +test_atom head authoremail:trim,mailmap 'athor@example.com' +test_atom head authoremail:mailmap,localpart 'athor' +test_atom head authoremail:localpart,mailmap 'athor' +test_atom head authoremail:mailmap,trim,localpart,mailmap,trim 'athor' test_atom head authordate 'Tue Jul 4 01:18:44 2006 +0200' test_atom head committer 'C O Mitter <committer@example.com> 1151968723 +0200' test_atom head committername 'C O Mitter' +test_atom head committername:mailmap 'C Mitter' test_atom head committeremail '<committer@example.com>' test_atom head committeremail:trim 'committer@example.com' test_atom head committeremail:localpart 'committer' +test_atom head committeremail:localpart,trim 'committer' +test_atom head committeremail:mailmap '<cmitter@example.com>' +test_atom head committeremail:mailmap,trim 'cmitter@example.com' +test_atom head committeremail:trim,mailmap 'cmitter@example.com' +test_atom head committeremail:mailmap,localpart 'cmitter' +test_atom head committeremail:localpart,mailmap 'cmitter' +test_atom head committeremail:trim,mailmap,trim,trim,localpart 'cmitter' test_atom head committerdate 'Tue Jul 4 01:18:43 2006 +0200' test_atom head tag '' test_atom head tagger '' @@ -198,22 +226,46 @@ test_atom tag '*objectname' $(git rev-parse refs/tags/testtag^{}) test_atom tag '*objecttype' 'commit' test_atom tag author '' test_atom tag authorname '' +test_atom tag authorname:mailmap '' test_atom tag authoremail '' test_atom tag authoremail:trim '' test_atom tag authoremail:localpart '' +test_atom tag authoremail:trim,localpart '' +test_atom tag authoremail:mailmap '' +test_atom tag authoremail:mailmap,trim '' +test_atom tag authoremail:trim,mailmap '' +test_atom tag authoremail:mailmap,localpart '' +test_atom tag authoremail:localpart,mailmap '' +test_atom tag authoremail:mailmap,trim,localpart,mailmap,trim '' test_atom tag authordate '' test_atom tag committer '' test_atom tag committername '' +test_atom tag committername:mailmap '' test_atom tag committeremail '' test_atom tag committeremail:trim '' test_atom tag committeremail:localpart '' +test_atom tag committeremail:localpart,trim '' +test_atom tag committeremail:mailmap '' +test_atom tag committeremail:mailmap,trim '' +test_atom tag committeremail:trim,mailmap '' +test_atom tag committeremail:mailmap,localpart '' +test_atom tag committeremail:localpart,mailmap '' +test_atom tag committeremail:trim,mailmap,trim,trim,localpart '' test_atom tag committerdate '' test_atom tag tag 'testtag' test_atom tag tagger 'C O Mitter <committer@example.com> 1151968725 +0200' test_atom tag taggername 'C O Mitter' +test_atom tag taggername:mailmap 'C Mitter' test_atom tag taggeremail '<committer@example.com>' test_atom tag taggeremail:trim 'committer@example.com' test_atom tag taggeremail:localpart 'committer' +test_atom tag taggeremail:trim,localpart 'committer' +test_atom tag taggeremail:mailmap '<cmitter@example.com>' +test_atom tag taggeremail:mailmap,trim 'cmitter@example.com' +test_atom tag taggeremail:trim,mailmap 'cmitter@example.com' +test_atom tag taggeremail:mailmap,localpart 'cmitter' +test_atom tag taggeremail:localpart,mailmap 'cmitter' +test_atom tag taggeremail:trim,mailmap,trim,localpart,localpart 'cmitter' test_atom tag taggerdate 'Tue Jul 4 01:18:45 2006 +0200' test_atom tag creator 'C O Mitter <committer@example.com> 1151968725 +0200' test_atom tag creatordate 'Tue Jul 4 01:18:45 2006 +0200' @@ -266,6 +318,66 @@ test_expect_success 'arguments to %(objectname:short=) must be positive integers test_must_fail git for-each-ref --format="%(objectname:short=foo)" ' +test_bad_atom () { + case "$1" in + head) ref=refs/heads/main ;; + tag) ref=refs/tags/testtag ;; + sym) ref=refs/heads/sym ;; + *) ref=$1 ;; + esac + format=$2 + test_do=test_expect_${4:-success} + + printf '%s\n' "$3" >expect + $test_do $PREREQ "err basic atom: $ref $format" ' + test_must_fail git for-each-ref \ + --format="%($format)" "$ref" 2>error && + test_cmp expect error + ' +} + +test_bad_atom head 'authoremail:foo' \ + 'fatal: unrecognized %(authoremail) argument: foo' + +test_bad_atom head 'authoremail:mailmap,trim,bar' \ + 'fatal: unrecognized %(authoremail) argument: bar' + +test_bad_atom head 'authoremail:trim,' \ + 'fatal: unrecognized %(authoremail) argument: ' + +test_bad_atom head 'authoremail:mailmaptrim' \ + 'fatal: unrecognized %(authoremail) argument: trim' + +test_bad_atom head 'committeremail: ' \ + 'fatal: unrecognized %(committeremail) argument: ' + +test_bad_atom head 'committeremail: trim,foo' \ + 'fatal: unrecognized %(committeremail) argument: trim,foo' + +test_bad_atom head 'committeremail:mailmap,localpart ' \ + 'fatal: unrecognized %(committeremail) argument: ' + +test_bad_atom head 'committeremail:trim_localpart' \ + 'fatal: unrecognized %(committeremail) argument: _localpart' + +test_bad_atom head 'committeremail:localpart,,,trim' \ + 'fatal: unrecognized %(committeremail) argument: ,,trim' + +test_bad_atom tag 'taggeremail:mailmap,trim, foo ' \ + 'fatal: unrecognized %(taggeremail) argument: foo ' + +test_bad_atom tag 'taggeremail:trim,localpart,' \ + 'fatal: unrecognized %(taggeremail) argument: ' + +test_bad_atom tag 'taggeremail:mailmap;localpart trim' \ + 'fatal: unrecognized %(taggeremail) argument: ;localpart trim' + +test_bad_atom tag 'taggeremail:localpart trim' \ + 'fatal: unrecognized %(taggeremail) argument: trim' + +test_bad_atom tag 'taggeremail:mailmap,mailmap,trim,qux,localpart,trim' \ + 'fatal: unrecognized %(taggeremail) argument: qux,localpart,trim' + test_date () { f=$1 && committer_date=$2 && @@ -448,6 +560,41 @@ test_expect_success 'exercise glob patterns with prefixes' ' ' cat >expected <<\EOF +refs/tags/bar +refs/tags/baz +refs/tags/testtag +EOF + +test_expect_success 'exercise patterns with prefix exclusions' ' + for tag in foo/one foo/two foo/three bar baz + do + git tag "$tag" || return 1 + done && + test_when_finished "git tag -d foo/one foo/two foo/three bar baz" && + git for-each-ref --format="%(refname)" \ + refs/tags/ --exclude=refs/tags/foo >actual && + test_cmp expected actual +' + +cat >expected <<\EOF +refs/tags/bar +refs/tags/baz +refs/tags/foo/one +refs/tags/testtag +EOF + +test_expect_success 'exercise patterns with pattern exclusions' ' + for tag in foo/one foo/two foo/three bar baz + do + git tag "$tag" || return 1 + done && + test_when_finished "git tag -d foo/one foo/two foo/three bar baz" && + git for-each-ref --format="%(refname)" \ + refs/tags/ --exclude="refs/tags/foo/t*" >actual && + test_cmp expected actual +' + +cat >expected <<\EOF 'refs/heads/main' 'refs/remotes/origin/main' 'refs/tags/testtag' @@ -561,6 +708,144 @@ test_expect_success 'color.ui=always does not override tty check' ' test_cmp expected.bare actual ' +test_expect_success 'setup for describe atom tests' ' + git init -b master describe-repo && + ( + cd describe-repo && + + test_commit --no-tag one && + git tag tagone && + + test_commit --no-tag two && + git tag -a -m "tag two" tagtwo + ) +' + +test_expect_success 'describe atom vs git describe' ' + ( + cd describe-repo && + + git for-each-ref --format="%(objectname)" \ + refs/tags/ >obj && + while read hash + do + if desc=$(git describe $hash) + then + : >expect-contains-good + else + : >expect-contains-bad + fi && + echo "$hash $desc" || return 1 + done <obj >expect && + test_path_exists expect-contains-good && + test_path_exists expect-contains-bad && + + git for-each-ref --format="%(objectname) %(describe)" \ + refs/tags/ >actual 2>err && + test_cmp expect actual && + test_must_be_empty err + ) +' + +test_expect_success 'describe:tags vs describe --tags' ' + ( + cd describe-repo && + git describe --tags >expect && + git for-each-ref --format="%(describe:tags)" \ + refs/heads/master >actual && + test_cmp expect actual + ) +' + +test_expect_success 'describe:abbrev=... vs describe --abbrev=...' ' + ( + cd describe-repo && + + # Case 1: We have commits between HEAD and the most + # recent tag reachable from it + test_commit --no-tag file && + git describe --abbrev=14 >expect && + git for-each-ref --format="%(describe:abbrev=14)" \ + refs/heads/master >actual && + test_cmp expect actual && + + # Make sure the hash used is atleast 14 digits long + sed -e "s/^.*-g\([0-9a-f]*\)$/\1/" <actual >hexpart && + test 15 -le $(wc -c <hexpart) && + + # Case 2: We have a tag at HEAD, describe directly gives + # the name of the tag + git tag -a -m tagged tagname && + git describe --abbrev=14 >expect && + git for-each-ref --format="%(describe:abbrev=14)" \ + refs/heads/master >actual && + test_cmp expect actual && + test tagname = $(cat actual) + ) +' + +test_expect_success 'describe:match=... vs describe --match ...' ' + ( + cd describe-repo && + git tag -a -m "tag foo" tag-foo && + git describe --match "*-foo" >expect && + git for-each-ref --format="%(describe:match="*-foo")" \ + refs/heads/master >actual && + test_cmp expect actual + ) +' + +test_expect_success 'describe:exclude:... vs describe --exclude ...' ' + ( + cd describe-repo && + git tag -a -m "tag bar" tag-bar && + git describe --exclude "*-bar" >expect && + git for-each-ref --format="%(describe:exclude="*-bar")" \ + refs/heads/master >actual && + test_cmp expect actual + ) +' + +test_expect_success 'deref with describe atom' ' + ( + cd describe-repo && + cat >expect <<-\EOF && + + tagname + tagname + tagname + + tagtwo + EOF + git for-each-ref --format="%(*describe)" >actual && + test_cmp expect actual + ) +' + +test_expect_success 'err on bad describe atom arg' ' + ( + cd describe-repo && + + # The bad arg is the only arg passed to describe atom + cat >expect <<-\EOF && + fatal: unrecognized %(describe) argument: baz + EOF + test_must_fail git for-each-ref --format="%(describe:baz)" \ + refs/heads/master 2>actual && + test_cmp expect actual && + + # The bad arg is in the middle of the option string + # passed to the describe atom + cat >expect <<-\EOF && + fatal: unrecognized %(describe) argument: qux=1,abbrev=14 + EOF + test_must_fail git for-each-ref \ + --format="%(describe:tags,qux=1,abbrev=14)" \ + ref/heads/master 2>actual && + test_cmp expect actual + ) +' + cat >expected <<\EOF heads/main tags/main @@ -843,16 +1128,16 @@ test_expect_success 'Verify sorts with raw' ' test_expect_success 'Verify sorts with raw:size' ' cat >expected <<-EOF && refs/myblobs/blob8 - refs/myblobs/first refs/myblobs/blob7 - refs/heads/main refs/myblobs/blob4 refs/myblobs/blob1 refs/myblobs/blob2 refs/myblobs/blob3 refs/myblobs/blob5 refs/myblobs/blob6 + refs/myblobs/first refs/mytrees/first + refs/heads/main EOF git for-each-ref --format="%(refname)" --sort=raw:size \ refs/heads/main refs/myblobs/ refs/mytrees/first >actual && @@ -964,6 +1249,17 @@ test_expect_success 'for-each-ref --format compare with cat-file --batch' ' test_cmp expected actual ' +test_expect_success 'verify sorts with contents:size' ' + cat >expect <<-\EOF && + refs/heads/main + refs/heads/newtag + refs/heads/ambiguous + EOF + git for-each-ref --format="%(refname)" \ + --sort=contents:size refs/heads/ >actual && + test_cmp expect actual +' + test_expect_success 'set up multiple-sort tags' ' for when in 100000 200000 do @@ -1039,6 +1335,27 @@ test_expect_success '--no-sort cancels the previous sort keys' ' test_cmp expected actual ' +test_expect_success '--no-sort without subsequent --sort prints expected refs' ' + cat >expected <<-\EOF && + refs/tags/multi-ref1-100000-user1 + refs/tags/multi-ref1-100000-user2 + refs/tags/multi-ref1-200000-user1 + refs/tags/multi-ref1-200000-user2 + refs/tags/multi-ref2-100000-user1 + refs/tags/multi-ref2-100000-user2 + refs/tags/multi-ref2-200000-user1 + refs/tags/multi-ref2-200000-user2 + EOF + + # Sort the results with `sort` for a consistent comparison against + # expected + git for-each-ref \ + --format="%(refname)" \ + --no-sort \ + "refs/tags/multi-*" | sort >actual && + test_cmp expected actual +' + test_expect_success 'do not dereference NULL upon %(HEAD) on unborn branch' ' test_when_finished "git checkout main" && git for-each-ref --format="%(HEAD) %(refname:short)" refs/heads/ >actual && @@ -1374,6 +1691,14 @@ test_expect_success 'for-each-ref --ignore-case ignores case' ' test_cmp expect actual ' +test_expect_success 'for-each-ref --omit-empty works' ' + git for-each-ref --format="%(refname)" >actual && + test_line_count -gt 1 actual && + git for-each-ref --format="%(if:equals=refs/heads/main)%(refname)%(then)%(refname)%(end)" --omit-empty >actual && + echo refs/heads/main >expect && + test_cmp expect actual +' + test_expect_success 'for-each-ref --ignore-case works on multiple sort keys' ' # name refs numerically to avoid case-insensitive filesystem conflicts nr=0 && @@ -1464,4 +1789,264 @@ sig_crlf="$(printf "%s" "$sig" | append_cr; echo dummy)" sig_crlf=${sig_crlf%dummy} test_atom refs/tags/fake-sig-crlf contents:signature "$sig_crlf" +test_expect_success 'git for-each-ref --stdin: empty' ' + >in && + git for-each-ref --format="%(refname)" --stdin <in >actual && + git for-each-ref --format="%(refname)" >expect && + test_cmp expect actual +' + +test_expect_success 'git for-each-ref --stdin: fails if extra args' ' + >in && + test_must_fail git for-each-ref --format="%(refname)" \ + --stdin refs/heads/extra <in 2>err && + grep "unknown arguments supplied with --stdin" err +' + +test_expect_success 'git for-each-ref --stdin: matches' ' + cat >in <<-EOF && + refs/tags/multi* + refs/heads/amb* + EOF + + cat >expect <<-EOF && + refs/heads/ambiguous + refs/tags/multi-ref1-100000-user1 + refs/tags/multi-ref1-100000-user2 + refs/tags/multi-ref1-200000-user1 + refs/tags/multi-ref1-200000-user2 + refs/tags/multi-ref2-100000-user1 + refs/tags/multi-ref2-100000-user2 + refs/tags/multi-ref2-200000-user1 + refs/tags/multi-ref2-200000-user2 + refs/tags/multiline + EOF + + git for-each-ref --format="%(refname)" --stdin <in >actual && + test_cmp expect actual +' + +test_expect_success 'git for-each-ref with non-existing refs' ' + cat >in <<-EOF && + refs/heads/this-ref-does-not-exist + refs/tags/bogus + EOF + + git for-each-ref --format="%(refname)" --stdin <in >actual && + test_must_be_empty actual && + + xargs git for-each-ref --format="%(refname)" <in >actual && + test_must_be_empty actual +' + +test_expect_success 'git for-each-ref with nested tags' ' + git tag -am "Normal tag" nested/base HEAD && + git tag -am "Nested tag" nested/nest1 refs/tags/nested/base && + git tag -am "Double nested tag" nested/nest2 refs/tags/nested/nest1 && + + head_oid="$(git rev-parse HEAD)" && + base_tag_oid="$(git rev-parse refs/tags/nested/base)" && + nest1_tag_oid="$(git rev-parse refs/tags/nested/nest1)" && + nest2_tag_oid="$(git rev-parse refs/tags/nested/nest2)" && + + cat >expect <<-EOF && + refs/tags/nested/base $base_tag_oid tag $head_oid commit + refs/tags/nested/nest1 $nest1_tag_oid tag $head_oid commit + refs/tags/nested/nest2 $nest2_tag_oid tag $head_oid commit + EOF + + git for-each-ref \ + --format="%(refname) %(objectname) %(objecttype) %(*objectname) %(*objecttype)" \ + refs/tags/nested/ >actual && + test_cmp expect actual +' + +GRADE_FORMAT="%(signature:grade)%0a%(signature:key)%0a%(signature:signer)%0a%(signature:fingerprint)%0a%(signature:primarykeyfingerprint)" +TRUSTLEVEL_FORMAT="%(signature:trustlevel)%0a%(signature:key)%0a%(signature:signer)%0a%(signature:fingerprint)%0a%(signature:primarykeyfingerprint)" + +test_expect_success GPG 'setup for signature atom using gpg' ' + git checkout -b signed && + + test_when_finished "test_unconfig commit.gpgSign" && + + echo "1" >file && + git add file && + test_tick && + git commit -S -m "file: 1" && + git tag first-signed && + + echo "2" >file && + test_tick && + git commit -a -m "file: 2" && + git tag second-unsigned && + + git config commit.gpgSign 1 && + echo "3" >file && + test_tick && + git commit -a --no-gpg-sign -m "file: 3" && + git tag third-unsigned && + + test_tick && + git rebase -f HEAD^^ && git tag second-signed HEAD^ && + git tag third-signed && + + echo "4" >file && + test_tick && + git commit -a -SB7227189 -m "file: 4" && + git tag fourth-signed && + + echo "5" >file && + test_tick && + git commit -a --no-gpg-sign -m "file: 5" && + git tag fifth-unsigned && + + echo "6" >file && + test_tick && + git commit -a --no-gpg-sign -m "file: 6" && + + test_tick && + git rebase -f HEAD^^ && + git tag fifth-signed HEAD^ && + git tag sixth-signed && + + echo "7" >file && + test_tick && + git commit -a --no-gpg-sign -m "file: 7" && + git tag seventh-unsigned +' + +test_expect_success GPGSSH 'setup for signature atom using ssh' ' + test_when_finished "test_unconfig gpg.format user.signingkey" && + + test_config gpg.format ssh && + test_config user.signingkey "${GPGSSH_KEY_PRIMARY}" && + echo "8" >file && + test_tick && + git add file && + git commit -S -m "file: 8" && + git tag eighth-signed-ssh +' + +test_expect_success GPG2 'bare signature atom' ' + git verify-commit first-signed 2>expect && + echo >>expect && + git for-each-ref refs/tags/first-signed \ + --format="%(signature)" >actual && + test_cmp expect actual +' + +test_expect_success GPG 'show good signature with custom format' ' + git verify-commit first-signed && + cat >expect <<-\EOF && + G + 13B6F51ECDDE430D + C O Mitter <committer@example.com> + 73D758744BE721698EC54E8713B6F51ECDDE430D + 73D758744BE721698EC54E8713B6F51ECDDE430D + EOF + git for-each-ref refs/tags/first-signed \ + --format="$GRADE_FORMAT" >actual && + test_cmp expect actual +' +test_expect_success GPGSSH 'show good signature with custom format + with ssh' ' + test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" && + FINGERPRINT=$(ssh-keygen -lf "${GPGSSH_KEY_PRIMARY}" | awk "{print \$2;}") && + cat >expect.tmpl <<-\EOF && + G + FINGERPRINT + principal with number 1 + FINGERPRINT + + EOF + sed "s|FINGERPRINT|$FINGERPRINT|g" expect.tmpl >expect && + git for-each-ref refs/tags/eighth-signed-ssh \ + --format="$GRADE_FORMAT" >actual && + test_cmp expect actual +' + +test_expect_success GPG 'signature atom with grade option and bad signature' ' + git cat-file commit third-signed >raw && + sed -e "s/^file: 3/file: 3 forged/" raw >forged1 && + FORGED1=$(git hash-object -w -t commit forged1) && + git update-ref refs/tags/third-signed "$FORGED1" && + test_must_fail git verify-commit "$FORGED1" && + + cat >expect <<-\EOF && + B + 13B6F51ECDDE430D + C O Mitter <committer@example.com> + + + EOF + git for-each-ref refs/tags/third-signed \ + --format="$GRADE_FORMAT" >actual && + test_cmp expect actual +' + +test_expect_success GPG 'show untrusted signature with custom format' ' + cat >expect <<-\EOF && + U + 65A0EEA02E30CAD7 + Eris Discordia <discord@example.net> + F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7 + D4BE22311AD3131E5EDA29A461092E85B7227189 + EOF + git for-each-ref refs/tags/fourth-signed \ + --format="$GRADE_FORMAT" >actual && + test_cmp expect actual +' + +test_expect_success GPG 'show untrusted signature with undefined trust level' ' + cat >expect <<-\EOF && + undefined + 65A0EEA02E30CAD7 + Eris Discordia <discord@example.net> + F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7 + D4BE22311AD3131E5EDA29A461092E85B7227189 + EOF + git for-each-ref refs/tags/fourth-signed \ + --format="$TRUSTLEVEL_FORMAT" >actual && + test_cmp expect actual +' + +test_expect_success GPG 'show untrusted signature with ultimate trust level' ' + cat >expect <<-\EOF && + ultimate + 13B6F51ECDDE430D + C O Mitter <committer@example.com> + 73D758744BE721698EC54E8713B6F51ECDDE430D + 73D758744BE721698EC54E8713B6F51ECDDE430D + EOF + git for-each-ref refs/tags/sixth-signed \ + --format="$TRUSTLEVEL_FORMAT" >actual && + test_cmp expect actual +' + +test_expect_success GPG 'show unknown signature with custom format' ' + cat >expect <<-\EOF && + E + 13B6F51ECDDE430D + + + + EOF + GNUPGHOME="$GNUPGHOME_NOT_USED" git for-each-ref \ + refs/tags/sixth-signed --format="$GRADE_FORMAT" >actual && + test_cmp expect actual +' + +test_expect_success GPG 'show lack of signature with custom format' ' + cat >expect <<-\EOF && + N + + + + + EOF + git for-each-ref refs/tags/seventh-unsigned \ + --format="$GRADE_FORMAT" >actual && + test_cmp expect actual +' + test_done diff --git a/t/t6301-for-each-ref-errors.sh b/t/t6301-for-each-ref-errors.sh index bfda1f46ad..83b8a19d94 100755 --- a/t/t6301-for-each-ref-errors.sh +++ b/t/t6301-for-each-ref-errors.sh @@ -15,7 +15,7 @@ test_expect_success setup ' git for-each-ref --format="%(objectname) %(refname)" >brief-list ' -test_expect_success 'Broken refs are reported correctly' ' +test_expect_success REFFILES 'Broken refs are reported correctly' ' r=refs/heads/bogus && : >.git/$r && test_when_finished "rm -f .git/$r" && @@ -25,7 +25,7 @@ test_expect_success 'Broken refs are reported correctly' ' test_cmp broken-err err ' -test_expect_success 'NULL_SHA1 refs are reported correctly' ' +test_expect_success REFFILES 'NULL_SHA1 refs are reported correctly' ' r=refs/heads/zeros && echo $ZEROS >.git/$r && test_when_finished "rm -f .git/$r" && @@ -39,19 +39,32 @@ test_expect_success 'NULL_SHA1 refs are reported correctly' ' ' test_expect_success 'Missing objects are reported correctly' ' - r=refs/heads/missing && - echo $MISSING >.git/$r && - test_when_finished "rm -f .git/$r" && - echo "fatal: missing object $MISSING for $r" >missing-err && + test_when_finished "git update-ref -d refs/heads/missing" && + test-tool ref-store main update-ref msg refs/heads/missing "$MISSING" "$ZERO_OID" REF_SKIP_OID_VERIFICATION && + echo "fatal: missing object $MISSING for refs/heads/missing" >missing-err && test_must_fail git for-each-ref 2>err && test_cmp missing-err err && ( cat brief-list && - echo "$MISSING $r" + echo "$MISSING refs/heads/missing" ) | sort -k 2 >missing-brief-expected && git for-each-ref --format="%(objectname) %(refname)" >brief-out 2>brief-err && test_cmp missing-brief-expected brief-out && test_must_be_empty brief-err ' +test_expect_success 'ahead-behind requires an argument' ' + test_must_fail git for-each-ref \ + --format="%(ahead-behind)" 2>err && + echo "fatal: expected format: %(ahead-behind:<committish>)" >expect && + test_cmp expect err +' + +test_expect_success 'missing ahead-behind base' ' + test_must_fail git for-each-ref \ + --format="%(ahead-behind:refs/heads/missing)" 2>err && + echo "fatal: failed to find '\''refs/heads/missing'\''" >expect && + test_cmp expect err +' + test_done diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh index 1ce5f490e9..82f3d1ea0f 100755 --- a/t/t6302-for-each-ref-filter.sh +++ b/t/t6302-for-each-ref-filter.sh @@ -45,6 +45,8 @@ test_expect_success 'check signed tags with --points-at' ' sed -e "s/Z$//" >expect <<-\EOF && refs/heads/side Z refs/tags/annotated-tag four + refs/tags/doubly-annotated-tag four + refs/tags/doubly-signed-tag four refs/tags/four Z refs/tags/signed-tag four EOF diff --git a/t/t6402-merge-rename.sh b/t/t6402-merge-rename.sh index 772238e582..2738b50c2a 100755 --- a/t/t6402-merge-rename.sh +++ b/t/t6402-merge-rename.sh @@ -311,13 +311,13 @@ test_expect_success 'Rename+D/F conflict; renamed file merges but dir in way' ' git checkout -q renamed-file-has-no-conflicts^0 && test_must_fail git merge --strategy=recursive dir-in-way >output && - test_i18ngrep "CONFLICT (modify/delete): dir/file-in-the-way" output && - test_i18ngrep "Auto-merging dir" output && + test_grep "CONFLICT (modify/delete): dir/file-in-the-way" output && + test_grep "Auto-merging dir" output && if test "$GIT_TEST_MERGE_ALGORITHM" = ort then - test_i18ngrep "moving it to dir~HEAD instead" output + test_grep "moving it to dir~HEAD instead" output else - test_i18ngrep "Adding as dir~HEAD instead" output + test_grep "Adding as dir~HEAD instead" output fi && test_stdout_line_count = 3 git ls-files -u && @@ -338,13 +338,13 @@ test_expect_success 'Same as previous, but merged other way' ' test_must_fail git merge --strategy=recursive renamed-file-has-no-conflicts >output 2>errors && ! grep "error: refusing to lose untracked file at" errors && - test_i18ngrep "CONFLICT (modify/delete): dir/file-in-the-way" output && - test_i18ngrep "Auto-merging dir" output && + test_grep "CONFLICT (modify/delete): dir/file-in-the-way" output && + test_grep "Auto-merging dir" output && if test "$GIT_TEST_MERGE_ALGORITHM" = ort then - test_i18ngrep "moving it to dir~renamed-file-has-no-conflicts instead" output + test_grep "moving it to dir~renamed-file-has-no-conflicts instead" output else - test_i18ngrep "Adding as dir~renamed-file-has-no-conflicts instead" output + test_grep "Adding as dir~renamed-file-has-no-conflicts instead" output fi && test_stdout_line_count = 3 git ls-files -u && diff --git a/t/t6403-merge-file.sh b/t/t6403-merge-file.sh index 1a7082323d..fb872c5a11 100755 --- a/t/t6403-merge-file.sh +++ b/t/t6403-merge-file.sh @@ -56,7 +56,67 @@ test_expect_success 'setup' ' deduxit me super semitas jusitiae, EOF - printf "propter nomen suum." >>new4.txt + printf "propter nomen suum." >>new4.txt && + + cat >base.c <<-\EOF && + int f(int x, int y) + { + if (x == 0) + { + return y; + } + return x; + } + + int g(size_t u) + { + while (u < 30) + { + u++; + } + return u; + } + EOF + + cat >ours.c <<-\EOF && + int g(size_t u) + { + while (u < 30) + { + u++; + } + return u; + } + + int h(int x, int y, int z) + { + if (z == 0) + { + return x; + } + return y; + } + EOF + + cat >theirs.c <<-\EOF + int f(int x, int y) + { + if (x == 0) + { + return y; + } + return x; + } + + int g(size_t u) + { + while (u > 34) + { + u--; + } + return u; + } + EOF ' test_expect_success 'merge with no changes' ' @@ -65,11 +125,30 @@ test_expect_success 'merge with no changes' ' test_cmp test.txt orig.txt ' +test_expect_success 'merge with no changes with --object-id' ' + git add orig.txt && + git merge-file -p --object-id :orig.txt :orig.txt :orig.txt >actual && + test_cmp actual orig.txt +' + test_expect_success "merge without conflict" ' cp new1.txt test.txt && git merge-file test.txt orig.txt new2.txt ' +test_expect_success 'merge without conflict with --object-id' ' + git add orig.txt new2.txt && + git merge-file --object-id :orig.txt :orig.txt :new2.txt >actual && + git rev-parse :new2.txt >expected && + test_cmp actual expected +' + +test_expect_success 'can accept object ID with --object-id' ' + git merge-file --object-id $(test_oid empty_blob) $(test_oid empty_blob) :new2.txt >actual && + git rev-parse :new2.txt >expected && + test_cmp actual expected +' + test_expect_success 'works in subdirectory' ' mkdir dir && cp new1.txt dir/a.txt && @@ -138,6 +217,31 @@ test_expect_success "expected conflict markers" ' test_cmp expect.txt test.txt ' +test_expect_success "merge with conflicts with --object-id" ' + git add backup.txt orig.txt new3.txt && + test_must_fail git merge-file -p --object-id :backup.txt :orig.txt :new3.txt >actual && + sed -e "s/<< test.txt/<< :backup.txt/" \ + -e "s/>> new3.txt/>> :new3.txt/" \ + expect.txt >expect && + test_cmp expect actual && + test_must_fail git merge-file --object-id :backup.txt :orig.txt :new3.txt >oid && + git cat-file blob "$(cat oid)" >actual && + test_cmp expect actual +' + +test_expect_success "merge with conflicts with --object-id with labels" ' + git add backup.txt orig.txt new3.txt && + test_must_fail git merge-file -p --object-id \ + -L test.txt -L orig.txt -L new3.txt \ + :backup.txt :orig.txt :new3.txt >actual && + test_cmp expect.txt actual && + test_must_fail git merge-file --object-id \ + -L test.txt -L orig.txt -L new3.txt \ + :backup.txt :orig.txt :new3.txt >oid && + git cat-file blob "$(cat oid)" >actual && + test_cmp expect.txt actual +' + test_expect_success "merge conflicting with --ours" ' cp backup.txt test.txt && @@ -256,6 +360,14 @@ test_expect_success 'binary files cannot be merged' ' grep "Cannot merge binary files" merge.err ' +test_expect_success 'binary files cannot be merged with --object-id' ' + cp "$TEST_DIRECTORY"/test-binary-1.png . && + git add orig.txt new1.txt test-binary-1.png && + test_must_fail git merge-file --object-id \ + :orig.txt :test-binary-1.png :new1.txt 2> merge.err && + grep "Cannot merge binary files" merge.err +' + test_expect_success 'MERGE_ZEALOUS simplifies non-conflicts' ' sed -e "s/deerit.\$/deerit;/" -e "s/me;\$/me./" <new5.txt >new6.txt && sed -e "s/deerit.\$/deerit,/" -e "s/me;\$/me,/" <new5.txt >new7.txt && @@ -389,4 +501,72 @@ test_expect_success 'conflict sections match existing line endings' ' test $(tr "\015" Q <nolf.txt | grep "^[<=>].*Q$" | wc -l) = 0 ' +test_expect_success '--object-id fails without repository' ' + empty="$(test_oid empty_blob)" && + nongit test_must_fail git merge-file --object-id $empty $empty $empty 2>err && + grep "not a git repository" err +' + +test_expect_success 'merging C files with "myers" diff algorithm creates some spurious conflicts' ' + cat >expect.c <<-\EOF && + int g(size_t u) + { + while (u < 30) + { + u++; + } + return u; + } + + int h(int x, int y, int z) + { + <<<<<<< ours.c + if (z == 0) + ||||||| base.c + while (u < 30) + ======= + while (u > 34) + >>>>>>> theirs.c + { + <<<<<<< ours.c + return x; + ||||||| base.c + u++; + ======= + u--; + >>>>>>> theirs.c + } + return y; + } + EOF + + test_must_fail git merge-file -p --diff3 --diff-algorithm myers ours.c base.c theirs.c >myers_output.c && + test_cmp expect.c myers_output.c +' + +test_expect_success 'merging C files with "histogram" diff algorithm avoids some spurious conflicts' ' + cat >expect.c <<-\EOF && + int g(size_t u) + { + while (u > 34) + { + u--; + } + return u; + } + + int h(int x, int y, int z) + { + if (z == 0) + { + return x; + } + return y; + } + EOF + + git merge-file -p --diff3 --diff-algorithm histogram ours.c base.c theirs.c >histogram_output.c && + test_cmp expect.c histogram_output.c +' + test_done diff --git a/t/t6406-merge-attr.sh b/t/t6406-merge-attr.sh index 5e4e4dd6d9..72f8c1722f 100755 --- a/t/t6406-merge-attr.sh +++ b/t/t6406-merge-attr.sh @@ -56,6 +56,12 @@ test_expect_success setup ' ) >"$ours+" cat "$ours+" >"$ours" rm -f "$ours+" + + if test -f ./please-abort + then + echo >>./please-abort killing myself + kill -9 $$ + fi exit "$exit" EOF chmod +x ./custom-merge @@ -162,6 +168,24 @@ test_expect_success 'custom merge backend' ' rm -f $o $a $b ' +test_expect_success !WINDOWS 'custom merge driver that is killed with a signal' ' + test_when_finished "rm -f output please-abort" && + + git reset --hard anchor && + git config --replace-all \ + merge.custom.driver "./custom-merge %O %A %B 0 %P" && + git config --replace-all \ + merge.custom.name "custom merge driver for testing" && + + >./please-abort && + echo "* merge=custom" >.gitattributes && + test_must_fail git merge main 2>err && + grep "^error: failed to execute internal merge" err && + git ls-files -u >output && + git diff --name-only HEAD >>output && + test_must_be_empty output +' + test_expect_success 'up-to-date merge without common ancestor' ' git init repo1 && git init repo2 && diff --git a/t/t6416-recursive-corner-cases.sh b/t/t6416-recursive-corner-cases.sh index 17b54d625d..5f414abc89 100755 --- a/t/t6416-recursive-corner-cases.sh +++ b/t/t6416-recursive-corner-cases.sh @@ -5,6 +5,7 @@ test_description='recursive merge corner cases involving criss-cross merges' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-merge.sh diff --git a/t/t6422-merge-rename-corner-cases.sh b/t/t6422-merge-rename-corner-cases.sh index 076b6a74d5..80d7b5eaba 100755 --- a/t/t6422-merge-rename-corner-cases.sh +++ b/t/t6422-merge-rename-corner-cases.sh @@ -476,7 +476,7 @@ test_expect_success 'handle rename-with-content-merge vs. add' ' git checkout A^0 && test_must_fail git merge -s recursive B^0 >out && - test_i18ngrep "CONFLICT (.*/add)" out && + test_grep "CONFLICT (.*/add)" out && git ls-files -s >out && test_line_count = 2 out && @@ -522,7 +522,7 @@ test_expect_success 'handle rename-with-content-merge vs. add, merge other way' git checkout B^0 && test_must_fail git merge -s recursive A^0 >out && - test_i18ngrep "CONFLICT (.*/add)" out && + test_grep "CONFLICT (.*/add)" out && git ls-files -s >out && test_line_count = 2 out && @@ -602,7 +602,7 @@ test_expect_success 'handle rename/rename (2to1) conflict correctly' ' git checkout B^0 && test_must_fail git merge -s recursive C^0 >out && - test_i18ngrep "CONFLICT (\(.*\)/\1)" out && + test_grep "CONFLICT (\(.*\)/\1)" out && git ls-files -s >out && test_line_count = 2 out && @@ -914,8 +914,8 @@ test_expect_merge_algorithm failure success 'rad-check: rename/add/delete confli # be flexible in the type of console output message(s) reported # for this particular case; we will be more stringent about the # contents of the index and working directory. - test_i18ngrep "CONFLICT (.*/add)" out && - test_i18ngrep "CONFLICT (rename.*/delete)" out && + test_grep "CONFLICT (.*/add)" out && + test_grep "CONFLICT (rename.*/delete)" out && test_must_be_empty err && git ls-files -s >file_count && @@ -988,8 +988,8 @@ test_expect_merge_algorithm failure success 'rrdd-check: rename/rename(2to1)/del # be flexible in the type of console output message(s) reported # for this particular case; we will be more stringent about the # contents of the index and working directory. - test_i18ngrep "CONFLICT (\(.*\)/\1)" out && - test_i18ngrep "CONFLICT (rename.*delete)" out && + test_grep "CONFLICT (\(.*\)/\1)" out && + test_grep "CONFLICT (rename.*delete)" out && test_must_be_empty err && git ls-files -s >file_count && @@ -1068,7 +1068,7 @@ test_expect_merge_algorithm failure success 'mod6-check: chains of rename/rename test_must_fail git merge -s recursive B^0 >out 2>err && - test_i18ngrep "CONFLICT (rename/rename)" out && + test_grep "CONFLICT (rename/rename)" out && test_must_be_empty err && git ls-files -s >file_count && diff --git a/t/t6423-merge-rename-directories.sh b/t/t6423-merge-rename-directories.sh index 944de75b80..88d1cf2cde 100755 --- a/t/t6423-merge-rename-directories.sh +++ b/t/t6423-merge-rename-directories.sh @@ -276,7 +276,7 @@ test_expect_success '1d: Directory renames cause a rename/rename(2to1) conflict' git checkout A^0 && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && - test_i18ngrep "CONFLICT (\(.*\)/\1)" out && + test_grep "CONFLICT (\(.*\)/\1)" out && git ls-files -s >out && test_line_count = 8 out && @@ -515,7 +515,7 @@ test_expect_success '2a: Directory split into two on one side, with equal number git checkout A^0 && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && - test_i18ngrep "CONFLICT.*directory rename split" out && + test_grep "CONFLICT.*directory rename split" out && git ls-files -s >out && test_line_count = 3 out && @@ -591,7 +591,7 @@ test_expect_success '2b: Directory split into two on one side, with equal number git rev-parse >expect \ O:z/b O:z/c B:x/d && test_cmp expect actual && - test_i18ngrep ! "CONFLICT.*directory rename split" out + test_grep ! "CONFLICT.*directory rename split" out ) ' @@ -726,8 +726,8 @@ test_expect_success '3b: Avoid implicit rename if involved as source on current git checkout A^0 && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && - test_i18ngrep CONFLICT.*rename/rename.*z/d.*x/d.*w/d out && - test_i18ngrep ! CONFLICT.*rename/rename.*y/d out && + test_grep CONFLICT.*rename/rename.*z/d.*x/d.*w/d out && + test_grep ! CONFLICT.*rename/rename.*y/d out && git ls-files -s >out && test_line_count = 5 out && @@ -938,7 +938,7 @@ test_expect_success '5a: Merge directories, other side adds files to original an git checkout A^0 && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && - test_i18ngrep "CONFLICT.*implicit dir rename" out && + test_grep "CONFLICT.*implicit dir rename" out && git ls-files -s >out && test_line_count = 6 out && @@ -1013,7 +1013,7 @@ test_expect_success '5b: Rename/delete in order to get add/add/add conflict' ' git checkout A^0 && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && - test_i18ngrep "CONFLICT (add/add).* y/d" out && + test_grep "CONFLICT (add/add).* y/d" out && git ls-files -s >out && test_line_count = 5 out && @@ -1094,8 +1094,8 @@ test_expect_success '5c: Transitive rename would cause rename/rename/rename/add/ git checkout A^0 && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && - test_i18ngrep "CONFLICT (rename/rename).*x/d.*w/d.*z/d" out && - test_i18ngrep "CONFLICT (add/add).* y/d" out && + test_grep "CONFLICT (rename/rename).*x/d.*w/d.*z/d" out && + test_grep "CONFLICT (add/add).* y/d" out && git ls-files -s >out && test_line_count = 9 out && @@ -1179,7 +1179,7 @@ test_expect_success '5d: Directory/file/file conflict due to directory rename' ' git checkout A^0 && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && - test_i18ngrep "CONFLICT (file/directory).*y/d" out && + test_grep "CONFLICT (file/directory).*y/d" out && git ls-files -s >out && test_line_count = 6 out && @@ -1278,7 +1278,7 @@ test_expect_success '6a: Tricky rename/delete' ' git checkout A^0 && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && - test_i18ngrep "CONFLICT (rename/delete).*z/c.*y/c" out && + test_grep "CONFLICT (rename/delete).*z/c.*y/c" out && if test "$GIT_TEST_MERGE_ALGORITHM" = ort then @@ -1740,8 +1740,8 @@ test_expect_success '7a: rename-dir vs. rename-dir (NOT split evenly) PLUS add-o git checkout A^0 && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && - test_i18ngrep "CONFLICT (rename/rename).*z/b.*y/b.*w/b" out && - test_i18ngrep "CONFLICT (rename/rename).*z/c.*y/c.*x/c" out && + test_grep "CONFLICT (rename/rename).*z/b.*y/b.*w/b" out && + test_grep "CONFLICT (rename/rename).*z/c.*y/c.*x/c" out && git ls-files -s >out && test_line_count = 7 out && @@ -1813,7 +1813,7 @@ test_expect_success '7b: rename/rename(2to1), but only due to transitive rename' git checkout A^0 && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && - test_i18ngrep "CONFLICT (\(.*\)/\1)" out && + test_grep "CONFLICT (\(.*\)/\1)" out && git ls-files -s >out && test_line_count = 4 out && @@ -1900,7 +1900,7 @@ test_expect_success '7c: rename/rename(1to...2or3); transitive rename may add co git checkout A^0 && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && - test_i18ngrep "CONFLICT (rename/rename).*x/d.*w/d.*y/d" out && + test_grep "CONFLICT (rename/rename).*x/d.*w/d.*y/d" out && git ls-files -s >out && test_line_count = 5 out && @@ -1965,7 +1965,7 @@ test_expect_success '7d: transitive rename involved in rename/delete; how is it git checkout A^0 && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && - test_i18ngrep "CONFLICT (rename/delete).*x/d.*y/d" out && + test_grep "CONFLICT (rename/delete).*x/d.*y/d" out && if test "$GIT_TEST_MERGE_ALGORITHM" = ort then @@ -2071,7 +2071,7 @@ test_expect_success '7e: transitive rename in rename/delete AND dirs in the way' git checkout A^0 && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && - test_i18ngrep "CONFLICT (rename/delete).*x/d.*y/d" out && + test_grep "CONFLICT (rename/delete).*x/d.*y/d" out && if test "$GIT_TEST_MERGE_ALGORITHM" = ort then @@ -2330,7 +2330,7 @@ test_expect_success '8c: modify/delete or rename+modify/delete' ' git checkout A^0 && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && - test_i18ngrep "CONFLICT (modify/delete).* z/d" out && + test_grep "CONFLICT (modify/delete).* z/d" out && git ls-files -s >out && test_line_count = 5 out && @@ -2491,8 +2491,8 @@ test_expect_success '8e: Both sides rename, one side adds to original directory' git checkout A^0 && test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && - test_i18ngrep CONFLICT.*rename/rename.*z/c.*y/c.*w/c out && - test_i18ngrep CONFLICT.*rename/rename.*z/b.*y/b.*w/b out && + test_grep CONFLICT.*rename/rename.*z/c.*y/c.*w/c out && + test_grep CONFLICT.*rename/rename.*z/b.*y/b.*w/b out && git ls-files -s >out && test_line_count = 7 out && @@ -2741,7 +2741,7 @@ test_expect_success '9c: Doubly transitive rename?' ' git checkout A^0 && git -c merge.directoryRenames=true merge -s recursive B^0 >out && - test_i18ngrep "WARNING: Avoiding applying x -> z rename to x/f" out && + test_grep "WARNING: Avoiding applying x -> z rename to x/f" out && git ls-files -s >out && test_line_count = 6 out && @@ -2830,10 +2830,10 @@ test_expect_success '9d: N-way transitive rename?' ' git checkout A^0 && git -c merge.directoryRenames=true merge -s recursive B^0 >out && - test_i18ngrep "WARNING: Avoiding applying z -> y rename to z/t" out && - test_i18ngrep "WARNING: Avoiding applying y -> x rename to y/a" out && - test_i18ngrep "WARNING: Avoiding applying x -> w rename to x/b" out && - test_i18ngrep "WARNING: Avoiding applying w -> v rename to w/c" out && + test_grep "WARNING: Avoiding applying z -> y rename to z/t" out && + test_grep "WARNING: Avoiding applying y -> x rename to y/a" out && + test_grep "WARNING: Avoiding applying x -> w rename to x/b" out && + test_grep "WARNING: Avoiding applying w -> v rename to w/c" out && git ls-files -s >out && test_line_count = 7 out && @@ -3215,7 +3215,7 @@ test_expect_success '10a: Overwrite untracked with normal rename/delete' ' test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && test_path_is_missing .git/MERGE_HEAD && - test_i18ngrep "The following untracked working tree files would be overwritten by merge" err && + test_grep "The following untracked working tree files would be overwritten by merge" err && git ls-files -s >out && test_line_count = 1 out && @@ -3287,7 +3287,7 @@ test_expect_success '10b: Overwrite untracked with dir rename + delete' ' if test "$GIT_TEST_MERGE_ALGORITHM" = ort then test_path_is_missing .git/MERGE_HEAD && - test_i18ngrep "error: The following untracked working tree files would be overwritten by merge" err && + test_grep "error: The following untracked working tree files would be overwritten by merge" err && git ls-files -s >out && test_line_count = 1 out && @@ -3296,8 +3296,8 @@ test_expect_success '10b: Overwrite untracked with dir rename + delete' ' git ls-files -o >out && test_line_count = 5 out else - test_i18ngrep "CONFLICT (rename/delete).*Version B\^0 of y/d left in tree at y/d~B\^0" out && - test_i18ngrep "Error: Refusing to lose untracked file at y/e; writing to y/e~B\^0 instead" out && + test_grep "CONFLICT (rename/delete).*Version B\^0 of y/d left in tree at y/d~B\^0" out && + test_grep "Error: Refusing to lose untracked file at y/e; writing to y/e~B\^0 instead" out && git ls-files -s >out && test_line_count = 3 out && @@ -3377,7 +3377,7 @@ test_expect_success '10c1: Overwrite untracked with dir rename/rename(1to2)' ' if test "$GIT_TEST_MERGE_ALGORITHM" = ort then test_path_is_missing .git/MERGE_HEAD && - test_i18ngrep "error: The following untracked working tree files would be overwritten by merge" err && + test_grep "error: The following untracked working tree files would be overwritten by merge" err && git ls-files -s >out && test_line_count = 4 out && @@ -3386,8 +3386,8 @@ test_expect_success '10c1: Overwrite untracked with dir rename/rename(1to2)' ' git ls-files -o >out && test_line_count = 3 out else - test_i18ngrep "CONFLICT (rename/rename)" out && - test_i18ngrep "Refusing to lose untracked file at y/c; adding as y/c~B\^0 instead" out && + test_grep "CONFLICT (rename/rename)" out && + test_grep "Refusing to lose untracked file at y/c; adding as y/c~B\^0 instead" out && git ls-files -s >out && test_line_count = 6 out && @@ -3428,7 +3428,7 @@ test_expect_success '10c2: Overwrite untracked with dir rename/rename(1to2), oth if test "$GIT_TEST_MERGE_ALGORITHM" = ort then test_path_is_missing .git/MERGE_HEAD && - test_i18ngrep "error: The following untracked working tree files would be overwritten by merge" err && + test_grep "error: The following untracked working tree files would be overwritten by merge" err && git ls-files -s >out && test_line_count = 4 out && @@ -3437,8 +3437,8 @@ test_expect_success '10c2: Overwrite untracked with dir rename/rename(1to2), oth git ls-files -o >out && test_line_count = 3 out else - test_i18ngrep "CONFLICT (rename/rename)" out && - test_i18ngrep "Refusing to lose untracked file at y/c; adding as y/c~HEAD instead" out && + test_grep "CONFLICT (rename/rename)" out && + test_grep "Refusing to lose untracked file at y/c; adding as y/c~HEAD instead" out && git ls-files -s >out && test_line_count = 6 out && @@ -3517,7 +3517,7 @@ test_expect_success '10d: Delete untracked with dir rename/rename(2to1)' ' if test "$GIT_TEST_MERGE_ALGORITHM" = ort then test_path_is_missing .git/MERGE_HEAD && - test_i18ngrep "error: The following untracked working tree files would be overwritten by merge" err && + test_grep "error: The following untracked working tree files would be overwritten by merge" err && git ls-files -s >out && test_line_count = 6 out && @@ -3526,8 +3526,8 @@ test_expect_success '10d: Delete untracked with dir rename/rename(2to1)' ' git ls-files -o >out && test_line_count = 3 out else - test_i18ngrep "CONFLICT (rename/rename)" out && - test_i18ngrep "Refusing to lose untracked file at y/wham" out && + test_grep "CONFLICT (rename/rename)" out && + test_grep "Refusing to lose untracked file at y/wham" out && git ls-files -s >out && test_line_count = 6 out && @@ -3606,7 +3606,7 @@ test_expect_merge_algorithm failure success '10e: Does git complain about untrac echo random >z/c && git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && - test_i18ngrep ! "following untracked working tree files would be overwritten by merge" err && + test_grep ! "following untracked working tree files would be overwritten by merge" err && git ls-files -s >out && test_line_count = 3 out && @@ -3690,9 +3690,9 @@ test_expect_success '11a: Avoid losing dirty contents with simple rename' ' if test "$GIT_TEST_MERGE_ALGORITHM" = ort then test_path_is_missing .git/MERGE_HEAD && - test_i18ngrep "error: Your local changes to the following files would be overwritten by merge" err + test_grep "error: Your local changes to the following files would be overwritten by merge" err else - test_i18ngrep "Refusing to lose dirty file at z/c" out && + test_grep "Refusing to lose dirty file at z/c" out && git ls-files -s >out && test_line_count = 2 out && @@ -3770,10 +3770,10 @@ test_expect_success '11b: Avoid losing dirty file involved in directory rename' then test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && test_path_is_missing .git/MERGE_HEAD && - test_i18ngrep "error: Your local changes to the following files would be overwritten by merge" err + test_grep "error: Your local changes to the following files would be overwritten by merge" err else git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && - test_i18ngrep "Refusing to lose dirty file at z/c" out && + test_grep "Refusing to lose dirty file at z/c" out && git ls-files -s >out && test_line_count = 3 out && @@ -3853,9 +3853,9 @@ test_expect_success '11c: Avoid losing not-uptodate with rename + D/F conflict' if test "$GIT_TEST_MERGE_ALGORITHM" = ort then test_path_is_missing .git/MERGE_HEAD && - test_i18ngrep "error: Your local changes to the following files would be overwritten by merge" err + test_grep "error: Your local changes to the following files would be overwritten by merge" err else - test_i18ngrep "following files would be overwritten by merge" err + test_grep "following files would be overwritten by merge" err fi && grep -q stuff y/c && @@ -3927,9 +3927,9 @@ test_expect_success '11d: Avoid losing not-uptodate with rename + D/F conflict' if test "$GIT_TEST_MERGE_ALGORITHM" = ort then test_path_is_missing .git/MERGE_HEAD && - test_i18ngrep "error: Your local changes to the following files would be overwritten by merge" err + test_grep "error: Your local changes to the following files would be overwritten by merge" err else - test_i18ngrep "Refusing to lose dirty file at z/c" out && + test_grep "Refusing to lose dirty file at z/c" out && git ls-files -s >out && test_line_count = 4 out && @@ -4013,10 +4013,10 @@ test_expect_success '11e: Avoid deleting not-uptodate with dir rename/rename(1to if test "$GIT_TEST_MERGE_ALGORITHM" = ort then test_path_is_missing .git/MERGE_HEAD && - test_i18ngrep "error: Your local changes to the following files would be overwritten by merge" err + test_grep "error: Your local changes to the following files would be overwritten by merge" err else - test_i18ngrep "CONFLICT (rename/rename)" out && - test_i18ngrep "Refusing to lose dirty file at y/c" out && + test_grep "CONFLICT (rename/rename)" out && + test_grep "Refusing to lose dirty file at y/c" out && git ls-files -s >out && test_line_count = 7 out && @@ -4102,10 +4102,10 @@ test_expect_success '11f: Avoid deleting not-uptodate with dir rename/rename(2to if test "$GIT_TEST_MERGE_ALGORITHM" = ort then test_path_is_missing .git/MERGE_HEAD && - test_i18ngrep "error: Your local changes to the following files would be overwritten by merge" err + test_grep "error: Your local changes to the following files would be overwritten by merge" err else - test_i18ngrep "CONFLICT (rename/rename)" out && - test_i18ngrep "Refusing to lose dirty file at y/wham" out && + test_grep "CONFLICT (rename/rename)" out && + test_grep "Refusing to lose dirty file at y/wham" out && git ls-files -s >out && test_line_count = 4 out && @@ -5417,8 +5417,8 @@ test_expect_success '13a(conflict): messages for newly added files' ' test_must_fail git merge -s recursive B^0 >out 2>err && - test_i18ngrep CONFLICT..file.location.*z/e/f.added.in.B^0.*y/e/f out && - test_i18ngrep CONFLICT..file.location.*z/d.added.in.B^0.*y/d out && + test_grep CONFLICT..file.location.*z/e/f.added.in.B^0.*y/e/f out && + test_grep CONFLICT..file.location.*z/d.added.in.B^0.*y/d out && git ls-files >paths && ! grep z/ paths && @@ -5441,8 +5441,8 @@ test_expect_success '13a(info): messages for newly added files' ' git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && - test_i18ngrep Path.updated:.*z/e/f.added.in.B^0.*y/e/f out && - test_i18ngrep Path.updated:.*z/d.added.in.B^0.*y/d out && + test_grep Path.updated:.*z/e/f.added.in.B^0.*y/e/f out && + test_grep Path.updated:.*z/d.added.in.B^0.*y/d out && git ls-files >paths && ! grep z/ paths && @@ -5507,8 +5507,8 @@ test_expect_success '13b(conflict): messages for transitive rename with conflict test_must_fail git merge -s recursive B^0 >out 2>err && - test_i18ngrep CONFLICT.*content.*Merge.conflict.in.y/d out && - test_i18ngrep CONFLICT..file.location.*x/d.renamed.to.z/d.*moved.to.y/d out && + test_grep CONFLICT.*content.*Merge.conflict.in.y/d out && + test_grep CONFLICT..file.location.*x/d.renamed.to.z/d.*moved.to.y/d out && git ls-files >paths && ! grep z/ paths && @@ -5529,8 +5529,8 @@ test_expect_success '13b(info): messages for transitive rename with conflicted c test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && - test_i18ngrep CONFLICT.*content.*Merge.conflict.in.y/d out && - test_i18ngrep Path.updated:.*x/d.renamed.to.z/d.in.B^0.*moving.it.to.y/d out && + test_grep CONFLICT.*content.*Merge.conflict.in.y/d out && + test_grep Path.updated:.*x/d.renamed.to.z/d.in.B^0.*moving.it.to.y/d out && git ls-files >paths && ! grep z/ paths && @@ -5593,7 +5593,7 @@ test_expect_success '13c(conflict): messages for rename/rename(1to1) via transit test_must_fail git merge -s recursive B^0 >out 2>err && - test_i18ngrep CONFLICT..file.location.*x/d.renamed.to.z/d.*moved.to.y/d out && + test_grep CONFLICT..file.location.*x/d.renamed.to.z/d.*moved.to.y/d out && git ls-files >paths && ! grep z/ paths && @@ -5614,7 +5614,7 @@ test_expect_success '13c(info): messages for rename/rename(1to1) via transitive git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && - test_i18ngrep Path.updated:.*x/d.renamed.to.z/d.in.B^0.*moving.it.to.y/d out && + test_grep Path.updated:.*x/d.renamed.to.z/d.in.B^0.*moving.it.to.y/d out && git ls-files >paths && ! grep z/ paths && @@ -5682,8 +5682,8 @@ test_expect_success '13d(conflict): messages for rename/rename(1to1) via dual tr test_must_fail git merge -s recursive B^0 >out 2>err && - test_i18ngrep CONFLICT..file.location.*a/y.renamed.to.b/y.*moved.to.d/y out && - test_i18ngrep CONFLICT..file.location.*a/y.renamed.to.c/y.*moved.to.d/y out && + test_grep CONFLICT..file.location.*a/y.renamed.to.b/y.*moved.to.d/y out && + test_grep CONFLICT..file.location.*a/y.renamed.to.c/y.*moved.to.d/y out && git ls-files >paths && ! grep b/ paths && @@ -5706,8 +5706,8 @@ test_expect_success '13d(info): messages for rename/rename(1to1) via dual transi git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && - test_i18ngrep Path.updated.*a/y.renamed.to.b/y.*moving.it.to.d/y out && - test_i18ngrep Path.updated.*a/y.renamed.to.c/y.*moving.it.to.d/y out && + test_grep Path.updated.*a/y.renamed.to.b/y.*moving.it.to.d/y out && + test_grep Path.updated.*a/y.renamed.to.c/y.*moving.it.to.d/y out && git ls-files >paths && ! grep b/ paths && @@ -5821,9 +5821,9 @@ test_expect_success '13e: directory rename detection in recursive case' ' git -c merge.directoryRenames=conflict merge -s recursive C^0 >out 2>err && - test_i18ngrep ! CONFLICT out && - test_i18ngrep ! BUG: err && - test_i18ngrep ! core.dumped err && + test_grep ! CONFLICT out && + test_grep ! BUG: err && + test_grep ! core.dumped err && test_must_be_empty err && git ls-files >paths && diff --git a/t/t6424-merge-unrelated-index-changes.sh b/t/t6424-merge-unrelated-index-changes.sh index a61f20c22f..7677c5f08d 100755 --- a/t/t6424-merge-unrelated-index-changes.sh +++ b/t/t6424-merge-unrelated-index-changes.sh @@ -178,7 +178,7 @@ test_expect_success 'merge-recursive, when index==head but head!=HEAD' ' test_when_finished "git clean -fd" && # Do not leave untracked around # Merge B & F, with B as "head" git merge-recursive A -- B F > out && - test_i18ngrep "Already up to date" out + test_grep "Already up to date" out ' test_expect_success 'recursive, when file has staged changes not matching HEAD nor what a merge would give' ' @@ -194,7 +194,7 @@ test_expect_success 'recursive, when file has staged changes not matching HEAD n test_must_fail git merge -s recursive E^0 2>err && git rev-parse --verify :subdir/a >actual && test_cmp expect actual && - test_i18ngrep "changes to the following files would be overwritten" err + test_grep "changes to the following files would be overwritten" err ' test_expect_success 'recursive, when file has staged changes matching what a merge would give' ' @@ -210,7 +210,7 @@ test_expect_success 'recursive, when file has staged changes matching what a mer test_must_fail git merge -s recursive E^0 2>err && git rev-parse --verify :subdir/a >actual && test_cmp expect actual && - test_i18ngrep "changes to the following files would be overwritten" err + test_grep "changes to the following files would be overwritten" err ' test_expect_success 'octopus, unrelated file touched' ' diff --git a/t/t6425-merge-rename-delete.sh b/t/t6425-merge-rename-delete.sh index 93cd2869b1..b95b064311 100755 --- a/t/t6425-merge-rename-delete.sh +++ b/t/t6425-merge-rename-delete.sh @@ -21,8 +21,8 @@ test_expect_success 'rename/delete' ' git commit -m "delete" && test_must_fail git merge --strategy=recursive rename >output && - test_i18ngrep "CONFLICT (rename/delete): A.* renamed .*to B.* in rename" output && - test_i18ngrep "CONFLICT (rename/delete): A.*deleted in HEAD." output + test_grep "CONFLICT (rename/delete): A.* renamed .*to B.* in rename" output && + test_grep "CONFLICT (rename/delete): A.*deleted in HEAD." output ' test_done diff --git a/t/t6426-merge-skip-unneeded-updates.sh b/t/t6426-merge-skip-unneeded-updates.sh index fd21c1a486..b059475ed0 100755 --- a/t/t6426-merge-skip-unneeded-updates.sh +++ b/t/t6426-merge-skip-unneeded-updates.sh @@ -375,7 +375,7 @@ test_expect_success '2c: Modify b & add c VS rename b->c' ' export GIT_MERGE_VERBOSITY && test_must_fail git merge -s recursive B^0 >out 2>err && - test_i18ngrep "CONFLICT (.*/add):" out && + test_grep "CONFLICT (.*/add):" out && test_must_be_empty err && git ls-files -s >index_files && diff --git a/t/t6429-merge-sequence-rename-caching.sh b/t/t6429-merge-sequence-rename-caching.sh index d02fa16614..0f39ed0d08 100755 --- a/t/t6429-merge-sequence-rename-caching.sh +++ b/t/t6429-merge-sequence-rename-caching.sh @@ -71,8 +71,9 @@ test_expect_success 'caching renames does not preclude finding new ones' ' git switch upstream && - test-tool fast-rebase --onto HEAD upstream~1 topic && - #git cherry-pick upstream~1..topic + git replay --onto HEAD upstream~1..topic >out && + git update-ref --stdin <out && + git checkout topic && git ls-files >tracked-files && test_line_count = 2 tracked-files && @@ -140,8 +141,9 @@ test_expect_success 'cherry-pick both a commit and its immediate revert' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - test-tool fast-rebase --onto HEAD upstream~1 topic && - #git cherry-pick upstream~1..topic && + git replay --onto HEAD upstream~1..topic >out && + git update-ref --stdin <out && + git checkout topic && grep region_enter.*diffcore_rename trace.output >calls && test_line_count = 1 calls @@ -199,8 +201,9 @@ test_expect_success 'rename same file identically, then reintroduce it' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - test-tool fast-rebase --onto HEAD upstream~1 topic && - #git cherry-pick upstream~1..topic && + git replay --onto HEAD upstream~1..topic >out && + git update-ref --stdin <out && + git checkout topic && git ls-files >tracked && test_line_count = 2 tracked && @@ -276,8 +279,9 @@ test_expect_success 'rename same file identically, then add file to old dir' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - test-tool fast-rebase --onto HEAD upstream~1 topic && - #git cherry-pick upstream~1..topic && + git replay --onto HEAD upstream~1..topic >out && + git update-ref --stdin <out && + git checkout topic && git ls-files >tracked && test_line_count = 4 tracked && @@ -353,10 +357,7 @@ test_expect_success 'cached dir rename does not prevent noticing later conflict' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - test_must_fail test-tool fast-rebase --onto HEAD upstream~1 topic >output && - #git cherry-pick upstream..topic && - - grep CONFLICT..rename/rename output && + test_must_fail git replay --onto HEAD upstream~1..topic >output && grep region_enter.*diffcore_rename trace.output >calls && test_line_count = 2 calls @@ -455,8 +456,9 @@ test_expect_success 'dir rename unneeded, then add new file to old dir' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - test-tool fast-rebase --onto HEAD upstream~1 topic && - #git cherry-pick upstream..topic && + git replay --onto HEAD upstream~1..topic >out && + git update-ref --stdin <out && + git checkout topic && grep region_enter.*diffcore_rename trace.output >calls && test_line_count = 2 calls && @@ -521,8 +523,9 @@ test_expect_success 'dir rename unneeded, then rename existing file into old dir GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - test-tool fast-rebase --onto HEAD upstream~1 topic && - #git cherry-pick upstream..topic && + git replay --onto HEAD upstream~1..topic >out && + git update-ref --stdin <out && + git checkout topic && grep region_enter.*diffcore_rename trace.output >calls && test_line_count = 3 calls && @@ -623,8 +626,9 @@ test_expect_success 'caching renames only on upstream side, part 1' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - test-tool fast-rebase --onto HEAD upstream~1 topic && - #git cherry-pick upstream..topic && + git replay --onto HEAD upstream~1..topic >out && + git update-ref --stdin <out && + git checkout topic && grep region_enter.*diffcore_rename trace.output >calls && test_line_count = 1 calls && @@ -681,8 +685,9 @@ test_expect_success 'caching renames only on upstream side, part 2' ' GIT_TRACE2_PERF="$(pwd)/trace.output" && export GIT_TRACE2_PERF && - test-tool fast-rebase --onto HEAD upstream~1 topic && - #git cherry-pick upstream..topic && + git replay --onto HEAD upstream~1..topic >out && + git update-ref --stdin <out && + git checkout topic && grep region_enter.*diffcore_rename trace.output >calls && test_line_count = 2 calls && diff --git a/t/t6430-merge-recursive.sh b/t/t6430-merge-recursive.sh index 07067bb347..ca15e6dd6d 100755 --- a/t/t6430-merge-recursive.sh +++ b/t/t6430-merge-recursive.sh @@ -308,13 +308,13 @@ test_expect_success 'fail if the index has unresolved entries' ' test_must_fail git merge "$c5" && test_must_fail git merge "$c5" 2> out && - test_i18ngrep "not possible because you have unmerged files" out && + test_grep "not possible because you have unmerged files" out && git add -u && test_must_fail git merge "$c5" 2> out && - test_i18ngrep "You have not concluded your merge" out && + test_grep "You have not concluded your merge" out && rm -f .git/MERGE_HEAD && test_must_fail git merge "$c5" 2> out && - test_i18ngrep "Your local changes to the following files would be overwritten by merge:" out + test_grep "Your local changes to the following files would be overwritten by merge:" out ' test_expect_success 'merge-recursive remove conflict' ' @@ -713,7 +713,7 @@ test_expect_success 'merge-recursive remembers the names of all base trees' ' test_must_fail git -c merge.verbosity=5 merge-recursive $(cat trees) -- $c1 $c3 >out && # ...but make sure it fails in the expected way - test_i18ngrep CONFLICT.*rename/rename out && + test_grep CONFLICT.*rename/rename out && # merge-recursive prints in reverse order, but we do not care sort <trees >expect && diff --git a/t/t6433-merge-toplevel.sh b/t/t6433-merge-toplevel.sh index b16031465f..ed7866d3e9 100755 --- a/t/t6433-merge-toplevel.sh +++ b/t/t6433-merge-toplevel.sh @@ -5,6 +5,7 @@ test_description='"git merge" top-level frontend' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh t3033_reset () { @@ -151,7 +152,7 @@ test_expect_success 'refuse two-project merge by default, quit before --autostas echo change >>one.t && git diff >expect && test_must_fail git merge --autostash five 2>err && - test_i18ngrep ! "stash" err && + test_grep ! "stash" err && git diff >actual && test_cmp expect actual ' @@ -169,7 +170,7 @@ test_expect_success 'two-project merge with --allow-unrelated-histories with --a echo change >>one.t && git diff one.t >expect && git merge --allow-unrelated-histories --autostash five 2>err && - test_i18ngrep "Applied autostash." err && + test_grep "Applied autostash." err && git diff one.t >actual && test_cmp expect actual ' diff --git a/t/t6436-merge-overwrite.sh b/t/t6436-merge-overwrite.sh index c0b7bd7c3f..4f4376421e 100755 --- a/t/t6436-merge-overwrite.sh +++ b/t/t6436-merge-overwrite.sh @@ -104,12 +104,12 @@ test_expect_success 'will not overwrite unstaged changes in renamed file' ' if test "$GIT_TEST_MERGE_ALGORITHM" = ort then test_must_fail git merge c1a >out 2>err && - test_i18ngrep "would be overwritten by merge" err && + test_grep "would be overwritten by merge" err && test_cmp important other.c && test_path_is_missing .git/MERGE_HEAD else test_must_fail git merge c1a >out && - test_i18ngrep "Refusing to lose dirty file at other.c" out && + test_grep "Refusing to lose dirty file at other.c" out && test_path_is_file other.c~HEAD && test $(git hash-object other.c~HEAD) = $(git rev-parse c1a:c1.c) && test_cmp important other.c diff --git a/t/t6437-submodule-merge.sh b/t/t6437-submodule-merge.sh index c9a86f2e94..70650521b0 100755 --- a/t/t6437-submodule-merge.sh +++ b/t/t6437-submodule-merge.sh @@ -8,6 +8,7 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB=1 export GIT_TEST_FATAL_REGISTER_SUBMODULE_ODB +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-merge.sh @@ -479,7 +480,7 @@ test_expect_merge_algorithm failure success !FAIL_PREREQS 'directory/submodule c # We do not want files within the submodule to prevent the # merge from starting; we should not be writing to such paths # anyway. - test_i18ngrep ! "refusing to lose untracked file at" err + test_grep ! "refusing to lose untracked file at" err ) ' diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh index d9acb63951..18fe1c25e6 100755 --- a/t/t6500-gc.sh +++ b/t/t6500-gc.sh @@ -41,7 +41,7 @@ test_expect_success 'gc does not leave behind pid file' ' test_expect_success 'gc --gobbledegook' ' test_expect_code 129 git gc --nonsense 2>err && - test_i18ngrep "[Uu]sage: git gc" err + test_grep "[Uu]sage: git gc" err ' test_expect_success 'gc -h with invalid configuration' ' @@ -52,7 +52,7 @@ test_expect_success 'gc -h with invalid configuration' ' echo "[gc] pruneexpire = CORRUPT" >>.git/config && test_expect_code 129 git gc -h >usage 2>&1 ) && - test_i18ngrep "[Uu]sage" broken/usage + test_grep "[Uu]sage" broken/usage ' test_expect_success 'gc is not aborted due to a stale symref' ' @@ -155,7 +155,7 @@ test_expect_success 'auto gc with too many loose objects does not attempt to cre test_commit "$(test_oid obj4)" && git gc --auto 2>err && - test_i18ngrep ! "^warning:" err && + test_grep ! "^warning:" err && ls .git/objects/pack/pack-*.pack | sort >post_packs && comm -1 -3 existing_packs post_packs >new && comm -2 -3 existing_packs post_packs >del && @@ -166,15 +166,15 @@ test_expect_success 'auto gc with too many loose objects does not attempt to cre test_expect_success 'gc --no-quiet' ' GIT_PROGRESS_DELAY=0 git -c gc.writeCommitGraph=true gc --no-quiet >stdout 2>stderr && test_must_be_empty stdout && - test_i18ngrep "Computing commit graph generation numbers" stderr + test_grep "Computing commit graph generation numbers" stderr ' test_expect_success TTY 'with TTY: gc --no-quiet' ' test_terminal env GIT_PROGRESS_DELAY=0 \ git -c gc.writeCommitGraph=true gc --no-quiet >stdout 2>stderr && test_must_be_empty stdout && - test_i18ngrep "Enumerating objects" stderr && - test_i18ngrep "Computing commit graph generation numbers" stderr + test_grep "Enumerating objects" stderr && + test_grep "Computing commit graph generation numbers" stderr ' test_expect_success 'gc --quiet' ' @@ -202,6 +202,30 @@ test_expect_success 'one of gc.reflogExpire{Unreachable,}=never does not skip "e grep -E "^trace: (built-in|exec|run_command): git reflog expire --" trace.out ' +test_expect_success 'gc.repackFilter launches repack with a filter' ' + git clone --no-local --bare . bare.git && + + git -C bare.git -c gc.cruftPacks=false gc && + test_stdout_line_count = 1 ls bare.git/objects/pack/*.pack && + + GIT_TRACE=$(pwd)/trace.out git -C bare.git -c gc.repackFilter=blob:none \ + -c repack.writeBitmaps=false -c gc.cruftPacks=false gc && + test_stdout_line_count = 2 ls bare.git/objects/pack/*.pack && + grep -E "^trace: (built-in|exec|run_command): git repack .* --filter=blob:none ?.*" trace.out +' + +test_expect_success 'gc.repackFilterTo store filtered out objects' ' + test_when_finished "rm -rf bare.git filtered.git" && + + git init --bare filtered.git && + git -C bare.git -c gc.repackFilter=blob:none \ + -c gc.repackFilterTo=../filtered.git/objects/pack/pack \ + -c repack.writeBitmaps=false -c gc.cruftPacks=false gc && + + test_stdout_line_count = 1 ls bare.git/objects/pack/*.pack && + test_stdout_line_count = 1 ls filtered.git/objects/pack/*.pack +' + prepare_cruft_history () { test_commit base && @@ -210,92 +234,124 @@ prepare_cruft_history () { git reset HEAD^^ } -assert_cruft_packs () { - find .git/objects/pack -name "*.mtimes" >mtimes && - sed -e 's/\.mtimes$/\.pack/g' mtimes >packs && - - test_file_not_empty packs && - while read pack - do - test_path_is_file "$pack" || return 1 - done <packs -} - assert_no_cruft_packs () { find .git/objects/pack -name "*.mtimes" >mtimes && test_must_be_empty mtimes } -test_expect_success 'gc --cruft generates a cruft pack' ' - test_when_finished "rm -fr crufts" && - git init crufts && +for argv in \ + "gc" \ + "-c gc.cruftPacks=true gc" \ + "-c gc.cruftPacks=false gc --cruft" +do + test_expect_success "git $argv generates a cruft pack" ' + test_when_finished "rm -fr repo" && + git init repo && + ( + cd repo && + + prepare_cruft_history && + git $argv && + + find .git/objects/pack -name "*.mtimes" >mtimes && + sed -e 's/\.mtimes$/\.pack/g' mtimes >packs && + + test_file_not_empty packs && + while read pack + do + test_path_is_file "$pack" || return 1 + done <packs + ) + ' +done + +for argv in \ + "gc --no-cruft" \ + "-c gc.cruftPacks=false gc" \ + "-c gc.cruftPacks=true gc --no-cruft" +do + test_expect_success "git $argv does not generate a cruft pack" ' + test_when_finished "rm -fr repo" && + git init repo && + ( + cd repo && + + prepare_cruft_history && + git $argv && + + assert_no_cruft_packs + ) + ' +done + +test_expect_success '--keep-largest-pack ignores cruft packs' ' + test_when_finished "rm -fr repo" && + git init repo && ( - cd crufts && + cd repo && + # Generate a pack for reachable objects (of which there + # are 3), and one for unreachable objects (of which + # there are 6). prepare_cruft_history && git gc --cruft && - assert_cruft_packs - ) -' -test_expect_success 'gc.cruftPacks=true generates a cruft pack' ' - test_when_finished "rm -fr crufts" && - git init crufts && - ( - cd crufts && + mtimes="$(find .git/objects/pack -type f -name "pack-*.mtimes")" && + sz="$(test_file_size "${mtimes%.mtimes}.pack")" && - prepare_cruft_history && - git -c gc.cruftPacks=true gc && - assert_cruft_packs + # Ensure that the cruft pack gets removed (due to + # `--prune=now`) despite it being the largest pack. + git -c gc.bigPackThreshold=$sz gc --cruft --prune=now && + + assert_no_cruft_packs ) ' -test_expect_success 'feature.experimental=true generates a cruft pack' ' - git init crufts && - test_when_finished "rm -fr crufts" && +test_expect_success 'gc.bigPackThreshold ignores cruft packs' ' + test_when_finished "rm -fr repo" && + git init repo && ( - cd crufts && + cd repo && + # Generate a pack for reachable objects (of which there + # are 3), and one for unreachable objects (of which + # there are 6). prepare_cruft_history && - git -c feature.experimental=true gc && - assert_cruft_packs - ) -' + git gc --cruft && -test_expect_success 'feature.experimental=false allows explicit cruft packs' ' - git init crufts && - test_when_finished "rm -fr crufts" && - ( - cd crufts && + # Ensure that the cruft pack gets removed (due to + # `--prune=now`) despite it being the largest pack. + git gc --cruft --prune=now --keep-largest-pack && - prepare_cruft_history && - git -c gc.cruftPacks=true -c feature.experimental=false gc && - assert_cruft_packs + assert_no_cruft_packs ) ' -test_expect_success 'feature.experimental=true can be overridden' ' - git init crufts && - test_when_finished "rm -fr crufts" && - ( - cd crufts && +cruft_max_size_opts="git repack -d -l --cruft --cruft-expiration=2.weeks.ago" - prepare_cruft_history && - git -c feature.expiremental=true -c gc.cruftPacks=false gc && - assert_no_cruft_packs +test_expect_success 'setup for --max-cruft-size tests' ' + git init cruft--max-size && + ( + cd cruft--max-size && + prepare_cruft_history ) ' -test_expect_success 'feature.experimental=false avoids cruft packs by default' ' - git init crufts && - test_when_finished "rm -fr crufts" && - ( - cd crufts && +test_expect_success '--max-cruft-size sets appropriate repack options' ' + GIT_TRACE2_EVENT=$(pwd)/trace2.txt git -C cruft--max-size \ + gc --cruft --max-cruft-size=1M && + test_subcommand $cruft_max_size_opts --max-cruft-size=1048576 <trace2.txt +' - prepare_cruft_history && - git -c feature.experimental=false gc && - assert_no_cruft_packs - ) +test_expect_success 'gc.maxCruftSize sets appropriate repack options' ' + GIT_TRACE2_EVENT=$(pwd)/trace2.txt \ + git -C cruft--max-size -c gc.maxCruftSize=2M gc --cruft && + test_subcommand $cruft_max_size_opts --max-cruft-size=2097152 <trace2.txt && + + GIT_TRACE2_EVENT=$(pwd)/trace2.txt \ + git -C cruft--max-size -c gc.maxCruftSize=2M gc --cruft \ + --max-cruft-size=3M && + test_subcommand $cruft_max_size_opts --max-cruft-size=3145728 <trace2.txt ' run_and_wait_for_auto_gc () { @@ -316,7 +372,7 @@ test_expect_success 'background auto gc does not run if gc.log is present and re test_config gc.autodetach true && echo fleem >.git/gc.log && git gc --auto 2>err && - test_i18ngrep "^warning:" err && + test_grep "^warning:" err && test_config gc.logexpiry 5.days && test-tool chmtime =-345600 .git/gc.log && git gc --auto && diff --git a/t/t6501-freshen-objects.sh b/t/t6501-freshen-objects.sh index 3968b47ed5..4521508b83 100755 --- a/t/t6501-freshen-objects.sh +++ b/t/t6501-freshen-objects.sh @@ -101,7 +101,7 @@ do ' test_expect_success "simultaneous gc ($title)" ' - git gc --prune=12.hours.ago + git gc --no-cruft --prune=12.hours.ago ' test_expect_success "finish writing out commit ($title)" ' @@ -131,7 +131,7 @@ do ' test_expect_success "simultaneous gc ($title)" ' - git gc --prune=12.hours.ago + git gc --no-cruft --prune=12.hours.ago ' # tree should have been refreshed by write-tree @@ -151,8 +151,8 @@ test_expect_success 'do not complain about existing broken links (commit)' ' some message EOF commit=$(git hash-object -t commit -w broken-commit) && - git gc -q 2>stderr && - verbose git cat-file -e $commit && + git gc --no-cruft -q 2>stderr && + git cat-file -e $commit && test_must_be_empty stderr ' @@ -161,7 +161,7 @@ test_expect_success 'do not complain about existing broken links (tree)' ' 100644 blob $(test_oid 003) foo EOF tree=$(git mktree --missing <broken-tree) && - git gc -q 2>stderr && + git gc --no-cruft -q 2>stderr && git cat-file -e $tree && test_must_be_empty stderr ' @@ -176,7 +176,7 @@ test_expect_success 'do not complain about existing broken links (tag)' ' this is a broken tag EOF tag=$(git hash-object -t tag -w broken-tag) && - git gc -q 2>stderr && + git gc --no-cruft -q 2>stderr && git cat-file -e $tag && test_must_be_empty stderr ' diff --git a/t/t6600-test-reach.sh b/t/t6600-test-reach.sh index 338a9c46a2..b330945f49 100755 --- a/t/t6600-test-reach.sh +++ b/t/t6600-test-reach.sh @@ -443,4 +443,173 @@ test_expect_success 'get_reachable_subset:none' ' test_all_modes get_reachable_subset ' +test_expect_success 'for-each-ref ahead-behind:linear' ' + cat >input <<-\EOF && + refs/heads/commit-1-1 + refs/heads/commit-1-3 + refs/heads/commit-1-5 + refs/heads/commit-1-8 + EOF + cat >expect <<-\EOF && + refs/heads/commit-1-1 0 8 + refs/heads/commit-1-3 0 6 + refs/heads/commit-1-5 0 4 + refs/heads/commit-1-8 0 1 + EOF + run_all_modes git for-each-ref \ + --format="%(refname) %(ahead-behind:commit-1-9)" --stdin +' + +test_expect_success 'for-each-ref ahead-behind:all' ' + cat >input <<-\EOF && + refs/heads/commit-1-1 + refs/heads/commit-2-4 + refs/heads/commit-4-2 + refs/heads/commit-4-4 + EOF + cat >expect <<-\EOF && + refs/heads/commit-1-1 0 24 + refs/heads/commit-2-4 0 17 + refs/heads/commit-4-2 0 17 + refs/heads/commit-4-4 0 9 + EOF + run_all_modes git for-each-ref \ + --format="%(refname) %(ahead-behind:commit-5-5)" --stdin +' + +test_expect_success 'for-each-ref ahead-behind:some' ' + cat >input <<-\EOF && + refs/heads/commit-1-1 + refs/heads/commit-5-3 + refs/heads/commit-4-8 + refs/heads/commit-9-9 + EOF + cat >expect <<-\EOF && + refs/heads/commit-1-1 0 53 + refs/heads/commit-4-8 8 30 + refs/heads/commit-5-3 0 39 + refs/heads/commit-9-9 27 0 + EOF + run_all_modes git for-each-ref \ + --format="%(refname) %(ahead-behind:commit-9-6)" --stdin +' + +test_expect_success 'for-each-ref ahead-behind:some, multibase' ' + cat >input <<-\EOF && + refs/heads/commit-1-1 + refs/heads/commit-5-3 + refs/heads/commit-7-8 + refs/heads/commit-4-8 + refs/heads/commit-9-9 + EOF + cat >expect <<-\EOF && + refs/heads/commit-1-1 0 53 0 53 + refs/heads/commit-4-8 8 30 0 22 + refs/heads/commit-5-3 0 39 0 39 + refs/heads/commit-7-8 14 12 8 6 + refs/heads/commit-9-9 27 0 27 0 + EOF + run_all_modes git for-each-ref \ + --format="%(refname) %(ahead-behind:commit-9-6) %(ahead-behind:commit-6-9)" \ + --stdin +' + +test_expect_success 'for-each-ref ahead-behind:none' ' + cat >input <<-\EOF && + refs/heads/commit-7-5 + refs/heads/commit-4-8 + refs/heads/commit-9-9 + EOF + cat >expect <<-\EOF && + refs/heads/commit-4-8 16 16 + refs/heads/commit-7-5 7 4 + refs/heads/commit-9-9 49 0 + EOF + run_all_modes git for-each-ref \ + --format="%(refname) %(ahead-behind:commit-8-4)" --stdin +' + +test_expect_success 'for-each-ref merged:linear' ' + cat >input <<-\EOF && + refs/heads/commit-1-1 + refs/heads/commit-1-3 + refs/heads/commit-1-5 + refs/heads/commit-1-8 + refs/heads/commit-2-1 + refs/heads/commit-5-1 + refs/heads/commit-9-1 + EOF + cat >expect <<-\EOF && + refs/heads/commit-1-1 + refs/heads/commit-1-3 + refs/heads/commit-1-5 + refs/heads/commit-1-8 + EOF + run_all_modes git for-each-ref --merged=commit-1-9 \ + --format="%(refname)" --stdin +' + +test_expect_success 'for-each-ref merged:all' ' + cat >input <<-\EOF && + refs/heads/commit-1-1 + refs/heads/commit-2-4 + refs/heads/commit-4-2 + refs/heads/commit-4-4 + EOF + cat >expect <<-\EOF && + refs/heads/commit-1-1 + refs/heads/commit-2-4 + refs/heads/commit-4-2 + refs/heads/commit-4-4 + EOF + run_all_modes git for-each-ref --merged=commit-5-5 \ + --format="%(refname)" --stdin +' + +test_expect_success 'for-each-ref ahead-behind:some' ' + cat >input <<-\EOF && + refs/heads/commit-1-1 + refs/heads/commit-5-3 + refs/heads/commit-4-8 + refs/heads/commit-9-9 + EOF + cat >expect <<-\EOF && + refs/heads/commit-1-1 + refs/heads/commit-5-3 + EOF + run_all_modes git for-each-ref --merged=commit-9-6 \ + --format="%(refname)" --stdin +' + +test_expect_success 'for-each-ref merged:some, multibase' ' + cat >input <<-\EOF && + refs/heads/commit-1-1 + refs/heads/commit-5-3 + refs/heads/commit-7-8 + refs/heads/commit-4-8 + refs/heads/commit-9-9 + EOF + cat >expect <<-\EOF && + refs/heads/commit-1-1 + refs/heads/commit-4-8 + refs/heads/commit-5-3 + EOF + run_all_modes git for-each-ref \ + --merged=commit-5-8 \ + --merged=commit-8-5 \ + --format="%(refname)" \ + --stdin +' + +test_expect_success 'for-each-ref merged:none' ' + cat >input <<-\EOF && + refs/heads/commit-7-5 + refs/heads/commit-4-8 + refs/heads/commit-9-9 + EOF + >expect && + run_all_modes git for-each-ref --merged=commit-8-4 \ + --format="%(refname)" --stdin +' + test_done diff --git a/t/t6700-tree-depth.sh b/t/t6700-tree-depth.sh new file mode 100755 index 0000000000..9e70a7c763 --- /dev/null +++ b/t/t6700-tree-depth.sh @@ -0,0 +1,95 @@ +#!/bin/sh + +test_description='handling of deep trees in various commands' + +TEST_PASSES_SANITIZE_LEAK=true +. ./test-lib.sh + +# We'll test against two depths here: a small one that will let us check the +# behavior of the config setting easily, and a large one that should be +# forbidden by default. Testing the default depth will let us know whether our +# default is enough to prevent segfaults on systems that run the tests. +small_depth=50 +big_depth=4100 + +small_ok="-c core.maxtreedepth=$small_depth" +small_no="-c core.maxtreedepth=$((small_depth-1))" + +# usage: mkdeep <name> <depth> +# Create a tag <name> containing a file whose path has depth <depth>. +# +# We'll use fast-import here for two reasons: +# +# 1. It's faster than creating $big_depth tree objects. +# +# 2. As we tighten tree limits, it's more likely to allow large sizes +# than trying to stuff a deep path into the index. +mkdeep () { + { + echo "commit refs/tags/$1" && + echo "committer foo <foo@example.com> 1234 -0000" && + echo "data <<EOF" && + echo "the commit message" && + echo "EOF" && + + printf 'M 100644 inline ' && + i=0 && + while test $i -lt $2 + do + printf 'a/' + i=$((i+1)) + done && + echo "file" && + + echo "data <<EOF" && + echo "the file contents" && + echo "EOF" && + echo + } | git fast-import +} + +test_expect_success 'create small tree' ' + mkdeep small $small_depth +' + +test_expect_success 'create big tree' ' + mkdeep big $big_depth +' + +test_expect_success 'limit recursion of git-archive' ' + git $small_ok archive small >/dev/null && + test_must_fail git $small_no archive small >/dev/null +' + +test_expect_success 'default limit for git-archive fails gracefully' ' + test_must_fail git archive big >/dev/null +' + +test_expect_success 'limit recursion of ls-tree -r' ' + git $small_ok ls-tree -r small && + test_must_fail git $small_no ls-tree -r small +' + +test_expect_success 'default limit for ls-tree fails gracefully' ' + test_must_fail git ls-tree -r big >/dev/null +' + +test_expect_success 'limit recursion of rev-list --objects' ' + git $small_ok rev-list --objects small >/dev/null && + test_must_fail git $small_no rev-list --objects small >/dev/null +' + +test_expect_success 'default limit for rev-list fails gracefully' ' + test_must_fail git rev-list --objects big >/dev/null +' + +test_expect_success 'limit recursion of diff-tree -r' ' + git $small_ok diff-tree -r $EMPTY_TREE small && + test_must_fail git $small_no diff-tree -r $EMPTY_TREE small +' + +test_expect_success 'default limit for diff-tree fails gracefully' ' + test_must_fail git diff-tree -r $EMPTY_TREE big +' + +test_done diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh index d72cef8826..879a6dce60 100755 --- a/t/t7001-mv.sh +++ b/t/t7001-mv.sh @@ -4,6 +4,10 @@ test_description='git mv in subdirs' . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff-data.sh +index_at_path () { + git ls-files --format='%(objectmode) %(objectname) %(stage)' "$@" +} + test_expect_success 'mv -f refreshes updated index entry' ' echo test >bar && git add bar && @@ -170,6 +174,13 @@ test_expect_success 'do not move directory over existing directory' ' test_must_fail git mv path2 path0 ' +test_expect_success 'rename directory to non-existing directory' ' + mkdir dir-a && + >dir-a/f && + git add dir-a && + git mv dir-a non-existing-dir +' + test_expect_success 'move into "."' ' git mv path1/path2/ . ' @@ -187,7 +198,8 @@ test_expect_success "Michael Cassar's test case" ' git mv papers/unsorted/Thesis.pdf papers/all-papers/moo-blah.pdf && T=$(git write-tree) && - git ls-tree -r $T | verbose grep partA/outline.txt + git ls-tree -r $T >out && + grep partA/outline.txt out ' rm -fr papers partA path? @@ -260,12 +272,12 @@ test_expect_success 'git mv should not change sha1 of moved cache entry' ' git init && echo 1 >dirty && git add dirty && - entry="$(git ls-files --stage dirty | cut -f 1)" && + entry="$(index_at_path dirty)" && git mv dirty dirty2 && - test "$entry" = "$(git ls-files --stage dirty2 | cut -f 1)" && + test "$entry" = "$(index_at_path dirty2)" && echo 2 >dirty2 && git mv dirty2 dirty && - test "$entry" = "$(git ls-files --stage dirty | cut -f 1)" + test "$entry" = "$(index_at_path dirty)" ' rm -f dirty dirty2 @@ -284,7 +296,7 @@ test_expect_success 'git mv error on conflicted file' ' EOF test_must_fail git mv conflict newname 2>actual && - test_i18ngrep "conflicted" actual + test_grep "conflicted" actual ' test_expect_success 'git mv should overwrite symlink to a file' ' @@ -342,7 +354,7 @@ test_expect_success 'git mv cannot move a submodule in a file' ' ' test_expect_success 'git mv moves a submodule with a .git directory and no .gitmodules' ' - entry="$(git ls-files --stage sub | cut -f 1)" && + entry="$(index_at_path sub)" && git rm .gitmodules && ( cd sub && @@ -353,7 +365,7 @@ test_expect_success 'git mv moves a submodule with a .git directory and no .gitm mkdir mod && git mv sub mod/sub && test_path_is_missing sub && - test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" && + test "$entry" = "$(index_at_path mod/sub)" && git -C mod/sub status && git update-index --refresh && git diff-files --quiet @@ -363,7 +375,7 @@ test_expect_success 'git mv moves a submodule with a .git directory and .gitmodu rm -rf mod && git reset --hard && git submodule update && - entry="$(git ls-files --stage sub | cut -f 1)" && + entry="$(index_at_path sub)" && ( cd sub && rm -f .git && @@ -373,7 +385,7 @@ test_expect_success 'git mv moves a submodule with a .git directory and .gitmodu mkdir mod && git mv sub mod/sub && test_path_is_missing sub && - test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" && + test "$entry" = "$(index_at_path mod/sub)" && git -C mod/sub status && echo mod/sub >expected && git config -f .gitmodules submodule.sub.path >actual && @@ -386,11 +398,11 @@ test_expect_success 'git mv moves a submodule with gitfile' ' rm -rf mod && git reset --hard && git submodule update && - entry="$(git ls-files --stage sub | cut -f 1)" && + entry="$(index_at_path sub)" && mkdir mod && git -C mod mv ../sub/ . && test_path_is_missing sub && - test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" && + test "$entry" = "$(index_at_path mod/sub)" && git -C mod/sub status && echo mod/sub >expected && git config -f .gitmodules submodule.sub.path >actual && @@ -404,12 +416,12 @@ test_expect_success 'mv does not complain when no .gitmodules file is found' ' git reset --hard && git submodule update && git rm .gitmodules && - entry="$(git ls-files --stage sub | cut -f 1)" && + entry="$(index_at_path sub)" && mkdir mod && git mv sub mod/sub 2>actual.err && test_must_be_empty actual.err && test_path_is_missing sub && - test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" && + test "$entry" = "$(index_at_path mod/sub)" && git -C mod/sub status && git update-index --refresh && git diff-files --quiet @@ -420,7 +432,7 @@ test_expect_success 'mv will error out on a modified .gitmodules file unless sta git reset --hard && git submodule update && git config -f .gitmodules foo.bar true && - entry="$(git ls-files --stage sub | cut -f 1)" && + entry="$(index_at_path sub)" && mkdir mod && test_must_fail git mv sub mod/sub 2>actual.err && test_file_not_empty actual.err && @@ -430,7 +442,7 @@ test_expect_success 'mv will error out on a modified .gitmodules file unless sta git mv sub mod/sub 2>actual.err && test_must_be_empty actual.err && test_path_is_missing sub && - test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" && + test "$entry" = "$(index_at_path mod/sub)" && git -C mod/sub status && git update-index --refresh && git diff-files --quiet @@ -442,13 +454,13 @@ test_expect_success 'mv issues a warning when section is not found in .gitmodule git submodule update && git config -f .gitmodules --remove-section submodule.sub && git add .gitmodules && - entry="$(git ls-files --stage sub | cut -f 1)" && + entry="$(index_at_path sub)" && echo "warning: Could not find section in .gitmodules where path=sub" >expect.err && mkdir mod && git mv sub mod/sub 2>actual.err && test_cmp expect.err actual.err && test_path_is_missing sub && - test "$entry" = "$(git ls-files --stage mod/sub | cut -f 1)" && + test "$entry" = "$(index_at_path mod/sub)" && git -C mod/sub status && git update-index --refresh && git diff-files --quiet @@ -470,7 +482,7 @@ test_expect_success 'checking out a commit before submodule moved needs manual u git mv sub sub2 && git commit -m "moved sub to sub2" && git checkout -q HEAD^ 2>actual && - test_i18ngrep "^warning: unable to rmdir '\''sub2'\'':" actual && + test_grep "^warning: unable to rmdir '\''sub2'\'':" actual && git status -s sub2 >actual && echo "?? sub2/" >expected && test_cmp expected actual && diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index 9aa1660651..b41a47eb94 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -792,6 +792,34 @@ test_expect_success 'annotations for blobs are empty' ' test_cmp expect actual ' +# Run this before doing any signing, so the test has the same results +# regardless of the GPG prereq. +test_expect_success 'git tag --format with ahead-behind' ' + test_when_finished git reset --hard tag-one-line && + git commit --allow-empty -m "left" && + git tag -a -m left tag-left && + git reset --hard HEAD~1 && + git commit --allow-empty -m "right" && + git tag -a -m left tag-right && + + # Use " !" at the end to demonstrate whitespace + # around empty ahead-behind token for tag-blob. + cat >expect <<-EOF && + refs/tags/tag-blob ! + refs/tags/tag-left 1 1 ! + refs/tags/tag-lines 0 1 ! + refs/tags/tag-one-line 0 1 ! + refs/tags/tag-right 0 0 ! + refs/tags/tag-zero-lines 0 1 ! + EOF + git tag -l --format="%(refname) %(ahead-behind:HEAD) !" >actual 2>err && + grep "refs/tags/tag" actual >actual.focus && + test_cmp expect actual.focus && + + # Error reported for tags that point to non-commits. + grep "error: object [0-9a-f]* is a blob, not a commit" err +' + # trying to verify annotated non-signed tags: test_expect_success GPG \ @@ -1834,6 +1862,51 @@ test_expect_success 'option override configured sort' ' test_cmp expect actual ' +test_expect_success '--no-sort cancels config sort keys' ' + test_config tag.sort "-refname" && + + # objecttype is identical for all of them, so sort falls back on + # default (ascending refname) + git tag -l \ + --no-sort \ + --sort="objecttype" \ + "foo*" >actual && + cat >expect <<-\EOF && + foo1.10 + foo1.3 + foo1.6 + EOF + test_cmp expect actual +' + +test_expect_success '--no-sort cancels command line sort keys' ' + # objecttype is identical for all of them, so sort falls back on + # default (ascending refname) + git tag -l \ + --sort="-refname" \ + --no-sort \ + --sort="objecttype" \ + "foo*" >actual && + cat >expect <<-\EOF && + foo1.10 + foo1.3 + foo1.6 + EOF + test_cmp expect actual +' + +test_expect_success '--no-sort without subsequent --sort prints expected tags' ' + # Sort the results with `sort` for a consistent comparison against + # expected + git tag -l --no-sort "foo*" | sort >actual && + cat >expect <<-\EOF && + foo1.10 + foo1.3 + foo1.6 + EOF + test_cmp expect actual +' + test_expect_success 'invalid sort parameter on command line' ' test_must_fail git tag -l --sort=notvalid "foo*" >actual ' @@ -1843,6 +1916,23 @@ test_expect_success 'invalid sort parameter in configuratoin' ' test_must_fail git tag -l "foo*" ' +test_expect_success 'version sort handles empty value for versionsort.{prereleaseSuffix,suffix}' ' + cp .git/config .git/config.orig && + test_when_finished mv .git/config.orig .git/config && + + cat >>.git/config <<-\EOF && + [versionsort] + prereleaseSuffix + suffix + EOF + cat >expect <<-\EOF && + error: missing value for '\''versionsort.suffix'\'' + error: missing value for '\''versionsort.prereleasesuffix'\'' + EOF + git tag -l --sort=version:refname 2>actual && + test_cmp expect actual +' + test_expect_success 'version sort with prerelease reordering' ' test_config versionsort.prereleaseSuffix -rc && git tag foo1.6-rc1 && @@ -2001,6 +2091,22 @@ test_expect_success '--format should list tags as per format given' ' test_cmp expect actual ' +test_expect_success '--format --omit-empty works' ' + cat >expect <<-\EOF && + refname : refs/tags/v1.0 + + refname : refs/tags/v1.1.3 + EOF + git tag -l --format="%(if:notequals=refs/tags/v1.0.1)%(refname)%(then)refname : %(refname)%(end)" "v1*" >actual && + test_cmp expect actual && + cat >expect <<-\EOF && + refname : refs/tags/v1.0 + refname : refs/tags/v1.1.3 + EOF + git tag -l --omit-empty --format="%(if:notequals=refs/tags/v1.0.1)%(refname)%(then)refname : %(refname)%(end)" "v1*" >actual && + test_cmp expect actual +' + test_expect_success 'git tag -l with --format="%(rest)" must fail' ' test_must_fail git tag -l --format="%(rest)" "v1*" ' @@ -2127,4 +2233,23 @@ test_expect_success 'Does --[no-]contains stop at commits? Yes!' ' test_cmp expected actual ' +test_expect_success 'If tag is created then tag message file is unlinked' ' + test_when_finished "git tag -d foo" && + write_script fakeeditor <<-\EOF && + echo Message >.git/TAG_EDITMSG + EOF + GIT_EDITOR=./fakeeditor git tag -a foo && + test_path_is_missing .git/TAG_EDITMSG +' + +test_expect_success 'If tag cannot be created then tag message file is not unlinked' ' + test_when_finished "git tag -d foo/bar && rm .git/TAG_EDITMSG" && + write_script fakeeditor <<-\EOF && + echo Message >.git/TAG_EDITMSG + EOF + git tag foo/bar && + test_must_fail env GIT_EDITOR=./fakeeditor git tag -a foo && + test_path_exists .git/TAG_EDITMSG +' + test_done diff --git a/t/t7031-verify-tag-signed-ssh.sh b/t/t7031-verify-tag-signed-ssh.sh index 36eb86a4b1..20913b3713 100755 --- a/t/t7031-verify-tag-signed-ssh.sh +++ b/t/t7031-verify-tag-signed-ssh.sh @@ -200,4 +200,14 @@ test_expect_success GPGSSH 'verifying a forged tag with --format should fail sil test_must_be_empty actual-forged ' +test_expect_success GPGSSH 'rev-list --format=%G' ' + test_config gpg.ssh.allowedSignersFile "${GPGSSH_ALLOWED_SIGNERS}" && + git rev-list -1 --format="%G? %H" sixth-signed >actual && + cat >expect <<-EOF && + commit $(git rev-parse sixth-signed^0) + G $(git rev-parse sixth-signed^0) + EOF + test_cmp expect actual +' + test_done diff --git a/t/t7101-reset-empty-subdirs.sh b/t/t7101-reset-empty-subdirs.sh index 638bb04e21..89cf98b30c 100755 --- a/t/t7101-reset-empty-subdirs.sh +++ b/t/t7101-reset-empty-subdirs.sh @@ -10,57 +10,57 @@ TEST_PASSES_SANITIZE_LEAK=true . "$TEST_DIRECTORY"/lib-diff-data.sh test_expect_success 'creating initial files' ' - mkdir path0 && - COPYING_test_data >path0/COPYING && - git add path0/COPYING && - git commit -m add -a + mkdir path0 && + COPYING_test_data >path0/COPYING && + git add path0/COPYING && + git commit -m add -a ' test_expect_success 'creating second files' ' - mkdir path1 && - mkdir path1/path2 && - COPYING_test_data >path1/path2/COPYING && - COPYING_test_data >path1/COPYING && - COPYING_test_data >COPYING && - COPYING_test_data >path0/COPYING-TOO && - git add path1/path2/COPYING && - git add path1/COPYING && - git add COPYING && - git add path0/COPYING-TOO && - git commit -m change -a + mkdir path1 && + mkdir path1/path2 && + COPYING_test_data >path1/path2/COPYING && + COPYING_test_data >path1/COPYING && + COPYING_test_data >COPYING && + COPYING_test_data >path0/COPYING-TOO && + git add path1/path2/COPYING && + git add path1/COPYING && + git add COPYING && + git add path0/COPYING-TOO && + git commit -m change -a ' test_expect_success 'resetting tree HEAD^' ' - git reset --hard HEAD^ + git reset --hard HEAD^ ' test_expect_success 'checking initial files exist after rewind' ' - test -d path0 && - test -f path0/COPYING + test -d path0 && + test -f path0/COPYING ' test_expect_success 'checking lack of path1/path2/COPYING' ' - ! test -f path1/path2/COPYING + ! test -f path1/path2/COPYING ' test_expect_success 'checking lack of path1/COPYING' ' - ! test -f path1/COPYING + ! test -f path1/COPYING ' test_expect_success 'checking lack of COPYING' ' - ! test -f COPYING + ! test -f COPYING ' test_expect_success 'checking checking lack of path1/COPYING-TOO' ' - ! test -f path0/COPYING-TOO + ! test -f path0/COPYING-TOO ' test_expect_success 'checking lack of path1/path2' ' - ! test -d path1/path2 + ! test -d path1/path2 ' test_expect_success 'checking lack of path1' ' - ! test -d path1 + ! test -d path1 ' test_done diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh index 2a3d22592f..62d9f846ce 100755 --- a/t/t7102-reset.sh +++ b/t/t7102-reset.sh @@ -71,6 +71,16 @@ check_changes () { done | test_cmp .cat_expect - } +# no negated form for various type of resets +for opt in soft mixed hard merge keep +do + test_expect_success "no 'git reset --no-$opt'" ' + test_when_finished "rm -f err" && + test_must_fail git reset --no-$opt 2>err && + grep "error: unknown option .no-$opt." err + ' +done + test_expect_success 'reset --hard message' ' hex=$(git log -1 --format="%h") && git reset --hard >.actual && diff --git a/t/t7105-reset-patch.sh b/t/t7105-reset-patch.sh index 9b46da7aaa..05079c7246 100755 --- a/t/t7105-reset-patch.sh +++ b/t/t7105-reset-patch.sh @@ -30,21 +30,21 @@ test_expect_success PERL 'git reset -p' ' test_write_lines n y | git reset -p >output && verify_state dir/foo work head && verify_saved_state bar && - test_i18ngrep "Unstage" output + test_grep "Unstage" output ' test_expect_success PERL 'git reset -p HEAD^' ' test_write_lines n y | git reset -p HEAD^ >output && verify_state dir/foo work parent && verify_saved_state bar && - test_i18ngrep "Apply" output + test_grep "Apply" output ' test_expect_success PERL 'git reset -p HEAD^^{tree}' ' test_write_lines n y | git reset -p HEAD^^{tree} >output && verify_state dir/foo work parent && verify_saved_state bar && - test_i18ngrep "Apply" output + test_grep "Apply" output ' test_expect_success PERL 'git reset -p HEAD^:dir/foo (blob fails)' ' diff --git a/t/t7106-reset-unborn-branch.sh b/t/t7106-reset-unborn-branch.sh index a0b67a0b84..d20e5709f9 100755 --- a/t/t7106-reset-unborn-branch.sh +++ b/t/t7106-reset-unborn-branch.sh @@ -42,7 +42,7 @@ test_expect_success PERL 'reset -p' ' git ls-files >actual && test_must_be_empty actual && - test_i18ngrep "Unstage" output + test_grep "Unstage" output ' test_expect_success 'reset --soft is a no-op' ' diff --git a/t/t7107-reset-pathspec-file.sh b/t/t7107-reset-pathspec-file.sh index af5ea406db..020db201d5 100755 --- a/t/t7107-reset-pathspec-file.sh +++ b/t/t7107-reset-pathspec-file.sh @@ -161,19 +161,19 @@ test_expect_success 'error conditions' ' git rm fileA.t && test_must_fail git reset --pathspec-from-file=list --patch 2>err && - test_i18ngrep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err && + test_grep -e "options .--pathspec-from-file. and .--patch. cannot be used together" err && test_must_fail git reset --pathspec-from-file=list -- fileA.t 2>err && - test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err && + test_grep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err && test_must_fail git reset --pathspec-file-nul 2>err && - test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err && + test_grep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err && test_must_fail git reset --soft --pathspec-from-file=list 2>err && - test_i18ngrep -e "fatal: Cannot do soft reset with paths" err && + test_grep -e "fatal: Cannot do soft reset with paths" err && test_must_fail git reset --hard --pathspec-from-file=list 2>err && - test_i18ngrep -e "fatal: Cannot do hard reset with paths" err + test_grep -e "fatal: Cannot do hard reset with paths" err ' test_done diff --git a/t/t7110-reset-merge.sh b/t/t7110-reset-merge.sh index eb881be95b..7ee180f81d 100755 --- a/t/t7110-reset-merge.sh +++ b/t/t7110-reset-merge.sh @@ -9,17 +9,17 @@ TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success setup ' - printf "line %d\n" 1 2 3 >file1 && - cat file1 >file2 && - git add file1 file2 && - test_tick && - git commit -m "Initial commit" && - git tag initial && - echo line 4 >>file1 && - cat file1 >file2 && - test_tick && - git commit -m "add line 4 to file1" file1 && - git tag second + printf "line %d\n" 1 2 3 >file1 && + cat file1 >file2 && + git add file1 file2 && + test_tick && + git commit -m "Initial commit" && + git tag initial && + echo line 4 >>file1 && + cat file1 >file2 && + test_tick && + git commit -m "add line 4 to file1" file1 && + git tag second ' # The next test will test the following: @@ -29,19 +29,19 @@ test_expect_success setup ' # file1: C C C D --merge D D D # file2: C D D D --merge C D D test_expect_success 'reset --merge is ok with changes in file it does not touch' ' - git reset --merge HEAD^ && - ! grep 4 file1 && - grep 4 file2 && - test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" && - test -z "$(git diff --cached)" + git reset --merge HEAD^ && + ! grep 4 file1 && + grep 4 file2 && + test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" && + test -z "$(git diff --cached)" ' test_expect_success 'reset --merge is ok when switching back' ' - git reset --merge second && - grep 4 file1 && - grep 4 file2 && - test "$(git rev-parse HEAD)" = "$(git rev-parse second)" && - test -z "$(git diff --cached)" + git reset --merge second && + grep 4 file1 && + grep 4 file2 && + test "$(git rev-parse HEAD)" = "$(git rev-parse second)" && + test -z "$(git diff --cached)" ' # The next test will test the following: @@ -51,21 +51,21 @@ test_expect_success 'reset --merge is ok when switching back' ' # file1: C C C D --keep D D D # file2: C D D D --keep C D D test_expect_success 'reset --keep is ok with changes in file it does not touch' ' - git reset --hard second && - cat file1 >file2 && - git reset --keep HEAD^ && - ! grep 4 file1 && - grep 4 file2 && - test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" && - test -z "$(git diff --cached)" + git reset --hard second && + cat file1 >file2 && + git reset --keep HEAD^ && + ! grep 4 file1 && + grep 4 file2 && + test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" && + test -z "$(git diff --cached)" ' test_expect_success 'reset --keep is ok when switching back' ' - git reset --keep second && - grep 4 file1 && - grep 4 file2 && - test "$(git rev-parse HEAD)" = "$(git rev-parse second)" && - test -z "$(git diff --cached)" + git reset --keep second && + grep 4 file1 && + grep 4 file2 && + test "$(git rev-parse HEAD)" = "$(git rev-parse second)" && + test -z "$(git diff --cached)" ' # The next test will test the following: @@ -75,28 +75,28 @@ test_expect_success 'reset --keep is ok when switching back' ' # file1: B B C D --merge D D D # file2: C D D D --merge C D D test_expect_success 'reset --merge discards changes added to index (1)' ' - git reset --hard second && - cat file1 >file2 && - echo "line 5" >> file1 && - git add file1 && - git reset --merge HEAD^ && - ! grep 4 file1 && - ! grep 5 file1 && - grep 4 file2 && - test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" && - test -z "$(git diff --cached)" + git reset --hard second && + cat file1 >file2 && + echo "line 5" >> file1 && + git add file1 && + git reset --merge HEAD^ && + ! grep 4 file1 && + ! grep 5 file1 && + grep 4 file2 && + test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" && + test -z "$(git diff --cached)" ' test_expect_success 'reset --merge is ok again when switching back (1)' ' - git reset --hard initial && - echo "line 5" >> file2 && - git add file2 && - git reset --merge second && - ! grep 4 file2 && - ! grep 5 file1 && - grep 4 file1 && - test "$(git rev-parse HEAD)" = "$(git rev-parse second)" && - test -z "$(git diff --cached)" + git reset --hard initial && + echo "line 5" >> file2 && + git add file2 && + git reset --merge second && + ! grep 4 file2 && + ! grep 5 file1 && + grep 4 file1 && + test "$(git rev-parse HEAD)" = "$(git rev-parse second)" && + test -z "$(git diff --cached)" ' # The next test will test the following: @@ -105,10 +105,10 @@ test_expect_success 'reset --merge is ok again when switching back (1)' ' # ---------------------------------------------------- # file1: B B C D --keep (disallowed) test_expect_success 'reset --keep fails with changes in index in files it touches' ' - git reset --hard second && - echo "line 5" >> file1 && - git add file1 && - test_must_fail git reset --keep HEAD^ + git reset --hard second && + echo "line 5" >> file1 && + git add file1 && + test_must_fail git reset --keep HEAD^ ' # The next test will test the following: @@ -118,23 +118,23 @@ test_expect_success 'reset --keep fails with changes in index in files it touche # file1: C C C D --merge D D D # file2: C C D D --merge D D D test_expect_success 'reset --merge discards changes added to index (2)' ' - git reset --hard second && - echo "line 4" >> file2 && - git add file2 && - git reset --merge HEAD^ && - ! grep 4 file2 && - test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" && - test -z "$(git diff)" && - test -z "$(git diff --cached)" + git reset --hard second && + echo "line 4" >> file2 && + git add file2 && + git reset --merge HEAD^ && + ! grep 4 file2 && + test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" && + test -z "$(git diff)" && + test -z "$(git diff --cached)" ' test_expect_success 'reset --merge is ok again when switching back (2)' ' - git reset --hard initial && - git reset --merge second && - ! grep 4 file2 && - grep 4 file1 && - test "$(git rev-parse HEAD)" = "$(git rev-parse second)" && - test -z "$(git diff --cached)" + git reset --hard initial && + git reset --merge second && + ! grep 4 file2 && + grep 4 file1 && + test "$(git rev-parse HEAD)" = "$(git rev-parse second)" && + test -z "$(git diff --cached)" ' # The next test will test the following: @@ -144,21 +144,21 @@ test_expect_success 'reset --merge is ok again when switching back (2)' ' # file1: C C C D --keep D D D # file2: C C D D --keep C D D test_expect_success 'reset --keep keeps changes it does not touch' ' - git reset --hard second && - echo "line 4" >> file2 && - git add file2 && - git reset --keep HEAD^ && - grep 4 file2 && - test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" && - test -z "$(git diff --cached)" + git reset --hard second && + echo "line 4" >> file2 && + git add file2 && + git reset --keep HEAD^ && + grep 4 file2 && + test "$(git rev-parse HEAD)" = "$(git rev-parse initial)" && + test -z "$(git diff --cached)" ' test_expect_success 'reset --keep keeps changes when switching back' ' - git reset --keep second && - grep 4 file2 && - grep 4 file1 && - test "$(git rev-parse HEAD)" = "$(git rev-parse second)" && - test -z "$(git diff --cached)" + git reset --keep second && + grep 4 file2 && + grep 4 file1 && + test "$(git rev-parse HEAD)" = "$(git rev-parse second)" && + test -z "$(git diff --cached)" ' # The next test will test the following: @@ -167,14 +167,14 @@ test_expect_success 'reset --keep keeps changes when switching back' ' # ---------------------------------------------------- # file1: A B B C --merge (disallowed) test_expect_success 'reset --merge fails with changes in file it touches' ' - git reset --hard second && - echo "line 5" >> file1 && - test_tick && - git commit -m "add line 5" file1 && - sed -e "s/line 1/changed line 1/" <file1 >file3 && - mv file3 file1 && - test_must_fail git reset --merge HEAD^ 2>err.log && - grep file1 err.log | grep "not uptodate" + git reset --hard second && + echo "line 5" >> file1 && + test_tick && + git commit -m "add line 5" file1 && + sed -e "s/line 1/changed line 1/" <file1 >file3 && + mv file3 file1 && + test_must_fail git reset --merge HEAD^ 2>err.log && + grep file1 err.log | grep "not uptodate" ' # The next test will test the following: @@ -183,36 +183,36 @@ test_expect_success 'reset --merge fails with changes in file it touches' ' # ---------------------------------------------------- # file1: A B B C --keep (disallowed) test_expect_success 'reset --keep fails with changes in file it touches' ' - git reset --hard second && - echo "line 5" >> file1 && - test_tick && - git commit -m "add line 5" file1 && - sed -e "s/line 1/changed line 1/" <file1 >file3 && - mv file3 file1 && - test_must_fail git reset --keep HEAD^ 2>err.log && - grep file1 err.log | grep "not uptodate" + git reset --hard second && + echo "line 5" >> file1 && + test_tick && + git commit -m "add line 5" file1 && + sed -e "s/line 1/changed line 1/" <file1 >file3 && + mv file3 file1 && + test_must_fail git reset --keep HEAD^ 2>err.log && + grep file1 err.log | grep "not uptodate" ' test_expect_success 'setup 3 different branches' ' - git reset --hard second && - git branch branch1 && - git branch branch2 && - git branch branch3 && - git checkout branch1 && - echo "line 5 in branch1" >> file1 && - test_tick && - git commit -a -m "change in branch1" && - git checkout branch2 && - echo "line 5 in branch2" >> file1 && - test_tick && - git commit -a -m "change in branch2" && - git tag third && - git checkout branch3 && - echo a new file >file3 && - rm -f file1 && - git add file3 && - test_tick && - git commit -a -m "change in branch3" + git reset --hard second && + git branch branch1 && + git branch branch2 && + git branch branch3 && + git checkout branch1 && + echo "line 5 in branch1" >> file1 && + test_tick && + git commit -a -m "change in branch1" && + git checkout branch2 && + echo "line 5 in branch2" >> file1 && + test_tick && + git commit -a -m "change in branch2" && + git tag third && + git checkout branch3 && + echo a new file >file3 && + rm -f file1 && + git add file3 && + test_tick && + git commit -a -m "change in branch3" ' # The next test will test the following: @@ -221,12 +221,12 @@ test_expect_success 'setup 3 different branches' ' # ---------------------------------------------------- # file1: X U B C --merge C C C test_expect_success '"reset --merge HEAD^" is ok with pending merge' ' - git checkout third && - test_must_fail git merge branch1 && - git reset --merge HEAD^ && - test "$(git rev-parse HEAD)" = "$(git rev-parse second)" && - test -z "$(git diff --cached)" && - test -z "$(git diff)" + git checkout third && + test_must_fail git merge branch1 && + git reset --merge HEAD^ && + test "$(git rev-parse HEAD)" = "$(git rev-parse second)" && + test -z "$(git diff --cached)" && + test -z "$(git diff)" ' # The next test will test the following: @@ -235,10 +235,10 @@ test_expect_success '"reset --merge HEAD^" is ok with pending merge' ' # ---------------------------------------------------- # file1: X U B C --keep (disallowed) test_expect_success '"reset --keep HEAD^" fails with pending merge' ' - git reset --hard third && - test_must_fail git merge branch1 && - test_must_fail git reset --keep HEAD^ 2>err.log && - test_i18ngrep "middle of a merge" err.log + git reset --hard third && + test_must_fail git merge branch1 && + test_must_fail git reset --keep HEAD^ 2>err.log && + test_grep "middle of a merge" err.log ' # The next test will test the following: @@ -247,12 +247,12 @@ test_expect_success '"reset --keep HEAD^" fails with pending merge' ' # ---------------------------------------------------- # file1: X U B B --merge B B B test_expect_success '"reset --merge HEAD" is ok with pending merge' ' - git reset --hard third && - test_must_fail git merge branch1 && - git reset --merge HEAD && - test "$(git rev-parse HEAD)" = "$(git rev-parse third)" && - test -z "$(git diff --cached)" && - test -z "$(git diff)" + git reset --hard third && + test_must_fail git merge branch1 && + git reset --merge HEAD && + test "$(git rev-parse HEAD)" = "$(git rev-parse third)" && + test -z "$(git diff --cached)" && + test -z "$(git diff)" ' # The next test will test the following: @@ -261,36 +261,36 @@ test_expect_success '"reset --merge HEAD" is ok with pending merge' ' # ---------------------------------------------------- # file1: X U B B --keep (disallowed) test_expect_success '"reset --keep HEAD" fails with pending merge' ' - git reset --hard third && - test_must_fail git merge branch1 && - test_must_fail git reset --keep HEAD 2>err.log && - test_i18ngrep "middle of a merge" err.log + git reset --hard third && + test_must_fail git merge branch1 && + test_must_fail git reset --keep HEAD 2>err.log && + test_grep "middle of a merge" err.log ' test_expect_success '--merge is ok with added/deleted merge' ' - git reset --hard third && - rm -f file2 && - test_must_fail git merge branch3 && - ! test -f file2 && - test -f file3 && - git diff --exit-code file3 && - git diff --exit-code branch3 file3 && - git reset --merge HEAD && - ! test -f file3 && - ! test -f file2 && - git diff --exit-code --cached + git reset --hard third && + rm -f file2 && + test_must_fail git merge branch3 && + ! test -f file2 && + test -f file3 && + git diff --exit-code file3 && + git diff --exit-code branch3 file3 && + git reset --merge HEAD && + ! test -f file3 && + ! test -f file2 && + git diff --exit-code --cached ' test_expect_success '--keep fails with added/deleted merge' ' - git reset --hard third && - rm -f file2 && - test_must_fail git merge branch3 && - ! test -f file2 && - test -f file3 && - git diff --exit-code file3 && - git diff --exit-code branch3 file3 && - test_must_fail git reset --keep HEAD 2>err.log && - test_i18ngrep "middle of a merge" err.log + git reset --hard third && + rm -f file2 && + test_must_fail git merge branch3 && + ! test -f file2 && + test -f file3 && + git diff --exit-code file3 && + git diff --exit-code branch3 file3 && + test_must_fail git reset --keep HEAD 2>err.log && + test_grep "middle of a merge" err.log ' test_done diff --git a/t/t7111-reset-table.sh b/t/t7111-reset-table.sh index 78f25c1c7e..01b7c3503c 100755 --- a/t/t7111-reset-table.sh +++ b/t/t7111-reset-table.sh @@ -10,9 +10,9 @@ TEST_PASSES_SANITIZE_LEAK=true test_expect_success 'creating initial commits' ' - test_commit E file1 && - test_commit D file1 && - test_commit C file1 + test_commit E file1 && + test_commit D file1 && + test_commit C file1 ' while read W1 I1 H1 T opt W2 I2 H2 @@ -74,13 +74,13 @@ B C C C keep B C C EOF test_expect_success 'setting up branches to test with unmerged entries' ' - git reset --hard C && - git branch branch1 && - git branch branch2 && - git checkout branch1 && - test_commit B1 file1 && - git checkout branch2 && - test_commit B file1 + git reset --hard C && + git branch branch1 && + git branch branch2 && + git checkout branch1 && + test_commit B1 file1 && + git checkout branch2 && + test_commit B file1 ' while read W1 I1 H1 T opt W2 I2 H2 diff --git a/t/t7201-co.sh b/t/t7201-co.sh index 61ad47b0c1..10cc6c4605 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -217,7 +217,7 @@ test_expect_success 'switch to another branch while carrying a deletion' ' git rm two && test_must_fail git checkout simple 2>errs && - test_i18ngrep overwritten errs && + test_grep overwritten errs && test_must_fail git read-tree --quiet -m -u HEAD simple 2>errs && test_must_be_empty errs @@ -229,7 +229,7 @@ test_expect_success 'checkout to detach HEAD (with advice declined)' ' git checkout -f renamer && git clean -f && git checkout renamer^ 2>messages && - test_i18ngrep "HEAD is now at $rev" messages && + test_grep "HEAD is now at $rev" messages && test_line_count = 1 messages && H=$(git rev-parse --verify HEAD) && M=$(git show-ref -s --verify refs/heads/main) && @@ -372,75 +372,75 @@ test_expect_success 'checkout specific path while in subdirectory' ' ' test_expect_success 'checkout w/--track sets up tracking' ' - git config branch.autosetupmerge false && - git checkout main && - git checkout --track -b track1 && - test "$(git config branch.track1.remote)" && - test "$(git config branch.track1.merge)" + git config branch.autosetupmerge false && + git checkout main && + git checkout --track -b track1 && + test "$(git config branch.track1.remote)" && + test "$(git config branch.track1.merge)" ' test_expect_success 'checkout w/autosetupmerge=always sets up tracking' ' - test_when_finished git config branch.autosetupmerge false && - git config branch.autosetupmerge always && - git checkout main && - git checkout -b track2 && - test "$(git config branch.track2.remote)" && - test "$(git config branch.track2.merge)" + test_when_finished git config branch.autosetupmerge false && + git config branch.autosetupmerge always && + git checkout main && + git checkout -b track2 && + test "$(git config branch.track2.remote)" && + test "$(git config branch.track2.merge)" ' test_expect_success 'checkout w/--track from non-branch HEAD fails' ' - git checkout main^0 && - test_must_fail git symbolic-ref HEAD && - test_must_fail git checkout --track -b track && - test_must_fail git rev-parse --verify track && - test_must_fail git symbolic-ref HEAD && - test "z$(git rev-parse main^0)" = "z$(git rev-parse HEAD)" + git checkout main^0 && + test_must_fail git symbolic-ref HEAD && + test_must_fail git checkout --track -b track && + test_must_fail git rev-parse --verify track && + test_must_fail git symbolic-ref HEAD && + test "z$(git rev-parse main^0)" = "z$(git rev-parse HEAD)" ' test_expect_success 'checkout w/--track from tag fails' ' - git checkout main^0 && - test_must_fail git symbolic-ref HEAD && - test_must_fail git checkout --track -b track frotz && - test_must_fail git rev-parse --verify track && - test_must_fail git symbolic-ref HEAD && - test "z$(git rev-parse main^0)" = "z$(git rev-parse HEAD)" + git checkout main^0 && + test_must_fail git symbolic-ref HEAD && + test_must_fail git checkout --track -b track frotz && + test_must_fail git rev-parse --verify track && + test_must_fail git symbolic-ref HEAD && + test "z$(git rev-parse main^0)" = "z$(git rev-parse HEAD)" ' test_expect_success 'detach a symbolic link HEAD' ' - git checkout main && - git config --bool core.prefersymlinkrefs yes && - git checkout side && - git checkout main && - it=$(git symbolic-ref HEAD) && - test "z$it" = zrefs/heads/main && - here=$(git rev-parse --verify refs/heads/main) && - git checkout side^ && - test "z$(git rev-parse --verify refs/heads/main)" = "z$here" + git checkout main && + git config --bool core.prefersymlinkrefs yes && + git checkout side && + git checkout main && + it=$(git symbolic-ref HEAD) && + test "z$it" = zrefs/heads/main && + here=$(git rev-parse --verify refs/heads/main) && + git checkout side^ && + test "z$(git rev-parse --verify refs/heads/main)" = "z$here" ' test_expect_success 'checkout with --track fakes a sensible -b <name>' ' - git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" && - git update-ref refs/remotes/origin/koala/bear renamer && + git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" && + git update-ref refs/remotes/origin/koala/bear renamer && - git checkout --track origin/koala/bear && - test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && - test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" && + git checkout --track origin/koala/bear && + test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && + test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" && - git checkout main && git branch -D koala/bear && + git checkout main && git branch -D koala/bear && - git checkout --track refs/remotes/origin/koala/bear && - test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && - test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" && + git checkout --track refs/remotes/origin/koala/bear && + test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && + test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" && - git checkout main && git branch -D koala/bear && + git checkout main && git branch -D koala/bear && - git checkout --track remotes/origin/koala/bear && - test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && - test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" + git checkout --track remotes/origin/koala/bear && + test "refs/heads/koala/bear" = "$(git symbolic-ref HEAD)" && + test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)" ' test_expect_success 'checkout with --track, but without -b, fails with too short tracked name' ' - test_must_fail git checkout --track renamer + test_must_fail git checkout --track renamer ' setup_conflicting_index () { @@ -497,6 +497,11 @@ test_expect_success 'checkout unmerged stage' ' test ztheirside = "z$(cat file)" ' +test_expect_success 'checkout path with --merge from tree-ish is a no-no' ' + setup_conflicting_index && + test_must_fail git checkout -m HEAD -- file +' + test_expect_success 'checkout with --merge' ' setup_conflicting_index && echo "none of the above" >sample && @@ -517,6 +522,48 @@ test_expect_success 'checkout with --merge' ' test_cmp merged file ' +test_expect_success 'checkout -m works after (mistaken) resolution' ' + setup_conflicting_index && + echo "none of the above" >sample && + cat sample >fild && + cat sample >file && + cat sample >filf && + # resolve to something + git add file && + git checkout --merge -- fild file filf && + { + echo "<<<<<<< ours" && + echo ourside && + echo "=======" && + echo theirside && + echo ">>>>>>> theirs" + } >merged && + test_cmp expect fild && + test_cmp expect filf && + test_cmp merged file +' + +test_expect_success 'checkout -m works after (mistaken) resolution to remove' ' + setup_conflicting_index && + echo "none of the above" >sample && + cat sample >fild && + cat sample >file && + cat sample >filf && + # resolve to remove + git rm file && + git checkout --merge -- fild file filf && + { + echo "<<<<<<< ours" && + echo ourside && + echo "=======" && + echo theirside && + echo ">>>>>>> theirs" + } >merged && + test_cmp expect fild && + test_cmp expect filf && + test_cmp merged file +' + test_expect_success 'checkout with --merge, in diff3 -m style' ' git config merge.conflictstyle diff3 && setup_conflicting_index && diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh index c975eb54d2..611b3dd3ae 100755 --- a/t/t7300-clean.sh +++ b/t/t7300-clean.sh @@ -120,7 +120,7 @@ test_expect_success 'git clean with relative prefix' ' grep part3 | sed -n -e "s|^Would remove ||p" ) && - verbose test "$would_clean" = ../src/part3.c + test "$would_clean" = ../src/part3.c ' test_expect_success 'git clean with absolute path' ' @@ -133,7 +133,7 @@ test_expect_success 'git clean with absolute path' ' grep part3 | sed -n -e "s|^Would remove ||p" ) && - verbose test "$would_clean" = ../src/part3.c + test "$would_clean" = ../src/part3.c ' test_expect_success 'git clean with out of work tree relative path' ' @@ -517,8 +517,12 @@ test_expect_success 'nested (empty) git should be kept' ' git init empty_repo && mkdir to_clean && >to_clean/should_clean.this && + # Note that we put the expect file in the .git directory so that it + # does not get cleaned. + find empty_repo | sort >.git/expect && git clean -f -d && - test_path_is_file empty_repo/.git/HEAD && + find empty_repo | sort >actual && + test_cmp .git/expect actual && test_path_is_missing to_clean ' @@ -559,10 +563,10 @@ test_expect_success 'giving path in nested git work tree will NOT remove it' ' mkdir -p bar/baz && test_commit msg bar/baz/hello.world ) && + find repo | sort >expect && git clean -f -d repo/bar/baz && - test_path_is_file repo/.git/HEAD && - test_path_is_dir repo/bar/ && - test_path_is_file repo/bar/baz/hello.world + find repo | sort >actual && + test_cmp expect actual ' test_expect_success 'giving path to nested .git will not remove it' ' @@ -573,10 +577,10 @@ test_expect_success 'giving path to nested .git will not remove it' ' git init && test_commit msg hello.world ) && + find repo | sort >expect && git clean -f -d repo/.git && - test_path_is_file repo/.git/HEAD && - test_path_is_dir repo/.git/refs && - test_path_is_dir repo/.git/objects && + find repo | sort >actual && + test_cmp expect actual && test_path_is_dir untracked/ ' @@ -588,9 +592,10 @@ test_expect_success 'giving path to nested .git/ will NOT remove contents' ' git init && test_commit msg hello.world ) && + find repo | sort >expect && git clean -f -d repo/.git/ && - test_path_is_dir repo/.git && - test_path_is_file repo/.git/HEAD && + find repo | sort >actual && + test_cmp expect actual && test_path_is_dir untracked/ ' @@ -735,7 +740,7 @@ test_expect_success MINGW 'handle clean & core.longpaths = false nicely' ' test_must_fail git clean -xdf 2>.git/err && # grepping for a strerror string is unportable but it is OK here with # MINGW prereq - test_i18ngrep "too long" .git/err + test_grep "too long" .git/err ' test_expect_success 'clean untracked paths by pathspec' ' diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index eae6a46ef3..00c1f1aab1 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -60,7 +60,7 @@ test_expect_success 'submodule init aborts on missing .gitmodules file' ' git update-index --add --cacheinfo 160000,$(git rev-parse HEAD),sub && # missing the .gitmodules file here test_must_fail git submodule init 2>actual && - test_i18ngrep "No url found for submodule path" actual + test_grep "No url found for submodule path" actual ' test_expect_success 'submodule update aborts on missing .gitmodules file' ' @@ -68,7 +68,7 @@ test_expect_success 'submodule update aborts on missing .gitmodules file' ' git update-index --add --cacheinfo 160000,$(git rev-parse HEAD),sub && # missing the .gitmodules file here git submodule update sub 2>actual && - test_i18ngrep "Submodule path .sub. not initialized" actual + test_grep "Submodule path .sub. not initialized" actual ' test_expect_success 'submodule update aborts on missing gitmodules url' ' @@ -100,7 +100,7 @@ test_expect_success 'status should ignore inner git repo when not added' ' ) && test_must_fail git submodule status inner 2>output.err && rm -fr inner && - test_i18ngrep "^error: .*did not match any file(s) known to git" output.err + test_grep "^error: .*did not match any file(s) known to git" output.err ' test_expect_success 'setup - repository in init subdirectory' ' @@ -196,7 +196,7 @@ test_expect_success 'redirected submodule add does not show progress' ' git -C addtest submodule add "file://$submodurl/parent" submod-redirected \ 2>err && ! grep % err && - test_i18ngrep ! "Checking connectivity" err + test_grep ! "Checking connectivity" err ' test_expect_success 'redirected submodule add --progress does show progress' ' @@ -263,7 +263,7 @@ test_expect_success 'submodule add relays add --dry-run stderr' ' cd addtest && : >.git/index.lock && ! git submodule add "$submodurl" sub-while-locked 2>output.err && - test_i18ngrep "^fatal: .*index\.lock" output.err && + test_grep "^fatal: .*index\.lock" output.err && test_path_is_missing sub-while-locked ) ' @@ -405,7 +405,7 @@ test_expect_success 'submodule add in subdirectory with relative path should fai cd addtest/sub && test_must_fail git submodule add ../../ submod3 2>../../output.err ) && - test_i18ngrep toplevel output.err + test_grep toplevel output.err ' test_expect_success 'setup - add an example entry to .gitmodules' ' @@ -486,7 +486,7 @@ test_expect_success 'status should still be "missing" after initializing' ' test_failure_with_unknown_submodule () { test_must_fail git submodule $1 no-such-submodule 2>output.err && - test_i18ngrep "^error: .*no-such-submodule" output.err + test_grep "^error: .*no-such-submodule" output.err } test_expect_success 'init should fail with unknown submodule' ' @@ -644,7 +644,7 @@ test_expect_success 'update --init' ' test_must_fail git config submodule.example.url && git submodule update init 2> update.out && - test_i18ngrep "not initialized" update.out && + test_grep "not initialized" update.out && test_must_fail git rev-parse --resolve-git-dir init/.git && git submodule update --init init && @@ -661,7 +661,7 @@ test_expect_success 'update --init from subdirectory' ' ( cd sub && git submodule update ../init 2>update.out && - test_i18ngrep "not initialized" update.out && + test_grep "not initialized" update.out && test_must_fail git rev-parse --resolve-git-dir ../init/.git && git submodule update --init ../init @@ -1121,7 +1121,7 @@ test_expect_success 'submodule deinit from subdirectory' ' cd sub && git submodule deinit ../init >../output ) && - test_i18ngrep "\\.\\./init" output && + test_grep "\\.\\./init" output && test -z "$(git config --get-regexp "submodule\.example\.")" && test -n "$(git config --get-regexp "submodule\.example2\.")" && test -f example2/.git && @@ -1136,8 +1136,8 @@ test_expect_success 'submodule deinit . deinits all initialized submodules' ' git submodule deinit . >actual && test -z "$(git config --get-regexp "submodule\.example\.")" && test -z "$(git config --get-regexp "submodule\.example2\.")" && - test_i18ngrep "Cleared directory .init" actual && - test_i18ngrep "Cleared directory .example2" actual && + test_grep "Cleared directory .init" actual && + test_grep "Cleared directory .example2" actual && rmdir init example2 ' @@ -1149,8 +1149,8 @@ test_expect_success 'submodule deinit --all deinits all initialized submodules' git submodule deinit --all >actual && test -z "$(git config --get-regexp "submodule\.example\.")" && test -z "$(git config --get-regexp "submodule\.example2\.")" && - test_i18ngrep "Cleared directory .init" actual && - test_i18ngrep "Cleared directory .example2" actual && + test_grep "Cleared directory .init" actual && + test_grep "Cleared directory .example2" actual && rmdir init example2 ' @@ -1160,8 +1160,8 @@ test_expect_success 'submodule deinit deinits a submodule when its work tree is git submodule deinit init example2 >actual && test -z "$(git config --get-regexp "submodule\.example\.")" && test -z "$(git config --get-regexp "submodule\.example2\.")" && - test_i18ngrep ! "Cleared directory .init" actual && - test_i18ngrep "Cleared directory .example2" actual && + test_grep ! "Cleared directory .init" actual && + test_grep "Cleared directory .example2" actual && rmdir init ' @@ -1173,7 +1173,7 @@ test_expect_success 'submodule deinit fails when the submodule contains modifica test -f example2/.git && git submodule deinit -f init >actual && test -z "$(git config --get-regexp "submodule\.example\.")" && - test_i18ngrep "Cleared directory .init" actual && + test_grep "Cleared directory .init" actual && rmdir init ' @@ -1185,7 +1185,7 @@ test_expect_success 'submodule deinit fails when the submodule contains untracke test -f example2/.git && git submodule deinit -f init >actual && test -z "$(git config --get-regexp "submodule\.example\.")" && - test_i18ngrep "Cleared directory .init" actual && + test_grep "Cleared directory .init" actual && rmdir init ' @@ -1200,30 +1200,30 @@ test_expect_success 'submodule deinit fails when the submodule HEAD does not mat test -f example2/.git && git submodule deinit -f init >actual && test -z "$(git config --get-regexp "submodule\.example\.")" && - test_i18ngrep "Cleared directory .init" actual && + test_grep "Cleared directory .init" actual && rmdir init ' test_expect_success 'submodule deinit is silent when used on an uninitialized submodule' ' git submodule update --init && git submodule deinit init >actual && - test_i18ngrep "Submodule .example. (.*) unregistered for path .init" actual && - test_i18ngrep "Cleared directory .init" actual && + test_grep "Submodule .example. (.*) unregistered for path .init" actual && + test_grep "Cleared directory .init" actual && git submodule deinit init >actual && - test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual && - test_i18ngrep "Cleared directory .init" actual && + test_grep ! "Submodule .example. (.*) unregistered for path .init" actual && + test_grep "Cleared directory .init" actual && git submodule deinit . >actual && - test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual && - test_i18ngrep "Submodule .example2. (.*) unregistered for path .example2" actual && - test_i18ngrep "Cleared directory .init" actual && + test_grep ! "Submodule .example. (.*) unregistered for path .init" actual && + test_grep "Submodule .example2. (.*) unregistered for path .example2" actual && + test_grep "Cleared directory .init" actual && git submodule deinit . >actual && - test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual && - test_i18ngrep ! "Submodule .example2. (.*) unregistered for path .example2" actual && - test_i18ngrep "Cleared directory .init" actual && + test_grep ! "Submodule .example. (.*) unregistered for path .init" actual && + test_grep ! "Submodule .example2. (.*) unregistered for path .example2" actual && + test_grep "Cleared directory .init" actual && git submodule deinit --all >actual && - test_i18ngrep ! "Submodule .example. (.*) unregistered for path .init" actual && - test_i18ngrep ! "Submodule .example2. (.*) unregistered for path .example2" actual && - test_i18ngrep "Cleared directory .init" actual && + test_grep ! "Submodule .example. (.*) unregistered for path .init" actual && + test_grep ! "Submodule .example2. (.*) unregistered for path .example2" actual && + test_grep "Cleared directory .init" actual && rmdir init example2 ' @@ -1351,6 +1351,22 @@ test_expect_success 'clone active submodule without submodule url set' ' ) ' +test_expect_success 'update submodules without url set in .gitconfig' ' + test_when_finished "rm -rf multisuper_clone" && + git clone file://"$pwd"/multisuper multisuper_clone && + + git -C multisuper_clone submodule init && + for s in sub0 sub1 sub2 sub3 + do + key=submodule.$s.url && + git -C multisuper_clone config --local --unset $key && + git -C multisuper_clone config --file .gitmodules --unset $key || return 1 + done && + + test_must_fail git -C multisuper_clone submodule update 2>err && + grep "cannot clone submodule .sub[0-3]. without a URL" err +' + test_expect_success 'clone --recurse-submodules with a pathspec works' ' test_when_finished "rm -rf multisuper_clone" && cat >expected <<-\EOF && diff --git a/t/t7402-submodule-rebase.sh b/t/t7402-submodule-rebase.sh index b19792b326..2b3c363078 100755 --- a/t/t7402-submodule-rebase.sh +++ b/t/t7402-submodule-rebase.sh @@ -56,12 +56,15 @@ chmod a+x fake-editor.sh test_expect_success 'interactive rebase with a dirty submodule' ' - test submodule = $(git diff --name-only) && + echo submodule >expect && + git diff --name-only >actual && + test_cmp expect actual && HEAD=$(git rev-parse HEAD) && GIT_EDITOR="\"$(pwd)/fake-editor.sh\"" EDITOR_TEXT="pick $HEAD" \ git rebase -i HEAD^ && - test submodule = $(git diff --name-only) - + echo submodule >expect && + git diff --name-only >actual && + test_cmp expect actual ' test_expect_success 'rebase with dirty file and submodule fails' ' @@ -83,11 +86,19 @@ test_expect_success 'stash with a dirty submodule' ' CURRENT=$(cd submodule && git rev-parse HEAD) && git stash && test new != $(cat file) && - test submodule = $(git diff --name-only) && - test $CURRENT = $(cd submodule && git rev-parse HEAD) && + echo submodule >expect && + git diff --name-only >actual && + test_cmp expect actual && + + echo "$CURRENT" >expect && + git -C submodule rev-parse HEAD >actual && + test_cmp expect actual && + git stash apply && test new = $(cat file) && - test $CURRENT = $(cd submodule && git rev-parse HEAD) + echo "$CURRENT" >expect && + git -C submodule rev-parse HEAD >actual && + test_cmp expect actual ' diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh index ff09443a0a..19b6135d11 100755 --- a/t/t7403-submodule-sync.sh +++ b/t/t7403-submodule-sync.sh @@ -163,7 +163,7 @@ test_expect_success '"git submodule sync" should update submodule URLs - subdire cd sub && git submodule sync >../../output ) && - test_i18ngrep "\\.\\./submodule" output && + test_grep "\\.\\./submodule" output && test -d "$( cd super-clone/submodule && git config remote.origin.url @@ -194,7 +194,7 @@ test_expect_success '"git submodule sync --recursive" should update all submodul cd sub && git submodule sync --recursive >../../output ) && - test_i18ngrep "\\.\\./submodule/sub-submodule" output && + test_grep "\\.\\./submodule/sub-submodule" output && test -d "$( cd super-clone/submodule && git config remote.origin.url diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index f094e3d7f3..8491b8c58b 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -945,7 +945,7 @@ test_expect_success 'submodule update places git-dir in superprojects git-dir re git clone super_update_r super_update_r2 && (cd super_update_r2 && git submodule update --init --recursive >actual && - test_i18ngrep "Submodule path .submodule/subsubmodule.: checked out" actual && + test_grep "Submodule path .submodule/subsubmodule.: checked out" actual && (cd submodule/subsubmodule && git log > ../../expected ) && @@ -1025,7 +1025,7 @@ test_expect_success 'submodule update clone shallow submodule outside of depth' # unadvertised objects, so restrict this test to v0. test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \ git submodule update --init --depth=1 2>actual && - test_i18ngrep "Direct fetching of that commit failed." actual && + test_grep "Direct fetching of that commit failed." actual && git -C ../submodule config uploadpack.allowReachableSHA1InWant true && git submodule update --init --depth=1 >actual && git -C submodule log --oneline >out && @@ -1039,7 +1039,7 @@ test_expect_success 'submodule update --recursive drops module name before recur git checkout HEAD^ ) && git submodule update --recursive deeper/submodule >actual && - test_i18ngrep "Submodule path .deeper/submodule/subsubmodule.: checked out" actual + test_grep "Submodule path .deeper/submodule/subsubmodule.: checked out" actual ) ' @@ -1179,4 +1179,27 @@ test_expect_success 'submodule update --recursive skip submodules with strategy= test_cmp expect.err actual.err ' +add_submodule_commit_and_validate () { + HASH=$(git rev-parse HEAD) && + git update-index --add --cacheinfo 160000,$HASH,sub && + git commit -m "create submodule" && + echo "160000 commit $HASH sub" >expect && + git ls-tree HEAD -- sub >actual && + test_cmp expect actual +} + +test_expect_success 'commit with staged submodule change' ' + add_submodule_commit_and_validate +' + +test_expect_success 'commit with staged submodule change with ignoreSubmodules dirty' ' + test_config diff.ignoreSubmodules dirty && + add_submodule_commit_and_validate +' + +test_expect_success 'commit with staged submodule change with ignoreSubmodules all' ' + test_config diff.ignoreSubmodules all && + add_submodule_commit_and_validate +' + test_done diff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh index c0167944ab..31271f8e0a 100755 --- a/t/t7411-submodule-config.sh +++ b/t/t7411-submodule-config.sh @@ -45,7 +45,7 @@ test_expect_success 'configuration parsing with error' ' ( cd repo && test_must_fail test-tool submodule-config "" s 2>actual && - test_i18ngrep "bad config" actual + test_grep "bad config" actual ) ' @@ -101,7 +101,7 @@ test_expect_success 'error in history of one submodule config lets continue, std >actual \ 2>actual_stderr && test_cmp expect_error actual && - test_i18ngrep "submodule-blob $sha1:.gitmodules" actual_stderr >/dev/null + test_grep "submodule-blob $sha1:.gitmodules" actual_stderr >/dev/null ) ' diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh index 7cdc263764..887d181b72 100755 --- a/t/t7413-submodule-is-active.sh +++ b/t/t7413-submodule-is-active.sh @@ -51,6 +51,22 @@ test_expect_success 'is-active works with submodule.<name>.active config' ' test-tool -C super submodule is-active sub1 ' +test_expect_success 'is-active handles submodule.active config missing a value' ' + cp super/.git/config super/.git/config.orig && + test_when_finished mv super/.git/config.orig super/.git/config && + + cat >>super/.git/config <<-\EOF && + [submodule] + active + EOF + + cat >expect <<-\EOF && + error: missing value for '\''submodule.active'\'' + EOF + test-tool -C super submodule is-active sub1 2>actual && + test_cmp expect actual +' + test_expect_success 'is-active works with basic submodule.active config' ' test_when_finished "git -C super config submodule.sub1.URL ../sub" && test_when_finished "git -C super config --unset-all submodule.active" && diff --git a/t/t7414-submodule-mistakes.sh b/t/t7414-submodule-mistakes.sh index 101afff30f..24f30e3bf9 100755 --- a/t/t7414-submodule-mistakes.sh +++ b/t/t7414-submodule-mistakes.sh @@ -13,13 +13,13 @@ test_expect_success 'create embedded repository' ' test_expect_success 'git-add on embedded repository warns' ' test_when_finished "git rm --cached -f embed" && git add embed 2>stderr && - test_i18ngrep warning stderr + test_grep warning stderr ' test_expect_success '--no-warn-embedded-repo suppresses warning' ' test_when_finished "git rm --cached -f embed" && git add --no-warn-embedded-repo embed 2>stderr && - test_i18ngrep ! warning stderr + test_grep ! warning stderr ' test_expect_success 'no warning when updating entry' ' @@ -27,14 +27,14 @@ test_expect_success 'no warning when updating entry' ' git add embed && git -C embed commit --allow-empty -m two && git add embed 2>stderr && - test_i18ngrep ! warning stderr + test_grep ! warning stderr ' test_expect_success 'submodule add does not warn' ' test_when_finished "git rm -rf submodule .gitmodules" && git -c protocol.file.allow=always \ submodule add ./embed submodule 2>stderr && - test_i18ngrep ! warning stderr + test_grep ! warning stderr ' test_done diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh index 7cf72b9a07..2ab566e717 100755 --- a/t/t7416-submodule-dash-url.sh +++ b/t/t7416-submodule-dash-url.sh @@ -41,7 +41,7 @@ test_expect_success 'remove ./ protection from .gitmodules url' ' test_expect_success 'clone rejects unprotected dash' ' test_when_finished "rm -rf dst" && test_must_fail git clone --recurse-submodules . dst 2>err && - test_i18ngrep ignoring err + test_grep ignoring err ' test_expect_success 'fsck rejects unprotected dash' ' @@ -63,7 +63,7 @@ test_expect_success 'trailing backslash is handled correctly' ' mv .new .gitmodules && git commit -am "Add testmodule" && test_must_fail git clone --verbose --recurse-submodules . dolly 2>err && - test_i18ngrep ! "unknown option" err + test_grep ! "unknown option" err ' test_expect_success 'fsck rejects missing URL scheme' ' diff --git a/t/t7417-submodule-path-url.sh b/t/t7417-submodule-path-url.sh index 2f4b25dfd7..5e3051da8b 100755 --- a/t/t7417-submodule-path-url.sh +++ b/t/t7417-submodule-path-url.sh @@ -21,7 +21,7 @@ test_expect_success 'create submodule with dash in path' ' test_expect_success 'clone rejects unprotected dash' ' test_when_finished "rm -rf dst" && git clone --recurse-submodules . dst 2>err && - test_i18ngrep ignoring err + test_grep ignoring err ' test_expect_success 'fsck rejects unprotected dash' ' @@ -46,7 +46,7 @@ test_expect_success MINGW 'submodule paths disallows trailing spaces' ' git -C super update-ref refs/heads/main $commit && test_must_fail git clone --recurse-submodules super dst 2>err && - test_i18ngrep "sub " err + test_grep "sub " err ' test_done diff --git a/t/t7419-submodule-set-branch.sh b/t/t7419-submodule-set-branch.sh index 232065504c..a5d1bc5c54 100755 --- a/t/t7419-submodule-set-branch.sh +++ b/t/t7419-submodule-set-branch.sh @@ -11,6 +11,10 @@ as expected. TEST_PASSES_SANITIZE_LEAK=true TEST_NO_CREATE_REPO=1 + +GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main +export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME + . ./test-lib.sh test_expect_success 'setup' ' @@ -27,26 +31,28 @@ test_expect_success 'submodule config cache setup' ' git checkout -b topic && echo b >a && git add . && - git commit -mb + git commit -mb && + git checkout main ) && mkdir super && (cd super && git init && git submodule add ../submodule && - git commit -m "add submodule" + git submodule add --name thename ../submodule thepath && + git commit -m "add submodules" ) ' test_expect_success 'ensure submodule branch is unset' ' (cd super && - ! grep branch .gitmodules + test_cmp_config "" -f .gitmodules --default "" submodule.submodule.branch ) ' test_expect_success 'test submodule set-branch --branch' ' (cd super && git submodule set-branch --branch topic submodule && - grep "branch = topic" .gitmodules && + test_cmp_config topic -f .gitmodules submodule.submodule.branch && git submodule update --remote && cat <<-\EOF >expect && b @@ -57,13 +63,12 @@ test_expect_success 'test submodule set-branch --branch' ' ' test_expect_success 'test submodule set-branch --default' ' - test_commit -C submodule c && (cd super && git submodule set-branch --default submodule && - ! grep branch .gitmodules && + test_cmp_config "" -f .gitmodules --default "" submodule.submodule.branch && git submodule update --remote && cat <<-\EOF >expect && - c + a EOF git -C submodule show -s --pretty=%s >actual && test_cmp expect actual @@ -71,10 +76,9 @@ test_expect_success 'test submodule set-branch --default' ' ' test_expect_success 'test submodule set-branch -b' ' - test_commit -C submodule b && (cd super && git submodule set-branch -b topic submodule && - grep "branch = topic" .gitmodules && + test_cmp_config topic -f .gitmodules submodule.submodule.branch && git submodule update --remote && cat <<-\EOF >expect && b @@ -85,17 +89,43 @@ test_expect_success 'test submodule set-branch -b' ' ' test_expect_success 'test submodule set-branch -d' ' - test_commit -C submodule d && (cd super && git submodule set-branch -d submodule && - ! grep branch .gitmodules && + test_cmp_config "" -f .gitmodules --default "" submodule.submodule.branch && git submodule update --remote && cat <<-\EOF >expect && - d + a EOF git -C submodule show -s --pretty=%s >actual && test_cmp expect actual ) ' +test_expect_success 'test submodule set-branch --branch with named submodule' ' + (cd super && + git submodule set-branch --branch topic thepath && + test_cmp_config topic -f .gitmodules submodule.thename.branch && + test_cmp_config "" -f .gitmodules --default "" submodule.thepath.branch && + git submodule update --remote && + cat <<-\EOF >expect && + b + EOF + git -C thepath show -s --pretty=%s >actual && + test_cmp expect actual + ) +' + +test_expect_success 'test submodule set-branch --default with named submodule' ' + (cd super && + git submodule set-branch --default thepath && + test_cmp_config "" -f .gitmodules --default "" submodule.thename.branch && + git submodule update --remote && + cat <<-\EOF >expect && + a + EOF + git -C thepath show -s --pretty=%s >actual && + test_cmp expect actual + ) +' + test_done diff --git a/t/t7420-submodule-set-url.sh b/t/t7420-submodule-set-url.sh index d6bf62b3ac..bf7f15ee79 100755 --- a/t/t7420-submodule-set-url.sh +++ b/t/t7420-submodule-set-url.sh @@ -25,17 +25,26 @@ test_expect_success 'submodule config cache setup' ' git add file && git commit -ma ) && + mkdir namedsubmodule && + ( + cd namedsubmodule && + git init && + echo 1 >file && + git add file && + git commit -m1 + ) && mkdir super && ( cd super && git init && git submodule add ../submodule && - git commit -m "add submodule" + git submodule add --name thename ../namedsubmodule thepath && + git commit -m "add submodules" ) ' test_expect_success 'test submodule set-url' ' - # add a commit and move the submodule (change the url) + # add commits and move the submodules (change the urls) ( cd submodule && echo b >>file && @@ -44,15 +53,28 @@ test_expect_success 'test submodule set-url' ' ) && mv submodule newsubmodule && + ( + cd namedsubmodule && + echo 2 >>file && + git add file && + git commit -m2 + ) && + mv namedsubmodule newnamedsubmodule && + git -C newsubmodule show >expect && + git -C newnamedsubmodule show >>expect && ( cd super && test_must_fail git submodule update --remote && git submodule set-url submodule ../newsubmodule && - grep -F "url = ../newsubmodule" .gitmodules && + test_cmp_config ../newsubmodule -f .gitmodules submodule.submodule.url && + git submodule set-url thepath ../newnamedsubmodule && + test_cmp_config ../newnamedsubmodule -f .gitmodules submodule.thename.url && + test_cmp_config "" -f .gitmodules --default "" submodule.thepath.url && git submodule update --remote ) && git -C super/submodule show >actual && + git -C super/thepath show >>actual && test_cmp expect actual ' diff --git a/t/t7450-bad-git-dotfiles.sh b/t/t7450-bad-git-dotfiles.sh index 0d0c3f2c68..35a31acd4d 100755 --- a/t/t7450-bad-git-dotfiles.sh +++ b/t/t7450-bad-git-dotfiles.sh @@ -238,7 +238,7 @@ test_expect_success 'fsck detects non-blob .gitmodules' ' git ls-tree HEAD | sed s/subdir/.gitmodules/ | git mktree && test_must_fail git fsck 2>output && - test_i18ngrep gitmodulesBlob output + test_grep gitmodulesBlob output ) ' @@ -252,8 +252,8 @@ test_expect_success 'fsck detects corrupt .gitmodules' ' git commit -m "broken gitmodules" && git fsck 2>output && - test_i18ngrep gitmodulesParse output && - test_i18ngrep ! "bad config" output + test_grep gitmodulesParse output && + test_grep ! "bad config" output ) ' @@ -275,7 +275,7 @@ test_expect_success WINDOWS 'prevent git~1 squatting on Windows' ' hash="$(echo x | git hash-object -w --stdin)" && test_must_fail git update-index --add \ --cacheinfo 160000,$rev,d\\a 2>err && - test_i18ngrep "Invalid path" err && + test_grep "Invalid path" err && git -c core.protectNTFS=false update-index --add \ --cacheinfo 100644,$modules,.gitmodules \ --cacheinfo 160000,$rev,c \ @@ -289,7 +289,7 @@ test_expect_success WINDOWS 'prevent git~1 squatting on Windows' ' then test_must_fail git -c core.protectNTFS=false \ clone --recurse-submodules squatting squatting-clone 2>err && - test_i18ngrep -e "directory not empty" -e "not an empty directory" err && + test_grep -e "directory not empty" -e "not an empty directory" err && ! grep gitdir squatting-clone/d/a/git~2 fi ' @@ -314,7 +314,7 @@ test_expect_success 'git dirs of sibling submodules must not be nested' ' git commit -m nested ) && test_must_fail git clone --recurse-submodules nested clone 2>err && - test_i18ngrep "is inside git dir" err + test_grep "is inside git dir" err ' test_done diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh index 5fcaa0b4f2..4dca8d97a7 100755 --- a/t/t7500-commit-template-squash-signoff.sh +++ b/t/t7500-commit-template-squash-signoff.sh @@ -555,7 +555,7 @@ test_expect_success 'commit without staging files fails and displays hints' ' git commit -m initial && echo "changes" >>file && test_must_fail git commit -m update >actual && - test_i18ngrep "no changes added to commit (use \"git add\" and/or \"git commit -a\")" actual + test_grep "no changes added to commit (use \"git add\" and/or \"git commit -a\")" actual ' test_done diff --git a/t/t7501-commit-basic-functionality.sh b/t/t7501-commit-basic-functionality.sh index fb5417d5e7..3d8500a52e 100755 --- a/t/t7501-commit-basic-functionality.sh +++ b/t/t7501-commit-basic-functionality.sh @@ -21,7 +21,7 @@ test_expect_success 'initial status' ' echo bongo bongo >file && git add file && git status >actual && - test_i18ngrep "No commits yet" actual + test_grep "No commits yet" actual ' test_expect_success 'fail initial amend' ' @@ -141,7 +141,7 @@ test_expect_success 'template "emptyness" check does not kick in with -F' ' test_expect_success 'template "emptyness" check' ' git checkout HEAD file && echo >>file && git add file && test_must_fail git commit -t file 2>err && - test_i18ngrep "did not edit" err + test_grep "did not edit" err ' test_expect_success 'setup: commit message from file' ' @@ -671,7 +671,7 @@ test_expect_success 'commit a file whose name is a dash' ' git add ./- && test_tick && git commit -m "add dash" >output </dev/null && - test_i18ngrep " changed, 5 insertions" output + test_grep " changed, 5 insertions" output ' test_expect_success '--only works on to-be-born branch' ' diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh index 38a532d81c..61c8e810cc 100755 --- a/t/t7502-commit-porcelain.sh +++ b/t/t7502-commit-porcelain.sh @@ -466,6 +466,25 @@ test_expect_success 'commit --trailer with -c and command' ' test_cmp expected actual ' +test_expect_success 'commit --trailer not confused by --- separator' ' + cat >msg <<-\EOF && + subject + + body with dashes + --- + in it + EOF + git commit --allow-empty --trailer="my-trailer: value" -F msg && + { + cat msg && + echo && + echo "my-trailer: value" + } >expected && + git cat-file commit HEAD >commit.msg && + sed -e "1,/^\$/d" commit.msg >actual && + test_cmp expected actual +' + test_expect_success 'multiple -m' ' >negative && @@ -687,14 +706,14 @@ test_expect_success 'cleanup commit message (whitespace config, -m)' ' test_expect_success 'message shows author when it is not equal to committer' ' echo >>negative && git commit -e -m "sample" -a && - test_i18ngrep \ + test_grep \ "^# Author: *A U Thor <author@example.com>\$" \ .git/COMMIT_EDITMSG ' test_expect_success 'message shows date when it is explicitly set' ' git commit --allow-empty -e -m foo --date="2010-01-02T03:04:05" && - test_i18ngrep \ + test_grep \ "^# Date: *Sat Jan 2 03:04:05 2010 +0000" \ .git/COMMIT_EDITMSG ' @@ -709,7 +728,7 @@ test_expect_success AUTOIDENT 'message shows committer when it is automatic' ' ) && # the ident is calculated from the system, so we cannot # check the actual value, only that it is there - test_i18ngrep "^# Committer: " .git/COMMIT_EDITMSG + test_grep "^# Committer: " .git/COMMIT_EDITMSG ' write_script .git/FAKE_EDITOR <<EOF @@ -841,9 +860,9 @@ try_commit () { GIT_EDITOR=.git/FAKE_EDITOR git commit -a $* $use_template && case "$use_template" in '') - test_i18ngrep ! "^## Custom template" .git/COMMIT_EDITMSG ;; + test_grep ! "^## Custom template" .git/COMMIT_EDITMSG ;; *) - test_i18ngrep "^## Custom template" .git/COMMIT_EDITMSG ;; + test_grep "^## Custom template" .git/COMMIT_EDITMSG ;; esac } @@ -851,53 +870,53 @@ try_commit_status_combo () { test_expect_success 'commit' ' try_commit "" && - test_i18ngrep "^# Changes to be committed:" .git/COMMIT_EDITMSG + test_grep "^# Changes to be committed:" .git/COMMIT_EDITMSG ' test_expect_success 'commit --status' ' try_commit --status && - test_i18ngrep "^# Changes to be committed:" .git/COMMIT_EDITMSG + test_grep "^# Changes to be committed:" .git/COMMIT_EDITMSG ' test_expect_success 'commit --no-status' ' try_commit --no-status && - test_i18ngrep ! "^# Changes to be committed:" .git/COMMIT_EDITMSG + test_grep ! "^# Changes to be committed:" .git/COMMIT_EDITMSG ' test_expect_success 'commit with commit.status = yes' ' test_config commit.status yes && try_commit "" && - test_i18ngrep "^# Changes to be committed:" .git/COMMIT_EDITMSG + test_grep "^# Changes to be committed:" .git/COMMIT_EDITMSG ' test_expect_success 'commit with commit.status = no' ' test_config commit.status no && try_commit "" && - test_i18ngrep ! "^# Changes to be committed:" .git/COMMIT_EDITMSG + test_grep ! "^# Changes to be committed:" .git/COMMIT_EDITMSG ' test_expect_success 'commit --status with commit.status = yes' ' test_config commit.status yes && try_commit --status && - test_i18ngrep "^# Changes to be committed:" .git/COMMIT_EDITMSG + test_grep "^# Changes to be committed:" .git/COMMIT_EDITMSG ' test_expect_success 'commit --no-status with commit.status = yes' ' test_config commit.status yes && try_commit --no-status && - test_i18ngrep ! "^# Changes to be committed:" .git/COMMIT_EDITMSG + test_grep ! "^# Changes to be committed:" .git/COMMIT_EDITMSG ' test_expect_success 'commit --status with commit.status = no' ' test_config commit.status no && try_commit --status && - test_i18ngrep "^# Changes to be committed:" .git/COMMIT_EDITMSG + test_grep "^# Changes to be committed:" .git/COMMIT_EDITMSG ' test_expect_success 'commit --no-status with commit.status = no' ' test_config commit.status no && try_commit --no-status && - test_i18ngrep ! "^# Changes to be committed:" .git/COMMIT_EDITMSG + test_grep ! "^# Changes to be committed:" .git/COMMIT_EDITMSG ' } @@ -911,13 +930,13 @@ try_commit_status_combo test_expect_success 'commit --status with custom comment character' ' test_config core.commentchar ";" && try_commit --status && - test_i18ngrep "^; Changes to be committed:" .git/COMMIT_EDITMSG + test_grep "^; Changes to be committed:" .git/COMMIT_EDITMSG ' test_expect_success 'switch core.commentchar' ' test_commit "#foo" foo && GIT_EDITOR=.git/FAKE_EDITOR git -c core.commentChar=auto commit --amend && - test_i18ngrep "^; Changes to be committed:" .git/COMMIT_EDITMSG + test_grep "^; Changes to be committed:" .git/COMMIT_EDITMSG ' test_expect_success 'switch core.commentchar but out of options' ' diff --git a/t/t7504-commit-msg-hook.sh b/t/t7504-commit-msg-hook.sh index 07ca46fb0d..d1255228d5 100755 --- a/t/t7504-commit-msg-hook.sh +++ b/t/t7504-commit-msg-hook.sh @@ -102,7 +102,9 @@ test_expect_success 'setup: commit-msg hook that always fails' ' ' commit_msg_is () { - test "$(git log --pretty=format:%s%b -1)" = "$1" + printf "%s" "$1" >expect && + git log --pretty=format:%s%b -1 >actual && + test_cmp expect actual } test_expect_success 'with failing hook' ' diff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh index d050091345..46566d529e 100755 --- a/t/t7506-status-submodule.sh +++ b/t/t7506-status-submodule.sh @@ -37,19 +37,19 @@ test_expect_success 'setup' ' test_expect_success 'status clean' ' git status >output && - test_i18ngrep "nothing to commit" output + test_grep "nothing to commit" output ' test_expect_success 'commit --dry-run -a clean' ' test_must_fail git commit --dry-run -a >output && - test_i18ngrep "nothing to commit" output + test_grep "nothing to commit" output ' test_expect_success 'status with modified file in submodule' ' (cd sub && git reset --hard) && echo "changed" >sub/foo && git status >output && - test_i18ngrep "modified: sub (modified content)" output + test_grep "modified: sub (modified content)" output ' test_expect_success 'status with modified file in submodule (porcelain)' ' @@ -73,7 +73,7 @@ test_expect_success 'status with modified file in submodule (short)' ' test_expect_success 'status with added file in submodule' ' (cd sub && git reset --hard && echo >foo && git add foo) && git status >output && - test_i18ngrep "modified: sub (modified content)" output + test_grep "modified: sub (modified content)" output ' test_expect_success 'status with added file in submodule (porcelain)' ' @@ -96,12 +96,12 @@ test_expect_success 'status with untracked file in submodule' ' (cd sub && git reset --hard) && echo "content" >sub/new-file && git status >output && - test_i18ngrep "modified: sub (untracked content)" output + test_grep "modified: sub (untracked content)" output ' test_expect_success 'status -uno with untracked file in submodule' ' git status -uno >output && - test_i18ngrep "^nothing to commit" output + test_grep "^nothing to commit" output ' test_expect_success 'status with untracked file in submodule (porcelain)' ' @@ -122,7 +122,7 @@ test_expect_success 'status with added and untracked file in submodule' ' (cd sub && git reset --hard && echo >foo && git add foo) && echo "content" >sub/new-file && git status >output && - test_i18ngrep "modified: sub (modified content, untracked content)" output + test_grep "modified: sub (modified content, untracked content)" output ' test_expect_success 'status with added and untracked file in submodule (porcelain)' ' @@ -140,7 +140,7 @@ test_expect_success 'status with modified file in modified submodule' ' (cd sub && echo "next change" >foo && git commit -m "next change" foo) && echo "changed" >sub/foo && git status >output && - test_i18ngrep "modified: sub (new commits, modified content)" output + test_grep "modified: sub (new commits, modified content)" output ' test_expect_success 'status with modified file in modified submodule (porcelain)' ' @@ -155,7 +155,7 @@ test_expect_success 'status with modified file in modified submodule (porcelain) test_expect_success 'status with added file in modified submodule' ' (cd sub && git reset --hard && echo >foo && git add foo) && git status >output && - test_i18ngrep "modified: sub (new commits, modified content)" output + test_grep "modified: sub (new commits, modified content)" output ' test_expect_success 'status with added file in modified submodule (porcelain)' ' @@ -170,7 +170,7 @@ test_expect_success 'status with untracked file in modified submodule' ' (cd sub && git reset --hard) && echo "content" >sub/new-file && git status >output && - test_i18ngrep "modified: sub (new commits, untracked content)" output + test_grep "modified: sub (new commits, untracked content)" output ' test_expect_success 'status with untracked file in modified submodule (porcelain)' ' @@ -184,7 +184,7 @@ test_expect_success 'status with added and untracked file in modified submodule' (cd sub && git reset --hard && echo >foo && git add foo) && echo "content" >sub/new-file && git status >output && - test_i18ngrep "modified: sub (new commits, modified content, untracked content)" output + test_grep "modified: sub (new commits, modified content, untracked content)" output ' test_expect_success 'status with added and untracked file in modified submodule (porcelain)' ' @@ -209,7 +209,7 @@ test_expect_success 'setup .git file for sub' ' test_expect_success 'status with added file in modified submodule with .git file' ' (cd sub && git reset --hard && echo >foo && git add foo) && git status >output && - test_i18ngrep "modified: sub (new commits, modified content)" output + test_grep "modified: sub (new commits, modified content)" output ' test_expect_success 'status with a lot of untracked files in the submodule' ' @@ -234,12 +234,12 @@ test_expect_success 'rm submodule contents' ' test_expect_success 'status clean (empty submodule dir)' ' git status >output && - test_i18ngrep "nothing to commit" output + test_grep "nothing to commit" output ' test_expect_success 'status -a clean (empty submodule dir)' ' test_must_fail git commit --dry-run -a >output && - test_i18ngrep "nothing to commit" output + test_grep "nothing to commit" output ' cat >status_expect <<\EOF diff --git a/t/t7507-commit-verbose.sh b/t/t7507-commit-verbose.sh index 916470c48b..c3281b192e 100755 --- a/t/t7507-commit-verbose.sh +++ b/t/t7507-commit-verbose.sh @@ -89,7 +89,7 @@ test_expect_success 'submodule log is stripped out too with -v' ' export GIT_EDITOR && test_must_fail git commit -a -v 2>err ) && - test_i18ngrep "Aborting commit due to empty commit message." err + test_grep "Aborting commit due to empty commit message." err ' test_expect_success 'verbose diff is stripped out with set core.commentChar' ' @@ -98,7 +98,7 @@ test_expect_success 'verbose diff is stripped out with set core.commentChar' ' export GIT_EDITOR && test_must_fail git -c core.commentchar=";" commit -a -v 2>err ) && - test_i18ngrep "Aborting commit due to empty commit message." err + test_grep "Aborting commit due to empty commit message." err ' test_expect_success 'status does not verbose without --verbose' ' diff --git a/t/t7508-status.sh b/t/t7508-status.sh index aed07c5b62..a3c18a4fc2 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -5,6 +5,7 @@ test_description='git status' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh . "$TEST_DIRECTORY"/lib-terminal.sh @@ -18,7 +19,7 @@ test_expect_success 'status -h in broken repository' ' echo "[status] showuntrackedfiles = CORRUPT" >>.git/config && test_expect_code 129 git status -h >usage 2>&1 ) && - test_i18ngrep "[Uu]sage" broken/usage + test_grep "[Uu]sage" broken/usage ' test_expect_success 'commit -h in broken repository' ' @@ -30,7 +31,7 @@ test_expect_success 'commit -h in broken repository' ' echo "[status] showuntrackedfiles = CORRUPT" >>.git/config && test_expect_code 129 git commit -h >usage 2>&1 ) && - test_i18ngrep "[Uu]sage" broken/usage + test_grep "[Uu]sage" broken/usage ' test_expect_success 'create upstream branch' ' @@ -71,7 +72,7 @@ test_expect_success 'setup' ' ' test_expect_success 'status (1)' ' - test_i18ngrep "use \"git rm --cached <file>\.\.\.\" to unstage" output + test_grep "use \"git rm --cached <file>\.\.\.\" to unstage" output ' strip_comments () { @@ -91,7 +92,7 @@ test_expect_success 'status --column' ' # On branch main # Your branch and '\''upstream'\'' have diverged, # and have 1 and 2 different commits each, respectively. -# (use "git pull" to merge the remote branch into yours) +# (use "git pull" if you want to integrate the remote branch with yours) # # Changes to be committed: # (use "git restore --staged <file>..." to unstage) @@ -122,7 +123,7 @@ cat >expect <<\EOF # On branch main # Your branch and 'upstream' have diverged, # and have 1 and 2 different commits each, respectively. -# (use "git pull" to merge the remote branch into yours) +# (use "git pull" if you want to integrate the remote branch with yours) # # Changes to be committed: # (use "git restore --staged <file>..." to unstage) @@ -269,7 +270,7 @@ test_expect_success 'status with gitignore' ' On branch main Your branch and '\''upstream'\'' have diverged, and have 1 and 2 different commits each, respectively. - (use "git pull" to merge the remote branch into yours) + (use "git pull" if you want to integrate the remote branch with yours) Changes to be committed: (use "git restore --staged <file>..." to unstage) @@ -334,7 +335,7 @@ test_expect_success 'status with gitignore (nothing untracked)' ' On branch main Your branch and '\''upstream'\'' have diverged, and have 1 and 2 different commits each, respectively. - (use "git pull" to merge the remote branch into yours) + (use "git pull" if you want to integrate the remote branch with yours) Changes to be committed: (use "git restore --staged <file>..." to unstage) @@ -404,7 +405,7 @@ test_expect_success 'status -uno' ' On branch main Your branch and '\''upstream'\'' have diverged, and have 1 and 2 different commits each, respectively. - (use "git pull" to merge the remote branch into yours) + (use "git pull" if you want to integrate the remote branch with yours) Changes to be committed: (use "git restore --staged <file>..." to unstage) @@ -466,7 +467,7 @@ test_expect_success 'status -unormal' ' On branch main Your branch and '\''upstream'\'' have diverged, and have 1 and 2 different commits each, respectively. - (use "git pull" to merge the remote branch into yours) + (use "git pull" if you want to integrate the remote branch with yours) Changes to be committed: (use "git restore --staged <file>..." to unstage) @@ -521,7 +522,7 @@ test_expect_success 'status -uall' ' On branch main Your branch and '\''upstream'\'' have diverged, and have 1 and 2 different commits each, respectively. - (use "git pull" to merge the remote branch into yours) + (use "git pull" if you want to integrate the remote branch with yours) Changes to be committed: (use "git restore --staged <file>..." to unstage) @@ -581,7 +582,7 @@ test_expect_success 'status with relative paths' ' On branch main Your branch and '\''upstream'\'' have diverged, and have 1 and 2 different commits each, respectively. - (use "git pull" to merge the remote branch into yours) + (use "git pull" if you want to integrate the remote branch with yours) Changes to be committed: (use "git restore --staged <file>..." to unstage) @@ -649,7 +650,7 @@ test_expect_success TTY 'status with color.ui' ' On branch <GREEN>main<RESET> Your branch and '\''upstream'\'' have diverged, and have 1 and 2 different commits each, respectively. - (use "git pull" to merge the remote branch into yours) + (use "git pull" if you want to integrate the remote branch with yours) Changes to be committed: (use "git restore --staged <file>..." to unstage) @@ -772,7 +773,7 @@ test_expect_success 'status without relative paths' ' On branch main Your branch and '\''upstream'\'' have diverged, and have 1 and 2 different commits each, respectively. - (use "git pull" to merge the remote branch into yours) + (use "git pull" if you want to integrate the remote branch with yours) Changes to be committed: (use "git restore --staged <file>..." to unstage) @@ -846,7 +847,6 @@ test_expect_success 'dry-run of partial commit excluding new file in index' ' On branch main Your branch and '\''upstream'\'' have diverged, and have 1 and 2 different commits each, respectively. - (use "git pull" to merge the remote branch into yours) Changes to be committed: (use "git restore --staged <file>..." to unstage) @@ -900,7 +900,7 @@ test_expect_success 'status submodule summary is disabled by default' ' On branch main Your branch and '\''upstream'\'' have diverged, and have 1 and 2 different commits each, respectively. - (use "git pull" to merge the remote branch into yours) + (use "git pull" if you want to integrate the remote branch with yours) Changes to be committed: (use "git restore --staged <file>..." to unstage) @@ -957,7 +957,7 @@ test_expect_success 'status submodule summary' ' On branch main Your branch and '\''upstream'\'' have diverged, and have 1 and 2 different commits each, respectively. - (use "git pull" to merge the remote branch into yours) + (use "git pull" if you want to integrate the remote branch with yours) Changes to be committed: (use "git restore --staged <file>..." to unstage) @@ -1012,11 +1012,11 @@ test_expect_success 'status -s submodule summary' ' ' test_expect_success 'status submodule summary (clean submodule): commit' ' - cat >expect <<EOF && + cat >expect-status <<EOF && On branch main Your branch and '\''upstream'\'' have diverged, and have 2 and 2 different commits each, respectively. - (use "git pull" to merge the remote branch into yours) + (use "git pull" if you want to integrate the remote branch with yours) Changes not staged for commit: (use "git add <file>..." to update what will be committed) @@ -1032,12 +1032,13 @@ Untracked files: no changes added to commit (use "git add" and/or "git commit -a") EOF + sed "/git pull/d" expect-status > expect-commit && git commit -m "commit submodule" && git config status.submodulesummary 10 && test_must_fail git commit --dry-run >output && - test_cmp expect output && + test_cmp expect-commit output && git status >output && - test_cmp expect output + test_cmp expect-status output ' cat >expect <<EOF @@ -1064,7 +1065,6 @@ test_expect_success 'commit --dry-run submodule summary (--amend)' ' On branch main Your branch and '\''upstream'\'' have diverged, and have 2 and 2 different commits each, respectively. - (use "git pull" to merge the remote branch into yours) Changes to be committed: (use "git restore --source=HEAD^1 --staged <file>..." to unstage) @@ -1116,7 +1116,7 @@ test_expect_success '--ignore-submodules=untracked suppresses submodules with un On branch main Your branch and '\''upstream'\'' have diverged, and have 2 and 2 different commits each, respectively. - (use "git pull" to merge the remote branch into yours) + (use "git pull" if you want to integrate the remote branch with yours) Changes to be committed: (use "git restore --staged <file>..." to unstage) @@ -1225,7 +1225,7 @@ test_expect_success "--ignore-submodules=untracked doesn't suppress submodules w On branch main Your branch and '\''upstream'\'' have diverged, and have 2 and 2 different commits each, respectively. - (use "git pull" to merge the remote branch into yours) + (use "git pull" if you want to integrate the remote branch with yours) Changes to be committed: (use "git restore --staged <file>..." to unstage) @@ -1282,7 +1282,7 @@ test_expect_success "--ignore-submodules=untracked doesn't suppress submodule su On branch main Your branch and '\''upstream'\'' have diverged, and have 2 and 2 different commits each, respectively. - (use "git pull" to merge the remote branch into yours) + (use "git pull" if you want to integrate the remote branch with yours) Changes to be committed: (use "git restore --staged <file>..." to unstage) @@ -1363,7 +1363,7 @@ cat > expect << EOF ; On branch main ; Your branch and 'upstream' have diverged, ; and have 2 and 2 different commits each, respectively. -; (use "git pull" to merge the remote branch into yours) +; (use "git pull" if you want to integrate the remote branch with yours) ; ; Changes to be committed: ; (use "git restore --staged <file>..." to unstage) @@ -1411,7 +1411,7 @@ test_expect_success "--ignore-submodules=all suppresses submodule summary" ' On branch main Your branch and '\''upstream'\'' have diverged, and have 2 and 2 different commits each, respectively. - (use "git pull" to merge the remote branch into yours) + (use "git pull" if you want to integrate the remote branch with yours) Changes not staged for commit: (use "git add <file>..." to update what will be committed) @@ -1437,7 +1437,7 @@ test_expect_success '.gitmodules ignore=all suppresses unstaged submodule summar On branch main Your branch and '\''upstream'\'' have diverged, and have 2 and 2 different commits each, respectively. - (use "git pull" to merge the remote branch into yours) + (use "git pull" if you want to integrate the remote branch with yours) Changes to be committed: (use "git restore --staged <file>..." to unstage) @@ -1519,8 +1519,8 @@ test_expect_success '"status.branch=true" weaker than "--no-branch"' ' ' test_expect_success '"status.branch=true" weaker than "--porcelain"' ' - git -c status.branch=true status --porcelain >actual && - test_cmp expected_nobranch actual + git -c status.branch=true status --porcelain >actual && + test_cmp expected_nobranch actual ' test_expect_success '"status.branch=false" same as "--no-branch"' ' @@ -1542,12 +1542,12 @@ test_expect_success 'git commit will commit a staged but ignored submodule' ' git config --add -f .gitmodules submodule.subname.path sm && git config --add submodule.subname.ignore all && git status -s --ignore-submodules=dirty >output && - test_i18ngrep "^M. sm" output && + test_grep "^M. sm" output && GIT_EDITOR="echo hello >>\"\$1\"" && export GIT_EDITOR && git commit -uno && git status -s --ignore-submodules=dirty >output && - test_i18ngrep ! "^M. sm" output + test_grep ! "^M. sm" output ' test_expect_success 'git commit --dry-run will show a staged but ignored submodule' ' @@ -1557,7 +1557,6 @@ test_expect_success 'git commit --dry-run will show a staged but ignored submodu On branch main Your branch and '\''upstream'\'' have diverged, and have 2 and 2 different commits each, respectively. - (use "git pull" to merge the remote branch into yours) Changes to be committed: (use "git restore --staged <file>..." to unstage) @@ -1573,13 +1572,13 @@ EOF git commit -uno --dry-run >output && test_cmp expect output && git status -s --ignore-submodules=dirty >output && - test_i18ngrep "^M. sm" output + test_grep "^M. sm" output ' test_expect_success 'git commit -m will commit a staged but ignored submodule' ' git commit -uno -m message && git status -s --ignore-submodules=dirty >output && - test_i18ngrep ! "^M. sm" output && + test_grep ! "^M. sm" output && git config --remove-section submodule.subname && git config -f .gitmodules --remove-section submodule.subname ' @@ -1592,7 +1591,7 @@ test_expect_success 'show stash info with "--show-stash"' ' git stash && git status >expected_default && git status --show-stash >expected_with_stash && - test_i18ngrep "^Your stash currently has 1 entry$" expected_with_stash + test_grep "^Your stash currently has 1 entry$" expected_with_stash ' test_expect_success 'no stash info with "--show-stash --no-show-stash"' ' @@ -1619,14 +1618,14 @@ test_expect_success 'no additional info if no stash entries' ' test_expect_success '"No commits yet" should be noted in status output' ' git checkout --orphan empty-branch-1 && git status >output && - test_i18ngrep "No commits yet" output + test_grep "No commits yet" output ' test_expect_success '"No commits yet" should not be noted in status output' ' git checkout --orphan empty-branch-2 && test_commit test-commit-1 && git status >output && - test_i18ngrep ! "No commits yet" output + test_grep ! "No commits yet" output ' test_expect_success '"Initial commit" should be noted in commit template' ' @@ -1634,7 +1633,7 @@ test_expect_success '"Initial commit" should be noted in commit template' ' touch to_be_committed_1 && git add to_be_committed_1 && git commit --dry-run >output && - test_i18ngrep "Initial commit" output + test_grep "Initial commit" output ' test_expect_success '"Initial commit" should not be noted in commit template' ' @@ -1643,7 +1642,7 @@ test_expect_success '"Initial commit" should not be noted in commit template' ' touch to_be_committed_2 && git add to_be_committed_2 && git commit --dry-run >output && - test_i18ngrep ! "Initial commit" output + test_grep ! "Initial commit" output ' test_expect_success '--no-optional-locks prevents index update' ' @@ -1746,4 +1745,20 @@ test_expect_success 'slow status advice when core.untrackedCache true, and fsmon ) ' +test_expect_success EXPENSIVE 'status does not re-read unchanged 4 or 8 GiB file' ' + ( + mkdir large-file && + cd large-file && + # Files are 2 GiB, 4 GiB, and 8 GiB sparse files. + test-tool truncate file-a 0x080000000 && + test-tool truncate file-b 0x100000000 && + test-tool truncate file-c 0x200000000 && + # This will be slow. + git add file-a file-b file-c && + git commit -m "add large files" && + git diff-index HEAD file-a file-b file-c >actual && + test_must_be_empty actual + ) +' + test_done diff --git a/t/t7509-commit-authorship.sh b/t/t7509-commit-authorship.sh index 5d890949f7..fd8c8f8f0b 100755 --- a/t/t7509-commit-authorship.sh +++ b/t/t7509-commit-authorship.sh @@ -99,7 +99,7 @@ test_expect_success '--amend option with empty author' ' echo "Empty author test" >>foo && test_tick && test_must_fail git commit -a -m "empty author" --amend 2>err && - test_i18ngrep "empty ident" err + test_grep "empty ident" err ' test_expect_success '--amend option with missing author' ' @@ -112,7 +112,7 @@ test_expect_success '--amend option with missing author' ' echo "Missing author test" >>foo && test_tick && test_must_fail git commit -a -m "malformed author" --amend 2>err && - test_i18ngrep "empty ident" err + test_grep "empty ident" err ' test_expect_success '--reset-author makes the commit ours even with --amend option' ' diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh index 48f86cb367..0d2dd29fe6 100755 --- a/t/t7510-signed-commit.sh +++ b/t/t7510-signed-commit.sh @@ -218,87 +218,101 @@ test_expect_success GPG 'amending already signed commit' ' ! grep "BAD signature from" actual ' +test_expect_success GPG2 'bare signature' ' + git verify-commit fifth-signed 2>expect && + echo >>expect && + git log -1 --format="%GG" fifth-signed >actual && + test_cmp expect actual +' + test_expect_success GPG 'show good signature with custom format' ' cat >expect <<-\EOF && G + ultimate 13B6F51ECDDE430D C O Mitter <committer@example.com> 73D758744BE721698EC54E8713B6F51ECDDE430D 73D758744BE721698EC54E8713B6F51ECDDE430D EOF - git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual && + git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual && test_cmp expect actual ' test_expect_success GPG 'show bad signature with custom format' ' cat >expect <<-\EOF && B + undefined 13B6F51ECDDE430D C O Mitter <committer@example.com> EOF - git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" $(cat forged1.commit) >actual && + git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" $(cat forged1.commit) >actual && test_cmp expect actual ' test_expect_success GPG 'show untrusted signature with custom format' ' cat >expect <<-\EOF && U + undefined 65A0EEA02E30CAD7 Eris Discordia <discord@example.net> F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7 D4BE22311AD3131E5EDA29A461092E85B7227189 EOF - git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual && + git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual && test_cmp expect actual ' test_expect_success GPG 'show untrusted signature with undefined trust level' ' cat >expect <<-\EOF && + U undefined 65A0EEA02E30CAD7 Eris Discordia <discord@example.net> F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7 D4BE22311AD3131E5EDA29A461092E85B7227189 EOF - git log -1 --format="%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual && + git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual && test_cmp expect actual ' test_expect_success GPG 'show untrusted signature with ultimate trust level' ' cat >expect <<-\EOF && + G ultimate 13B6F51ECDDE430D C O Mitter <committer@example.com> 73D758744BE721698EC54E8713B6F51ECDDE430D 73D758744BE721698EC54E8713B6F51ECDDE430D EOF - git log -1 --format="%GT%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual && + git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual && test_cmp expect actual ' test_expect_success GPG 'show unknown signature with custom format' ' cat >expect <<-\EOF && E + undefined 65A0EEA02E30CAD7 EOF - GNUPGHOME="$GNUPGHOME_NOT_USED" git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual && + GNUPGHOME="$GNUPGHOME_NOT_USED" git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual && test_cmp expect actual ' test_expect_success GPG 'show lack of signature with custom format' ' cat >expect <<-\EOF && N + undefined EOF - git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" seventh-unsigned >actual && + git log -1 --format="%G?%n%GT%n%GK%n%GS%n%GF%n%GP" seventh-unsigned >actual && test_cmp expect actual ' diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh index 2f16d5787e..c2ab8a444a 100755 --- a/t/t7512-status-help.sh +++ b/t/t7512-status-help.sh @@ -774,6 +774,28 @@ EOF test_cmp expected actual ' +test_expect_success 'status when cherry-picking multiple commits' ' + git reset --hard cherry_branch && + test_when_finished "git cherry-pick --abort" && + test_must_fail git cherry-pick cherry_branch_second one_cherry && + TO_CHERRY_PICK=$(git rev-parse --short CHERRY_PICK_HEAD) && + cat >expected <<EOF && +On branch cherry_branch +You are currently cherry-picking commit $TO_CHERRY_PICK. + (fix conflicts and run "git cherry-pick --continue") + (use "git cherry-pick --skip" to skip this patch) + (use "git cherry-pick --abort" to cancel the cherry-pick operation) + +Unmerged paths: + (use "git add <file>..." to mark resolution) + both modified: main.txt + +no changes added to commit (use "git add" and/or "git commit -a") +EOF + git status --untracked-files=no >actual && + test_cmp expected actual +' + test_expect_success 'status when cherry-picking after committing conflict resolution' ' git reset --hard cherry_branch && test_when_finished "git cherry-pick --abort" && diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh index 97f10905d2..832aff0616 100755 --- a/t/t7513-interpret-trailers.sh +++ b/t/t7513-interpret-trailers.sh @@ -489,7 +489,7 @@ test_expect_success 'multiline field treated as atomic for neighbor check' ' ' test_expect_success 'with config setup' ' - git config trailer.ack.key "Acked-by: " && + test_config trailer.ack.key "Acked-by: " && cat >expected <<-\EOF && Acked-by: Peff @@ -503,8 +503,8 @@ test_expect_success 'with config setup' ' ' test_expect_success 'with config setup and ":=" as separators' ' - git config trailer.separators ":=" && - git config trailer.ack.key "Acked-by= " && + test_config trailer.separators ":=" && + test_config trailer.ack.key "Acked-by= " && cat >expected <<-\EOF && Acked-by= Peff @@ -518,7 +518,7 @@ test_expect_success 'with config setup and ":=" as separators' ' ' test_expect_success 'with config setup and "%" as separators' ' - git config trailer.separators "%" && + test_config trailer.separators "%" && cat >expected <<-\EOF && bug% 42 @@ -532,6 +532,7 @@ test_expect_success 'with config setup and "%" as separators' ' ' test_expect_success 'with "%" as separators and a message with trailers' ' + test_config trailer.separators "%" && cat >special_message <<-\EOF && Special Message @@ -553,8 +554,8 @@ test_expect_success 'with "%" as separators and a message with trailers' ' ' test_expect_success 'with config setup and ":=#" as separators' ' - git config trailer.separators ":=#" && - git config trailer.bug.key "Bug #" && + test_config trailer.separators ":=#" && + test_config trailer.bug.key "Bug #" && cat >expected <<-\EOF && Bug #42 @@ -581,6 +582,8 @@ test_expect_success 'with basic patch' ' ' test_expect_success 'with commit complex message as argument' ' + test_config trailer.separators ":=" && + test_config trailer.ack.key "Acked-by= " && cat complex_message_body complex_message_trailers >complex_message && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && @@ -594,6 +597,8 @@ test_expect_success 'with commit complex message as argument' ' ' test_expect_success 'with 2 files arguments' ' + test_config trailer.separators ":=" && + test_config trailer.ack.key "Acked-by= " && cat basic_message >>expected && echo >>expected && cat basic_patch >>expected && @@ -677,6 +682,9 @@ test_expect_success 'with message that has an old style conflict block' ' ' test_expect_success 'with commit complex message and trailer args' ' + test_config trailer.separators ":=#" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.bug.key "Bug #" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Fixes: Z @@ -692,6 +700,9 @@ test_expect_success 'with commit complex message and trailer args' ' ' test_expect_success 'with complex patch, args and --trim-empty' ' + test_config trailer.separators ":=#" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.bug.key "Bug #" && cat complex_message >complex_patch && cat basic_patch >>complex_patch && cat complex_message_body >expected && @@ -746,7 +757,10 @@ test_expect_success POSIXPERM,SANITY "in-place editing doesn't clobber original ' test_expect_success 'using "where = before"' ' - git config trailer.bug.where "before" && + test_config trailer.separators ":=#" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -762,7 +776,9 @@ test_expect_success 'using "where = before"' ' ' test_expect_success 'overriding configuration with "--where after"' ' - git config trailer.ack.where "before" && + test_config trailer.separators ":=" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "before" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Fixes: Z @@ -776,7 +792,12 @@ test_expect_success 'overriding configuration with "--where after"' ' test_cmp expected actual ' -test_expect_success 'using "where = before" with "--no-where"' ' +test_expect_success 'using "--where after" with "--no-where"' ' + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "before" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -791,8 +812,59 @@ test_expect_success 'using "where = before" with "--no-where"' ' test_cmp expected actual ' +# Check whether using "--no-where" clears out only the "--where after", such +# that we still use the configuration in trailer.where (which is different from +# the hardcoded default (in WHERE_END) assuming the absence of .gitconfig). +# Here, the "start" setting of trailer.where is respected, so the new "Acked-by" +# and "Bug" trailers are placed at the beginning, and not at the end which is +# the harcoded default. +test_expect_success 'using "--where after" with "--no-where" defaults to configuration' ' + test_config trailer.ack.key "Acked-by= " && + test_config trailer.bug.key "Bug #" && + test_config trailer.separators ":=#" && + test_config trailer.where "start" && + cat complex_message_body >expected && + sed -e "s/ Z\$/ /" >>expected <<-\EOF && + Bug #42 + Acked-by= Peff + Fixes: Z + Acked-by= Z + Reviewed-by: Z + Signed-off-by: Z + EOF + git interpret-trailers --where after --no-where --trailer "ack: Peff" \ + --trailer "bug: 42" complex_message >actual && + test_cmp expected actual +' + +# The "--where after" will only get respected for the trailer that came +# immediately after it. For the next trailer (Bug #42), we default to using the +# hardcoded WHERE_END because we don't have any "trailer.where" or +# "trailer.bug.where" configured. +test_expect_success 'using "--no-where" defaults to harcoded default if nothing configured' ' + test_config trailer.ack.key "Acked-by= " && + test_config trailer.bug.key "Bug #" && + test_config trailer.separators ":=#" && + cat complex_message_body >expected && + sed -e "s/ Z\$/ /" >>expected <<-\EOF && + Fixes: Z + Acked-by= Z + Acked-by= Peff + Reviewed-by: Z + Signed-off-by: Z + Bug #42 + EOF + git interpret-trailers --where after --trailer "ack: Peff" --no-where \ + --trailer "bug: 42" complex_message >actual && + test_cmp expected actual +' + test_expect_success 'using "where = after"' ' - git config trailer.ack.where "after" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -808,8 +880,11 @@ test_expect_success 'using "where = after"' ' ' test_expect_success 'using "where = end"' ' - git config trailer.review.key "Reviewed-by" && - git config trailer.review.where "end" && + test_config trailer.review.key "Reviewed-by" && + test_config trailer.review.where "end" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.separators ":=" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Fixes: Z @@ -827,8 +902,11 @@ test_expect_success 'using "where = end"' ' ' test_expect_success 'using "where = start"' ' - git config trailer.review.key "Reviewed-by" && - git config trailer.review.where "start" && + test_config trailer.review.key "Reviewed-by" && + test_config trailer.review.where "start" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.separators ":=" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Reviewed-by: Johannes @@ -846,8 +924,13 @@ test_expect_success 'using "where = start"' ' ' test_expect_success 'using "where = before" for a token in the middle of the message' ' - git config trailer.review.key "Reviewed-by:" && - git config trailer.review.where "before" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.review.where "before" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -864,6 +947,12 @@ test_expect_success 'using "where = before" for a token in the middle of the mes ' test_expect_success 'using "where = before" and --trim-empty' ' + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && cat >>expected <<-\EOF && Bug #46 @@ -878,6 +967,13 @@ test_expect_success 'using "where = before" and --trim-empty' ' ' test_expect_success 'the default is "ifExists = addIfDifferentNeighbor"' ' + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.review.where "before" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -896,7 +992,13 @@ test_expect_success 'the default is "ifExists = addIfDifferentNeighbor"' ' ' test_expect_success 'default "ifExists" is now "addIfDifferent"' ' - git config trailer.ifexists "addIfDifferent" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -914,8 +1016,14 @@ test_expect_success 'default "ifExists" is now "addIfDifferent"' ' ' test_expect_success 'using "ifExists = addIfDifferent" with "where = end"' ' - git config trailer.ack.ifExists "addIfDifferent" && - git config trailer.ack.where "end" && + test_config trailer.ack.ifExists "addIfDifferent" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "end" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -932,8 +1040,14 @@ test_expect_success 'using "ifExists = addIfDifferent" with "where = end"' ' ' test_expect_success 'using "ifExists = addIfDifferent" with "where = before"' ' - git config trailer.ack.ifExists "addIfDifferent" && - git config trailer.ack.where "before" && + test_config trailer.ack.ifExists "addIfDifferent" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "before" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -950,8 +1064,14 @@ test_expect_success 'using "ifExists = addIfDifferent" with "where = before"' ' ' test_expect_success 'using "ifExists = addIfDifferentNeighbor" with "where = end"' ' - git config trailer.ack.ifExists "addIfDifferentNeighbor" && - git config trailer.ack.where "end" && + test_config trailer.ack.ifExists "addIfDifferentNeighbor" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "end" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -973,8 +1093,14 @@ test_expect_success 'using "ifExists = addIfDifferentNeighbor" with "where = end ' test_expect_success 'using "ifExists = addIfDifferentNeighbor" with "where = after"' ' - git config trailer.ack.ifExists "addIfDifferentNeighbor" && - git config trailer.ack.where "after" && + test_config trailer.ack.ifExists "addIfDifferentNeighbor" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -995,7 +1121,11 @@ test_expect_success 'using "ifExists = addIfDifferentNeighbor" with "where = af ' test_expect_success 'using "ifExists = addIfDifferentNeighbor" and --trim-empty' ' - git config trailer.ack.ifExists "addIfDifferentNeighbor" && + test_config trailer.ack.ifExists "addIfDifferentNeighbor" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && cat >>expected <<-\EOF && Bug #42 @@ -1011,8 +1141,14 @@ test_expect_success 'using "ifExists = addIfDifferentNeighbor" and --trim-empty' ' test_expect_success 'using "ifExists = add" with "where = end"' ' - git config trailer.ack.ifExists "add" && - git config trailer.ack.where "end" && + test_config trailer.ack.ifExists "add" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "end" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -1036,8 +1172,14 @@ test_expect_success 'using "ifExists = add" with "where = end"' ' ' test_expect_success 'using "ifExists = add" with "where = after"' ' - git config trailer.ack.ifExists "add" && - git config trailer.ack.where "after" && + test_config trailer.ack.ifExists "add" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -1058,8 +1200,15 @@ test_expect_success 'using "ifExists = add" with "where = after"' ' ' test_expect_success 'overriding configuration with "--if-exists replace"' ' - git config trailer.fix.key "Fixes: " && - git config trailer.fix.ifExists "add" && + test_config trailer.fix.key "Fixes: " && + test_config trailer.fix.ifExists "add" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.review.where "before" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -1074,9 +1223,66 @@ test_expect_success 'overriding configuration with "--if-exists replace"' ' test_cmp expected actual ' +# "trailer.ifexists" is set to "doNothing", so using "--no-if-exists" defaults +# to this "doNothing" behavior. So the "Fixes: 53" trailer does not get added. +test_expect_success 'using "--if-exists replace" with "--no-if-exists" defaults to configuration' ' + test_config trailer.ifexists "doNothing" && + cat complex_message_body >expected && + sed -e "s/ Z\$/ /" >>expected <<-\EOF && + Fixes: Z + Acked-by: Z + Reviewed-by: Z + Signed-off-by: Z + EOF + git interpret-trailers --if-exists replace --no-if-exists --trailer "Fixes: 53" \ + <complex_message >actual && + test_cmp expected actual +' + +# No "ifexists" configuration is set, so using "--no-if-exists" makes it default +# to addIfDifferentNeighbor. Because we do have a different neighbor "Fixes: 53" +# (because it got added by overriding with "--if-exists replace" earlier in the +# arguments list), we add "Signed-off-by: addme". +test_expect_success 'using "--no-if-exists" defaults to hardcoded default if nothing configured' ' + cat complex_message_body >expected && + sed -e "s/ Z\$/ /" >>expected <<-\EOF && + Acked-by: Z + Reviewed-by: Z + Signed-off-by: Z + Fixes: 53 + Signed-off-by: addme + EOF + git interpret-trailers --if-exists replace --trailer "Fixes: 53" --no-if-exists \ + --trailer "Signed-off-by: addme" <complex_message >actual && + test_cmp expected actual +' + +# The second "Fixes: 53" trailer is discarded, because the "--no-if-exists" here +# makes us default to addIfDifferentNeighbor, and we already added the "Fixes: +# 53" trailer earlier in the argument list. +test_expect_success 'using "--no-if-exists" defaults to hardcoded default if nothing configured (no addition)' ' + cat complex_message_body >expected && + sed -e "s/ Z\$/ /" >>expected <<-\EOF && + Acked-by: Z + Reviewed-by: Z + Signed-off-by: Z + Fixes: 53 + EOF + git interpret-trailers --if-exists replace --trailer "Fixes: 53" --no-if-exists \ + --trailer "Fixes: 53" <complex_message >actual && + test_cmp expected actual +' + test_expect_success 'using "ifExists = replace"' ' - git config trailer.fix.key "Fixes: " && - git config trailer.fix.ifExists "replace" && + test_config trailer.fix.key "Fixes: " && + test_config trailer.fix.ifExists "replace" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -1095,7 +1301,16 @@ test_expect_success 'using "ifExists = replace"' ' ' test_expect_success 'using "ifExists = replace" with "where = after"' ' - git config trailer.fix.where "after" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.fix.key "Fixes: " && + test_config trailer.fix.ifExists "replace" && + test_config trailer.fix.where "after" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -1114,7 +1329,15 @@ test_expect_success 'using "ifExists = replace" with "where = after"' ' ' test_expect_success 'using "ifExists = doNothing"' ' - git config trailer.fix.ifExists "doNothing" && + test_config trailer.fix.ifExists "doNothing" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.fix.key "Fixes: " && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -1133,8 +1356,17 @@ test_expect_success 'using "ifExists = doNothing"' ' ' test_expect_success 'the default is "ifMissing = add"' ' - git config trailer.cc.key "Cc: " && - git config trailer.cc.where "before" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.cc.key "Cc: " && + test_config trailer.cc.where "before" && + test_config trailer.fix.key "Fixes: " && + test_config trailer.fix.ifExists "doNothing" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -1154,7 +1386,14 @@ test_expect_success 'the default is "ifMissing = add"' ' ' test_expect_success 'overriding configuration with "--if-missing doNothing"' ' - git config trailer.ifmissing "add" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.fix.key "Fixes: " && + test_config trailer.fix.ifExists "doNothing" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.ifmissing "add" && + test_config trailer.separators ":=" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Fixes: Z @@ -1173,7 +1412,13 @@ test_expect_success 'overriding configuration with "--if-missing doNothing"' ' ' test_expect_success 'when default "ifMissing" is "doNothing"' ' - git config trailer.ifmissing "doNothing" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.fix.ifExists "doNothing" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.ifmissing "doNothing" && + test_config trailer.separators ":=" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Fixes: Z @@ -1187,14 +1432,21 @@ test_expect_success 'when default "ifMissing" is "doNothing"' ' --trailer "cc=Linus" --trailer "ack: Junio" \ --trailer "fix=22" --trailer "bug: 42" --trailer "ack: Peff" \ <complex_message >actual && - test_cmp expected actual && - git config trailer.ifmissing "add" + test_cmp expected actual ' test_expect_success 'using "ifMissing = add" with "where = end"' ' - git config trailer.cc.key "Cc: " && - git config trailer.cc.where "end" && - git config trailer.cc.ifMissing "add" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.cc.key "Cc: " && + test_config trailer.cc.ifMissing "add" && + test_config trailer.cc.where "end" && + test_config trailer.fix.ifExists "doNothing" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -1214,9 +1466,17 @@ test_expect_success 'using "ifMissing = add" with "where = end"' ' ' test_expect_success 'using "ifMissing = add" with "where = before"' ' - git config trailer.cc.key "Cc: " && - git config trailer.cc.where "before" && - git config trailer.cc.ifMissing "add" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.cc.key "Cc: " && + test_config trailer.cc.ifMissing "add" && + test_config trailer.cc.where "before" && + test_config trailer.fix.ifExists "doNothing" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Cc: Linus @@ -1236,7 +1496,15 @@ test_expect_success 'using "ifMissing = add" with "where = before"' ' ' test_expect_success 'using "ifMissing = doNothing"' ' - git config trailer.cc.ifMissing "doNothing" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.cc.ifMissing "doNothing" && + test_config trailer.fix.ifExists "doNothing" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -1254,9 +1522,50 @@ test_expect_success 'using "ifMissing = doNothing"' ' test_cmp expected actual ' +# Ignore the "IgnoredTrailer" because of "--if-missing doNothing", but also +# ignore the "StillIgnoredTrailer" because we set "trailer.ifMissing" to +# "doNothing" in configuration. +test_expect_success 'using "--no-if-missing" defaults to configuration' ' + test_config trailer.ifMissing "doNothing" && + cat complex_message_body >expected && + sed -e "s/ Z\$/ /" >>expected <<-\EOF && + Fixes: Z + Acked-by: Z + Reviewed-by: Z + Signed-off-by: Z + EOF + git interpret-trailers --if-missing doNothing --trailer "IgnoredTrailer: ignoreme" --no-if-missing \ + --trailer "StillIgnoredTrailer: ignoreme" <complex_message >actual && + test_cmp expected actual +' + +# Add the "AddedTrailer" because the "--no-if-missing" clears the "--if-missing +# doNothing" from earlier in the argument list. +test_expect_success 'using "--no-if-missing" defaults to hardcoded default if nothing configured' ' + cat complex_message_body >expected && + sed -e "s/ Z\$/ /" >>expected <<-\EOF && + Fixes: Z + Acked-by: Z + Reviewed-by: Z + Signed-off-by: Z + AddedTrailer: addme + EOF + git interpret-trailers --if-missing doNothing --trailer "IgnoredTrailer: ignoreme" --no-if-missing \ + --trailer "AddedTrailer: addme" <complex_message >actual && + test_cmp expected actual +' + test_expect_success 'default "where" is now "after"' ' git config trailer.where "after" && - git config --unset trailer.ack.where && + test_config trailer.ack.ifExists "add" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.ack.where "after" && + test_config trailer.bug.key "Bug #" && + test_config trailer.bug.where "before" && + test_config trailer.fix.ifExists "doNothing" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=#" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Bug #42 @@ -1280,10 +1589,15 @@ test_expect_success 'default "where" is now "after"' ' ' test_expect_success 'with simple command' ' - git config trailer.sign.key "Signed-off-by: " && - git config trailer.sign.where "after" && - git config trailer.sign.ifExists "addIfDifferentNeighbor" && - git config trailer.sign.command "echo \"A U Thor <author@example.com>\"" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.fix.ifExists "doNothing" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.sign.command "echo \"A U Thor <author@example.com>\"" && + test_config trailer.sign.key "Signed-off-by: " && + test_config trailer.sign.ifExists "addIfDifferentNeighbor" && + test_config trailer.sign.where "after" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Fixes: Z @@ -1298,8 +1612,14 @@ test_expect_success 'with simple command' ' ' test_expect_success 'with command using committer information' ' - git config trailer.sign.ifExists "addIfDifferent" && - git config trailer.sign.command "echo \"\$GIT_COMMITTER_NAME <\$GIT_COMMITTER_EMAIL>\"" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.fix.ifExists "doNothing" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.sign.command "echo \"\$GIT_COMMITTER_NAME <\$GIT_COMMITTER_EMAIL>\"" && + test_config trailer.sign.key "Signed-off-by: " && + test_config trailer.sign.ifExists "addIfDifferent" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Fixes: Z @@ -1314,10 +1634,15 @@ test_expect_success 'with command using committer information' ' ' test_expect_success 'with command using author information' ' - git config trailer.sign.key "Signed-off-by: " && - git config trailer.sign.where "after" && - git config trailer.sign.ifExists "addIfDifferentNeighbor" && - git config trailer.sign.command "echo \"\$GIT_AUTHOR_NAME <\$GIT_AUTHOR_EMAIL>\"" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.fix.ifExists "doNothing" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.sign.command "echo \"\$GIT_AUTHOR_NAME <\$GIT_AUTHOR_EMAIL>\"" && + test_config trailer.sign.key "Signed-off-by: " && + test_config trailer.sign.ifExists "addIfDifferentNeighbor" && + test_config trailer.sign.where "after" && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-\EOF && Fixes: Z @@ -1338,12 +1663,19 @@ test_expect_success 'setup a commit' ' ' test_expect_success 'cmd takes precedence over command' ' - test_when_finished "git config --unset trailer.fix.cmd" && - git config trailer.fix.ifExists "replace" && - git config trailer.fix.cmd "test -n \"\$1\" && git log -1 --oneline --format=\"%h (%aN)\" \ - --abbrev-commit --abbrev=14 \"\$1\" || true" && - git config trailer.fix.command "git log -1 --oneline --format=\"%h (%s)\" \ + test_config trailer.ack.key "Acked-by= " && + test_config trailer.fix.command "git log -1 --oneline --format=\"%h (%s)\" \ --abbrev-commit --abbrev=14 \$ARG" && + test_config trailer.fix.cmd "test -n \"\$1\" && git log -1 --oneline --format=\"%h (%aN)\" \ + --abbrev-commit --abbrev=14 \"\$1\" || true" && + test_config trailer.fix.key "Fixes: " && + test_config trailer.fix.ifExists "replace" && + test_config trailer.fix.where "after" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.sign.command "echo \"\$GIT_AUTHOR_NAME <\$GIT_AUTHOR_EMAIL>\"" && + test_config trailer.sign.key "Signed-off-by: " && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=" && FIXED=$(git log -1 --oneline --format="%h (%aN)" --abbrev-commit --abbrev=14 HEAD) && cat complex_message_body >expected2 && sed -e "s/ Z\$/ /" >>expected2 <<-EOF && @@ -1359,8 +1691,16 @@ test_expect_success 'cmd takes precedence over command' ' ' test_expect_success 'with command using $ARG' ' - git config trailer.fix.ifExists "replace" && - git config trailer.fix.command "git log -1 --oneline --format=\"%h (%s)\" --abbrev-commit --abbrev=14 \$ARG" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.fix.command "git log -1 --oneline --format=\"%h (%s)\" --abbrev-commit --abbrev=14 \$ARG" && + test_config trailer.fix.key "Fixes: " && + test_config trailer.fix.ifExists "replace" && + test_config trailer.fix.where "after" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.sign.command "echo \"\$GIT_AUTHOR_NAME <\$GIT_AUTHOR_EMAIL>\"" && + test_config trailer.sign.key "Signed-off-by: " && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=" && FIXED=$(git log -1 --oneline --format="%h (%s)" --abbrev-commit --abbrev=14 HEAD) && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-EOF && @@ -1376,8 +1716,16 @@ test_expect_success 'with command using $ARG' ' ' test_expect_success 'with failing command using $ARG' ' - git config trailer.fix.ifExists "replace" && - git config trailer.fix.command "false \$ARG" && + test_config trailer.ack.key "Acked-by= " && + test_config trailer.fix.command "false \$ARG" && + test_config trailer.fix.key "Fixes: " && + test_config trailer.fix.ifExists "replace" && + test_config trailer.fix.where "after" && + test_config trailer.review.key "Reviewed-by:" && + test_config trailer.sign.command "echo \"\$GIT_AUTHOR_NAME <\$GIT_AUTHOR_EMAIL>\"" && + test_config trailer.sign.key "Signed-off-by: " && + test_config trailer.ifexists "addIfDifferent" && + test_config trailer.separators ":=" && cat complex_message_body >expected && sed -e "s/ Z\$/ /" >>expected <<-EOF && Fixes: Z @@ -1392,7 +1740,9 @@ test_expect_success 'with failing command using $ARG' ' ' test_expect_success 'with empty tokens' ' - git config --unset trailer.fix.command && + test_config trailer.sign.command "echo \"\$GIT_AUTHOR_NAME <\$GIT_AUTHOR_EMAIL>\"" && + test_config trailer.sign.key "Signed-off-by: " && + test_config trailer.ifexists "addIfDifferent" && cat >expected <<-EOF && Signed-off-by: A U Thor <author@example.com> @@ -1403,7 +1753,8 @@ test_expect_success 'with empty tokens' ' ' test_expect_success 'with command but no key' ' - git config --unset trailer.sign.key && + test_config trailer.sign.command "echo \"\$GIT_AUTHOR_NAME <\$GIT_AUTHOR_EMAIL>\"" && + test_config trailer.ifexists "addIfDifferent" && cat >expected <<-EOF && sign: A U Thor <author@example.com> @@ -1414,7 +1765,9 @@ test_expect_success 'with command but no key' ' ' test_expect_success 'with no command and no key' ' - git config --unset trailer.review.key && + test_config trailer.review.where "before" && + test_config trailer.sign.command "echo \"\$GIT_AUTHOR_NAME <\$GIT_AUTHOR_EMAIL>\"" && + test_config trailer.ifexists "addIfDifferent" && cat >expected <<-EOF && review: Junio @@ -1426,6 +1779,8 @@ test_expect_success 'with no command and no key' ' ' test_expect_success 'with cut line' ' + test_config trailer.review.where "before" && + test_config trailer.sign.command "echo \"\$GIT_AUTHOR_NAME <\$GIT_AUTHOR_EMAIL>\"" && cat >expected <<-\EOF && my subject @@ -1443,7 +1798,8 @@ test_expect_success 'with cut line' ' ' test_expect_success 'only trailers' ' - git config trailer.sign.command "echo config-value" && + test_config trailer.sign.command "echo config-value" && + test_config trailer.ifexists "addIfDifferent" && cat >expected <<-\EOF && existing: existing-value sign: config-value @@ -1462,7 +1818,7 @@ test_expect_success 'only trailers' ' ' test_expect_success 'only-trailers omits non-trailer in middle of block' ' - git config trailer.sign.command "echo config-value" && + test_config trailer.sign.command "echo config-value" && cat >expected <<-\EOF && Signed-off-by: nobody <nobody@nowhere> Signed-off-by: somebody <somebody@somewhere> @@ -1482,7 +1838,7 @@ test_expect_success 'only-trailers omits non-trailer in middle of block' ' ' test_expect_success 'only input' ' - git config trailer.sign.command "echo config-value" && + test_config trailer.sign.command "echo config-value" && cat >expected <<-\EOF && existing: existing-value EOF diff --git a/t/t7516-commit-races.sh b/t/t7516-commit-races.sh index f2ce14e907..bb95f09810 100755 --- a/t/t7516-commit-races.sh +++ b/t/t7516-commit-races.sh @@ -1,6 +1,8 @@ #!/bin/sh test_description='git commit races' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'race to create orphan commit' ' @@ -10,7 +12,8 @@ test_expect_success 'race to create orphan commit' ' test_must_fail env EDITOR=./hare-editor git commit --allow-empty -m tortoise -e && git show -s --pretty=format:%s >subject && grep hare subject && - test -z "$(git show -s --pretty=format:%P)" + git show -s --pretty=format:%P >out && + test_must_be_empty out ' test_expect_success 'race to create non-orphan commit' ' diff --git a/t/t7518-ident-corner-cases.sh b/t/t7518-ident-corner-cases.sh index fffdb6ff2e..b37de0af49 100755 --- a/t/t7518-ident-corner-cases.sh +++ b/t/t7518-ident-corner-cases.sh @@ -15,15 +15,24 @@ test_expect_success 'empty name and missing email' ' sane_unset GIT_AUTHOR_EMAIL && GIT_AUTHOR_NAME= && test_must_fail git commit --allow-empty -m foo 2>err && - test_i18ngrep ! "(null)" err + test_grep ! "(null)" err ) ' test_expect_success 'commit rejects all-crud name' ' - test_must_fail env GIT_AUTHOR_NAME=" .;<>" \ + test_must_fail env GIT_AUTHOR_NAME=" ,;<>" \ git commit --allow-empty -m foo ' +test_expect_success 'commit does not strip trailing dot' ' + author_name="Pat Doe Jr." && + env GIT_AUTHOR_NAME="$author_name" \ + git commit --allow-empty -m foo && + git log -1 --format=%an >actual && + echo "$author_name" >expected && + test_cmp actual expected +' + # We must test the actual error message here, as an unwanted # auto-detection could fail for other reasons. test_expect_success 'empty configured name does not auto-detect' ' @@ -31,8 +40,8 @@ test_expect_success 'empty configured name does not auto-detect' ' sane_unset GIT_AUTHOR_NAME && test_must_fail \ git -c user.name= commit --allow-empty -m foo 2>err && - test_i18ngrep "empty ident name" err && - test_i18ngrep "Author identity unknown" err + test_grep "empty ident name" err && + test_grep "Author identity unknown" err ) ' @@ -41,8 +50,8 @@ test_expect_success 'empty configured name does not auto-detect for committer' ' sane_unset GIT_COMMITTER_NAME && test_must_fail \ git -c user.name= commit --allow-empty -m foo 2>err && - test_i18ngrep "empty ident name" err && - test_i18ngrep "Committer identity unknown" err + test_grep "empty ident name" err && + test_grep "Committer identity unknown" err ) ' diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh index 8348e3ae7d..7ee69ecdd4 100755 --- a/t/t7519-status-fsmonitor.sh +++ b/t/t7519-status-fsmonitor.sh @@ -322,14 +322,14 @@ do rm -f marker && git status >actual && test_path_is_file marker && - test_i18ngrep ! "Changes not staged for commit:" actual && + test_grep ! "Changes not staged for commit:" actual && if test $uc_val = true then - test_i18ngrep ! "Untracked files:" actual + test_grep ! "Untracked files:" actual fi && if test $uc_val = false then - test_i18ngrep "Untracked files:" actual + test_grep "Untracked files:" actual fi && rm -f marker ' diff --git a/t/t7520-ignored-hook-warning.sh b/t/t7520-ignored-hook-warning.sh index 184b258989..3b63c34a30 100755 --- a/t/t7520-ignored-hook-warning.sh +++ b/t/t7520-ignored-hook-warning.sh @@ -13,27 +13,27 @@ test_expect_success setup ' test_expect_success 'no warning if hook is not ignored' ' git commit --allow-empty -m "more" 2>message && - test_i18ngrep ! -e "hook was ignored" message + test_grep ! -e "hook was ignored" message ' test_expect_success POSIXPERM 'warning if hook is ignored' ' test_hook --disable pre-commit && git commit --allow-empty -m "even more" 2>message && - test_i18ngrep -e "hook was ignored" message + test_grep -e "hook was ignored" message ' test_expect_success POSIXPERM 'no warning if advice.ignoredHook set to false' ' test_config advice.ignoredHook false && test_hook --disable pre-commit && git commit --allow-empty -m "even more" 2>message && - test_i18ngrep ! -e "hook was ignored" message + test_grep ! -e "hook was ignored" message ' test_expect_success 'no warning if unset advice.ignoredHook and hook removed' ' test_hook --remove pre-commit && test_unconfig advice.ignoredHook && git commit --allow-empty -m "even more" 2>message && - test_i18ngrep ! -e "hook was ignored" message + test_grep ! -e "hook was ignored" message ' test_done diff --git a/t/t7525-status-rename.sh b/t/t7525-status-rename.sh index 22bf5c7e5d..a9210d3a3a 100755 --- a/t/t7525-status-rename.sh +++ b/t/t7525-status-rename.sh @@ -21,81 +21,81 @@ test_expect_success 'setup' ' test_expect_success 'status no-options' ' git status >actual && - test_i18ngrep "renamed:" actual + test_grep "renamed:" actual ' test_expect_success 'status --no-renames' ' git status --no-renames >actual && - test_i18ngrep "deleted:" actual && - test_i18ngrep "new file:" actual + test_grep "deleted:" actual && + test_grep "new file:" actual ' test_expect_success 'status.renames inherits from diff.renames false' ' git -c diff.renames=false status >actual && - test_i18ngrep "deleted:" actual && - test_i18ngrep "new file:" actual + test_grep "deleted:" actual && + test_grep "new file:" actual ' test_expect_success 'status.renames inherits from diff.renames true' ' git -c diff.renames=true status >actual && - test_i18ngrep "renamed:" actual + test_grep "renamed:" actual ' test_expect_success 'status.renames overrides diff.renames false' ' git -c diff.renames=true -c status.renames=false status >actual && - test_i18ngrep "deleted:" actual && - test_i18ngrep "new file:" actual + test_grep "deleted:" actual && + test_grep "new file:" actual ' test_expect_success 'status.renames overrides from diff.renames true' ' git -c diff.renames=false -c status.renames=true status >actual && - test_i18ngrep "renamed:" actual + test_grep "renamed:" actual ' test_expect_success 'status status.renames=false' ' git -c status.renames=false status >actual && - test_i18ngrep "deleted:" actual && - test_i18ngrep "new file:" actual + test_grep "deleted:" actual && + test_grep "new file:" actual ' test_expect_success 'status status.renames=true' ' git -c status.renames=true status >actual && - test_i18ngrep "renamed:" actual + test_grep "renamed:" actual ' test_expect_success 'commit honors status.renames=false' ' git -c status.renames=false commit --dry-run >actual && - test_i18ngrep "deleted:" actual && - test_i18ngrep "new file:" actual + test_grep "deleted:" actual && + test_grep "new file:" actual ' test_expect_success 'commit honors status.renames=true' ' git -c status.renames=true commit --dry-run >actual && - test_i18ngrep "renamed:" actual + test_grep "renamed:" actual ' test_expect_success 'status config overridden' ' git -c status.renames=true status --no-renames >actual && - test_i18ngrep "deleted:" actual && - test_i18ngrep "new file:" actual + test_grep "deleted:" actual && + test_grep "new file:" actual ' test_expect_success 'status score=100%' ' git status -M=100% >actual && - test_i18ngrep "deleted:" actual && - test_i18ngrep "new file:" actual && + test_grep "deleted:" actual && + test_grep "new file:" actual && git status --find-renames=100% >actual && - test_i18ngrep "deleted:" actual && - test_i18ngrep "new file:" actual + test_grep "deleted:" actual && + test_grep "new file:" actual ' test_expect_success 'status score=01%' ' git status -M=01% >actual && - test_i18ngrep "renamed:" actual && + test_grep "renamed:" actual && git status --find-renames=01% >actual && - test_i18ngrep "renamed:" actual + test_grep "renamed:" actual ' test_expect_success 'copies not overridden by find-renames' ' @@ -103,12 +103,12 @@ test_expect_success 'copies not overridden by find-renames' ' git add copy && git -c status.renames=copies status -M=01% >actual && - test_i18ngrep "copied:" actual && - test_i18ngrep "renamed:" actual && + test_grep "copied:" actual && + test_grep "renamed:" actual && git -c status.renames=copies status --find-renames=01% >actual && - test_i18ngrep "copied:" actual && - test_i18ngrep "renamed:" actual + test_grep "copied:" actual && + test_grep "renamed:" actual ' test_done diff --git a/t/t7526-commit-pathspec-file.sh b/t/t7526-commit-pathspec-file.sh index ad011bb9f1..c97c550021 100755 --- a/t/t7526-commit-pathspec-file.sh +++ b/t/t7526-commit-pathspec-file.sh @@ -141,25 +141,25 @@ test_expect_success 'error conditions' ' >empty_list && test_must_fail git commit --pathspec-from-file=list --interactive -m "Commit" 2>err && - test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err && + test_grep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err && test_must_fail git commit --pathspec-from-file=list --patch -m "Commit" 2>err && - test_i18ngrep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err && + test_grep -e "options .--pathspec-from-file. and .--interactive/--patch. cannot be used together" err && test_must_fail git commit --pathspec-from-file=list --all -m "Commit" 2>err && - test_i18ngrep -e "options .--pathspec-from-file. and .-a. cannot be used together" err && + test_grep -e "options .--pathspec-from-file. and .-a. cannot be used together" err && test_must_fail git commit --pathspec-from-file=list -m "Commit" -- fileA.t 2>err && - test_i18ngrep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err && + test_grep -e ".--pathspec-from-file. and pathspec arguments cannot be used together" err && test_must_fail git commit --pathspec-file-nul -m "Commit" 2>err && - test_i18ngrep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err && + test_grep -e "the option .--pathspec-file-nul. requires .--pathspec-from-file." err && test_must_fail git commit --pathspec-from-file=empty_list --include -m "Commit" 2>err && - test_i18ngrep -e "No paths with --include/--only does not make sense." err && + test_grep -e "No paths with --include/--only does not make sense." err && test_must_fail git commit --pathspec-from-file=empty_list --only -m "Commit" 2>err && - test_i18ngrep -e "No paths with --include/--only does not make sense." err + test_grep -e "No paths with --include/--only does not make sense." err ' test_done diff --git a/t/t7527-builtin-fsmonitor.sh b/t/t7527-builtin-fsmonitor.sh index 4c0327b2bb..78503158fd 100755 --- a/t/t7527-builtin-fsmonitor.sh +++ b/t/t7527-builtin-fsmonitor.sh @@ -809,6 +809,11 @@ my_match_and_clean () { status --porcelain=v2 >actual.without && test_cmp actual.with actual.without && + git -C super --no-optional-locks diff-index --name-status HEAD >actual.with && + git -C super --no-optional-locks -c core.fsmonitor=false \ + diff-index --name-status HEAD >actual.without && + test_cmp actual.with actual.without && + git -C super/dir_1/dir_2/sub reset --hard && git -C super/dir_1/dir_2/sub clean -d -f } @@ -995,4 +1000,41 @@ test_expect_success !UNICODE_COMPOSITION_SENSITIVE 'Unicode nfc/nfd' ' grep -E "^event: nfd/d_${utf8_nfc}/?$" ./unicode.trace ' +test_expect_success 'split-index and FSMonitor work well together' ' + git init split-index && + test_when_finished "git -C \"$PWD/split-index\" \ + fsmonitor--daemon stop" && + ( + cd split-index && + git config core.splitIndex true && + # force split-index in most cases + git config splitIndex.maxPercentChange 99 && + git config core.fsmonitor true && + + # Create the following commit topology: + # + # * merge three + # |\ + # | * three + # * | merge two + # |\| + # | * two + # * | one + # |/ + # * 5a5efd7 initial + + test_commit initial && + test_commit two && + test_commit three && + git reset --hard initial && + test_commit one && + test_tick && + git merge two && + test_tick && + git merge three && + + git rebase --force-rebase -r one + ) +' + test_done diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh index 060e145957..e5ff073099 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -175,7 +175,7 @@ test_expect_success 'merge -h with invalid index' ' >.git/index && test_expect_code 129 git merge -h 2>usage ) && - test_i18ngrep "[Uu]sage: git merge" broken/usage + test_grep "[Uu]sage: git merge" broken/usage ' test_expect_success 'reject non-strategy with a git-merge-foo name' ' @@ -639,41 +639,41 @@ test_expect_success 'merge log message' ' test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c1 with c0, c2, c0, and c1' ' - git reset --hard c1 && - test_tick && - git merge c0 c2 c0 c1 && - verify_merge file result.1-5 && - verify_parents $c1 $c2 + git reset --hard c1 && + test_tick && + git merge c0 c2 c0 c1 && + verify_merge file result.1-5 && + verify_parents $c1 $c2 ' test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c1 with c0, c2, c0, and c1' ' - git reset --hard c1 && - test_tick && - git merge c0 c2 c0 c1 && - verify_merge file result.1-5 && - verify_parents $c1 $c2 + git reset --hard c1 && + test_tick && + git merge c0 c2 c0 c1 && + verify_merge file result.1-5 && + verify_parents $c1 $c2 ' test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c1 with c1 and c2' ' - git reset --hard c1 && - test_tick && - git merge c1 c2 && - verify_merge file result.1-5 && - verify_parents $c1 $c2 + git reset --hard c1 && + test_tick && + git merge c1 c2 && + verify_merge file result.1-5 && + verify_parents $c1 $c2 ' test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge fast-forward in a dirty tree' ' - git reset --hard c0 && - mv file file1 && - cat file1 >file && - rm -f file1 && - git merge c2 + git reset --hard c0 && + mv file file1 && + cat file1 >file && + rm -f file1 && + git merge c2 ' test_debug 'git log --graph --decorate --oneline --all' @@ -681,7 +681,7 @@ test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'in-index merge' ' git reset --hard c0 && git merge --no-ff -s resolve c1 >out && - test_i18ngrep "Wonderful." out && + test_grep "Wonderful." out && verify_parents $c0 $c1 ' @@ -697,7 +697,7 @@ 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 && + test_grep "Applied autostash." err && git show HEAD:file >merge-result && test_cmp result.1-5 merge-result && test_cmp result.1-5-9 file @@ -708,7 +708,7 @@ test_expect_success 'merge with merge.autoStash' ' git reset --hard c1 && git merge-file file file.orig file.9 && git merge c2 2>err && - test_i18ngrep "Applied autostash." err && + test_grep "Applied autostash." err && git show HEAD:file >merge-result && test_cmp result.1-5 merge-result && test_cmp result.1-5-9 file @@ -718,7 +718,7 @@ 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_grep "Applied autostash." err && test_cmp result.1-5 file ' @@ -728,7 +728,7 @@ test_expect_success 'failed fast-forward merge with --autostash' ' cp file.5 other && test_when_finished "rm other" && test_must_fail git merge --autostash c1 2>err && - test_i18ngrep "Applied autostash." err && + test_grep "Applied autostash." err && test_cmp file.5 file ' @@ -736,7 +736,7 @@ 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 && + test_grep "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 @@ -746,7 +746,7 @@ test_expect_success 'failed merge (exit 2) with --autostash' ' git reset --hard c1 && git merge-file file file.orig file.5 && test_must_fail git merge -s recursive --autostash c2 c3 2>err && - test_i18ngrep "Applied autostash." err && + test_grep "Applied autostash." err && test_cmp result.1-5 file ' @@ -755,7 +755,7 @@ test_expect_success 'conflicted merge with --autostash, --abort restores stash' cp file.1 file && test_must_fail git merge --autostash c7 && git merge --abort 2>err && - test_i18ngrep "Applied autostash." err && + test_grep "Applied autostash." err && test_cmp file.1 file ' @@ -767,7 +767,7 @@ test_expect_success 'completed merge (git commit) with --no-commit and --autosta git stash show -p MERGE_AUTOSTASH >actual && test_cmp expect actual && git commit 2>err && - test_i18ngrep "Applied autostash." err && + test_grep "Applied autostash." err && git show HEAD:file >merge-result && test_cmp result.1-5 merge-result && test_cmp result.1-5-9 file @@ -781,7 +781,7 @@ test_expect_success 'completed merge (git merge --continue) with --no-commit and git stash show -p MERGE_AUTOSTASH >actual && test_cmp expect actual && git merge --continue 2>err && - test_i18ngrep "Applied autostash." err && + test_grep "Applied autostash." err && git show HEAD:file >merge-result && test_cmp result.1-5 merge-result && test_cmp result.1-5-9 file @@ -795,7 +795,7 @@ test_expect_success 'aborted merge (merge --abort) with --no-commit and --autost git stash show -p MERGE_AUTOSTASH >actual && test_cmp expect actual && git merge --abort 2>err && - test_i18ngrep "Applied autostash." err && + test_grep "Applied autostash." err && git diff >actual && test_cmp expect actual ' @@ -808,7 +808,7 @@ test_expect_success 'aborted merge (reset --hard) with --no-commit and --autosta 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 && + test_grep "Autostash exists; creating a new stash entry." err && git diff --exit-code ' @@ -821,7 +821,7 @@ test_expect_success 'quit merge with --no-commit and --autostash' ' test_cmp expect actual && git diff HEAD >expect && git merge --quit 2>err && - test_i18ngrep "Autostash exists; creating a new stash entry." err && + test_grep "Autostash exists; creating a new stash entry." err && git diff HEAD >actual && test_cmp expect actual ' @@ -832,7 +832,7 @@ test_expect_success 'merge with conflicted --autostash changes' ' 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 && + test_grep "Applying autostash resulted in conflicts." err && git show HEAD:file >merge-result && test_cmp result.1-9 merge-result && git stash show -p >actual && diff --git a/t/t7601-merge-pull-config.sh b/t/t7601-merge-pull-config.sh index bd238d89b0..a94387a75f 100755 --- a/t/t7601-merge-pull-config.sh +++ b/t/t7601-merge-pull-config.sh @@ -30,117 +30,117 @@ test_expect_success 'setup' ' test_expect_success 'pull.rebase not set, ff possible' ' git reset --hard c0 && git pull . c1 2>err && - test_i18ngrep ! "You have divergent branches" err + test_grep ! "You have divergent branches" err ' test_expect_success 'pull.rebase not set and pull.ff=true' ' git reset --hard c0 && test_config pull.ff true && git pull . c1 2>err && - test_i18ngrep ! "You have divergent branches" err + test_grep ! "You have divergent branches" err ' test_expect_success 'pull.rebase not set and pull.ff=false' ' git reset --hard c0 && test_config pull.ff false && git pull . c1 2>err && - test_i18ngrep ! "You have divergent branches" err + test_grep ! "You have divergent branches" err ' test_expect_success 'pull.rebase not set and pull.ff=only' ' git reset --hard c0 && test_config pull.ff only && git pull . c1 2>err && - test_i18ngrep ! "You have divergent branches" err + test_grep ! "You have divergent branches" err ' test_expect_success 'pull.rebase not set and --rebase given' ' git reset --hard c0 && git pull --rebase . c1 2>err && - test_i18ngrep ! "You have divergent branches" err + test_grep ! "You have divergent branches" err ' test_expect_success 'pull.rebase not set and --no-rebase given' ' git reset --hard c0 && git pull --no-rebase . c1 2>err && - test_i18ngrep ! "You have divergent branches" err + test_grep ! "You have divergent branches" err ' test_expect_success 'pull.rebase not set and --ff given' ' git reset --hard c0 && git pull --ff . c1 2>err && - test_i18ngrep ! "You have divergent branches" err + test_grep ! "You have divergent branches" err ' test_expect_success 'pull.rebase not set and --no-ff given' ' git reset --hard c0 && git pull --no-ff . c1 2>err && - test_i18ngrep ! "You have divergent branches" err + test_grep ! "You have divergent branches" err ' test_expect_success 'pull.rebase not set and --ff-only given' ' git reset --hard c0 && git pull --ff-only . c1 2>err && - test_i18ngrep ! "You have divergent branches" err + test_grep ! "You have divergent branches" err ' test_expect_success 'pull.rebase not set (not-fast-forward)' ' git reset --hard c2 && test_must_fail git -c color.advice=always pull . c1 2>err && test_decode_color <err >decoded && - test_i18ngrep "<YELLOW>hint: " decoded && - test_i18ngrep "You have divergent branches" decoded + test_grep "<YELLOW>hint: " decoded && + test_grep "You have divergent branches" decoded ' test_expect_success 'pull.rebase not set and pull.ff=true (not-fast-forward)' ' git reset --hard c2 && test_config pull.ff true && git pull . c1 2>err && - test_i18ngrep ! "You have divergent branches" err + test_grep ! "You have divergent branches" err ' test_expect_success 'pull.rebase not set and pull.ff=false (not-fast-forward)' ' git reset --hard c2 && test_config pull.ff false && git pull . c1 2>err && - test_i18ngrep ! "You have divergent branches" err + test_grep ! "You have divergent branches" err ' test_expect_success 'pull.rebase not set and pull.ff=only (not-fast-forward)' ' git reset --hard c2 && test_config pull.ff only && test_must_fail git pull . c1 2>err && - test_i18ngrep ! "You have divergent branches" err + test_grep ! "You have divergent branches" err ' test_expect_success 'pull.rebase not set and --rebase given (not-fast-forward)' ' git reset --hard c2 && git pull --rebase . c1 2>err && - test_i18ngrep ! "You have divergent branches" err + test_grep ! "You have divergent branches" err ' test_expect_success 'pull.rebase not set and --no-rebase given (not-fast-forward)' ' git reset --hard c2 && git pull --no-rebase . c1 2>err && - test_i18ngrep ! "You have divergent branches" err + test_grep ! "You have divergent branches" err ' test_expect_success 'pull.rebase not set and --ff given (not-fast-forward)' ' git reset --hard c2 && git pull --ff . c1 2>err && - test_i18ngrep ! "You have divergent branches" err + test_grep ! "You have divergent branches" err ' test_expect_success 'pull.rebase not set and --no-ff given (not-fast-forward)' ' git reset --hard c2 && git pull --no-ff . c1 2>err && - test_i18ngrep ! "You have divergent branches" err + test_grep ! "You have divergent branches" err ' test_expect_success 'pull.rebase not set and --ff-only given (not-fast-forward)' ' git reset --hard c2 && test_must_fail git pull --ff-only . c1 2>err && - test_i18ngrep ! "You have divergent branches" err + test_grep ! "You have divergent branches" err ' test_does_rebase () { @@ -202,7 +202,7 @@ test_falls_back_to_full_merge () { test_attempts_fast_forward () { git reset --hard c2 && test_must_fail git "$@" . c1 2>err && - test_i18ngrep "Not possible to fast-forward, aborting" err + test_grep "Not possible to fast-forward, aborting" err } # @@ -328,34 +328,34 @@ test_expect_success 'pull.rebase=false and --ff, ff not possible' ' test_expect_success 'Multiple heads warns about inability to fast forward' ' git reset --hard c1 && test_must_fail git pull . c2 c3 2>err && - test_i18ngrep "You have divergent branches" err + test_grep "You have divergent branches" err ' test_expect_success 'Multiple can never be fast forwarded' ' git reset --hard c0 && test_must_fail git -c pull.ff=only pull . c1 c2 c3 2>err && - test_i18ngrep ! "You have divergent branches" err && + test_grep ! "You have divergent branches" err && # In addition to calling out "cannot fast-forward", we very much # want the "multiple branches" piece to be called out to users. - test_i18ngrep "Cannot fast-forward to multiple branches" err + test_grep "Cannot fast-forward to multiple branches" err ' test_expect_success 'Cannot rebase with multiple heads' ' git reset --hard c0 && test_must_fail git -c pull.rebase=true pull . c1 c2 c3 2>err && - test_i18ngrep ! "You have divergent branches" err && - test_i18ngrep "Cannot rebase onto multiple branches." err + test_grep ! "You have divergent branches" err && + test_grep "Cannot rebase onto multiple branches." err ' test_expect_success 'merge c1 with c2' ' git reset --hard c1 && - test -f c0.c && - test -f c1.c && - test ! -f c2.c && - test ! -f c3.c && + test_path_is_file c0.c && + test_path_is_file c1.c && + test_path_is_missing c2.c && + test_path_is_missing c3.c && git merge c2 && - test -f c1.c && - test -f c2.c + test_path_is_file c1.c && + test_path_is_file c2.c ' test_expect_success 'fast-forward pull succeeds with "true" in pull.ff' ' @@ -411,8 +411,8 @@ test_expect_success 'merge c1 with c2 (ours in pull.twohead)' ' git reset --hard c1 && git config pull.twohead ours && git merge c2 && - test -f c1.c && - ! test -f c2.c + test_path_is_file c1.c && + test_path_is_missing c2.c ' test_expect_success 'merge c1 with c2 and c3 (recursive in pull.octopus)' ' @@ -431,10 +431,10 @@ test_expect_success 'merge c1 with c2 and c3 (recursive and octopus in pull.octo test "$(git rev-parse c2)" = "$(git rev-parse HEAD^2)" && test "$(git rev-parse c3)" = "$(git rev-parse HEAD^3)" && git diff --exit-code && - test -f c0.c && - test -f c1.c && - test -f c2.c && - test -f c3.c + test_path_is_file c0.c && + test_path_is_file c1.c && + test_path_is_file c2.c && + test_path_is_file c3.c ' conflict_count() diff --git a/t/t7602-merge-octopus-many.sh b/t/t7602-merge-octopus-many.sh index ff085b086c..3669d33bd5 100755 --- a/t/t7602-merge-octopus-many.sh +++ b/t/t7602-merge-octopus-many.sh @@ -4,6 +4,7 @@ test_description='git merge Testing octopus merge with more than 25 refs.' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t7603-merge-reduce-heads.sh b/t/t7603-merge-reduce-heads.sh index 4887ca705b..0e85b21ec8 100755 --- a/t/t7603-merge-reduce-heads.sh +++ b/t/t7603-merge-reduce-heads.sh @@ -4,6 +4,7 @@ test_description='git merge Testing octopus merge when reducing parents to independent branches.' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh # 0 - 1 diff --git a/t/t7607-merge-state.sh b/t/t7607-merge-state.sh index 89a62ac53b..9001674f2e 100755 --- a/t/t7607-merge-state.sh +++ b/t/t7607-merge-state.sh @@ -4,6 +4,7 @@ test_description="Test that merge state is as expected after failed merge" GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'Ensure we restore original state if no merge strategy handles it' ' diff --git a/t/t7608-merge-messages.sh b/t/t7608-merge-messages.sh index 0b908ab2e7..2179938c43 100755 --- a/t/t7608-merge-messages.sh +++ b/t/t7608-merge-messages.sh @@ -4,6 +4,7 @@ test_description='test auto-generated merge messages' GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh check_oneline() { diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh index 7b957022f1..22b3a85b3e 100755 --- a/t/t7610-mergetool.sh +++ b/t/t7610-mergetool.sh @@ -860,4 +860,42 @@ test_expect_success 'mergetool hideResolved' ' git commit -m "test resolved with mergetool" ' +test_expect_success 'mergetool with guiDefault' ' + test_config merge.guitool myguitool && + test_config mergetool.myguitool.cmd "(printf \"gui \" && cat \"\$REMOTE\") >\"\$MERGED\"" && + test_config mergetool.myguitool.trustExitCode true && + test_when_finished "git reset --hard" && + git checkout -b test$test_count branch1 && + git submodule update -N && + test_must_fail git merge main && + + test_config mergetool.guiDefault auto && + DISPLAY=SOMETHING && export DISPLAY && + yes "" | git mergetool both && + yes "" | git mergetool file1 file1 && + + DISPLAY= && export DISPLAY && + yes "" | git mergetool file2 "spaced name" && + + test_config mergetool.guiDefault true && + yes "" | git mergetool subdir/file3 && + + yes "d" | git mergetool file11 && + yes "d" | git mergetool file12 && + yes "l" | git mergetool submod && + + echo "gui main updated" >expect && + test_cmp expect file1 && + + echo "main new" >expect && + test_cmp expect file2 && + + echo "gui main new sub" >expect && + test_cmp expect subdir/file3 && + + echo "branch1 submodule" >expect && + test_cmp expect submod/bar && + git commit -m "branch1 resolved with mergetool" +' + test_done diff --git a/t/t7611-merge-abort.sh b/t/t7611-merge-abort.sh index c0e9425115..d6975ca48d 100755 --- a/t/t7611-merge-abort.sh +++ b/t/t7611-merge-abort.sh @@ -50,7 +50,7 @@ pre_merge_head="$(git rev-parse HEAD)" test_expect_success 'fails without MERGE_HEAD (unstarted merge)' ' test_must_fail git merge --abort 2>output && - test_i18ngrep MERGE_HEAD output + test_grep MERGE_HEAD output ' test_expect_success 'fails without MERGE_HEAD (unstarted merge): .git/MERGE_HEAD sanity' ' @@ -64,7 +64,7 @@ test_expect_success 'fails without MERGE_HEAD (completed merge)' ' # Merge successfully completed post_merge_head="$(git rev-parse HEAD)" && test_must_fail git merge --abort 2>output && - test_i18ngrep MERGE_HEAD output + test_grep MERGE_HEAD output ' test_expect_success 'fails without MERGE_HEAD (completed merge): .git/MERGE_HEAD sanity' ' diff --git a/t/t7612-merge-verify-signatures.sh b/t/t7612-merge-verify-signatures.sh index f5c90cc22a..84ddb56851 100755 --- a/t/t7612-merge-verify-signatures.sh +++ b/t/t7612-merge-verify-signatures.sh @@ -41,54 +41,54 @@ test_expect_success GPG 'create signed commits' ' test_expect_success GPG 'merge unsigned commit with verification' ' test_when_finished "git reset --hard && git checkout initial" && test_must_fail git merge --ff-only --verify-signatures side-unsigned 2>mergeerror && - test_i18ngrep "does not have a GPG signature" mergeerror + test_grep "does not have a GPG signature" mergeerror ' test_expect_success GPG 'merge unsigned commit with merge.verifySignatures=true' ' test_when_finished "git reset --hard && git checkout initial" && test_config merge.verifySignatures true && test_must_fail git merge --ff-only side-unsigned 2>mergeerror && - test_i18ngrep "does not have a GPG signature" mergeerror + test_grep "does not have a GPG signature" mergeerror ' test_expect_success GPG 'merge commit with bad signature with verification' ' test_when_finished "git reset --hard && git checkout initial" && test_must_fail git merge --ff-only --verify-signatures $(cat forged.commit) 2>mergeerror && - test_i18ngrep "has a bad GPG signature" mergeerror + test_grep "has a bad GPG signature" mergeerror ' test_expect_success GPG 'merge commit with bad signature with merge.verifySignatures=true' ' test_when_finished "git reset --hard && git checkout initial" && test_config merge.verifySignatures true && test_must_fail git merge --ff-only $(cat forged.commit) 2>mergeerror && - test_i18ngrep "has a bad GPG signature" mergeerror + test_grep "has a bad GPG signature" mergeerror ' test_expect_success GPG 'merge commit with untrusted signature with verification' ' test_when_finished "git reset --hard && git checkout initial" && test_must_fail git merge --ff-only --verify-signatures side-untrusted 2>mergeerror && - test_i18ngrep "has an untrusted GPG signature" mergeerror + test_grep "has an untrusted GPG signature" mergeerror ' test_expect_success GPG 'merge commit with untrusted signature with verification and high minTrustLevel' ' test_when_finished "git reset --hard && git checkout initial" && test_config gpg.minTrustLevel marginal && test_must_fail git merge --ff-only --verify-signatures side-untrusted 2>mergeerror && - test_i18ngrep "has an untrusted GPG signature" mergeerror + test_grep "has an untrusted GPG signature" mergeerror ' test_expect_success GPG 'merge commit with untrusted signature with verification and low minTrustLevel' ' test_when_finished "git reset --hard && git checkout initial" && test_config gpg.minTrustLevel undefined && git merge --ff-only --verify-signatures side-untrusted >mergeoutput && - test_i18ngrep "has a good GPG signature" mergeoutput + test_grep "has a good GPG signature" mergeoutput ' test_expect_success GPG 'merge commit with untrusted signature with merge.verifySignatures=true' ' test_when_finished "git reset --hard && git checkout initial" && test_config merge.verifySignatures true && test_must_fail git merge --ff-only side-untrusted 2>mergeerror && - test_i18ngrep "has an untrusted GPG signature" mergeerror + test_grep "has an untrusted GPG signature" mergeerror ' test_expect_success GPG 'merge commit with untrusted signature with merge.verifySignatures=true and minTrustLevel' ' @@ -96,20 +96,20 @@ test_expect_success GPG 'merge commit with untrusted signature with merge.verify test_config merge.verifySignatures true && test_config gpg.minTrustLevel marginal && test_must_fail git merge --ff-only side-untrusted 2>mergeerror && - test_i18ngrep "has an untrusted GPG signature" mergeerror + test_grep "has an untrusted GPG signature" mergeerror ' test_expect_success GPG 'merge signed commit with verification' ' test_when_finished "git reset --hard && git checkout initial" && git merge --verbose --ff-only --verify-signatures side-signed >mergeoutput && - test_i18ngrep "has a good GPG signature" mergeoutput + test_grep "has a good GPG signature" mergeoutput ' test_expect_success GPG 'merge signed commit with merge.verifySignatures=true' ' test_when_finished "git reset --hard && git checkout initial" && test_config merge.verifySignatures true && git merge --verbose --ff-only side-signed >mergeoutput && - test_i18ngrep "has a good GPG signature" mergeoutput + test_grep "has a good GPG signature" mergeoutput ' test_expect_success GPG 'merge commit with bad signature without verification' ' @@ -133,7 +133,7 @@ test_expect_success GPG 'merge unsigned commit into unborn branch' ' test_when_finished "git checkout initial" && git checkout --orphan unborn && test_must_fail git merge --verify-signatures side-unsigned 2>mergeerror && - test_i18ngrep "does not have a GPG signature" mergeerror + test_grep "does not have a GPG signature" mergeerror ' test_done diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh index 4aabe98139..94f9f4a1da 100755 --- a/t/t7700-repack.sh +++ b/t/t7700-repack.sh @@ -10,6 +10,10 @@ test_description='git repack works correctly' commit_and_pack () { test_commit "$@" 1>&2 && incrpackid=$(git pack-objects --all --unpacked --incremental .git/objects/pack/pack </dev/null) && + # Remove any loose object(s) created by test_commit, since they have + # already been packed. Leaving these around can create subtly different + # packs with `pack-objects`'s `--unpacked` option. + git prune-packed 1>&2 && echo pack-${incrpackid}.pack } @@ -106,6 +110,23 @@ test_expect_success SYMLINKS '--local keeps packs when alternate is objectdir ' test_cmp expect actual ' +test_expect_success '--local disables writing bitmaps when connected to alternate ODB' ' + test_when_finished "rm -rf shared member" && + + git init shared && + git clone --shared shared member && + ( + cd member && + test_commit "object" && + GIT_TEST_MULTI_PACK_INDEX=0 git repack -Adl --write-bitmap-index 2>err && + cat >expect <<-EOF && + warning: disabling bitmap writing, as some objects are not being packed + EOF + test_cmp expect err && + test_path_is_missing .git/objects/pack-*.bitmap + ) +' + test_expect_success 'packed obs in alt ODB are repacked even when local repo is packless' ' mkdir alt_objects/pack && mv .git/objects/pack/* alt_objects/pack && @@ -192,6 +213,8 @@ test_expect_success 'repack --keep-pack' ' test_create_repo keep-pack && ( cd keep-pack && + # avoid producing different packs due to delta/base choices + git config pack.window 0 && P1=$(commit_and_pack 1) && P2=$(commit_and_pack 2) && P3=$(commit_and_pack 3) && @@ -203,10 +226,61 @@ test_expect_success 'repack --keep-pack' ' grep -q $P1 new-counts && grep -q $P4 new-counts && test_line_count = 3 new-counts && + git fsck && + + P5=$(commit_and_pack --no-tag 5) && + git reset --hard HEAD^ && + git reflog expire --all --expire=all && + rm -f ".git/objects/pack/${P5%.pack}.idx" && + rm -f ".git/objects/info/commit-graph" && + for from in $(find .git/objects/pack -type f -name "${P5%.pack}.*") + do + to="$(dirname "$from")/.tmp-1234-$(basename "$from")" && + mv "$from" "$to" || return 1 + done && + + # A .idx file without a .pack should not stop us from + # repacking what we can. + touch .git/objects/pack/pack-does-not-exist.idx && + + git repack --cruft -d --keep-pack $P1 --keep-pack $P4 && + + ls .git/objects/pack/*.pack >newer-counts && + test_cmp new-counts newer-counts && git fsck ) ' +test_expect_success 'repacking fails when missing .pack actually means missing objects' ' + test_create_repo idx-without-pack && + ( + cd idx-without-pack && + + # Avoid producing different packs due to delta/base choices + git config pack.window 0 && + P1=$(commit_and_pack 1) && + P2=$(commit_and_pack 2) && + P3=$(commit_and_pack 3) && + P4=$(commit_and_pack 4) && + ls .git/objects/pack/*.pack >old-counts && + test_line_count = 4 old-counts && + + # Remove one .pack file + rm .git/objects/pack/$P2 && + + ls .git/objects/pack/*.pack >before-pack-dir && + + test_must_fail git fsck && + test_must_fail env GIT_COMMIT_GRAPH_PARANOIA=true git repack --cruft -d 2>err && + grep "bad object" err && + + # Before failing, the repack did not modify the + # pack directory. + ls .git/objects/pack/*.pack >after-pack-dir && + test_cmp before-pack-dir after-pack-dir + ) +' + test_expect_success 'bitmaps are created by default in bare repos' ' git clone --bare .git bare.git && rm -f bare.git/objects/pack/*.bitmap && @@ -253,6 +327,203 @@ test_expect_success 'auto-bitmaps do not complain if unavailable' ' test_must_be_empty actual ' +test_expect_success 'repacking with a filter works' ' + git -C bare.git repack -a -d && + test_stdout_line_count = 1 ls bare.git/objects/pack/*.pack && + git -C bare.git -c repack.writebitmaps=false repack -a -d --filter=blob:none && + test_stdout_line_count = 2 ls bare.git/objects/pack/*.pack && + commit_pack=$(test-tool -C bare.git find-pack -c 1 HEAD) && + blob_pack=$(test-tool -C bare.git find-pack -c 1 HEAD:file1) && + test "$commit_pack" != "$blob_pack" && + tree_pack=$(test-tool -C bare.git find-pack -c 1 HEAD^{tree}) && + test "$tree_pack" = "$commit_pack" && + blob_pack2=$(test-tool -C bare.git find-pack -c 1 HEAD:file2) && + test "$blob_pack2" = "$blob_pack" +' + +test_expect_success '--filter fails with --write-bitmap-index' ' + test_must_fail \ + env GIT_TEST_MULTI_PACK_INDEX_WRITE_BITMAP=0 \ + git -C bare.git repack -a -d --write-bitmap-index --filter=blob:none +' + +test_expect_success 'repacking with two filters works' ' + git init two-filters && + ( + cd two-filters && + mkdir subdir && + test_commit foo && + test_commit subdir_bar subdir/bar && + test_commit subdir_baz subdir/baz + ) && + git clone --no-local --bare two-filters two-filters.git && + ( + cd two-filters.git && + test_stdout_line_count = 1 ls objects/pack/*.pack && + git -c repack.writebitmaps=false repack -a -d \ + --filter=blob:none --filter=tree:1 && + test_stdout_line_count = 2 ls objects/pack/*.pack && + commit_pack=$(test-tool find-pack -c 1 HEAD) && + blob_pack=$(test-tool find-pack -c 1 HEAD:foo.t) && + root_tree_pack=$(test-tool find-pack -c 1 HEAD^{tree}) && + subdir_tree_hash=$(git ls-tree --object-only HEAD -- subdir) && + subdir_tree_pack=$(test-tool find-pack -c 1 "$subdir_tree_hash") && + + # Root tree and subdir tree are not in the same packfiles + test "$commit_pack" != "$blob_pack" && + test "$commit_pack" = "$root_tree_pack" && + test "$blob_pack" = "$subdir_tree_pack" + ) +' + +prepare_for_keep_packs () { + git init keep-packs && + ( + cd keep-packs && + test_commit foo && + test_commit bar + ) && + git clone --no-local --bare keep-packs keep-packs.git && + ( + cd keep-packs.git && + + # Create two packs + # The first pack will contain all of the objects except one blob + git rev-list --objects --all >objs && + grep -v "bar.t" objs | git pack-objects pack && + # The second pack will contain the excluded object and be kept + packid=$(grep "bar.t" objs | git pack-objects pack) && + >pack-$packid.keep && + + # Replace the existing pack with the 2 new ones + rm -f objects/pack/pack* && + mv pack-* objects/pack/ + ) +} + +test_expect_success '--filter works with .keep packs' ' + prepare_for_keep_packs && + ( + cd keep-packs.git && + + foo_pack=$(test-tool find-pack -c 1 HEAD:foo.t) && + bar_pack=$(test-tool find-pack -c 1 HEAD:bar.t) && + head_pack=$(test-tool find-pack -c 1 HEAD) && + + test "$foo_pack" != "$bar_pack" && + test "$foo_pack" = "$head_pack" && + + git -c repack.writebitmaps=false repack -a -d --filter=blob:none && + + foo_pack_1=$(test-tool find-pack -c 1 HEAD:foo.t) && + bar_pack_1=$(test-tool find-pack -c 1 HEAD:bar.t) && + head_pack_1=$(test-tool find-pack -c 1 HEAD) && + + # Object bar is still only in the old .keep pack + test "$foo_pack_1" != "$foo_pack" && + test "$bar_pack_1" = "$bar_pack" && + test "$head_pack_1" != "$head_pack" && + + test "$foo_pack_1" != "$bar_pack_1" && + test "$foo_pack_1" != "$head_pack_1" && + test "$bar_pack_1" != "$head_pack_1" + ) +' + +test_expect_success '--filter works with --pack-kept-objects and .keep packs' ' + rm -rf keep-packs keep-packs.git && + prepare_for_keep_packs && + ( + cd keep-packs.git && + + foo_pack=$(test-tool find-pack -c 1 HEAD:foo.t) && + bar_pack=$(test-tool find-pack -c 1 HEAD:bar.t) && + head_pack=$(test-tool find-pack -c 1 HEAD) && + + test "$foo_pack" != "$bar_pack" && + test "$foo_pack" = "$head_pack" && + + git -c repack.writebitmaps=false repack -a -d --filter=blob:none \ + --pack-kept-objects && + + foo_pack_1=$(test-tool find-pack -c 1 HEAD:foo.t) && + test-tool find-pack -c 2 HEAD:bar.t >bar_pack_1 && + head_pack_1=$(test-tool find-pack -c 1 HEAD) && + + test "$foo_pack_1" != "$foo_pack" && + test "$foo_pack_1" != "$bar_pack" && + test "$head_pack_1" != "$head_pack" && + + # Object bar is in both the old .keep pack and the new + # pack that contained the filtered out objects + grep "$bar_pack" bar_pack_1 && + grep "$foo_pack_1" bar_pack_1 && + test "$foo_pack_1" != "$head_pack_1" + ) +' + +test_expect_success '--filter-to stores filtered out objects' ' + git -C bare.git repack -a -d && + test_stdout_line_count = 1 ls bare.git/objects/pack/*.pack && + + git init --bare filtered.git && + git -C bare.git -c repack.writebitmaps=false repack -a -d \ + --filter=blob:none \ + --filter-to=../filtered.git/objects/pack/pack && + test_stdout_line_count = 1 ls bare.git/objects/pack/pack-*.pack && + test_stdout_line_count = 1 ls filtered.git/objects/pack/pack-*.pack && + + commit_pack=$(test-tool -C bare.git find-pack -c 1 HEAD) && + blob_pack=$(test-tool -C bare.git find-pack -c 0 HEAD:file1) && + blob_hash=$(git -C bare.git rev-parse HEAD:file1) && + test -n "$blob_hash" && + blob_pack=$(test-tool -C filtered.git find-pack -c 1 $blob_hash) && + + echo $(pwd)/filtered.git/objects >bare.git/objects/info/alternates && + blob_pack=$(test-tool -C bare.git find-pack -c 1 HEAD:file1) && + blob_content=$(git -C bare.git show $blob_hash) && + test "$blob_content" = "content1" +' + +test_expect_success '--filter works with --max-pack-size' ' + rm -rf filtered.git && + git init --bare filtered.git && + git init max-pack-size && + ( + cd max-pack-size && + test_commit base && + # two blobs which exceed the maximum pack size + test-tool genrandom foo 1048576 >foo && + git hash-object -w foo && + test-tool genrandom bar 1048576 >bar && + git hash-object -w bar && + git add foo bar && + git commit -m "adding foo and bar" + ) && + git clone --no-local --bare max-pack-size max-pack-size.git && + ( + cd max-pack-size.git && + git -c repack.writebitmaps=false repack -a -d --filter=blob:none \ + --max-pack-size=1M \ + --filter-to=../filtered.git/objects/pack/pack && + echo $(cd .. && pwd)/filtered.git/objects >objects/info/alternates && + + # Check that the 3 blobs are in different packfiles in filtered.git + test_stdout_line_count = 3 ls ../filtered.git/objects/pack/pack-*.pack && + test_stdout_line_count = 1 ls objects/pack/pack-*.pack && + foo_pack=$(test-tool find-pack -c 1 HEAD:foo) && + bar_pack=$(test-tool find-pack -c 1 HEAD:bar) && + base_pack=$(test-tool find-pack -c 1 HEAD:base.t) && + test "$foo_pack" != "$bar_pack" && + test "$foo_pack" != "$base_pack" && + test "$bar_pack" != "$base_pack" && + for pack in "$foo_pack" "$bar_pack" "$base_pack" + do + case "$foo_pack" in */filtered.git/objects/pack/*) true ;; *) return 1 ;; esac + done + ) +' + objdir=.git/objects midx=$objdir/pack/multi-pack-index @@ -443,10 +714,10 @@ test_expect_success '--write-midx -b packs non-kept objects' ' ' test_expect_success '--write-midx removes stale pack-based bitmaps' ' - rm -fr repo && - git init repo && - test_when_finished "rm -fr repo" && - ( + rm -fr repo && + git init repo && + test_when_finished "rm -fr repo" && + ( cd repo && test_commit base && GIT_TEST_MULTI_PACK_INDEX=0 git repack -Ab && @@ -460,7 +731,7 @@ test_expect_success '--write-midx removes stale pack-based bitmaps' ' test_path_is_file $midx && test_path_is_file $midx-$(midx_checksum $objdir).bitmap && test_path_is_missing $pack_bitmap - ) + ) ' test_expect_success '--write-midx with --pack-kept-objects' ' @@ -559,125 +830,4 @@ test_expect_success '-n overrides repack.updateServerInfo=true' ' test_server_info_missing ' -test_expect_success '--expire-to stores pruned objects (now)' ' - git init expire-to-now && - ( - cd expire-to-now && - - git branch -M main && - - test_commit base && - - git checkout -b cruft && - test_commit --no-tag cruft && - - git rev-list --objects --no-object-names main..cruft >moved.raw && - sort moved.raw >moved.want && - - git rev-list --all --objects --no-object-names >expect.raw && - sort expect.raw >expect && - - git checkout main && - git branch -D cruft && - git reflog expire --all --expire=all && - - git init --bare expired.git && - git repack -d \ - --cruft --cruft-expiration="now" \ - --expire-to="expired.git/objects/pack/pack" && - - expired="$(ls expired.git/objects/pack/pack-*.idx)" && - test_path_is_file "${expired%.idx}.mtimes" && - - # Since the `--cruft-expiration` is "now", the effective - # behavior is to move _all_ unreachable objects out to - # the location in `--expire-to`. - git show-index <$expired >expired.raw && - cut -d" " -f2 expired.raw | sort >expired.objects && - git rev-list --all --objects --no-object-names \ - >remaining.objects && - - # ...in other words, the combined contents of this - # repository and expired.git should be the same as the - # set of objects we started with. - cat expired.objects remaining.objects | sort >actual && - test_cmp expect actual && - - # The "moved" objects (i.e., those in expired.git) - # should be the same as the cruft objects which were - # expired in the previous step. - test_cmp moved.want expired.objects - ) -' - -test_expect_success '--expire-to stores pruned objects (5.minutes.ago)' ' - git init expire-to-5.minutes.ago && - ( - cd expire-to-5.minutes.ago && - - git branch -M main && - - test_commit base && - - # Create two classes of unreachable objects, one which - # is older than 5 minutes (stale), and another which is - # newer (recent). - for kind in stale recent - do - git checkout -b $kind main && - test_commit --no-tag $kind || return 1 - done && - - git rev-list --objects --no-object-names main..stale >in && - stale="$(git pack-objects $objdir/pack/pack <in)" && - mtime="$(test-tool chmtime --get =-600 $objdir/pack/pack-$stale.pack)" && - - # expect holds the set of objects we expect to find in - # this repository after repacking - git rev-list --objects --no-object-names recent >expect.raw && - sort expect.raw >expect && - - # moved.want holds the set of objects we expect to find - # in expired.git - git rev-list --objects --no-object-names main..stale >out && - sort out >moved.want && - - git checkout main && - git branch -D stale recent && - git reflog expire --all --expire=all && - git prune-packed && - - git init --bare expired.git && - git repack -d \ - --cruft --cruft-expiration=5.minutes.ago \ - --expire-to="expired.git/objects/pack/pack" && - - # Some of the remaining objects in this repository are - # unreachable, so use `cat-file --batch-all-objects` - # instead of `rev-list` to get their names - git cat-file --batch-all-objects --batch-check="%(objectname)" \ - >remaining.objects && - sort remaining.objects >actual && - test_cmp expect actual && - - ( - cd expired.git && - - expired="$(ls objects/pack/pack-*.mtimes)" && - test-tool pack-mtimes $(basename $expired) >out && - cut -d" " -f1 out | sort >../moved.got && - - # Ensure that there are as many objects with the - # expected mtime as were moved to expired.git. - # - # In other words, ensure that the recorded - # mtimes of any moved objects was written - # correctly. - grep " $mtime$" out >matching && - test_line_count = $(wc -l <../moved.want) matching - ) && - test_cmp moved.want moved.got - ) -' - test_done diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh index ebb267855f..fe6c3e77a3 100755 --- a/t/t7701-repack-unpack-unreachable.sh +++ b/t/t7701-repack-unpack-unreachable.sh @@ -113,6 +113,48 @@ test_expect_success 'do not bother loosening old objects' ' test_must_fail git cat-file -p $obj2 ' +test_expect_success 'gc.recentObjectsHook' ' + obj1=$(echo one | git hash-object -w --stdin) && + obj2=$(echo two | git hash-object -w --stdin) && + obj3=$(echo three | git hash-object -w --stdin) && + pack1=$(echo $obj1 | git pack-objects .git/objects/pack/pack) && + pack2=$(echo $obj2 | git pack-objects .git/objects/pack/pack) && + pack3=$(echo $obj3 | git pack-objects .git/objects/pack/pack) && + git prune-packed && + + git cat-file -p $obj1 && + git cat-file -p $obj2 && + git cat-file -p $obj3 && + + # make an unreachable annotated tag object to ensure we rescue objects + # which are reachable from non-pruned unreachable objects + obj2_tag="$(git mktag <<-EOF + object $obj2 + type blob + tag obj2-tag + tagger T A Gger <tagger@example.com> 1234567890 -0000 + EOF + )" && + + obj2_tag_pack="$(echo $obj2_tag | git pack-objects .git/objects/pack/pack)" && + git prune-packed && + + write_script precious-objects <<-EOF && + echo $obj2_tag + EOF + git config gc.recentObjectsHook ./precious-objects && + + test-tool chmtime =-86400 .git/objects/pack/pack-$pack2.pack && + test-tool chmtime =-86400 .git/objects/pack/pack-$pack3.pack && + test-tool chmtime =-86400 .git/objects/pack/pack-$obj2_tag_pack.pack && + git repack -A -d --unpack-unreachable=1.hour.ago && + + git cat-file -p $obj1 && + git cat-file -p $obj2 && + git cat-file -p $obj2_tag && + test_must_fail git cat-file -p $obj3 +' + test_expect_success 'keep packed objects found only in index' ' echo my-unique-content >file && git add file && diff --git a/t/t7703-repack-geometric.sh b/t/t7703-repack-geometric.sh index 8821fbd2dd..9fc1626fbf 100755 --- a/t/t7703-repack-geometric.sh +++ b/t/t7703-repack-geometric.sh @@ -10,6 +10,12 @@ objdir=.git/objects packdir=$objdir/pack midx=$objdir/pack/multi-pack-index +packed_objects () { + git show-index <"$1" >tmp-object-list && + cut -d' ' -f2 tmp-object-list | sort && + rm tmp-object-list + } + test_expect_success '--geometric with no packs' ' git init geometric && test_when_finished "rm -fr geometric" && @@ -17,7 +23,7 @@ test_expect_success '--geometric with no packs' ' cd geometric && git repack --write-midx --geometric 2 >out && - test_i18ngrep "Nothing new to pack" out + test_grep "Nothing new to pack" out ) ' @@ -32,7 +38,7 @@ test_expect_success '--geometric with one pack' ' git repack --geometric 2 >out && - test_i18ngrep "Nothing new to pack" out + test_grep "Nothing new to pack" out ) ' @@ -281,4 +287,162 @@ test_expect_success '--geometric with pack.packSizeLimit' ' ) ' +test_expect_success '--geometric --write-midx with packfiles in main and alternate ODB' ' + test_when_finished "rm -fr shared member" && + + # Create a shared repository that will serve as the alternate object + # database for the member linked to it. It has got some objects on its + # own that are packed into a single packfile. + git init shared && + test_commit -C shared common-object && + git -C shared repack -ad && + + # We create member so that its alternates file points to the shared + # repository. We then create a commit in it so that git-repack(1) has + # something to repack. + # of the shared object database. + git clone --shared shared member && + test_commit -C member unique-object && + git -C member repack --geometric=2 --write-midx 2>err && + test_must_be_empty err && + + # We should see that a new packfile was generated. + find shared/.git/objects/pack -type f -name "*.pack" >packs && + test_line_count = 1 packs && + + # We should also see a multi-pack-index. This multi-pack-index should + # never refer to any packfiles in the alternate object database. + test_path_is_file member/.git/objects/pack/multi-pack-index && + test-tool read-midx member/.git/objects >packs.midx && + grep "^pack-.*\.idx$" packs.midx | sort >actual && + basename member/.git/objects/pack/pack-*.idx >expect && + test_cmp expect actual +' + +test_expect_success '--geometric --with-midx with no local objects' ' + test_when_finished "rm -fr shared member" && + + # Create a repository with a single packfile that acts as alternate + # object database. + git init shared && + test_commit -C shared "shared-objects" && + git -C shared repack -ad && + + # Create a second repository linked to the first one and perform a + # geometric repack on it. + git clone --shared shared member && + git -C member repack --geometric 2 --write-midx 2>err && + test_must_be_empty err && + + # Assert that we wrote neither a new packfile nor a multi-pack-index. + # We should not have a packfile because the single packfile in the + # alternate object database does not invalidate the geometric sequence. + # And we should not have a multi-pack-index because these only index + # local packfiles, and there are none. + test_dir_is_empty member/$packdir +' + +test_expect_success '--geometric with same pack in main and alternate ODB' ' + test_when_finished "rm -fr shared member" && + + # Create a repository with a single packfile that acts as alternate + # object database. + git init shared && + test_commit -C shared "shared-objects" && + git -C shared repack -ad && + + # We create the member repository as an exact copy so that it has the + # same packfile. + cp -r shared member && + test-tool path-utils real_path shared/.git/objects >member/.git/objects/info/alternates && + find shared/.git/objects -type f >expected-files && + + # Verify that we can repack objects as expected without observing any + # error. Having the same packfile in both ODBs used to cause an error + # in git-pack-objects(1). + git -C member repack --geometric 2 2>err && + test_must_be_empty err && + # Nothing should have changed. + find shared/.git/objects -type f >actual-files && + test_cmp expected-files actual-files +' + +test_expect_success '--geometric -l with non-intact geometric sequence across ODBs' ' + test_when_finished "rm -fr shared member" && + + git init shared && + test_commit_bulk -C shared --start=1 1 && + + git clone --shared shared member && + test_commit_bulk -C member --start=2 1 && + + # Verify that our assumptions actually hold: both generated packfiles + # should have three objects and should be non-equal. + packed_objects shared/.git/objects/pack/pack-*.idx >shared-objects && + packed_objects member/.git/objects/pack/pack-*.idx >member-objects && + test_line_count = 3 shared-objects && + test_line_count = 3 member-objects && + ! test_cmp shared-objects member-objects && + + # Perform the geometric repack. With `-l`, we should only see the local + # packfile and thus arrive at the conclusion that the geometric + # sequence is intact. We thus expect no changes. + # + # Note that we are tweaking mtimes of the packfiles so that we can + # verify they did not change. This is done in order to detect the case + # where we do repack objects, but the resulting packfile is the same. + test-tool chmtime --verbose =0 member/.git/objects/pack/* >expected-member-packs && + git -C member repack --geometric=2 -l -d && + test-tool chmtime --verbose member/.git/objects/pack/* >actual-member-packs && + test_cmp expected-member-packs actual-member-packs && + + { + packed_objects shared/.git/objects/pack/pack-*.idx && + packed_objects member/.git/objects/pack/pack-*.idx + } | sort >expected-objects && + + # On the other hand, when doing a non-local geometric repack we should + # see both packfiles and thus repack them. We expect that the shared + # object database was not changed. + test-tool chmtime --verbose =0 shared/.git/objects/pack/* >expected-shared-packs && + git -C member repack --geometric=2 -d && + test-tool chmtime --verbose shared/.git/objects/pack/* >actual-shared-packs && + test_cmp expected-shared-packs actual-shared-packs && + + # Furthermore, we expect that the member repository now has a single + # packfile that contains the combined shared and non-shared objects. + ls member/.git/objects/pack/pack-*.idx >actual && + test_line_count = 1 actual && + packed_objects member/.git/objects/pack/pack-*.idx >actual-objects && + test_line_count = 6 actual-objects && + test_cmp expected-objects actual-objects +' + +test_expect_success '--geometric -l disables writing bitmaps with non-local packfiles' ' + test_when_finished "rm -fr shared member" && + + git init shared && + test_commit_bulk -C shared --start=1 1 && + + git clone --shared shared member && + test_commit_bulk -C member --start=2 1 && + + # When performing a geometric repack with `-l` while connected to an + # alternate object database that has a packfile we do not have full + # coverage of objects. As a result, we expect that writing the bitmap + # will be disabled. + git -C member repack -l --geometric=2 --write-midx --write-bitmap-index 2>err && + cat >expect <<-EOF && + warning: disabling bitmap writing, as some objects are not being packed + EOF + test_cmp expect err && + test_path_is_missing member/.git/objects/pack/multi-pack-index-*.bitmap && + + # On the other hand, when we repack without `-l`, we should see that + # the bitmap gets created. + git -C member repack --geometric=2 --write-midx --write-bitmap-index 2>err && + test_must_be_empty err && + test_path_is_file member/.git/objects/pack/multi-pack-index-*.bitmap +' + test_done diff --git a/t/t7704-repack-cruft.sh b/t/t7704-repack-cruft.sh new file mode 100755 index 0000000000..be3735dff0 --- /dev/null +++ b/t/t7704-repack-cruft.sh @@ -0,0 +1,414 @@ +#!/bin/sh + +test_description='git repack works correctly' + +. ./test-lib.sh + +objdir=.git/objects +packdir=$objdir/pack + +test_expect_success '--expire-to stores pruned objects (now)' ' + git init expire-to-now && + ( + cd expire-to-now && + + git branch -M main && + + test_commit base && + + git checkout -b cruft && + test_commit --no-tag cruft && + + git rev-list --objects --no-object-names main..cruft >moved.raw && + sort moved.raw >moved.want && + + git rev-list --all --objects --no-object-names >expect.raw && + sort expect.raw >expect && + + git checkout main && + git branch -D cruft && + git reflog expire --all --expire=all && + + git init --bare expired.git && + git repack -d \ + --cruft --cruft-expiration="now" \ + --expire-to="expired.git/objects/pack/pack" && + + expired="$(ls expired.git/objects/pack/pack-*.idx)" && + test_path_is_file "${expired%.idx}.mtimes" && + + # Since the `--cruft-expiration` is "now", the effective + # behavior is to move _all_ unreachable objects out to + # the location in `--expire-to`. + git show-index <$expired >expired.raw && + cut -d" " -f2 expired.raw | sort >expired.objects && + git rev-list --all --objects --no-object-names \ + >remaining.objects && + + # ...in other words, the combined contents of this + # repository and expired.git should be the same as the + # set of objects we started with. + cat expired.objects remaining.objects | sort >actual && + test_cmp expect actual && + + # The "moved" objects (i.e., those in expired.git) + # should be the same as the cruft objects which were + # expired in the previous step. + test_cmp moved.want expired.objects + ) +' + +test_expect_success '--expire-to stores pruned objects (5.minutes.ago)' ' + git init expire-to-5.minutes.ago && + ( + cd expire-to-5.minutes.ago && + + git branch -M main && + + test_commit base && + + # Create two classes of unreachable objects, one which + # is older than 5 minutes (stale), and another which is + # newer (recent). + for kind in stale recent + do + git checkout -b $kind main && + test_commit --no-tag $kind || return 1 + done && + + git rev-list --objects --no-object-names main..stale >in && + stale="$(git pack-objects $objdir/pack/pack <in)" && + mtime="$(test-tool chmtime --get =-600 $objdir/pack/pack-$stale.pack)" && + + # expect holds the set of objects we expect to find in + # this repository after repacking + git rev-list --objects --no-object-names recent >expect.raw && + sort expect.raw >expect && + + # moved.want holds the set of objects we expect to find + # in expired.git + git rev-list --objects --no-object-names main..stale >out && + sort out >moved.want && + + git checkout main && + git branch -D stale recent && + git reflog expire --all --expire=all && + git prune-packed && + + git init --bare expired.git && + git repack -d \ + --cruft --cruft-expiration=5.minutes.ago \ + --expire-to="expired.git/objects/pack/pack" && + + # Some of the remaining objects in this repository are + # unreachable, so use `cat-file --batch-all-objects` + # instead of `rev-list` to get their names + git cat-file --batch-all-objects --batch-check="%(objectname)" \ + >remaining.objects && + sort remaining.objects >actual && + test_cmp expect actual && + + ( + cd expired.git && + + expired="$(ls objects/pack/pack-*.mtimes)" && + test-tool pack-mtimes $(basename $expired) >out && + cut -d" " -f1 out | sort >../moved.got && + + # Ensure that there are as many objects with the + # expected mtime as were moved to expired.git. + # + # In other words, ensure that the recorded + # mtimes of any moved objects was written + # correctly. + grep " $mtime$" out >matching && + test_line_count = $(wc -l <../moved.want) matching + ) && + test_cmp moved.want moved.got + ) +' + +generate_random_blob() { + test-tool genrandom "$@" >blob && + git hash-object -w -t blob blob && + rm blob +} + +pack_random_blob () { + generate_random_blob "$@" && + git repack -d -q >/dev/null +} + +generate_cruft_pack () { + pack_random_blob "$@" >/dev/null && + + ls $packdir/pack-*.pack | xargs -n 1 basename >in && + pack="$(git pack-objects --cruft $packdir/pack <in)" && + git prune-packed && + + echo "$packdir/pack-$pack.mtimes" +} + +test_expect_success '--max-cruft-size creates new packs when above threshold' ' + git init max-cruft-size-large && + ( + cd max-cruft-size-large && + test_commit base && + + foo="$(pack_random_blob foo $((1*1024*1024)))" && + git repack --cruft -d && + cruft_foo="$(ls $packdir/pack-*.mtimes)" && + + bar="$(pack_random_blob bar $((1*1024*1024)))" && + git repack --cruft -d --max-cruft-size=1M && + cruft_bar="$(ls $packdir/pack-*.mtimes | grep -v $cruft_foo)" && + + test-tool pack-mtimes $(basename "$cruft_foo") >foo.objects && + test-tool pack-mtimes $(basename "$cruft_bar") >bar.objects && + + grep "^$foo" foo.objects && + test_line_count = 1 foo.objects && + grep "^$bar" bar.objects && + test_line_count = 1 bar.objects + ) +' + +test_expect_success '--max-cruft-size combines existing packs when below threshold' ' + git init max-cruft-size-small && + ( + cd max-cruft-size-small && + test_commit base && + + foo="$(pack_random_blob foo $((1*1024*1024)))" && + git repack --cruft -d && + + bar="$(pack_random_blob bar $((1*1024*1024)))" && + git repack --cruft -d --max-cruft-size=10M && + + cruft=$(ls $packdir/pack-*.mtimes) && + test-tool pack-mtimes $(basename "$cruft") >cruft.objects && + + grep "^$foo" cruft.objects && + grep "^$bar" cruft.objects && + test_line_count = 2 cruft.objects + ) +' + +test_expect_success '--max-cruft-size combines smaller packs first' ' + git init max-cruft-size-consume-small && + ( + cd max-cruft-size-consume-small && + + test_commit base && + git repack -ad && + + cruft_foo="$(generate_cruft_pack foo 524288)" && # 0.5 MiB + cruft_bar="$(generate_cruft_pack bar 524288)" && # 0.5 MiB + cruft_baz="$(generate_cruft_pack baz 1048576)" && # 1.0 MiB + cruft_quux="$(generate_cruft_pack quux 1572864)" && # 1.5 MiB + + test-tool pack-mtimes "$(basename $cruft_foo)" >expect.raw && + test-tool pack-mtimes "$(basename $cruft_bar)" >>expect.raw && + sort expect.raw >expect.objects && + + # repacking with `--max-cruft-size=2M` should combine + # both 0.5 MiB packs together, instead of, say, one of + # the 0.5 MiB packs with the 1.0 MiB pack + ls $packdir/pack-*.mtimes | sort >cruft.before && + git repack -d --cruft --max-cruft-size=2M && + ls $packdir/pack-*.mtimes | sort >cruft.after && + + comm -13 cruft.before cruft.after >cruft.new && + comm -23 cruft.before cruft.after >cruft.removed && + + test_line_count = 1 cruft.new && + test_line_count = 2 cruft.removed && + + # the two smaller packs should be rolled up first + printf "%s\n" $cruft_foo $cruft_bar | sort >expect.removed && + test_cmp expect.removed cruft.removed && + + # ...and contain the set of objects rolled up + test-tool pack-mtimes "$(basename $(cat cruft.new))" >actual.raw && + sort actual.raw >actual.objects && + + test_cmp expect.objects actual.objects + ) +' + +test_expect_success 'setup --max-cruft-size with freshened objects' ' + git init max-cruft-size-freshen && + ( + cd max-cruft-size-freshen && + + test_commit base && + git repack -ad && + + foo="$(generate_random_blob foo 64)" && + test-tool chmtime --get -10000 \ + "$objdir/$(test_oid_to_path "$foo")" >foo.mtime && + + git repack --cruft -d && + + cruft="$(ls $packdir/pack-*.mtimes)" && + test-tool pack-mtimes "$(basename $cruft)" >actual && + echo "$foo $(cat foo.mtime)" >expect && + test_cmp expect actual + ) +' + +test_expect_success '--max-cruft-size with freshened objects (loose)' ' + ( + cd max-cruft-size-freshen && + + # regenerate the object, setting its mtime to be more recent + foo="$(generate_random_blob foo 64)" && + test-tool chmtime --get -100 \ + "$objdir/$(test_oid_to_path "$foo")" >foo.mtime && + + git repack --cruft -d && + + cruft="$(ls $packdir/pack-*.mtimes)" && + test-tool pack-mtimes "$(basename $cruft)" >actual && + echo "$foo $(cat foo.mtime)" >expect && + test_cmp expect actual + ) +' + +test_expect_success '--max-cruft-size with freshened objects (packed)' ' + ( + cd max-cruft-size-freshen && + + # regenerate the object and store it in a packfile, + # setting its mtime to be more recent + # + # store it alongside another cruft object so that we + # do not create an identical copy of the existing + # cruft pack (which contains $foo). + foo="$(generate_random_blob foo 64)" && + bar="$(generate_random_blob bar 64)" && + foo_pack="$(printf "%s\n" $foo $bar | git pack-objects $packdir/pack)" && + git prune-packed && + + test-tool chmtime --get -10 \ + "$packdir/pack-$foo_pack.pack" >foo.mtime && + + git repack --cruft -d && + + cruft="$(ls $packdir/pack-*.mtimes)" && + test-tool pack-mtimes "$(basename $cruft)" >actual && + echo "$foo $(cat foo.mtime)" >expect.raw && + echo "$bar $(cat foo.mtime)" >>expect.raw && + sort expect.raw >expect && + test_cmp expect actual + ) +' + +test_expect_success '--max-cruft-size with pruning' ' + git init max-cruft-size-prune && + ( + cd max-cruft-size-prune && + + test_commit base && + foo="$(generate_random_blob foo $((1024*1024)))" && + bar="$(generate_random_blob bar $((1024*1024)))" && + baz="$(generate_random_blob baz $((1024*1024)))" && + + test-tool chmtime -10000 "$objdir/$(test_oid_to_path "$foo")" && + + git repack -d --cruft --max-cruft-size=1M && + + # backdate the mtimes of all cruft packs to validate + # that they were rewritten as a result of pruning + ls $packdir/pack-*.mtimes | sort >cruft.before && + for cruft in $(cat cruft.before) + do + mtime="$(test-tool chmtime --get -10000 "$cruft")" && + echo $cruft $mtime >>mtimes || return 1 + done && + + # repack (and prune) with a --max-cruft-size to ensure + # that we appropriately split the resulting set of packs + git repack -d --cruft --max-cruft-size=1M \ + --cruft-expiration=10.seconds.ago && + ls $packdir/pack-*.mtimes | sort >cruft.after && + + for cruft in $(cat cruft.after) + do + old_mtime="$(grep $cruft mtimes | cut -d" " -f2)" && + new_mtime="$(test-tool chmtime --get $cruft)" && + test $old_mtime -lt $new_mtime || return 1 + done && + + test_line_count = 3 cruft.before && + test_line_count = 2 cruft.after && + test_must_fail git cat-file -e $foo && + git cat-file -e $bar && + git cat-file -e $baz + ) +' + +test_expect_success '--max-cruft-size ignores non-local packs' ' + repo="max-cruft-size-non-local" && + git init $repo && + ( + cd $repo && + test_commit base && + generate_random_blob foo 64 && + git repack --cruft -d + ) && + + git clone --reference=$repo $repo $repo-alt && + ( + cd $repo-alt && + + test_commit other && + generate_random_blob bar 64 && + + # ensure that we do not attempt to pick up packs from + # the non-alternated repository, which would result in a + # crash + git repack --cruft --max-cruft-size=1M -d + ) +' + +test_expect_success 'reachable packs are preferred over cruft ones' ' + repo="cruft-preferred-packs" && + git init "$repo" && + ( + cd "$repo" && + + # This test needs to exercise careful control over when a MIDX + # is and is not written. Unset the corresponding TEST variable + # accordingly. + sane_unset GIT_TEST_MULTI_PACK_INDEX && + + test_commit base && + test_commit --no-tag cruft && + + non_cruft="$(echo base | git pack-objects --revs $packdir/pack)" && + # Write a cruft pack which both (a) sorts ahead of the non-cruft + # pack in lexical order, and (b) has an older mtime to appease + # the MIDX preferred pack selection routine. + cruft="$(echo pack-$non_cruft.pack | git pack-objects --cruft $packdir/pack-A)" && + test-tool chmtime -1000 $packdir/pack-A-$cruft.pack && + + test_commit other && + git repack -d && + + git repack --geometric 2 -d --write-midx --write-bitmap-index && + + # After repacking, there are two packs left: one reachable one + # (which is the result of combining both of the existing two + # non-cruft packs), and one cruft pack. + find .git/objects/pack -type f -name "*.pack" >packs && + test_line_count = 2 packs && + + # Make sure that the pack we just wrote is marked as preferred, + # not the cruft one. + pack="$(test-tool read-midx --preferred-pack $objdir)" && + test_path_is_missing "$packdir/$(basename "$pack" ".idx").mtimes" + ) +' + +test_done diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh index 24297e26ca..6a36be1e63 100755 --- a/t/t7800-difftool.sh +++ b/t/t7800-difftool.sh @@ -28,14 +28,14 @@ prompt_given () test_expect_success 'basic usage requires no repo' ' test_expect_code 129 git difftool -h >output && - test_i18ngrep ^usage: output && + test_grep ^usage: output && # create a ceiling directory to prevent Git from finding a repo mkdir -p not/repo && test_when_finished rm -r not && test_expect_code 129 \ env GIT_CEILING_DIRECTORIES="$(pwd)/not" \ git -C not/repo difftool -h >output && - test_i18ngrep ^usage: output + test_grep ^usage: output ' # Create a file on main and change it on branch @@ -155,6 +155,58 @@ test_expect_success 'difftool honors --gui' ' test_cmp expect actual ' +test_expect_success 'difftool with guiDefault auto selects gui tool when there is DISPLAY' ' + difftool_test_setup && + test_config merge.tool bogus-tool && + test_config diff.tool bogus-tool && + test_config diff.guitool test-tool && + test_config difftool.guiDefault auto && + DISPLAY=SOMETHING && export DISPLAY && + + echo branch >expect && + git difftool --no-prompt branch >actual && + test_cmp expect actual +' +test_expect_success 'difftool with guiDefault auto selects regular tool when no DISPLAY' ' + difftool_test_setup && + test_config diff.guitool bogus-tool && + test_config diff.tool test-tool && + test_config difftool.guiDefault Auto && + DISPLAY= && export DISPLAY && + + echo branch >expect && + git difftool --no-prompt branch >actual && + test_cmp expect actual +' + +test_expect_success 'difftool with guiDefault true selects gui tool' ' + difftool_test_setup && + test_config diff.tool bogus-tool && + test_config diff.guitool test-tool && + test_config difftool.guiDefault true && + + DISPLAY= && export DISPLAY && + echo branch >expect && + git difftool --no-prompt branch >actual && + test_cmp expect actual && + + DISPLAY=Something && export DISPLAY && + echo branch >expect && + git difftool --no-prompt branch >actual && + test_cmp expect actual +' + +test_expect_success 'difftool --no-gui trumps config guiDefault' ' + difftool_test_setup && + test_config diff.guitool bogus-tool && + test_config diff.tool test-tool && + test_config difftool.guiDefault true && + + echo branch >expect && + git difftool --no-prompt --no-gui branch >actual && + test_cmp expect actual +' + test_expect_success 'difftool --gui last setting wins' ' difftool_test_setup && : >expect && diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index 8eded6ab27..875dcfd98f 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -808,6 +808,19 @@ test_expect_success 'grep -f, ignore empty lines, read patterns from stdin' ' test_cmp expected actual ' +test_expect_success 'grep -f, use cwd relative file' ' + test_when_finished "git rm -f sub/dir/file" && + mkdir -p sub/dir && + echo hit >sub/dir/file && + git add sub/dir/file && + echo hit >sub/dir/pattern && + echo miss >pattern && + ( + cd sub/dir && git grep -f pattern file + ) && + git -C sub/dir grep -f pattern file +' + cat >expected <<EOF y:y yy -- @@ -1001,7 +1014,9 @@ test_expect_success 'log --committer does not search in timestamp' ' test_expect_success 'grep with CE_VALID file' ' git update-index --assume-unchanged t/t && rm t/t && - test "$(git grep test)" = "t/t:test" && + echo "t/t:test" >expect && + git grep test >actual && + test_cmp expect actual && git update-index --no-assume-unchanged t/t && git checkout t/t ' @@ -1232,6 +1247,33 @@ test_expect_success 'outside of git repository with fallbackToNoIndex' ' ) ' +test_expect_success 'no repository with path outside $cwd' ' + test_when_finished rm -fr non && + rm -fr non && + mkdir -p non/git/sub non/tig && + ( + GIT_CEILING_DIRECTORIES="$(pwd)/non" && + export GIT_CEILING_DIRECTORIES && + cd non/git && + test_expect_code 128 git grep --no-index search .. 2>error && + grep "is outside the directory tree" error + ) && + ( + GIT_CEILING_DIRECTORIES="$(pwd)/non" && + export GIT_CEILING_DIRECTORIES && + cd non/git && + test_expect_code 128 git grep --no-index search ../tig 2>error && + grep "is outside the directory tree" error + ) && + ( + GIT_CEILING_DIRECTORIES="$(pwd)/non" && + export GIT_CEILING_DIRECTORIES && + cd non/git && + test_expect_code 128 git grep --no-index search ../non 2>error && + grep "no such path in the working tree" error + ) +' + test_expect_success 'inside git repository but with --no-index' ' rm -fr is && mkdir -p is/git/sub && @@ -1384,7 +1426,7 @@ test_expect_success 'grep --no-index pattern -- path' ' test_expect_success 'grep --no-index complains of revs' ' test_must_fail git grep --no-index o main -- 2>err && - test_i18ngrep "cannot be used with revs" err + test_grep "cannot be used with revs" err ' test_expect_success 'grep --no-index prefers paths to revs' ' @@ -1397,7 +1439,7 @@ test_expect_success 'grep --no-index prefers paths to revs' ' test_expect_success 'grep --no-index does not "diagnose" revs' ' test_must_fail git grep --no-index o :1:hello.c 2>err && - test_i18ngrep ! -i "did you mean" err + test_grep ! -i "did you mean" err ' cat >expected <<EOF diff --git a/t/t7811-grep-open.sh b/t/t7811-grep-open.sh index 1dd07141a7..fe38d88a1a 100755 --- a/t/t7811-grep-open.sh +++ b/t/t7811-grep-open.sh @@ -63,7 +63,7 @@ test_expect_success SIMPLEPAGER 'git grep -O' ' test_expect_success 'git grep -O --cached' ' test_must_fail git grep --cached -O GREP_PATTERN >out 2>msg && - test_i18ngrep open-files-in-pager msg + test_grep open-files-in-pager msg ' test_expect_success 'git grep -O --no-index' ' diff --git a/t/t7814-grep-recurse-submodules.sh b/t/t7814-grep-recurse-submodules.sh index 8143817b19..167fe66150 100755 --- a/t/t7814-grep-recurse-submodules.sh +++ b/t/t7814-grep-recurse-submodules.sh @@ -348,7 +348,7 @@ test_incompatible_with_recurse_submodules () { test_expect_success "--recurse-submodules and $1 are incompatible" " test_must_fail git grep -e. --recurse-submodules $1 2>actual && - test_i18ngrep 'not supported with --recurse-submodules' actual + test_grep 'not supported with --recurse-submodules' actual " } @@ -594,4 +594,44 @@ test_expect_success 'grep partially-cloned submodule' ' ) ' +test_expect_success 'check scope of core.useReplaceRefs' ' + git init base && + git init base/sub && + + echo A >base/a && + echo B >base/b && + echo C >base/sub/c && + echo D >base/sub/d && + + git -C base/sub add c d && + git -C base/sub commit -m "Add files" && + + git -C base submodule add ./sub && + git -C base add a b sub && + git -C base commit -m "Add files and submodule" && + + A=$(git -C base rev-parse HEAD:a) && + B=$(git -C base rev-parse HEAD:b) && + C=$(git -C base/sub rev-parse HEAD:c) && + D=$(git -C base/sub rev-parse HEAD:d) && + + git -C base replace $A $B && + git -C base/sub replace $C $D && + + test_must_fail git -C base grep --cached --recurse-submodules A && + test_must_fail git -C base grep --cached --recurse-submodules C && + + git -C base config core.useReplaceRefs false && + git -C base grep --recurse-submodules A && + test_must_fail git -C base grep --cached --recurse-submodules C && + + git -C base/sub config core.useReplaceRefs false && + git -C base grep --cached --recurse-submodules A && + git -C base grep --cached --recurse-submodules C && + + git -C base config --unset core.useReplaceRefs && + test_must_fail git -C base grep --cached --recurse-submodules A && + git -C base grep --cached --recurse-submodules C +' + test_done diff --git a/t/t7816-grep-binary-pattern.sh b/t/t7816-grep-binary-pattern.sh index fdb2355649..4353be5adb 100755 --- a/t/t7816-grep-binary-pattern.sh +++ b/t/t7816-grep-binary-pattern.sh @@ -26,7 +26,7 @@ nul_match_internal () { >stderr && printf '$pattern' | q_to_nul >f && test_must_fail env LC_ALL=\"$lc_all\" git grep $extra_flags -f f $flags a 2>stderr && - test_i18ngrep ! 'This is only supported with -P under PCRE v2' stderr + test_grep ! 'This is only supported with -P under PCRE v2' stderr " elif test "$matches" = P then @@ -34,7 +34,7 @@ nul_match_internal () { >stderr && printf '$pattern' | q_to_nul >f && test_must_fail env LC_ALL=\"$lc_all\" git grep -f f $flags a 2>stderr && - test_i18ngrep 'This is only supported with -P under PCRE v2' stderr + test_grep 'This is only supported with -P under PCRE v2' stderr " else test_expect_success "PANIC: Test framework error. Unknown matches value $matches" 'false' diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh index 823331e44a..00d29871e6 100755 --- a/t/t7900-maintenance.sh +++ b/t/t7900-maintenance.sh @@ -33,13 +33,13 @@ test_systemd_analyze_verify () { test_expect_success 'help text' ' test_expect_code 129 git maintenance -h >actual && - test_i18ngrep "usage: git maintenance <subcommand>" actual && + test_grep "usage: git maintenance <subcommand>" actual && test_expect_code 129 git maintenance barf 2>err && - test_i18ngrep "unknown subcommand: \`barf'\''" err && - test_i18ngrep "usage: git maintenance" err && + test_grep "unknown subcommand: \`barf'\''" err && + test_grep "usage: git maintenance" err && test_expect_code 129 git maintenance 2>err && - test_i18ngrep "error: need a subcommand" err && - test_i18ngrep "usage: git maintenance" err + test_grep "error: need a subcommand" err && + test_grep "usage: git maintenance" err ' test_expect_success 'run [--auto|--quiet]' ' @@ -131,12 +131,12 @@ test_expect_success 'commit-graph auto condition' ' test_expect_success 'run --task=bogus' ' test_must_fail git maintenance run --task=bogus 2>err && - test_i18ngrep "is not a valid task" err + test_grep "is not a valid task" err ' test_expect_success 'run --task duplicate' ' test_must_fail git maintenance run --task=gc --task=gc 2>err && - test_i18ngrep "cannot be selected multiple times" err + test_grep "cannot be selected multiple times" err ' test_expect_success 'run --task=prefetch with no remotes' ' @@ -157,7 +157,8 @@ test_expect_success 'prefetch multiple remotes' ' fetchargs="--prefetch --prune --no-tags --no-write-fetch-head --recurse-submodules=no --quiet" && test_subcommand git fetch remote1 $fetchargs <run-prefetch.txt && test_subcommand git fetch remote2 $fetchargs <run-prefetch.txt && - test_path_is_missing .git/refs/remotes && + git for-each-ref refs/remotes >actual && + test_must_be_empty actual && git log prefetch/remotes/remote1/one && git log prefetch/remotes/remote2/two && git fetch --all && @@ -377,12 +378,12 @@ test_expect_success 'pack-refs task' ' test_expect_success '--auto and --schedule incompatible' ' test_must_fail git maintenance run --auto --schedule=daily 2>err && - test_i18ngrep "at most one" err + test_grep "at most one" err ' test_expect_success 'invalid --schedule value' ' test_must_fail git maintenance run --schedule=annually 2>err && - test_i18ngrep "unrecognized --schedule" err + test_grep "unrecognized --schedule" err ' test_expect_success '--schedule inheritance weekly -> daily -> hourly' ' @@ -524,6 +525,44 @@ test_expect_success 'register and unregister' ' git maintenance unregister --config-file ./other --force ' +test_expect_success 'register with no value for maintenance.repo' ' + cp .git/config .git/config.orig && + test_when_finished mv .git/config.orig .git/config && + + cat >>.git/config <<-\EOF && + [maintenance] + repo + EOF + cat >expect <<-\EOF && + error: missing value for '\''maintenance.repo'\'' + EOF + git maintenance register 2>actual && + test_cmp expect actual && + git config maintenance.repo +' + +test_expect_success 'unregister with no value for maintenance.repo' ' + cp .git/config .git/config.orig && + test_when_finished mv .git/config.orig .git/config && + + cat >>.git/config <<-\EOF && + [maintenance] + repo + EOF + cat >expect <<-\EOF && + error: missing value for '\''maintenance.repo'\'' + EOF + test_expect_code 128 git maintenance unregister 2>actual.raw && + grep ^error actual.raw >actual && + test_cmp expect actual && + git config maintenance.repo && + + git maintenance unregister --force 2>actual.raw && + grep ^error actual.raw >actual && + test_cmp expect actual && + git config maintenance.repo +' + test_expect_success !MINGW 'register and unregister with regex metacharacters' ' META="a+b*c" && git init "$META" && @@ -538,15 +577,15 @@ test_expect_success !MINGW 'register and unregister with regex metacharacters' ' test_expect_success 'start --scheduler=<scheduler>' ' test_expect_code 129 git maintenance start --scheduler=foo 2>err && - test_i18ngrep "unrecognized --scheduler argument" err && + test_grep "unrecognized --scheduler argument" err && test_expect_code 129 git maintenance start --no-scheduler 2>err && - test_i18ngrep "unknown option" err && + test_grep "unknown option" err && test_expect_code 128 \ env GIT_TEST_MAINT_SCHEDULER="launchctl:true,schtasks:true" \ git maintenance start --scheduler=crontab 2>err && - test_i18ngrep "fatal: crontab scheduler is not available" err + test_grep "fatal: crontab scheduler is not available" err ' test_expect_success 'start from empty cron table' ' @@ -706,7 +745,15 @@ test_expect_success 'start and stop Linux/systemd maintenance' ' # start registers the repo git config --get --global --fixed-value maintenance.repo "$(pwd)" && - test_systemd_analyze_verify "systemd/user/git-maintenance@.service" && + for schedule in hourly daily weekly + do + test_path_is_file "systemd/user/git-maintenance@$schedule.timer" || return 1 + done && + test_path_is_file "systemd/user/git-maintenance@.service" && + + test_systemd_analyze_verify "systemd/user/git-maintenance@hourly.service" && + test_systemd_analyze_verify "systemd/user/git-maintenance@daily.service" && + test_systemd_analyze_verify "systemd/user/git-maintenance@weekly.service" && printf -- "--user enable --now git-maintenance@%s.timer\n" hourly daily weekly >expect && test_cmp expect args && @@ -717,7 +764,10 @@ test_expect_success 'start and stop Linux/systemd maintenance' ' # stop does not unregister the repo git config --get --global --fixed-value maintenance.repo "$(pwd)" && - test_path_is_missing "systemd/user/git-maintenance@.timer" && + for schedule in hourly daily weekly + do + test_path_is_missing "systemd/user/git-maintenance@$schedule.timer" || return 1 + done && test_path_is_missing "systemd/user/git-maintenance@.service" && printf -- "--user disable --now git-maintenance@%s.timer\n" hourly daily weekly >expect && @@ -800,4 +850,17 @@ test_expect_success 'register and unregister bare repo' ' ) ' +test_expect_success 'failed schedule prevents config change' ' + git init --bare failcase && + + for scheduler in crontab launchctl schtasks systemctl + do + GIT_TEST_MAINT_SCHEDULER="$scheduler:false" && + export GIT_TEST_MAINT_SCHEDULER && + test_must_fail \ + git -C failcase maintenance start && + test_must_fail git -C failcase config maintenance.auto || return 1 + done +' + test_done diff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh index 8bcd39e81b..731265541a 100755 --- a/t/t8003-blame-corner-cases.sh +++ b/t/t8003-blame-corner-cases.sh @@ -207,7 +207,7 @@ EOF test_expect_success 'blame -L with invalid start' ' test_must_fail git blame -L5 tres 2>errors && - test_i18ngrep "has only 2 lines" errors + test_grep "has only 2 lines" errors ' test_expect_success 'blame -L with invalid end' ' diff --git a/t/t8013-blame-ignore-revs.sh b/t/t8013-blame-ignore-revs.sh index b18633dee1..9a03b0f361 100755 --- a/t/t8013-blame-ignore-revs.sh +++ b/t/t8013-blame-ignore-revs.sh @@ -129,14 +129,14 @@ test_expect_success override_ignore_revs_file ' ' test_expect_success bad_files_and_revs ' test_must_fail git blame file --ignore-rev NOREV 2>err && - test_i18ngrep "cannot find revision NOREV to ignore" err && + test_grep "cannot find revision NOREV to ignore" err && test_must_fail git blame file --ignore-revs-file NOFILE 2>err && - test_i18ngrep "could not open.*: NOFILE" err && + test_grep "could not open.*: NOFILE" err && echo NOREV >ignore_norev && test_must_fail git blame file --ignore-revs-file ignore_norev 2>err && - test_i18ngrep "invalid object name: NOREV" err + test_grep "invalid object name: NOREV" err ' # For ignored revs that have added 'unblamable' lines, mark those lines with a diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index 323952a572..5a771000c9 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -12,7 +12,7 @@ PREREQ="PERL" replace_variable_fields () { sed -e "s/^\(Date:\).*/\1 DATE-STRING/" \ - -e "s/^\(Message-Id:\).*/\1 MESSAGE-ID-STRING/" \ + -e "s/^\(Message-ID:\).*/\1 MESSAGE-ID-STRING/" \ -e "s/^\(X-Mailer:\).*/\1 X-MAILER-STRING/" } @@ -47,7 +47,7 @@ clean_fake_sendmail () { test_expect_success $PREREQ 'Extract patches' ' patches=$(git format-patch -s --cc="One <one@example.com>" --cc=two@example.com -n HEAD^1) && - threaded_patches=$(git format-patch -o threaded -s --in-reply-to="format" HEAD^1) + threaded_patches=$(git format-patch -o threaded --thread=shallow -s --in-reply-to="format" HEAD^1) ' # Test no confirm early to ensure remaining tests will not hang @@ -61,8 +61,8 @@ test_no_confirm () { --smtp-server="$(pwd)/fake.sendmail" \ $@ \ $patches >stdout && - ! grep "Send this email" stdout && - >no_confirm_okay + ! grep "Send this email" stdout && + >no_confirm_okay } # Exit immediately to prevent hang if a no-confirm test fails @@ -225,7 +225,7 @@ Cc: cc@example.com, two@example.com Subject: [PATCH 1/1] Second. Date: DATE-STRING -Message-Id: MESSAGE-ID-STRING +Message-ID: MESSAGE-ID-STRING X-Mailer: X-MAILER-STRING In-Reply-To: <unique-message-id@example.com> References: <unique-message-id@example.com> @@ -337,13 +337,14 @@ test_expect_success $PREREQ 'Show all headers' ' test_expect_success $PREREQ 'Prompting works' ' clean_fake_sendmail && (echo "to@example.com" && - echo "" + echo "my-message-id@example.com" ) | GIT_SEND_EMAIL_NOTTY=1 git send-email \ --smtp-server="$(pwd)/fake.sendmail" \ $patches \ 2>errors && grep "^From: A U Thor <author@example.com>\$" msgtxt1 && - grep "^To: to@example.com\$" msgtxt1 + grep "^To: to@example.com\$" msgtxt1 && + grep "^In-Reply-To: <my-message-id@example.com>" msgtxt1 ' test_expect_success $PREREQ,AUTOIDENT 'implicit ident is allowed' ' @@ -370,17 +371,20 @@ test_expect_success $PREREQ,!AUTOIDENT 'broken implicit ident aborts send-email' --smtp-server="$(pwd)/fake.sendmail" \ --to=to@example.com \ $patches </dev/null 2>errors && - test_i18ngrep "tell me who you are" errors + test_grep "tell me who you are" errors ) ' -test_expect_success $PREREQ 'setup tocmd and cccmd scripts' ' +test_expect_success $PREREQ 'setup cmd scripts' ' write_script tocmd-sed <<-\EOF && sed -n -e "s/^tocmd--//p" "$1" EOF - write_script cccmd-sed <<-\EOF + write_script cccmd-sed <<-\EOF && sed -n -e "s/^cccmd--//p" "$1" EOF + write_script headercmd-sed <<-\EOF + sed -n -e "s/^headercmd--//p" "$1" + EOF ' test_expect_success $PREREQ 'tocmd works' ' @@ -410,6 +414,70 @@ test_expect_success $PREREQ 'cccmd works' ' grep "^ cccmd@example.com" msgtxt1 ' +test_expect_success $PREREQ 'headercmd works' ' + clean_fake_sendmail && + cp $patches headercmd.patch && + echo "headercmd--X-Debbugs-CC: dummy@example.com" >>headercmd.patch && + git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --header-cmd=./headercmd-sed \ + --smtp-server="$(pwd)/fake.sendmail" \ + headercmd.patch \ + && + grep "^X-Debbugs-CC: dummy@example.com" msgtxt1 +' + +test_expect_success $PREREQ '--no-header-cmd works' ' + clean_fake_sendmail && + cp $patches headercmd.patch && + echo "headercmd--X-Debbugs-CC: dummy@example.com" >>headercmd.patch && + git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --header-cmd=./headercmd-sed \ + --no-header-cmd \ + --smtp-server="$(pwd)/fake.sendmail" \ + headercmd.patch \ + && + ! grep "^X-Debbugs-CC: dummy@example.com" msgtxt1 +' + +test_expect_success $PREREQ 'multiline fields are correctly unfolded' ' + clean_fake_sendmail && + cp $patches headercmd.patch && + write_script headercmd-multiline <<-\EOF && + echo "X-Debbugs-CC: someone@example.com +FoldedField: This is a tale + best told using + multiple lines." + EOF + git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --header-cmd=./headercmd-multiline \ + --smtp-server="$(pwd)/fake.sendmail" \ + headercmd.patch && + grep "^FoldedField: This is a tale best told using multiple lines.$" msgtxt1 +' + +# Blank lines in the middle of the output of a command are invalid. +test_expect_success $PREREQ 'malform output reported on blank lines in command output' ' + clean_fake_sendmail && + cp $patches headercmd.patch && + write_script headercmd-malformed-output <<-\EOF && + echo "X-Debbugs-CC: someone@example.com + +SomeOtherField: someone-else@example.com" + EOF + ! git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --header-cmd=./headercmd-malformed-output \ + --smtp-server="$(pwd)/fake.sendmail" \ + headercmd.patch +' + test_expect_success $PREREQ 'reject long lines' ' z8=zzzzzzzz && z64=$z8$z8$z8$z8$z8$z8$z8$z8 && @@ -540,7 +608,7 @@ test_expect_success $PREREQ "--validate respects relative core.hooksPath path" ' test_path_is_file my-hooks.ran && cat >expect <<-EOF && fatal: longline.patch: rejected by sendemail-validate hook - fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch>'"'"' died with exit code 1 + fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch> <header>'"'"' died with exit code 1 warning: no patches were sent EOF test_cmp expect actual @@ -559,12 +627,68 @@ test_expect_success $PREREQ "--validate respects absolute core.hooksPath path" ' test_path_is_file my-hooks.ran && cat >expect <<-EOF && fatal: longline.patch: rejected by sendemail-validate hook - fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch>'"'"' died with exit code 1 + fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch> <header>'"'"' died with exit code 1 warning: no patches were sent EOF test_cmp expect actual ' +test_expect_success $PREREQ "--validate hook supports multiple addresses in arguments" ' + hooks_path="$(pwd)/my-hooks" && + test_config core.hooksPath "$hooks_path" && + test_when_finished "rm my-hooks.ran" && + test_must_fail git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com,abc@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + --validate \ + longline.patch 2>actual && + test_path_is_file my-hooks.ran && + cat >expect <<-EOF && + fatal: longline.patch: rejected by sendemail-validate hook + fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch> <header>'"'"' died with exit code 1 + warning: no patches were sent + EOF + test_cmp expect actual +' + +test_expect_success $PREREQ "--validate hook supports header argument" ' + write_script my-hooks/sendemail-validate <<-\EOF && + if test "$#" -ge 2 + then + grep "X-test-header: v1.0" "$2" + else + echo "No header arg passed" + exit 1 + fi + EOF + test_config core.hooksPath "my-hooks" && + rm -fr outdir && + git format-patch \ + --add-header="X-test-header: v1.0" \ + -n HEAD^1 -o outdir && + git send-email \ + --dry-run \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + --validate \ + outdir/000?-*.patch +' + +test_expect_success $PREREQ 'clear message-id before parsing a new message' ' + clean_fake_sendmail && + echo true | write_script my-hooks/sendemail-validate && + test_config core.hooksPath my-hooks && + git send-email --validate --to=recipient@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + $patches $threaded_patches && + id0=$(grep "^Message-ID: " $threaded_patches) && + id1=$(grep "^Message-ID: " msgtxt1) && + id2=$(grep "^Message-ID: " msgtxt2) && + test "z$id0" = "z$id2" && + test "z$id1" != "z$id2" +' + for enc in 7bit 8bit quoted-printable base64 do test_expect_success $PREREQ "--transfer-encoding=$enc produces correct header" ' @@ -617,7 +741,7 @@ test_expect_success $PREREQ 'In-Reply-To without --chain-reply-to' ' sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt1 >actual && test_cmp expect actual && # Second and subsequent messages are replies to the first one - sed -n -e "s/^Message-Id: *\(.*\)/\1/p" msgtxt1 >expect && + sed -n -e "s/^Message-ID: *\(.*\)/\1/p" msgtxt1 >expect && sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt2 >actual && test_cmp expect actual && sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt3 >actual && @@ -637,10 +761,10 @@ test_expect_success $PREREQ 'In-Reply-To with --chain-reply-to' ' 2>errors && sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt1 >actual && test_cmp expect actual && - sed -n -e "s/^Message-Id: *\(.*\)/\1/p" msgtxt1 >expect && + sed -n -e "s/^Message-ID: *\(.*\)/\1/p" msgtxt1 >expect && sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt2 >actual && test_cmp expect actual && - sed -n -e "s/^Message-Id: *\(.*\)/\1/p" msgtxt2 >expect && + sed -n -e "s/^Message-ID: *\(.*\)/\1/p" msgtxt2 >expect && sed -n -e "s/^In-Reply-To: *\(.*\)/\1/p" msgtxt3 >actual && test_cmp expect actual ' @@ -713,7 +837,7 @@ Cc: cc@example.com, two@example.com Subject: [PATCH 1/1] Second. Date: DATE-STRING -Message-Id: MESSAGE-ID-STRING +Message-ID: MESSAGE-ID-STRING X-Mailer: X-MAILER-STRING MIME-Version: 1.0 Content-Transfer-Encoding: 8bit @@ -759,7 +883,7 @@ Cc: A <author@example.com>, two@example.com Subject: [PATCH 1/1] Second. Date: DATE-STRING -Message-Id: MESSAGE-ID-STRING +Message-ID: MESSAGE-ID-STRING X-Mailer: X-MAILER-STRING MIME-Version: 1.0 Content-Transfer-Encoding: 8bit @@ -796,7 +920,7 @@ Cc: A <author@example.com>, C O Mitter <committer@example.com> Subject: [PATCH 1/1] Second. Date: DATE-STRING -Message-Id: MESSAGE-ID-STRING +Message-ID: MESSAGE-ID-STRING X-Mailer: X-MAILER-STRING MIME-Version: 1.0 Content-Transfer-Encoding: 8bit @@ -824,7 +948,7 @@ From: Example <from@example.com> To: to@example.com Subject: [PATCH 1/1] Second. Date: DATE-STRING -Message-Id: MESSAGE-ID-STRING +Message-ID: MESSAGE-ID-STRING X-Mailer: X-MAILER-STRING MIME-Version: 1.0 Content-Transfer-Encoding: 8bit @@ -860,7 +984,7 @@ Cc: A <author@example.com>, cc-cmd@example.com Subject: [PATCH 1/1] Second. Date: DATE-STRING -Message-Id: MESSAGE-ID-STRING +Message-ID: MESSAGE-ID-STRING X-Mailer: X-MAILER-STRING MIME-Version: 1.0 Content-Transfer-Encoding: 8bit @@ -893,7 +1017,7 @@ Cc: A <author@example.com>, two@example.com Subject: [PATCH 1/1] Second. Date: DATE-STRING -Message-Id: MESSAGE-ID-STRING +Message-ID: MESSAGE-ID-STRING X-Mailer: X-MAILER-STRING MIME-Version: 1.0 Content-Transfer-Encoding: 8bit @@ -926,7 +1050,7 @@ Cc: A <author@example.com>, two@example.com Subject: [PATCH 1/1] Second. Date: DATE-STRING -Message-Id: MESSAGE-ID-STRING +Message-ID: MESSAGE-ID-STRING X-Mailer: X-MAILER-STRING MIME-Version: 1.0 Content-Transfer-Encoding: 8bit @@ -963,7 +1087,7 @@ Cc: A <author@example.com>, C O Mitter <committer@example.com> Subject: [PATCH 1/1] Second. Date: DATE-STRING -Message-Id: MESSAGE-ID-STRING +Message-ID: MESSAGE-ID-STRING X-Mailer: X-MAILER-STRING MIME-Version: 1.0 Content-Transfer-Encoding: 8bit @@ -993,7 +1117,7 @@ Cc: A <author@example.com>, C O Mitter <committer@example.com> Subject: [PATCH 1/1] Second. Date: DATE-STRING -Message-Id: MESSAGE-ID-STRING +Message-ID: MESSAGE-ID-STRING X-Mailer: X-MAILER-STRING MIME-Version: 1.0 Content-Transfer-Encoding: 8bit @@ -1478,7 +1602,7 @@ test_expect_success $PREREQ 'To headers from files reset each patch' ' test_expect_success $PREREQ 'setup expect' ' cat >email-using-8bit <<\EOF From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001 -Message-Id: <bogus-message-id@example.com> +Message-ID: <bogus-message-id@example.com> From: author@example.com Date: Sat, 12 Jun 2010 15:53:58 +0200 Subject: subject goes here @@ -1564,7 +1688,7 @@ test_expect_success $PREREQ '--8bit-encoding overrides sendemail.8bitEncoding' ' test_expect_success $PREREQ 'setup expect' ' cat >email-using-8bit <<-\EOF From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001 - Message-Id: <bogus-message-id@example.com> + Message-ID: <bogus-message-id@example.com> From: author@example.com Date: Sat, 12 Jun 2010 15:53:58 +0200 Subject: Dieser Betreff enthält auch einen Umlaut! @@ -1593,7 +1717,7 @@ test_expect_success $PREREQ '--8bit-encoding also treats subject' ' test_expect_success $PREREQ 'setup expect' ' cat >email-using-8bit <<-\EOF From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001 - Message-Id: <bogus-message-id@example.com> + Message-ID: <bogus-message-id@example.com> From: A U Thor <author@example.com> Date: Sat, 12 Jun 2010 15:53:58 +0200 Content-Type: text/plain; charset=UTF-8 @@ -1674,7 +1798,7 @@ test_expect_success $PREREQ '8-bit and sendemail.transferencoding=base64' ' test_expect_success $PREREQ 'setup expect' ' cat >email-using-qp <<-\EOF From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001 - Message-Id: <bogus-message-id@example.com> + Message-ID: <bogus-message-id@example.com> From: A U Thor <author@example.com> Date: Sat, 12 Jun 2010 15:53:58 +0200 MIME-Version: 1.0 @@ -1700,7 +1824,7 @@ test_expect_success $PREREQ 'convert from quoted-printable to base64' ' test_expect_success $PREREQ 'setup expect' " tr -d '\\015' | tr '%' '\\015' >email-using-crlf <<EOF From fe6ecc66ece37198fe5db91fa2fc41d9f4fe5cc4 Mon Sep 17 00:00:00 2001 -Message-Id: <bogus-message-id@example.com> +Message-ID: <bogus-message-id@example.com> From: A U Thor <author@example.com> Date: Sat, 12 Jun 2010 15:53:58 +0200 Content-Type: text/plain; charset=UTF-8 @@ -1957,7 +2081,7 @@ test_expect_success $PREREQ 'aliases and sendemail.identity' ' -c sendemail.aliasesfile=default-aliases \ -c sendemail.cloud.aliasesfile=cloud-aliases \ send-email -1 2>stderr && - test_i18ngrep "cloud-aliases" stderr + test_grep "cloud-aliases" stderr ' test_sendmail_aliases () { @@ -2322,10 +2446,41 @@ test_expect_success $PREREQ 'invoke hook' ' --to=nobody@example.com \ --smtp-server="$(pwd)/../fake.sendmail" \ ../another.patch 2>err && - test_i18ngrep "rejected by sendemail-validate hook" err + test_grep "rejected by sendemail-validate hook" err ) ' +expected_file_counter_output () { + total=$1 + count=0 + while test $count -ne $total + do + count=$((count + 1)) && + echo "$count/$total" || return + done +} + +test_expect_success $PREREQ '--validate hook allows counting of messages' ' + test_when_finished "rm -rf my-hooks.log" && + test_config core.hooksPath "my-hooks" && + mkdir -p my-hooks && + + write_script my-hooks/sendemail-validate <<-\EOF && + num=$GIT_SENDEMAIL_FILE_COUNTER && + tot=$GIT_SENDEMAIL_FILE_TOTAL && + echo "$num/$tot" >>my-hooks.log || exit 1 + EOF + + >my-hooks.log && + expected_file_counter_output 4 >expect && + git send-email \ + --from="Example <from@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + --validate -3 --cover-letter --force && + test_cmp expect my-hooks.log +' + test_expect_success $PREREQ 'test that send-email works outside a repo' ' nongit git send-email \ --from="Example <nobody@example.com>" \ @@ -2347,7 +2502,7 @@ test_expect_success $PREREQ 'test that sendmail config is rejected' ' --to=nobody@example.com \ --smtp-server="$(pwd)/fake.sendmail" \ HEAD^ 2>err && - test_i18ngrep "found configuration options for '"'"sendmail"'"'" err + test_grep "found configuration options for '"'"sendmail"'"'" err ' test_expect_success $PREREQ 'test that sendmail config rejection is specific' ' @@ -2369,4 +2524,45 @@ test_expect_success $PREREQ 'test forbidSendmailVariables behavior override' ' HEAD^ ' +test_expect_success $PREREQ '--compose handles lowercase headers' ' + write_script fake-editor <<-\EOF && + sed "s/^From:.*/from: edited-from@example.com/i" "$1" >"$1.tmp" && + mv "$1.tmp" "$1" + EOF + clean_fake_sendmail && + git send-email \ + --compose \ + --from="Example <from@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + HEAD^ && + grep "From: edited-from@example.com" msgtxt1 +' + +test_expect_success $PREREQ '--compose handles to headers' ' + write_script fake-editor <<-\EOF && + sed "s/^To: .*/&, edited-to@example.com/" <"$1" >"$1.tmp" && + echo this is the body >>"$1.tmp" && + mv "$1.tmp" "$1" + EOF + clean_fake_sendmail && + GIT_SEND_EMAIL_NOTTY=1 \ + git send-email \ + --compose \ + --from="Example <from@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + HEAD^ && + # Check both that the cover letter used our modified "to" line, + # but also that it was picked up for the patch. + q_to_tab >expect <<-\EOF && + To: nobody@example.com, + Qedited-to@example.com + EOF + grep -A1 "^To:" msgtxt1 >msgtxt1.to && + test_cmp expect msgtxt1.to && + grep -A1 "^To:" msgtxt2 >msgtxt2.to && + test_cmp expect msgtxt2.to +' + test_done diff --git a/t/t9002-column.sh b/t/t9002-column.sh index 6d3dbde3fe..348cc40658 100755 --- a/t/t9002-column.sh +++ b/t/t9002-column.sh @@ -1,6 +1,7 @@ #!/bin/sh test_description='git column' +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'setup' ' diff --git a/t/t9004-example.sh b/t/t9004-example.sh index 7e8894a4a7..590aab0304 100755 --- a/t/t9004-example.sh +++ b/t/t9004-example.sh @@ -1,6 +1,8 @@ #!/bin/sh test_description='check that example code compiles and runs' + +TEST_PASSES_SANITIZE_LEAK=true . ./test-lib.sh test_expect_success 'decorate' ' diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh index fea41b3c36..af28b01fef 100755 --- a/t/t9100-git-svn-basic.sh +++ b/t/t9100-git-svn-basic.sh @@ -21,7 +21,7 @@ test_expect_success 'git svn help works anywhere' ' ' test_expect_success \ - 'initialize git svn' ' + 'initialize git svn' ' mkdir import && ( cd import && @@ -38,9 +38,9 @@ test_expect_success \ rm -rf import && git svn init "$svnrepo"' -test_expect_success \ - 'import an SVN revision into git' \ - 'git svn fetch' +test_expect_success 'import an SVN revision into git' ' + git svn fetch +' test_expect_success "checkout from svn" 'svn co "$svnrepo" "$SVN_TREE"' @@ -233,27 +233,26 @@ test_expect_success POSIXPERM,SYMLINKS "$name" ' ' test_expect_success 'exit if remote refs are ambigious' ' - git config --add svn-remote.svn.fetch \ + git config --add svn-remote.svn.fetch \ bar:refs/remotes/git-svn && test_must_fail git svn migrate ' test_expect_success 'exit if init-ing a would clobber a URL' ' - svnadmin create "${PWD}/svnrepo2" && - svn mkdir -m "mkdir bar" "${svnrepo}2/bar" && - git config --unset svn-remote.svn.fetch \ + svnadmin create "${PWD}/svnrepo2" && + svn mkdir -m "mkdir bar" "${svnrepo}2/bar" && + git config --unset svn-remote.svn.fetch \ "^bar:refs/remotes/git-svn$" && test_must_fail git svn init "${svnrepo}2/bar" ' -test_expect_success \ - 'init allows us to connect to another directory in the same repo' ' - git svn init --minimize-url -i bar "$svnrepo/bar" && - git config --get svn-remote.svn.fetch \ - "^bar:refs/remotes/bar$" && - git config --get svn-remote.svn.fetch \ - "^:refs/remotes/git-svn$" - ' +test_expect_success 'init allows us to connect to another directory in the same repo' ' + git svn init --minimize-url -i bar "$svnrepo/bar" && + git config --get svn-remote.svn.fetch \ + "^bar:refs/remotes/bar$" && + git config --get svn-remote.svn.fetch \ + "^:refs/remotes/git-svn$" +' test_expect_success 'dcommit $rev does not clobber current branch' ' git svn fetch -i bar && diff --git a/t/t9104-git-svn-follow-parent.sh b/t/t9104-git-svn-follow-parent.sh index 85d735861f..b5845e28fe 100755 --- a/t/t9104-git-svn-follow-parent.sh +++ b/t/t9104-git-svn-follow-parent.sh @@ -41,51 +41,51 @@ test_expect_success 'init and fetch a moved directory' ' ' test_expect_success 'init and fetch from one svn-remote' ' - git config svn-remote.svn.url "$svnrepo" && - git config --add svn-remote.svn.fetch \ - trunk:refs/remotes/svn/trunk && - git config --add svn-remote.svn.fetch \ - thunk:refs/remotes/svn/thunk && - git svn fetch -i svn/thunk && + git config svn-remote.svn.url "$svnrepo" && + git config --add svn-remote.svn.fetch \ + trunk:refs/remotes/svn/trunk && + git config --add svn-remote.svn.fetch \ + thunk:refs/remotes/svn/thunk && + git svn fetch -i svn/thunk && test "$(git rev-parse --verify refs/remotes/svn/trunk)" \ - = "$(git rev-parse --verify refs/remotes/svn/thunk~1)" && + = "$(git rev-parse --verify refs/remotes/svn/thunk~1)" && git cat-file blob refs/remotes/svn/thunk:readme >actual && test "$(sed -n -e "3p" actual)" = goodbye - ' +' test_expect_success 'follow deleted parent' ' - (svn_cmd cp -m "resurrecting trunk as junk" \ - "$svnrepo"/trunk@2 "$svnrepo"/junk || - svn cp -m "resurrecting trunk as junk" \ - -r2 "$svnrepo"/trunk "$svnrepo"/junk) && - git config --add svn-remote.svn.fetch \ - junk:refs/remotes/svn/junk && - git svn fetch -i svn/thunk && - git svn fetch -i svn/junk && + (svn_cmd cp -m "resurrecting trunk as junk" \ + "$svnrepo"/trunk@2 "$svnrepo"/junk || + svn cp -m "resurrecting trunk as junk" \ + -r2 "$svnrepo"/trunk "$svnrepo"/junk) && + git config --add svn-remote.svn.fetch \ + junk:refs/remotes/svn/junk && + git svn fetch -i svn/thunk && + git svn fetch -i svn/junk && test -z "$(git diff svn/junk svn/trunk)" && test "$(git merge-base svn/junk svn/trunk)" \ - = "$(git rev-parse svn/trunk)" - ' + = "$(git rev-parse svn/trunk)" +' test_expect_success 'follow larger parent' ' - mkdir -p import/trunk/thunk/bump/thud && - echo hi > import/trunk/thunk/bump/thud/file && - svn import -m "import a larger parent" import "$svnrepo"/larger-parent && - svn cp -m "hi" "$svnrepo"/larger-parent "$svnrepo"/another-larger && - git svn init --minimize-url -i larger \ - "$svnrepo"/larger-parent/trunk/thunk/bump/thud && - git svn fetch -i larger && + mkdir -p import/trunk/thunk/bump/thud && + echo hi > import/trunk/thunk/bump/thud/file && + svn import -m "import a larger parent" import "$svnrepo"/larger-parent && + svn cp -m "hi" "$svnrepo"/larger-parent "$svnrepo"/another-larger && + git svn init --minimize-url -i larger \ + "$svnrepo"/larger-parent/trunk/thunk/bump/thud && + git svn fetch -i larger && git svn init --minimize-url -i larger-parent \ - "$svnrepo"/another-larger/trunk/thunk/bump/thud && + "$svnrepo"/another-larger/trunk/thunk/bump/thud && git svn fetch -i larger-parent && - git rev-parse --verify refs/remotes/larger && - git rev-parse --verify \ - refs/remotes/larger-parent && + git rev-parse --verify refs/remotes/larger && + git rev-parse --verify \ + refs/remotes/larger-parent && test "$(git merge-base \ refs/remotes/larger-parent \ refs/remotes/larger)" = \ - "$(git rev-parse refs/remotes/larger)" - ' + "$(git rev-parse refs/remotes/larger)" +' test_expect_success 'follow higher-level parent' ' svn mkdir -m "follow higher-level parent" "$svnrepo"/blob && diff --git a/t/t9114-git-svn-dcommit-merge.sh b/t/t9114-git-svn-dcommit-merge.sh index 32317d6bca..e06538b1c8 100755 --- a/t/t9114-git-svn-dcommit-merge.sh +++ b/t/t9114-git-svn-dcommit-merge.sh @@ -27,7 +27,7 @@ cat << EOF # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, see <http://www.gnu.org/licenses/>. +# along with this program; if not, see <https://www.gnu.org/licenses/>. # EOF } diff --git a/t/t9133-git-svn-nested-git-repo.sh b/t/t9133-git-svn-nested-git-repo.sh index d8d536269c..8ca24670ac 100755 --- a/t/t9133-git-svn-nested-git-repo.sh +++ b/t/t9133-git-svn-nested-git-repo.sh @@ -11,7 +11,7 @@ test_expect_success 'setup repo with a git repo inside it' ' ( cd s && git init && - test -f .git/HEAD && + git symbolic-ref HEAD && > .git/a && echo a > a && svn_cmd add .git a && diff --git a/t/t9164-git-svn-dcommit-concurrent.sh b/t/t9164-git-svn-dcommit-concurrent.sh index c8e6c0733f..d1dec89c3b 100755 --- a/t/t9164-git-svn-dcommit-concurrent.sh +++ b/t/t9164-git-svn-dcommit-concurrent.sh @@ -46,6 +46,14 @@ setup_hook() "passed to setup_hook" >&2 ; return 1; } echo "cnt=$skip_revs" > "$hook_type-counter" rm -f "$rawsvnrepo/hooks/"*-commit # drop previous hooks + + # Subversion hooks run with an empty environment by default. We thus + # need to propagate PATH so that we can find executables. + cat >"$rawsvnrepo/conf/hooks-env" <<-EOF + [default] + PATH = ${PATH} + EOF + hook="$rawsvnrepo/hooks/$hook_type" cat > "$hook" <<- 'EOF1' #!/bin/sh @@ -63,7 +71,6 @@ EOF1 if [ "$hook_type" = "pre-commit" ]; then echo "echo 'commit disallowed' >&2; exit 1" >>"$hook" else - echo "PATH=\"$PATH\"; export PATH" >>"$hook" echo "svnconf=\"$svnconf\"" >>"$hook" cat >>"$hook" <<- 'EOF2' cd work-auto-commits.svn diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh index c5946cb0b8..a44eabf0d8 100755 --- a/t/t9200-git-cvsexportcommit.sh +++ b/t/t9200-git-cvsexportcommit.sh @@ -50,56 +50,56 @@ check_entries () { fi } -test_expect_success \ - 'New file' \ - 'mkdir A B C D E F && - echo hello1 >A/newfile1.txt && - echo hello2 >B/newfile2.txt && - cp "$TEST_DIRECTORY"/test-binary-1.png C/newfile3.png && - cp "$TEST_DIRECTORY"/test-binary-1.png D/newfile4.png && - git add A/newfile1.txt && - git add B/newfile2.txt && - git add C/newfile3.png && - git add D/newfile4.png && - git commit -a -m "Test: New file" && - id=$(git rev-list --max-count=1 HEAD) && - (cd "$CVSWORK" && - git cvsexportcommit -c $id && - check_entries A "newfile1.txt/1.1/" && - check_entries B "newfile2.txt/1.1/" && - check_entries C "newfile3.png/1.1/-kb" && - check_entries D "newfile4.png/1.1/-kb" && - test_cmp A/newfile1.txt ../A/newfile1.txt && - test_cmp B/newfile2.txt ../B/newfile2.txt && - test_cmp C/newfile3.png ../C/newfile3.png && - test_cmp D/newfile4.png ../D/newfile4.png - )' +test_expect_success 'New file' ' + mkdir A B C D E F && + echo hello1 >A/newfile1.txt && + echo hello2 >B/newfile2.txt && + cp "$TEST_DIRECTORY"/test-binary-1.png C/newfile3.png && + cp "$TEST_DIRECTORY"/test-binary-1.png D/newfile4.png && + git add A/newfile1.txt && + git add B/newfile2.txt && + git add C/newfile3.png && + git add D/newfile4.png && + git commit -a -m "Test: New file" && + id=$(git rev-list --max-count=1 HEAD) && + (cd "$CVSWORK" && + git cvsexportcommit -c $id && + check_entries A "newfile1.txt/1.1/" && + check_entries B "newfile2.txt/1.1/" && + check_entries C "newfile3.png/1.1/-kb" && + check_entries D "newfile4.png/1.1/-kb" && + test_cmp A/newfile1.txt ../A/newfile1.txt && + test_cmp B/newfile2.txt ../B/newfile2.txt && + test_cmp C/newfile3.png ../C/newfile3.png && + test_cmp D/newfile4.png ../D/newfile4.png + ) +' -test_expect_success \ - 'Remove two files, add two and update two' \ - 'echo Hello1 >>A/newfile1.txt && - rm -f B/newfile2.txt && - rm -f C/newfile3.png && - echo Hello5 >E/newfile5.txt && - cp "$TEST_DIRECTORY"/test-binary-2.png D/newfile4.png && - cp "$TEST_DIRECTORY"/test-binary-1.png F/newfile6.png && - git add E/newfile5.txt && - git add F/newfile6.png && - git commit -a -m "Test: Remove, add and update" && - id=$(git rev-list --max-count=1 HEAD) && - (cd "$CVSWORK" && - git cvsexportcommit -c $id && - check_entries A "newfile1.txt/1.2/" && - check_entries B "" && - check_entries C "" && - check_entries D "newfile4.png/1.2/-kb" && - check_entries E "newfile5.txt/1.1/" && - check_entries F "newfile6.png/1.1/-kb" && - test_cmp A/newfile1.txt ../A/newfile1.txt && - test_cmp D/newfile4.png ../D/newfile4.png && - test_cmp E/newfile5.txt ../E/newfile5.txt && - test_cmp F/newfile6.png ../F/newfile6.png - )' +test_expect_success 'Remove two files, add two and update two' ' + echo Hello1 >>A/newfile1.txt && + rm -f B/newfile2.txt && + rm -f C/newfile3.png && + echo Hello5 >E/newfile5.txt && + cp "$TEST_DIRECTORY"/test-binary-2.png D/newfile4.png && + cp "$TEST_DIRECTORY"/test-binary-1.png F/newfile6.png && + git add E/newfile5.txt && + git add F/newfile6.png && + git commit -a -m "Test: Remove, add and update" && + id=$(git rev-list --max-count=1 HEAD) && + (cd "$CVSWORK" && + git cvsexportcommit -c $id && + check_entries A "newfile1.txt/1.2/" && + check_entries B "" && + check_entries C "" && + check_entries D "newfile4.png/1.2/-kb" && + check_entries E "newfile5.txt/1.1/" && + check_entries F "newfile6.png/1.1/-kb" && + test_cmp A/newfile1.txt ../A/newfile1.txt && + test_cmp D/newfile4.png ../D/newfile4.png && + test_cmp E/newfile5.txt ../E/newfile5.txt && + test_cmp F/newfile6.png ../F/newfile6.png + ) +' # Should fail (but only on the git cvsexportcommit stage) test_expect_success \ @@ -129,67 +129,67 @@ test_expect_success \ # This test is here because a patch for only binary files will # fail with gnu patch, so cvsexportcommit must handle that. -test_expect_success \ - 'Remove only binary files' \ - 'git reset --hard HEAD^^ && - rm -f D/newfile4.png && - git commit -a -m "test: remove only a binary file" && - id=$(git rev-list --max-count=1 HEAD) && - (cd "$CVSWORK" && - git cvsexportcommit -c $id && - check_entries A "newfile1.txt/1.2/" && - check_entries B "" && - check_entries C "" && - check_entries D "" && - check_entries E "newfile5.txt/1.1/" && - check_entries F "newfile6.png/1.1/-kb" && - test_cmp A/newfile1.txt ../A/newfile1.txt && - test_cmp E/newfile5.txt ../E/newfile5.txt && - test_cmp F/newfile6.png ../F/newfile6.png - )' +test_expect_success 'Remove only binary files' ' + git reset --hard HEAD^^ && + rm -f D/newfile4.png && + git commit -a -m "test: remove only a binary file" && + id=$(git rev-list --max-count=1 HEAD) && + (cd "$CVSWORK" && + git cvsexportcommit -c $id && + check_entries A "newfile1.txt/1.2/" && + check_entries B "" && + check_entries C "" && + check_entries D "" && + check_entries E "newfile5.txt/1.1/" && + check_entries F "newfile6.png/1.1/-kb" && + test_cmp A/newfile1.txt ../A/newfile1.txt && + test_cmp E/newfile5.txt ../E/newfile5.txt && + test_cmp F/newfile6.png ../F/newfile6.png + ) +' -test_expect_success \ - 'Remove only a text file' \ - 'rm -f A/newfile1.txt && - git commit -a -m "test: remove only a binary file" && - id=$(git rev-list --max-count=1 HEAD) && - (cd "$CVSWORK" && - git cvsexportcommit -c $id && - check_entries A "" && - check_entries B "" && - check_entries C "" && - check_entries D "" && - check_entries E "newfile5.txt/1.1/" && - check_entries F "newfile6.png/1.1/-kb" && - test_cmp E/newfile5.txt ../E/newfile5.txt && - test_cmp F/newfile6.png ../F/newfile6.png - )' +test_expect_success 'Remove only a text file' ' + rm -f A/newfile1.txt && + git commit -a -m "test: remove only a binary file" && + id=$(git rev-list --max-count=1 HEAD) && + (cd "$CVSWORK" && + git cvsexportcommit -c $id && + check_entries A "" && + check_entries B "" && + check_entries C "" && + check_entries D "" && + check_entries E "newfile5.txt/1.1/" && + check_entries F "newfile6.png/1.1/-kb" && + test_cmp E/newfile5.txt ../E/newfile5.txt && + test_cmp F/newfile6.png ../F/newfile6.png + ) +' -test_expect_success \ - 'New file with spaces in file name' \ - 'mkdir "G g" && - echo ok then >"G g/with spaces.txt" && - git add "G g/with spaces.txt" && \ - cp "$TEST_DIRECTORY"/test-binary-1.png "G g/with spaces.png" && \ - git add "G g/with spaces.png" && - git commit -a -m "With spaces" && - id=$(git rev-list --max-count=1 HEAD) && - (cd "$CVSWORK" && - git cvsexportcommit -c $id && - check_entries "G g" "with spaces.png/1.1/-kb|with spaces.txt/1.1/" - )' +test_expect_success 'New file with spaces in file name' ' + mkdir "G g" && + echo ok then >"G g/with spaces.txt" && + git add "G g/with spaces.txt" && \ + cp "$TEST_DIRECTORY"/test-binary-1.png "G g/with spaces.png" && \ + git add "G g/with spaces.png" && + git commit -a -m "With spaces" && + id=$(git rev-list --max-count=1 HEAD) && + (cd "$CVSWORK" && + git cvsexportcommit -c $id && + check_entries "G g" "with spaces.png/1.1/-kb|with spaces.txt/1.1/" + ) +' -test_expect_success \ - 'Update file with spaces in file name' \ - 'echo Ok then >>"G g/with spaces.txt" && - cat "$TEST_DIRECTORY"/test-binary-1.png >>"G g/with spaces.png" && \ - git add "G g/with spaces.png" && - git commit -a -m "Update with spaces" && - id=$(git rev-list --max-count=1 HEAD) && - (cd "$CVSWORK" && - git cvsexportcommit -c $id && - check_entries "G g" "with spaces.png/1.2/-kb|with spaces.txt/1.2/" - )' +test_expect_success 'Update file with spaces in file name' ' + echo Ok then >>"G g/with spaces.txt" && + cat "$TEST_DIRECTORY"/test-binary-1.png >>"G g/with spaces.png" && \ + git add "G g/with spaces.png" && + git commit -a -m "Update with spaces" && + id=$(git rev-list --max-count=1 HEAD) && + (cd "$CVSWORK" && + git cvsexportcommit -c $id && + check_entries "G g" "with spaces.png/1.2/-kb|with spaces.txt/1.2/" + ) +' # Some filesystems mangle pathnames with UTF-8 characters -- # check and skip @@ -202,68 +202,68 @@ if p="Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö" && then # This test contains UTF-8 characters -test_expect_success !MINGW \ - 'File with non-ascii file name' \ - 'mkdir -p Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö && - echo Foo >Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.txt && - git add Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.txt && - cp "$TEST_DIRECTORY"/test-binary-1.png Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png && - git add Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png && - git commit -a -m "Går det så går det" && \ - id=$(git rev-list --max-count=1 HEAD) && - (cd "$CVSWORK" && - git cvsexportcommit -v -c $id && - check_entries \ - "Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö" \ - "gårdetsågårdet.png/1.1/-kb|gårdetsågårdet.txt/1.1/" - )' +test_expect_success !MINGW 'File with non-ascii file name' ' + mkdir -p Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö && + echo Foo >Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.txt && + git add Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.txt && + cp "$TEST_DIRECTORY"/test-binary-1.png Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png && + git add Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png && + git commit -a -m "Går det så går det" && \ + id=$(git rev-list --max-count=1 HEAD) && + (cd "$CVSWORK" && + git cvsexportcommit -v -c $id && + check_entries \ + "Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö" \ + "gårdetsågårdet.png/1.1/-kb|gårdetsågårdet.txt/1.1/" + ) +' fi rm -fr tst -test_expect_success \ - 'Mismatching patch should fail' \ - 'date >>"E/newfile5.txt" && - git add "E/newfile5.txt" && - git commit -a -m "Update one" && - date >>"E/newfile5.txt" && - git add "E/newfile5.txt" && - git commit -a -m "Update two" && - id=$(git rev-list --max-count=1 HEAD) && - (cd "$CVSWORK" && - test_must_fail git cvsexportcommit -c $id - )' - -test_expect_success FILEMODE \ - 'Retain execute bit' \ - 'mkdir G && - echo executeon >G/on && - chmod +x G/on && - echo executeoff >G/off && - git add G/on && - git add G/off && - git commit -a -m "Execute test" && - (cd "$CVSWORK" && - git cvsexportcommit -c HEAD && - test -x G/on && - ! test -x G/off - )' +test_expect_success 'Mismatching patch should fail' ' + date >>"E/newfile5.txt" && + git add "E/newfile5.txt" && + git commit -a -m "Update one" && + date >>"E/newfile5.txt" && + git add "E/newfile5.txt" && + git commit -a -m "Update two" && + id=$(git rev-list --max-count=1 HEAD) && + (cd "$CVSWORK" && + test_must_fail git cvsexportcommit -c $id + ) +' + +test_expect_success FILEMODE 'Retain execute bit' ' + mkdir G && + echo executeon >G/on && + chmod +x G/on && + echo executeoff >G/off && + git add G/on && + git add G/off && + git commit -a -m "Execute test" && + (cd "$CVSWORK" && + git cvsexportcommit -c HEAD && + test -x G/on && + ! test -x G/off + ) +' test_expect_success '-w option should work with relative GIT_DIR' ' - mkdir W && - echo foobar >W/file1.txt && - echo bazzle >W/file2.txt && - git add W/file1.txt && - git add W/file2.txt && - git commit -m "More updates" && - id=$(git rev-list --max-count=1 HEAD) && - (cd "$GIT_DIR" && - GIT_DIR=. git cvsexportcommit -w "$CVSWORK" -c $id && - check_entries "$CVSWORK/W" "file1.txt/1.1/|file2.txt/1.1/" && - test_cmp "$CVSWORK/W/file1.txt" ../W/file1.txt && - test_cmp "$CVSWORK/W/file2.txt" ../W/file2.txt - ) + mkdir W && + echo foobar >W/file1.txt && + echo bazzle >W/file2.txt && + git add W/file1.txt && + git add W/file2.txt && + git commit -m "More updates" && + id=$(git rev-list --max-count=1 HEAD) && + (cd "$GIT_DIR" && + GIT_DIR=. git cvsexportcommit -w "$CVSWORK" -c $id && + check_entries "$CVSWORK/W" "file1.txt/1.1/|file2.txt/1.1/" && + test_cmp "$CVSWORK/W/file1.txt" ../W/file1.txt && + test_cmp "$CVSWORK/W/file2.txt" ../W/file2.txt + ) ' test_expect_success 'check files before directories' ' @@ -290,21 +290,20 @@ test_expect_success 'check files before directories' ' ' test_expect_success 're-commit a removed filename which remains in CVS attic' ' - - (cd "$CVSWORK" && - echo >attic_gremlin && - cvs -Q add attic_gremlin && - cvs -Q ci -m "added attic_gremlin" && - rm attic_gremlin && - cvs -Q rm attic_gremlin && - cvs -Q ci -m "removed attic_gremlin") && - - echo > attic_gremlin && - git add attic_gremlin && - git commit -m "Added attic_gremlin" && + (cd "$CVSWORK" && + echo >attic_gremlin && + cvs -Q add attic_gremlin && + cvs -Q ci -m "added attic_gremlin" && + rm attic_gremlin && + cvs -Q rm attic_gremlin && + cvs -Q ci -m "removed attic_gremlin") && + + echo > attic_gremlin && + git add attic_gremlin && + git commit -m "Added attic_gremlin" && git cvsexportcommit -w "$CVSWORK" -c HEAD && - (cd "$CVSWORK" && cvs -Q update -d) && - test -f "$CVSWORK/attic_gremlin" + (cd "$CVSWORK" && cvs -Q update -d) && + test -f "$CVSWORK/attic_gremlin" ' # the state of the CVS sandbox may be indeterminate for ' space' diff --git a/t/t9211-scalar-clone.sh b/t/t9211-scalar-clone.sh index 872ad1c9c2..7869f45ee6 100755 --- a/t/t9211-scalar-clone.sh +++ b/t/t9211-scalar-clone.sh @@ -180,4 +180,16 @@ test_expect_success 'scalar clone warns when background maintenance fails' ' grep "could not turn on maintenance" err ' +test_expect_success '`scalar clone --no-src`' ' + scalar clone --src "file://$(pwd)/to-clone" with-src && + scalar clone --no-src "file://$(pwd)/to-clone" without-src && + + test_path_is_dir with-src/src && + test_path_is_missing without-src/src && + + (cd with-src/src && ls ?*) >with && + (cd without-src && ls ?*) >without && + test_cmp with without +' + test_done diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index aa55b41b9a..dbb5042b0b 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -388,9 +388,7 @@ test_expect_success 'B: accept branch name "TEMP_TAG"' ' INPUT_END - test_when_finished "rm -f .git/TEMP_TAG - git gc - git prune" && + test_when_finished "rm -f .git/TEMP_TAG && git gc --prune=now" && git fast-import <input && test $(test-tool ref-store main resolve-ref TEMP_TAG 0 | cut -f1 -d " " ) != "$ZERO_OID" && test $(git rev-parse main) = $(git rev-parse TEMP_TAG^) @@ -406,8 +404,7 @@ test_expect_success 'B: accept empty committer' ' INPUT_END test_when_finished "git update-ref -d refs/heads/empty-committer-1 - git gc - git prune" && + git gc --prune=now" && git fast-import <input && out=$(git fsck) && echo "$out" && @@ -452,8 +449,7 @@ test_expect_success 'B: accept and fixup committer with no name' ' INPUT_END test_when_finished "git update-ref -d refs/heads/empty-committer-2 - git gc - git prune" && + git gc --prune=now" && git fast-import <input && out=$(git fsck) && echo "$out" && @@ -1778,8 +1774,7 @@ test_expect_success 'P: verbatim SHA gitlinks' ' INPUT_END git branch -D sub && - git gc && - git prune && + git gc --prune=now && git fast-import <input && test $(git rev-parse --verify subuse2) = $(git rev-parse --verify subuse1) ' @@ -2884,7 +2879,7 @@ test_expect_success 'S: filemodify with garbage after mark must fail' ' COMMIT M 100644 :403x hello.c EOF - test_i18ngrep "space after mark" err + test_grep "space after mark" err ' # inline is misspelled; fast-import thinks it is some unknown dataref @@ -2900,7 +2895,7 @@ test_expect_success 'S: filemodify with garbage after inline must fail' ' inline BLOB EOF - test_i18ngrep "nvalid dataref" err + test_grep "nvalid dataref" err ' test_expect_success 'S: filemodify with garbage after sha1 must fail' ' @@ -2913,7 +2908,7 @@ test_expect_success 'S: filemodify with garbage after sha1 must fail' ' COMMIT M 100644 ${sha1}x hello.c EOF - test_i18ngrep "space after SHA1" err + test_grep "space after SHA1" err ' # @@ -2928,7 +2923,7 @@ test_expect_success 'S: notemodify with garbage after mark dataref must fail' ' COMMIT N :202x :302 EOF - test_i18ngrep "space after mark" err + test_grep "space after mark" err ' test_expect_success 'S: notemodify with garbage after inline dataref must fail' ' @@ -2943,7 +2938,7 @@ test_expect_success 'S: notemodify with garbage after inline dataref must fail' note blob BLOB EOF - test_i18ngrep "nvalid dataref" err + test_grep "nvalid dataref" err ' test_expect_success 'S: notemodify with garbage after sha1 dataref must fail' ' @@ -2956,7 +2951,7 @@ test_expect_success 'S: notemodify with garbage after sha1 dataref must fail' ' COMMIT N ${sha1}x :302 EOF - test_i18ngrep "space after SHA1" err + test_grep "space after SHA1" err ' # @@ -2971,7 +2966,7 @@ test_expect_success 'S: notemodify with garbage after mark commit-ish must fail' COMMIT N :202 :302x EOF - test_i18ngrep "after mark" err + test_grep "after mark" err ' # @@ -3004,7 +2999,7 @@ test_expect_success 'S: from with garbage after mark must fail' ' EOF # now evaluate the error - test_i18ngrep "after mark" err + test_grep "after mark" err ' @@ -3023,7 +3018,7 @@ test_expect_success 'S: merge with garbage after mark must fail' ' merge :303x M 100644 :403 hello.c EOF - test_i18ngrep "after mark" err + test_grep "after mark" err ' # @@ -3038,7 +3033,7 @@ test_expect_success 'S: tag with garbage after mark must fail' ' tag S TAG EOF - test_i18ngrep "after mark" err + test_grep "after mark" err ' # @@ -3048,7 +3043,7 @@ test_expect_success 'S: cat-blob with garbage after mark must fail' ' test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && cat-blob :403x EOF - test_i18ngrep "after mark" err + test_grep "after mark" err ' # @@ -3058,7 +3053,7 @@ test_expect_success 'S: ls with garbage after mark must fail' ' test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && ls :302x hello.c EOF - test_i18ngrep "space after mark" err + test_grep "space after mark" err ' test_expect_success 'S: ls with garbage after sha1 must fail' ' @@ -3066,7 +3061,7 @@ test_expect_success 'S: ls with garbage after sha1 must fail' ' test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && ls ${sha1}x hello.c EOF - test_i18ngrep "space after tree-ish" err + test_grep "space after tree-ish" err ' ### diff --git a/t/t9304-fast-import-marks.sh b/t/t9304-fast-import-marks.sh index a98ef032d9..410a871c52 100755 --- a/t/t9304-fast-import-marks.sh +++ b/t/t9304-fast-import-marks.sh @@ -49,4 +49,33 @@ test_expect_success 'import with submodule mapping' ' test_cmp expect actual ' +test_expect_success 'paths adjusted for relative subdir' ' + git init deep-dst && + mkdir deep-dst/subdir && + >deep-dst/subdir/empty-marks && + git -C deep-dst/subdir fast-import \ + --rewrite-submodules-from=sub:../../from \ + --rewrite-submodules-to=sub:../../to \ + --import-marks=empty-marks \ + --export-marks=exported-marks \ + --export-pack-edges=exported-edges \ + <dump && + # we do not bother checking resulting repo; we just care that nothing + # complained about failing to open files for reading, and that files + # for writing were created in the expected spot + test_path_is_file deep-dst/subdir/exported-marks && + test_path_is_file deep-dst/subdir/exported-edges +' + +test_expect_success 'relative marks are not affected by subdir' ' + git init deep-relative && + mkdir deep-relative/subdir && + git -C deep-relative/subdir fast-import \ + --relative-marks \ + --export-marks=exported-marks \ + <dump && + test_path_is_missing deep-relative/subdir/exported-marks && + test_path_is_file deep-relative/.git/info/fast-import/exported-marks +' + test_done diff --git a/t/t9351-fast-export-anonymize.sh b/t/t9351-fast-export-anonymize.sh index 77047e250d..156a647484 100755 --- a/t/t9351-fast-export-anonymize.sh +++ b/t/t9351-fast-export-anonymize.sh @@ -25,6 +25,7 @@ test_expect_success 'setup simple repo' ' test_expect_success 'export anonymized stream' ' git fast-export --anonymize --all \ --anonymize-map=retain-me \ + --anonymize-map=xyzzy:should-not-appear \ --anonymize-map=xyzzy:custom-name \ --anonymize-map=other \ >stream @@ -41,6 +42,7 @@ test_expect_success 'stream omits path names' ' test_expect_success 'stream contains user-specified names' ' grep retain-me stream && + ! grep should-not-appear stream && grep custom-name stream ' diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh index 379b19f2f8..003c0b61d0 100755 --- a/t/t9400-git-cvsserver-server.sh +++ b/t/t9400-git-cvsserver-server.sh @@ -66,10 +66,11 @@ test_expect_success 'setup' ' # note that cvs doesn't accept absolute pathnames # as argument to co -d -test_expect_success 'basic checkout' \ - 'GIT_CONFIG="$git_config" cvs -Q co -d cvswork main && - test "$(echo $(grep -v ^D cvswork/CVS/Entries|cut -d/ -f2,3,5 | head -n 1))" = "empty/1.1/" && - test "$(echo $(grep -v ^D cvswork/CVS/Entries|cut -d/ -f2,3,5 | sed -ne \$p))" = "secondrootfile/1.1/"' +test_expect_success 'basic checkout' ' + GIT_CONFIG="$git_config" cvs -Q co -d cvswork main && + test "$(echo $(grep -v ^D cvswork/CVS/Entries|cut -d/ -f2,3,5 | head -n 1))" = "empty/1.1/" && + test "$(echo $(grep -v ^D cvswork/CVS/Entries|cut -d/ -f2,3,5 | sed -ne \$p))" = "secondrootfile/1.1/" +' #------------------------ # PSERVER AUTHENTICATION @@ -115,35 +116,40 @@ Ah<Z:yZZ30 e END VERIFICATION REQUEST EOF -test_expect_success 'pserver authentication' \ - 'cat request-anonymous | git-cvsserver pserver >log 2>&1 && - sed -ne \$p log | grep "^I LOVE YOU\$"' +test_expect_success 'pserver authentication' ' + cat request-anonymous | git-cvsserver pserver >log 2>&1 && + sed -ne \$p log | grep "^I LOVE YOU\$" +' -test_expect_success 'pserver authentication failure (non-anonymous user)' \ - 'if cat request-git | git-cvsserver pserver >log 2>&1 - then - false - else - true - fi && - sed -ne \$p log | grep "^I HATE YOU\$"' +test_expect_success 'pserver authentication failure (non-anonymous user)' ' + if cat request-git | git-cvsserver pserver >log 2>&1 + then + false + else + true + fi && + sed -ne \$p log | grep "^I HATE YOU\$" +' -test_expect_success 'pserver authentication success (non-anonymous user with password)' \ - 'cat login-git-ok | git-cvsserver pserver >log 2>&1 && - sed -ne \$p log | grep "^I LOVE YOU\$"' +test_expect_success 'pserver authentication success (non-anonymous user with password)' ' + cat login-git-ok | git-cvsserver pserver >log 2>&1 && + sed -ne \$p log | grep "^I LOVE YOU\$" +' -test_expect_success 'pserver authentication (login)' \ - 'cat login-anonymous | git-cvsserver pserver >log 2>&1 && - sed -ne \$p log | grep "^I LOVE YOU\$"' +test_expect_success 'pserver authentication (login)' ' + cat login-anonymous | git-cvsserver pserver >log 2>&1 && + sed -ne \$p log | grep "^I LOVE YOU\$" +' -test_expect_success 'pserver authentication failure (login/non-anonymous user)' \ - 'if cat login-git | git-cvsserver pserver >log 2>&1 - then - false - else - true - fi && - sed -ne \$p log | grep "^I HATE YOU\$"' +test_expect_success 'pserver authentication failure (login/non-anonymous user)' ' + if cat login-git | git-cvsserver pserver >log 2>&1 + then + false + else + true + fi && + sed -ne \$p log | grep "^I HATE YOU\$" +' # misuse pserver authentication for testing of req_Root @@ -165,36 +171,40 @@ END AUTH REQUEST Root $WORKDIR EOF -test_expect_success 'req_Root failure (relative pathname)' \ - 'if cat request-relative | git-cvsserver pserver >log 2>&1 - then - echo unexpected success - false - else - true - fi && - tail log | grep "^error 1 Root must be an absolute pathname$"' +test_expect_success 'req_Root failure (relative pathname)' ' + if cat request-relative | git-cvsserver pserver >log 2>&1 + then + echo unexpected success + false + else + true + fi && + tail log | grep "^error 1 Root must be an absolute pathname$" +' -test_expect_success 'req_Root failure (conflicting roots)' \ - 'cat request-conflict | git-cvsserver pserver >log 2>&1 && - tail log | grep "^error 1 Conflicting roots specified$"' +test_expect_success 'req_Root failure (conflicting roots)' ' + cat request-conflict | git-cvsserver pserver >log 2>&1 && + tail log | grep "^error 1 Conflicting roots specified$" +' -test_expect_success 'req_Root (strict paths)' \ - 'cat request-anonymous | git-cvsserver --strict-paths pserver "$SERVERDIR" >log 2>&1 && - sed -ne \$p log | grep "^I LOVE YOU\$"' +test_expect_success 'req_Root (strict paths)' ' + cat request-anonymous | git-cvsserver --strict-paths pserver "$SERVERDIR" >log 2>&1 && + sed -ne \$p log | grep "^I LOVE YOU\$" +' test_expect_success 'req_Root failure (strict-paths)' ' - ! cat request-anonymous | - git-cvsserver --strict-paths pserver "$WORKDIR" >log 2>&1 + ! cat request-anonymous | + git-cvsserver --strict-paths pserver "$WORKDIR" >log 2>&1 ' -test_expect_success 'req_Root (w/o strict-paths)' \ - 'cat request-anonymous | git-cvsserver pserver "$WORKDIR/" >log 2>&1 && - sed -ne \$p log | grep "^I LOVE YOU\$"' +test_expect_success 'req_Root (w/o strict-paths)' ' + cat request-anonymous | git-cvsserver pserver "$WORKDIR/" >log 2>&1 && + sed -ne \$p log | grep "^I LOVE YOU\$" +' test_expect_success 'req_Root failure (w/o strict-paths)' ' - ! cat request-anonymous | - git-cvsserver pserver "$WORKDIR/gitcvs" >log 2>&1 + ! cat request-anonymous | + git-cvsserver pserver "$WORKDIR/gitcvs" >log 2>&1 ' cat >request-base <<EOF @@ -206,27 +216,30 @@ END AUTH REQUEST Root /gitcvs.git EOF -test_expect_success 'req_Root (base-path)' \ - 'cat request-base | git-cvsserver --strict-paths --base-path "$WORKDIR/" pserver "$SERVERDIR" >log 2>&1 && - sed -ne \$p log | grep "^I LOVE YOU\$"' +test_expect_success 'req_Root (base-path)' ' + cat request-base | git-cvsserver --strict-paths --base-path "$WORKDIR/" pserver "$SERVERDIR" >log 2>&1 && + sed -ne \$p log | grep "^I LOVE YOU\$" +' test_expect_success 'req_Root failure (base-path)' ' - ! cat request-anonymous | - git-cvsserver --strict-paths --base-path "$WORKDIR" pserver "$SERVERDIR" >log 2>&1 + ! cat request-anonymous | + git-cvsserver --strict-paths --base-path "$WORKDIR" pserver "$SERVERDIR" >log 2>&1 ' GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled false || exit 1 -test_expect_success 'req_Root (export-all)' \ - 'cat request-anonymous | git-cvsserver --export-all pserver "$WORKDIR" >log 2>&1 && - sed -ne \$p log | grep "^I LOVE YOU\$"' +test_expect_success 'req_Root (export-all)' ' + cat request-anonymous | git-cvsserver --export-all pserver "$WORKDIR" >log 2>&1 && + sed -ne \$p log | grep "^I LOVE YOU\$" +' -test_expect_success 'req_Root failure (export-all w/o directory list)' \ - '! (cat request-anonymous | git-cvsserver --export-all pserver >log 2>&1 || false)' +test_expect_success 'req_Root failure (export-all w/o directory list)' ' + ! (cat request-anonymous | git-cvsserver --export-all pserver >log 2>&1 || false)' -test_expect_success 'req_Root (everything together)' \ - 'cat request-base | git-cvsserver --export-all --strict-paths --base-path "$WORKDIR/" pserver "$SERVERDIR" >log 2>&1 && - sed -ne \$p log | grep "^I LOVE YOU\$"' +test_expect_success 'req_Root (everything together)' ' + cat request-base | git-cvsserver --export-all --strict-paths --base-path "$WORKDIR/" pserver "$SERVERDIR" >log 2>&1 && + sed -ne \$p log | grep "^I LOVE YOU\$" +' GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true || exit 1 @@ -247,45 +260,49 @@ test_expect_success 'gitcvs.enabled = false' \ test ! -d cvswork2' rm -fr cvswork2 -test_expect_success 'gitcvs.ext.enabled = true' \ - 'GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled true && - GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled false && - GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 main >cvs.log 2>&1 && - test_cmp cvswork cvswork2' +test_expect_success 'gitcvs.ext.enabled = true' ' + GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled true && + GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled false && + GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 main >cvs.log 2>&1 && + test_cmp cvswork cvswork2 +' rm -fr cvswork2 -test_expect_success 'gitcvs.ext.enabled = false' \ - 'GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled false && - GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true && - if GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 main >cvs.log 2>&1 - then - echo unexpected cvs success - false - else - true - fi && - grep "GITCVS emulation disabled" cvs.log && - test ! -d cvswork2' +test_expect_success 'gitcvs.ext.enabled = false' ' + GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled false && + GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true && + if GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 main >cvs.log 2>&1 + then + echo unexpected cvs success + false + else + true + fi && + grep "GITCVS emulation disabled" cvs.log && + test ! -d cvswork2 +' rm -fr cvswork2 -test_expect_success 'gitcvs.dbname' \ - 'GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled true && - GIT_DIR="$SERVERDIR" git config gitcvs.dbname %Ggitcvs.%a.%m.sqlite && - GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 main >cvs.log 2>&1 && - test_cmp cvswork cvswork2 && - test -f "$SERVERDIR/gitcvs.ext.main.sqlite" && - cmp "$SERVERDIR/gitcvs.main.sqlite" "$SERVERDIR/gitcvs.ext.main.sqlite"' +test_expect_success 'gitcvs.dbname' ' + GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled true && + GIT_DIR="$SERVERDIR" git config gitcvs.dbname %Ggitcvs.%a.%m.sqlite && + GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 main >cvs.log 2>&1 && + test_cmp cvswork cvswork2 && + test -f "$SERVERDIR/gitcvs.ext.main.sqlite" && + cmp "$SERVERDIR/gitcvs.main.sqlite" "$SERVERDIR/gitcvs.ext.main.sqlite" +' rm -fr cvswork2 -test_expect_success 'gitcvs.ext.dbname' \ - 'GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled true && - GIT_DIR="$SERVERDIR" git config gitcvs.ext.dbname %Ggitcvs1.%a.%m.sqlite && - GIT_DIR="$SERVERDIR" git config gitcvs.dbname %Ggitcvs2.%a.%m.sqlite && - GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 main >cvs.log 2>&1 && - test_cmp cvswork cvswork2 && - test -f "$SERVERDIR/gitcvs1.ext.main.sqlite" && - test ! -f "$SERVERDIR/gitcvs2.ext.main.sqlite" && - cmp "$SERVERDIR/gitcvs.main.sqlite" "$SERVERDIR/gitcvs1.ext.main.sqlite"' +test_expect_success 'gitcvs.ext.dbname' ' + GIT_DIR="$SERVERDIR" git config --bool gitcvs.ext.enabled true && + GIT_DIR="$SERVERDIR" git config gitcvs.ext.dbname %Ggitcvs1.%a.%m.sqlite && + GIT_DIR="$SERVERDIR" git config gitcvs.dbname %Ggitcvs2.%a.%m.sqlite && + GIT_CONFIG="$git_config" cvs -Q co -d cvswork2 main >cvs.log 2>&1 && + test_cmp cvswork cvswork2 && + test -f "$SERVERDIR/gitcvs1.ext.main.sqlite" && + test ! -f "$SERVERDIR/gitcvs2.ext.main.sqlite" && + cmp "$SERVERDIR/gitcvs.main.sqlite" "$SERVERDIR/gitcvs1.ext.main.sqlite" +' #------------ @@ -299,109 +316,115 @@ GIT_DIR="$SERVERDIR" git config --bool gitcvs.enabled true && GIT_DIR="$SERVERDIR" git config gitcvs.logfile "$SERVERDIR/gitcvs.log" || exit 1 -test_expect_success 'cvs update (create new file)' \ - 'echo testfile1 >testfile1 && - git add testfile1 && - git commit -q -m "Add testfile1" && - git push gitcvs.git >/dev/null && - cd cvswork && - GIT_CONFIG="$git_config" cvs -Q update && - test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.1/" && - test_cmp testfile1 ../testfile1' +test_expect_success 'cvs update (create new file)' ' + echo testfile1 >testfile1 && + git add testfile1 && + git commit -q -m "Add testfile1" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs -Q update && + test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.1/" && + test_cmp testfile1 ../testfile1 +' cd "$WORKDIR" -test_expect_success 'cvs update (update existing file)' \ - 'echo line 2 >>testfile1 && - git add testfile1 && - git commit -q -m "Append to testfile1" && - git push gitcvs.git >/dev/null && - cd cvswork && - GIT_CONFIG="$git_config" cvs -Q update && - test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.2/" && - test_cmp testfile1 ../testfile1' +test_expect_success 'cvs update (update existing file)' ' + echo line 2 >>testfile1 && + git add testfile1 && + git commit -q -m "Append to testfile1" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs -Q update && + test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.2/" && + test_cmp testfile1 ../testfile1 +' cd "$WORKDIR" #TODO: cvsserver doesn't support update w/o -d test_expect_failure "cvs update w/o -d doesn't create subdir (TODO)" ' - mkdir test && - echo >test/empty && - git add test && - git commit -q -m "Single Subdirectory" && - git push gitcvs.git >/dev/null && - cd cvswork && - GIT_CONFIG="$git_config" cvs -Q update && - test ! -d test + mkdir test && + echo >test/empty && + git add test && + git commit -q -m "Single Subdirectory" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs -Q update && + test ! -d test ' cd "$WORKDIR" -test_expect_success 'cvs update (subdirectories)' \ - '(for dir in A A/B A/B/C A/D E; do - mkdir $dir && - echo "test file in $dir" >"$dir/file_in_$(echo $dir|sed -e "s#/# #g")" && - git add $dir || exit 1 - done) && - git commit -q -m "deep sub directory structure" && - git push gitcvs.git >/dev/null && - cd cvswork && - GIT_CONFIG="$git_config" cvs -Q update -d && - (for dir in A A/B A/B/C A/D E; do - filename="file_in_$(echo $dir|sed -e "s#/# #g")" && - if test "$(echo $(grep -v ^D $dir/CVS/Entries|cut -d/ -f2,3,5))" = "$filename/1.1/" && - test_cmp "$dir/$filename" "../$dir/$filename"; then - : - else - exit 1 - fi - done)' +test_expect_success 'cvs update (subdirectories)' ' + (for dir in A A/B A/B/C A/D E; do + mkdir $dir && + echo "test file in $dir" >"$dir/file_in_$(echo $dir|sed -e "s#/# #g")" && + git add $dir || exit 1 + done) && + git commit -q -m "deep sub directory structure" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs -Q update -d && + (for dir in A A/B A/B/C A/D E; do + filename="file_in_$(echo $dir|sed -e "s#/# #g")" && + if test "$(echo $(grep -v ^D $dir/CVS/Entries|cut -d/ -f2,3,5))" = "$filename/1.1/" && + test_cmp "$dir/$filename" "../$dir/$filename"; then + : + else + exit 1 + fi + done) +' cd "$WORKDIR" -test_expect_success 'cvs update (delete file)' \ - 'git rm testfile1 && - git commit -q -m "Remove testfile1" && - git push gitcvs.git >/dev/null && - cd cvswork && - GIT_CONFIG="$git_config" cvs -Q update && - test -z "$(grep testfile1 CVS/Entries)" && - test ! -f testfile1' +test_expect_success 'cvs update (delete file)' ' + git rm testfile1 && + git commit -q -m "Remove testfile1" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs -Q update && + test -z "$(grep testfile1 CVS/Entries)" && + test ! -f testfile1 +' cd "$WORKDIR" -test_expect_success 'cvs update (re-add deleted file)' \ - 'echo readded testfile >testfile1 && - git add testfile1 && - git commit -q -m "Re-Add testfile1" && - git push gitcvs.git >/dev/null && - cd cvswork && - GIT_CONFIG="$git_config" cvs -Q update && - test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.4/" && - test_cmp testfile1 ../testfile1' +test_expect_success 'cvs update (re-add deleted file)' ' + echo readded testfile >testfile1 && + git add testfile1 && + git commit -q -m "Re-Add testfile1" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs -Q update && + test "$(echo $(grep testfile1 CVS/Entries|cut -d/ -f2,3,5))" = "testfile1/1.4/" && + test_cmp testfile1 ../testfile1 +' cd "$WORKDIR" -test_expect_success 'cvs update (merge)' \ - 'echo Line 0 >expected && - for i in 1 2 3 4 5 6 7 - do - echo Line $i >>merge && - echo Line $i >>expected || return 1 - done && - echo Line 8 >>expected && - git add merge && - git commit -q -m "Merge test (pre-merge)" && - git push gitcvs.git >/dev/null && - cd cvswork && - GIT_CONFIG="$git_config" cvs -Q update && - test "$(echo $(grep merge CVS/Entries|cut -d/ -f2,3,5))" = "merge/1.1/" && - test_cmp merge ../merge && - ( echo Line 0 && cat merge ) >merge.tmp && - mv merge.tmp merge && - cd "$WORKDIR" && - echo Line 8 >>merge && - git add merge && - git commit -q -m "Merge test (merge)" && - git push gitcvs.git >/dev/null && - cd cvswork && - sleep 1 && touch merge && - GIT_CONFIG="$git_config" cvs -Q update && - test_cmp merge ../expected' +test_expect_success 'cvs update (merge)' ' + echo Line 0 >expected && + for i in 1 2 3 4 5 6 7 + do + echo Line $i >>merge && + echo Line $i >>expected || return 1 + done && + echo Line 8 >>expected && + git add merge && + git commit -q -m "Merge test (pre-merge)" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs -Q update && + test "$(echo $(grep merge CVS/Entries|cut -d/ -f2,3,5))" = "merge/1.1/" && + test_cmp merge ../merge && + ( echo Line 0 && cat merge ) >merge.tmp && + mv merge.tmp merge && + cd "$WORKDIR" && + echo Line 8 >>merge && + git add merge && + git commit -q -m "Merge test (merge)" && + git push gitcvs.git >/dev/null && + cd cvswork && + sleep 1 && touch merge && + GIT_CONFIG="$git_config" cvs -Q update && + test_cmp merge ../expected +' cd "$WORKDIR" @@ -418,55 +441,58 @@ do echo Line $i >>expected.C done -test_expect_success 'cvs update (conflict merge)' \ - '( echo LINE 0 && cat merge ) >merge.tmp && - mv merge.tmp merge && - git add merge && - git commit -q -m "Merge test (conflict)" && - git push gitcvs.git >/dev/null && - cd cvswork && - GIT_CONFIG="$git_config" cvs -Q update && - test_cmp merge ../expected.C' +test_expect_success 'cvs update (conflict merge)' ' + ( echo LINE 0 && cat merge ) >merge.tmp && + mv merge.tmp merge && + git add merge && + git commit -q -m "Merge test (conflict)" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs -Q update && + test_cmp merge ../expected.C +' cd "$WORKDIR" -test_expect_success 'cvs update (-C)' \ - 'cd cvswork && - GIT_CONFIG="$git_config" cvs -Q update -C && - test_cmp merge ../merge' +test_expect_success 'cvs update (-C)' ' + cd cvswork && + GIT_CONFIG="$git_config" cvs -Q update -C && + test_cmp merge ../merge +' cd "$WORKDIR" -test_expect_success 'cvs update (merge no-op)' \ - 'echo Line 9 >>merge && - cp merge cvswork/merge && - git add merge && - git commit -q -m "Merge test (no-op)" && - git push gitcvs.git >/dev/null && - cd cvswork && - sleep 1 && touch merge && - GIT_CONFIG="$git_config" cvs -Q update && - test_cmp merge ../merge' +test_expect_success 'cvs update (merge no-op)' ' + echo Line 9 >>merge && + cp merge cvswork/merge && + git add merge && + git commit -q -m "Merge test (no-op)" && + git push gitcvs.git >/dev/null && + cd cvswork && + sleep 1 && touch merge && + GIT_CONFIG="$git_config" cvs -Q update && + test_cmp merge ../merge +' cd "$WORKDIR" test_expect_success 'cvs update (-p)' ' - touch really-empty && - echo Line 1 > no-lf && - printf "Line 2" >> no-lf && - git add really-empty no-lf && - git commit -q -m "Update -p test" && - git push gitcvs.git >/dev/null && - cd cvswork && - GIT_CONFIG="$git_config" cvs update && - for i in merge no-lf empty really-empty; do - GIT_CONFIG="$git_config" cvs update -p "$i" >$i.out && - test_cmp $i.out ../$i || return 1 - done + touch really-empty && + echo Line 1 > no-lf && + printf "Line 2" >> no-lf && + git add really-empty no-lf && + git commit -q -m "Update -p test" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs update && + for i in merge no-lf empty really-empty; do + GIT_CONFIG="$git_config" cvs update -p "$i" >$i.out && + test_cmp $i.out ../$i || return 1 + done ' cd "$WORKDIR" test_expect_success 'cvs update (module list supports packed refs)' ' - GIT_DIR="$SERVERDIR" git pack-refs --all && - GIT_CONFIG="$git_config" cvs -n up -d 2> out && - grep "cvs update: New directory \`main'\''" < out + GIT_DIR="$SERVERDIR" git pack-refs --all && + GIT_CONFIG="$git_config" cvs -n up -d 2> out && + grep "cvs update: New directory \`main'\''" < out ' #------------ @@ -475,30 +501,30 @@ test_expect_success 'cvs update (module list supports packed refs)' ' cd "$WORKDIR" test_expect_success 'cvs status' ' - mkdir status.dir && - echo Line > status.dir/status.file && - echo Line > status.file && - git add status.dir status.file && - git commit -q -m "Status test" && - git push gitcvs.git >/dev/null && - cd cvswork && - GIT_CONFIG="$git_config" cvs update && - GIT_CONFIG="$git_config" cvs status | grep "^File: status.file" >../out && - test_line_count = 2 ../out + mkdir status.dir && + echo Line > status.dir/status.file && + echo Line > status.file && + git add status.dir status.file && + git commit -q -m "Status test" && + git push gitcvs.git >/dev/null && + cd cvswork && + GIT_CONFIG="$git_config" cvs update && + GIT_CONFIG="$git_config" cvs status | grep "^File: status.file" >../out && + test_line_count = 2 ../out ' cd "$WORKDIR" test_expect_success 'cvs status (nonrecursive)' ' - cd cvswork && - GIT_CONFIG="$git_config" cvs status -l | grep "^File: status.file" >../out && - test_line_count = 1 ../out + cd cvswork && + GIT_CONFIG="$git_config" cvs status -l | grep "^File: status.file" >../out && + test_line_count = 1 ../out ' cd "$WORKDIR" test_expect_success 'cvs status (no subdirs in header)' ' - cd cvswork && - GIT_CONFIG="$git_config" cvs status | grep ^File: >../out && - ! grep / <../out + cd cvswork && + GIT_CONFIG="$git_config" cvs status | grep ^File: >../out && + ! grep / <../out ' #------------ @@ -507,9 +533,9 @@ test_expect_success 'cvs status (no subdirs in header)' ' cd "$WORKDIR" test_expect_success 'cvs co -c (shows module database)' ' - GIT_CONFIG="$git_config" cvs co -c > out && - grep "^main[ ][ ]*main$" <out && - ! grep -v "^main[ ][ ]*main$" <out + GIT_CONFIG="$git_config" cvs co -c > out && + grep "^main[ ][ ]*main$" <out && + ! grep -v "^main[ ][ ]*main$" <out ' #------------ @@ -575,11 +601,11 @@ expectStat="$?" cd "$WORKDIR" test_expect_success 'cvs log' ' - cd cvswork && - test x"$expectStat" = x"0" && - GIT_CONFIG="$git_config" cvs log merge >../out && - sed -e "s%2[0-9][0-9][0-9]/[01][0-9]/[0-3][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9]%__DATE__%" ../out > ../actual && - test_cmp ../expect ../actual + cd cvswork && + test x"$expectStat" = x"0" && + GIT_CONFIG="$git_config" cvs log merge >../out && +sed -e "s%2[0-9][0-9][0-9]/[01][0-9]/[0-3][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9]%__DATE__%" ../out > ../actual && + test_cmp ../expect ../actual ' #------------ @@ -588,11 +614,11 @@ test_expect_success 'cvs log' ' cd "$WORKDIR" test_expect_success 'cvs annotate' ' - cd cvswork && - GIT_CONFIG="$git_config" cvs annotate merge >../out && - sed -e "s/ .*//" ../out >../actual && - printf "1.%d\n" 3 1 1 1 1 1 1 1 2 4 >../expect && - test_cmp ../expect ../actual + cd cvswork && + GIT_CONFIG="$git_config" cvs annotate merge >../out && + sed -e "s/ .*//" ../out >../actual && + printf "1.%d\n" 3 1 1 1 1 1 1 1 2 4 >../expect && + test_cmp ../expect ../actual ' #------------ diff --git a/t/t9700/test.pl b/t/t9700/test.pl index 6d753708d2..d8e85482ab 100755 --- a/t/t9700/test.pl +++ b/t/t9700/test.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl use lib (split(/:/, $ENV{GITPERLLIB})); -use 5.008; +use 5.008001; use warnings; use strict; diff --git a/t/t9800-git-p4-basic.sh b/t/t9800-git-p4-basic.sh index dc88d0e064..53af8e34ac 100755 --- a/t/t9800-git-p4-basic.sh +++ b/t/t9800-git-p4-basic.sh @@ -54,7 +54,7 @@ test_expect_success 'git p4 sync uninitialized repo' ' ( cd "$git" && test_must_fail git p4 sync 2>errs && - test_i18ngrep "Perhaps you never did" errs + test_grep "Perhaps you never did" errs ) ' @@ -86,7 +86,7 @@ test_expect_success 'git p4 sync existing branch without changes' ' test_commit head && git p4 sync --branch=depot //depot@all && git p4 sync --branch=refs/remotes/p4/depot >out && - test_i18ngrep "No changes to import!" out + test_grep "No changes to import!" out ) ' @@ -101,7 +101,7 @@ test_expect_success 'git p4 sync existing branch with relative name' ' test_commit head && git p4 sync --branch=branch1 //depot@all && git p4 sync --branch=p4/branch1 >out && - test_i18ngrep "No changes to import!" out + test_grep "No changes to import!" out ) ' @@ -116,7 +116,7 @@ test_expect_success 'git p4 sync existing branch with nested path' ' test_commit head && git p4 sync --branch=p4/some/path //depot@all && git p4 sync --branch=some/path >out && - test_i18ngrep "No changes to import!" out + test_grep "No changes to import!" out ) ' @@ -131,7 +131,7 @@ test_expect_success 'git p4 sync branch explicit ref without p4 in path' ' test_commit head && git p4 sync --branch=refs/remotes/someremote/depot //depot@all && git p4 sync --branch=refs/remotes/someremote/depot >out && - test_i18ngrep "No changes to import!" out + test_grep "No changes to import!" out ) ' @@ -143,7 +143,7 @@ test_expect_success 'git p4 sync nonexistent ref' ' test_commit head && git p4 sync --branch=depot //depot@all && test_must_fail git p4 sync --branch=depot2 2>errs && - test_i18ngrep "Perhaps you never did" errs + test_grep "Perhaps you never did" errs ) ' @@ -155,7 +155,7 @@ test_expect_success 'git p4 sync existing non-p4-imported ref' ' test_commit head && git p4 sync --branch=depot //depot@all && test_must_fail git p4 sync --branch=refs/heads/master 2>errs && - test_i18ngrep "Perhaps you never did" errs + test_grep "Perhaps you never did" errs ) ' @@ -290,7 +290,7 @@ test_expect_success 'exit when p4 fails to produce marshaled output' ' export PATH && test_expect_code 1 git p4 clone --dest="$git" //depot >errs 2>&1 ) && - test_i18ngrep ! Traceback errs + test_grep ! Traceback errs ' # Hide a file from p4d, make sure we catch its complaint. This won't fail in @@ -301,7 +301,7 @@ test_expect_success 'exit gracefully for p4 server errors' ' mv "$db"/depot/file1,v "$db"/depot/file1,v,hidden && test_when_finished cleanup_git && test_expect_code 1 git p4 clone --dest="$git" //depot@1 >out 2>err && - test_i18ngrep "Error from p4 print" err + test_grep "Error from p4 print" err ' test_expect_success 'clone --bare should make a bare repository' ' @@ -330,7 +330,7 @@ test_expect_success 'initial import time from top change time' ' test_when_finished cleanup_git && ( cd "$git" && - gittime=$(git show -s --raw --pretty=format:%at HEAD) && + gittime=$(git show -s --pretty=format:%at HEAD) && echo $p4time $gittime && test $p4time = $gittime ) diff --git a/t/t9801-git-p4-branch.sh b/t/t9801-git-p4-branch.sh index 759a14fa87..c598011635 100755 --- a/t/t9801-git-p4-branch.sh +++ b/t/t9801-git-p4-branch.sh @@ -135,7 +135,7 @@ test_expect_success 'sync specific detected branch' ' ( cd "$git" && git p4 sync --branch=depot/branch2 >out && - test_i18ngrep "No changes to import!" out + test_grep "No changes to import!" out ) ' @@ -466,7 +466,7 @@ test_expect_success 'git p4 clone complex branches with excluded files' ' ) ' -# From a report in http://stackoverflow.com/questions/11893688 +# From a report in https://stackoverflow.com/questions/11893688 # where --use-client-spec caused branch prefixes not to be removed; # every file in git appeared into a subdirectory of the branch name. test_expect_success 'use-client-spec detect-branches setup' ' diff --git a/t/t9807-git-p4-submit.sh b/t/t9807-git-p4-submit.sh index 7d4109f29d..af4b286f9d 100755 --- a/t/t9807-git-p4-submit.sh +++ b/t/t9807-git-p4-submit.sh @@ -75,7 +75,7 @@ test_expect_success 'submit --dry-run' ' test_commit "dry-run1" && test_commit "dry-run2" && git p4 submit --dry-run >out && - test_i18ngrep "Would apply" out + test_grep "Would apply" out ) && ( cd "$cli" && @@ -99,7 +99,7 @@ test_expect_success 'submit --dry-run --export-labels' ' git commit -m "dry-run2" dry-run2 && git tag -m "dry-run-tag1" dry-run-tag1 HEAD^ && git p4 submit --dry-run --export-labels >out && - test_i18ngrep "Would create p4 label" out + test_grep "Would create p4 label" out ) && ( cd "$cli" && @@ -443,7 +443,7 @@ test_expect_success 'description with Jobs section and bogus following text' ' # build a job make_job $(cat jobname) && test_must_fail git p4 submit 2>err && - test_i18ngrep "Unknown field name" err + test_grep "Unknown field name" err ) && ( cd "$cli" && @@ -461,9 +461,9 @@ test_expect_success 'submit --prepare-p4-only' ' git add prep-only-add && git commit -m "prep only add" && git p4 submit --prepare-p4-only >out && - test_i18ngrep "prepared for submission" out && - test_i18ngrep "must be deleted" out && - test_i18ngrep ! "everything below this line is just the diff" out + test_grep "prepared for submission" out && + test_grep "must be deleted" out && + test_grep ! "everything below this line is just the diff" out ) && ( cd "$cli" && diff --git a/t/t9815-git-p4-submit-fail.sh b/t/t9815-git-p4-submit-fail.sh index 0ca9937de6..c766fd159f 100755 --- a/t/t9815-git-p4-submit-fail.sh +++ b/t/t9815-git-p4-submit-fail.sh @@ -35,7 +35,7 @@ test_expect_success 'conflict on one commit' ' git add file1 && git commit -m "line3 in file1 will conflict" && test_expect_code 1 git p4 submit >out && - test_i18ngrep "No commits applied" out + test_grep "No commits applied" out ) ' @@ -58,7 +58,7 @@ test_expect_success 'conflict on second of two commits' ' git add file1 && git commit -m "line4 in file1 will conflict" && test_expect_code 1 git p4 submit >out && - test_i18ngrep "Applied only the commits" out + test_grep "Applied only the commits" out ) ' @@ -81,7 +81,7 @@ test_expect_success 'conflict on first of two commits, skip' ' # but this commit is okay test_commit "okay_commit_after_skip" && echo s | test_expect_code 1 git p4 submit >out && - test_i18ngrep "Applied only the commits" out + test_grep "Applied only the commits" out ) ' @@ -104,7 +104,7 @@ test_expect_success 'conflict on first of two commits, quit' ' # but this commit is okay test_commit "okay_commit_after_quit" && echo q | test_expect_code 1 git p4 submit >out && - test_i18ngrep "No commits applied" out + test_grep "No commits applied" out ) ' @@ -144,7 +144,7 @@ test_expect_success 'conflict on first of two commits, --conflict=skip' ' # but this commit is okay test_commit "okay_commit_after_auto_skip" && test_expect_code 1 git p4 submit --conflict=skip >out && - test_i18ngrep "Applied only the commits" out + test_grep "Applied only the commits" out ) ' @@ -167,7 +167,7 @@ test_expect_success 'conflict on first of two commits, --conflict=quit' ' # but this commit is okay test_commit "okay_commit_after_auto_quit" && test_expect_code 1 git p4 submit --conflict=quit >out && - test_i18ngrep "No commits applied" out + test_grep "No commits applied" out ) ' diff --git a/t/t9816-git-p4-locked.sh b/t/t9816-git-p4-locked.sh index 932841003c..5e904ac80d 100755 --- a/t/t9816-git-p4-locked.sh +++ b/t/t9816-git-p4-locked.sh @@ -9,7 +9,7 @@ test_expect_success 'start p4d' ' ' # See -# http://www.perforce.com/perforce/doc.current/manuals/p4sag/03_superuser.html#1088563 +# https://web.archive.org/web/20150602090517/http://www.perforce.com/perforce/doc.current/manuals/p4sag/chapter.superuser.html#superuser.basic.typemap_locking # for suggestions on how to configure "sitewide pessimistic locking" # where only one person can have a file open for edit at a time. test_expect_success 'init depot' ' diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh index d6c0478d98..aa9a614de3 100755 --- a/t/t9902-completion.sh +++ b/t/t9902-completion.sh @@ -405,40 +405,40 @@ test_expect_success '__gitdir - remote as argument' ' test_expect_success '__git_dequote - plain unquoted word' ' __git_dequote unquoted-word && - verbose test unquoted-word = "$dequoted_word" + test unquoted-word = "$dequoted_word" ' # input: b\a\c\k\'\\\"s\l\a\s\h\es # expected: back'\"slashes test_expect_success '__git_dequote - backslash escaped' ' __git_dequote "b\a\c\k\\'\''\\\\\\\"s\l\a\s\h\es" && - verbose test "back'\''\\\"slashes" = "$dequoted_word" + test "back'\''\\\"slashes" = "$dequoted_word" ' # input: sin'gle\' '"quo'ted # expected: single\ "quoted test_expect_success '__git_dequote - single quoted' ' __git_dequote "'"sin'gle\\\\' '\\\"quo'ted"'" && - verbose test '\''single\ "quoted'\'' = "$dequoted_word" + test '\''single\ "quoted'\'' = "$dequoted_word" ' # input: dou"ble\\" "\"\quot"ed # expected: double\ "\quoted test_expect_success '__git_dequote - double quoted' ' __git_dequote '\''dou"ble\\" "\"\quot"ed'\'' && - verbose test '\''double\ "\quoted'\'' = "$dequoted_word" + test '\''double\ "\quoted'\'' = "$dequoted_word" ' # input: 'open single quote test_expect_success '__git_dequote - open single quote' ' __git_dequote "'\''open single quote" && - verbose test "open single quote" = "$dequoted_word" + test "open single quote" = "$dequoted_word" ' # input: "open double quote test_expect_success '__git_dequote - open double quote' ' __git_dequote "\"open double quote" && - verbose test "open double quote" = "$dequoted_word" + test "open double quote" = "$dequoted_word" ' @@ -616,7 +616,7 @@ test_expect_success '__git_is_configured_remote' ' test_when_finished "git remote remove remote_2" && git remote add remote_2 git://remote_2 && ( - verbose __git_is_configured_remote remote_2 && + __git_is_configured_remote remote_2 && test_must_fail __git_is_configured_remote non-existent ) ' @@ -1571,7 +1571,7 @@ test_expect_success FUNNYNAMES,!CYGWIN 'cone mode sparse-checkout completes dire ) ' -test_expect_success 'non-cone mode sparse-checkout uses bash completion' ' +test_expect_success 'non-cone mode sparse-checkout gives rooted paths' ' # reset sparse-checkout repo to non-cone mode git -C sparse-checkout sparse-checkout disable && git -C sparse-checkout sparse-checkout set --no-cone && @@ -1581,7 +1581,12 @@ test_expect_success 'non-cone mode sparse-checkout uses bash completion' ' # expected to be empty since we have not configured # custom completion for non-cone mode test_completion "git sparse-checkout set f" <<-\EOF - + /folder1/0/1/t.txt Z + /folder1/expected Z + /folder1/out Z + /folder1/out_sorted Z + /folder2/0/t.txt Z + /folder3/t.txt Z EOF ) ' @@ -1622,14 +1627,22 @@ test_expect_success 'git checkout - with -d, complete only references' ' ' test_expect_success 'git switch - with --track, complete only remote branches' ' - test_completion "git switch --track " <<-\EOF + test_completion "git switch --track " <<-\EOF && + other/branch-in-other Z + other/main-in-other Z + EOF + test_completion "git switch -t " <<-\EOF other/branch-in-other Z other/main-in-other Z EOF ' test_expect_success 'git checkout - with --track, complete only remote branches' ' - test_completion "git checkout --track " <<-\EOF + test_completion "git checkout --track " <<-\EOF && + other/branch-in-other Z + other/main-in-other Z + EOF + test_completion "git checkout -t " <<-\EOF other/branch-in-other Z other/main-in-other Z EOF @@ -2456,6 +2469,24 @@ test_expect_success 'completion used <cmd> completion for alias: !f() { : git <c EOF ' +test_expect_success 'completion used <cmd> completion for alias: !f() { : <cmd> ; ... }' ' + test_config alias.co "!f() { : checkout ; if ... } f" && + test_completion "git co m" <<-\EOF + main Z + mybranch Z + mytag Z + EOF +' + +test_expect_success 'completion used <cmd> completion for alias: !f() { : <cmd>; ... }' ' + test_config alias.co "!f() { : checkout; if ... } f" && + test_completion "git co m" <<-\EOF + main Z + mybranch Z + mytag Z + EOF +' + test_expect_success 'completion without explicit _git_xxx function' ' test_completion "git version --" <<-\EOF --build-options Z @@ -2596,30 +2627,30 @@ test_expect_success 'options with value' ' test_expect_success 'sourcing the completion script clears cached commands' ' ( __git_compute_all_commands && - verbose test -n "$__git_all_commands" && + test -n "$__git_all_commands" && . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" && - verbose test -z "$__git_all_commands" + test -z "$__git_all_commands" ) ' test_expect_success 'sourcing the completion script clears cached merge strategies' ' ( __git_compute_merge_strategies && - verbose test -n "$__git_merge_strategies" && + test -n "$__git_merge_strategies" && . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" && - verbose test -z "$__git_merge_strategies" + test -z "$__git_merge_strategies" ) ' test_expect_success 'sourcing the completion script clears cached --options' ' ( __gitcomp_builtin checkout && - verbose test -n "$__gitcomp_builtin_checkout" && + test -n "$__gitcomp_builtin_checkout" && __gitcomp_builtin notes_edit && - verbose test -n "$__gitcomp_builtin_notes_edit" && + test -n "$__gitcomp_builtin_notes_edit" && . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" && - verbose test -z "$__gitcomp_builtin_checkout" && - verbose test -z "$__gitcomp_builtin_notes_edit" + test -z "$__gitcomp_builtin_checkout" && + test -z "$__gitcomp_builtin_notes_edit" ) ' diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh index d459fae655..d667dda654 100755 --- a/t/t9903-bash-prompt.sh +++ b/t/t9903-bash-prompt.sh @@ -13,10 +13,10 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME . "$GIT_BUILD_DIR/contrib/completion/git-prompt.sh" actual="$TRASH_DIRECTORY/actual" -c_red='\\[\\e[31m\\]' -c_green='\\[\\e[32m\\]' -c_lblue='\\[\\e[1;34m\\]' -c_clear='\\[\\e[0m\\]' +c_red='\001\e[31m\002' +c_green='\001\e[32m\002' +c_lblue='\001\e[1;34m\002' +c_clear='\001\e[0m\002' test_expect_success 'setup for prompt tests' ' git init otherrepo && diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index 999d46fafe..03292602fb 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -14,7 +14,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see http://www.gnu.org/licenses/ . +# along with this program. If not, see https://www.gnu.org/licenses/ . # The semantics of the editor variables are that of invoking # sh -c "$EDITOR \"$@\"" files ... @@ -251,6 +251,61 @@ debug () { done } +# Usage: test_ref_exists [options] <ref> +# +# -C <dir>: +# Run all git commands in directory <dir> +# +# This helper function checks whether a reference exists. Symrefs or object IDs +# will not be resolved. Can be used to check references with bad names. +test_ref_exists () { + local indir= + + while test $# != 0 + do + case "$1" in + -C) + indir="$2" + shift + ;; + *) + break + ;; + esac + shift + done && + + indir=${indir:+"$indir"/} && + + if test "$#" != 1 + then + BUG "expected exactly one reference" + fi && + + git ${indir:+ -C "$indir"} show-ref --exists "$1" +} + +# Behaves the same as test_ref_exists, except that it checks for the absence of +# a reference. This is preferable to `! test_ref_exists` as this function is +# able to distinguish actually-missing references from other, generic errors. +test_ref_missing () { + test_ref_exists "$@" + case "$?" in + 2) + # This is the good case. + return 0 + ;; + 0) + echo >&4 "test_ref_missing: reference exists" + return 1 + ;; + *) + echo >&4 "test_ref_missing: generic error" + return 1 + ;; + esac +} + # Usage: test_commit [options] <message> [<file> [<contents> [<tag>]]] # -C <dir>: # Run all git commands in directory <dir> @@ -542,8 +597,17 @@ test_config () { config_dir=$1 shift fi - test_when_finished "test_unconfig ${config_dir:+-C '$config_dir'} '$1'" && - git ${config_dir:+-C "$config_dir"} config "$@" + + # If --worktree is provided, use it to configure/unconfigure + is_worktree= + if test "$1" = --worktree + then + is_worktree=1 + shift + fi + + test_when_finished "test_unconfig ${config_dir:+-C '$config_dir'} ${is_worktree:+--worktree} '$1'" && + git ${config_dir:+-C "$config_dir"} config ${is_worktree:+--worktree} "$@" } test_config_global () { @@ -901,6 +965,15 @@ test_path_is_symlink () { fi } +test_path_is_executable () { + test "$#" -ne 1 && BUG "1 param" + if ! test -x "$1" + then + echo "$1 is not executable" + false + fi +} + # Check if the directory exists and is empty as expected, barf otherwise. test_dir_is_empty () { test "$#" -ne 1 && BUG "1 param" @@ -1190,14 +1263,16 @@ test_cmp_bin () { cmp "$@" } -# Wrapper for grep which used to be used for -# GIT_TEST_GETTEXT_POISON=false. Only here as a shim for other -# in-flight changes. Should not be used and will be removed soon. +# Deprecated - do not use this in new code test_i18ngrep () { + test_grep "$@" +} + +test_grep () { eval "last_arg=\${$#}" test -f "$last_arg" || - BUG "test_i18ngrep requires a file to read as the last parameter" + BUG "test_grep requires a file to read as the last parameter" if test $# -lt 2 || { test "x!" = "x$1" && test $# -lt 3 ; } @@ -1227,15 +1302,6 @@ test_i18ngrep () { return 1 } -# Call any command "$@" but be more verbose about its -# failure. This is handy for commands like "test" which do -# not output anything when they fail. -verbose () { - "$@" && return 0 - echo >&4 "command failed: $(git rev-parse --sq-quote "$@")" - return 1 -} - # Check if the file expected to be empty is indeed empty, and barfs # otherwise. @@ -1282,6 +1348,39 @@ test_cmp_rev () { fi } +# Tests that a commit message matches the expected text +# +# Usage: test_commit_message <rev> [-m <msg> | <file>] +# +# When using "-m" <msg> will have a line feed appended. If the second +# argument is omitted then the expected message is read from stdin. + +test_commit_message () { + local msg_file=expect.msg + + case $# in + 3) + if test "$2" = "-m" + then + printf "%s\n" "$3" >"$msg_file" + else + BUG "Usage: test_commit_message <rev> [-m <message> | <file>]" + fi + ;; + 2) + msg_file="$2" + ;; + 1) + cat >"$msg_file" + ;; + *) + BUG "Usage: test_commit_message <rev> [-m <message> | <file>]" + ;; + esac + git show --no-patch --pretty=format:%B "$1" -- >actual.msg && + test_cmp "$msg_file" actual.msg +} + # Compare paths respecting core.ignoreCase test_cmp_fspath () { if test "x$1" = "x$2" diff --git a/t/test-lib-github-workflow-markup.sh b/t/test-lib-github-workflow-markup.sh index 9c5339c577..970c6538cb 100644 --- a/t/test-lib-github-workflow-markup.sh +++ b/t/test-lib-github-workflow-markup.sh @@ -14,7 +14,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see http://www.gnu.org/licenses/ . +# along with this program. If not, see https://www.gnu.org/licenses/ . # # The idea is for `test-lib.sh` to source this file when run in GitHub # workflows; these functions will then override (empty) functions diff --git a/t/test-lib-junit.sh b/t/test-lib-junit.sh index 79c31c788b..76cbbd3299 100644 --- a/t/test-lib-junit.sh +++ b/t/test-lib-junit.sh @@ -15,7 +15,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see http://www.gnu.org/licenses/ . +# along with this program. If not, see https://www.gnu.org/licenses/ . # # The idea is for `test-lib.sh` to source this file when the user asks # for JUnit XML; these functions will then override (empty) functions diff --git a/t/test-lib.sh b/t/test-lib.sh index 62136caee5..876b99562a 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -13,7 +13,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program. If not, see http://www.gnu.org/licenses/ . +# along with this program. If not, see https://www.gnu.org/licenses/ . # Test the binaries we have just built. The tests are kept in # t/ subdirectory and are run in 'trash directory' subdirectory. @@ -89,6 +89,9 @@ prepend_var LSAN_OPTIONS : $GIT_SAN_OPTIONS prepend_var LSAN_OPTIONS : fast_unwind_on_malloc=0 export LSAN_OPTIONS +prepend_var UBSAN_OPTIONS : $GIT_SAN_OPTIONS +export UBSAN_OPTIONS + if test ! -f "$GIT_BUILD_DIR"/GIT-BUILD-OPTIONS then echo >&2 'error: GIT-BUILD-OPTIONS missing (has Git been built?).' @@ -334,6 +337,7 @@ nr_san_dir_leaks_ () { find "$TEST_RESULTS_SAN_DIR" \ -type f \ -name "$TEST_RESULTS_SAN_FILE_PFX.*" 2>/dev/null | + xargs grep -lv "Unable to get registers from thread" | wc -l } @@ -1041,10 +1045,7 @@ want_trace () { # (and we want to make sure we run any cleanup like # "set +x"). test_eval_inner_ () { - # Do not add anything extra (including LF) after '$*' - eval " - want_trace && trace_level_=$(($trace_level_+1)) && set -x - $*" + eval "$*" } test_eval_ () { @@ -1069,7 +1070,10 @@ test_eval_ () { # be _inside_ the block to avoid polluting the "set -x" output # - test_eval_inner_ "$@" </dev/null >&3 2>&4 + # Do not add anything extra (including LF) after '$*' + test_eval_inner_ </dev/null >&3 2>&4 " + want_trace && trace_level_=$(($trace_level_+1)) && set -x + $*" { test_eval_ret_=$? if want_trace @@ -1086,22 +1090,22 @@ test_eval_ () { return $test_eval_ret_ } +fail_117 () { + return 117 +} + test_run_ () { test_cleanup=: expecting_failure=$2 if test "${GIT_TEST_CHAIN_LINT:-1}" != 0; then - # turn off tracing for this test-eval, as it simply creates - # confusing noise in the "-x" output - trace_tmp=$trace - trace= # 117 is magic because it is unlikely to match the exit # code of other programs - if test "OK-117" != "$(test_eval_ "(exit 117) && $1${LF}${LF}echo OK-\$?" 3>&1)" + test_eval_inner_ "fail_117 && $1" </dev/null >&3 2>&4 + if test $? != 117 then - BUG "broken &&-chain or run-away HERE-DOC: $1" + BUG "broken &&-chain: $1" fi - trace=$trace_tmp fi setup_malloc_check @@ -1593,7 +1597,8 @@ then BAIL_OUT_ENV_NEEDS_SANITIZE_LEAK "GIT_TEST_SANITIZE_LEAK_LOG=true" fi -if test "${GIT_TEST_CHAIN_LINT:-1}" != 0 +if test "${GIT_TEST_CHAIN_LINT:-1}" != 0 && + test "${GIT_TEST_EXT_CHAIN_LINT:-1}" != 0 then "$PERL_PATH" "$TEST_DIRECTORY/chainlint.pl" "$0" || BUG "lint error (see '?!...!? annotations above)" diff --git a/t/test-terminal.perl b/t/test-terminal.perl index 1bcf01a9a4..3810e9bb43 100755 --- a/t/test-terminal.perl +++ b/t/test-terminal.perl @@ -1,5 +1,5 @@ #!/usr/bin/perl -use 5.008; +use 5.008001; use strict; use warnings; use IO::Pty; diff --git a/t/unit-tests/.gitignore b/t/unit-tests/.gitignore new file mode 100644 index 0000000000..5e56e040ec --- /dev/null +++ b/t/unit-tests/.gitignore @@ -0,0 +1 @@ +/bin diff --git a/t/unit-tests/t-basic.c b/t/unit-tests/t-basic.c new file mode 100644 index 0000000000..fda1ae59a6 --- /dev/null +++ b/t/unit-tests/t-basic.c @@ -0,0 +1,95 @@ +#include "test-lib.h" + +/* + * The purpose of this "unit test" is to verify a few invariants of the unit + * test framework itself, as well as to provide examples of output from actually + * failing tests. As such, it is intended that this test fails, and thus it + * should not be run as part of `make unit-tests`. Instead, we verify it behaves + * as expected in the integration test t0080-unit-test-output.sh + */ + +/* Used to store the return value of check_int(). */ +static int check_res; + +/* Used to store the return value of TEST(). */ +static int test_res; + +static void t_res(int expect) +{ + check_int(check_res, ==, expect); + check_int(test_res, ==, expect); +} + +static void t_todo(int x) +{ + check_res = TEST_TODO(check(x)); +} + +static void t_skip(void) +{ + check(0); + test_skip("missing prerequisite"); + check(1); +} + +static int do_skip(void) +{ + test_skip("missing prerequisite"); + return 1; +} + +static void t_skip_todo(void) +{ + check_res = TEST_TODO(do_skip()); +} + +static void t_todo_after_fail(void) +{ + check(0); + TEST_TODO(check(0)); +} + +static void t_fail_after_todo(void) +{ + check(1); + TEST_TODO(check(0)); + check(0); +} + +static void t_messages(void) +{ + check_str("\thello\\", "there\"\n"); + check_str("NULL", NULL); + check_char('a', ==, '\n'); + check_char('\\', ==, '\''); +} + +static void t_empty(void) +{ + ; /* empty */ +} + +int cmd_main(int argc, const char **argv) +{ + test_res = TEST(check_res = check_int(1, ==, 1), "passing test"); + TEST(t_res(1), "passing test and assertion return 1"); + test_res = TEST(check_res = check_int(1, ==, 2), "failing test"); + TEST(t_res(0), "failing test and assertion return 0"); + test_res = TEST(t_todo(0), "passing TEST_TODO()"); + TEST(t_res(1), "passing TEST_TODO() returns 1"); + test_res = TEST(t_todo(1), "failing TEST_TODO()"); + TEST(t_res(0), "failing TEST_TODO() returns 0"); + test_res = TEST(t_skip(), "test_skip()"); + TEST(check_int(test_res, ==, 1), "skipped test returns 1"); + test_res = TEST(t_skip_todo(), "test_skip() inside TEST_TODO()"); + TEST(t_res(1), "test_skip() inside TEST_TODO() returns 1"); + test_res = TEST(t_todo_after_fail(), "TEST_TODO() after failing check"); + TEST(check_int(test_res, ==, 0), "TEST_TODO() after failing check returns 0"); + test_res = TEST(t_fail_after_todo(), "failing check after TEST_TODO()"); + TEST(check_int(test_res, ==, 0), "failing check after TEST_TODO() returns 0"); + TEST(t_messages(), "messages from failing string and char comparison"); + test_res = TEST(t_empty(), "test with no checks"); + TEST(check_int(test_res, ==, 0), "test with no checks returns 0"); + + return test_done(); +} diff --git a/t/unit-tests/t-strbuf.c b/t/unit-tests/t-strbuf.c new file mode 100644 index 0000000000..de434a4441 --- /dev/null +++ b/t/unit-tests/t-strbuf.c @@ -0,0 +1,120 @@ +#include "test-lib.h" +#include "strbuf.h" + +/* wrapper that supplies tests with an empty, initialized strbuf */ +static void setup(void (*f)(struct strbuf*, void*), void *data) +{ + struct strbuf buf = STRBUF_INIT; + + f(&buf, data); + strbuf_release(&buf); + check_uint(buf.len, ==, 0); + check_uint(buf.alloc, ==, 0); +} + +/* wrapper that supplies tests with a populated, initialized strbuf */ +static void setup_populated(void (*f)(struct strbuf*, void*), char *init_str, void *data) +{ + struct strbuf buf = STRBUF_INIT; + + strbuf_addstr(&buf, init_str); + check_uint(buf.len, ==, strlen(init_str)); + f(&buf, data); + strbuf_release(&buf); + check_uint(buf.len, ==, 0); + check_uint(buf.alloc, ==, 0); +} + +static int assert_sane_strbuf(struct strbuf *buf) +{ + /* Initialized strbufs should always have a non-NULL buffer */ + if (!check(!!buf->buf)) + return 0; + /* Buffers should always be NUL-terminated */ + if (!check_char(buf->buf[buf->len], ==, '\0')) + return 0; + /* + * Freshly-initialized strbufs may not have a dynamically allocated + * buffer + */ + if (buf->len == 0 && buf->alloc == 0) + return 1; + /* alloc must be at least one byte larger than len */ + return check_uint(buf->len, <, buf->alloc); +} + +static void t_static_init(void) +{ + struct strbuf buf = STRBUF_INIT; + + check_uint(buf.len, ==, 0); + check_uint(buf.alloc, ==, 0); + check_char(buf.buf[0], ==, '\0'); +} + +static void t_dynamic_init(void) +{ + struct strbuf buf; + + strbuf_init(&buf, 1024); + check(assert_sane_strbuf(&buf)); + check_uint(buf.len, ==, 0); + check_uint(buf.alloc, >=, 1024); + check_char(buf.buf[0], ==, '\0'); + strbuf_release(&buf); +} + +static void t_addch(struct strbuf *buf, void *data) +{ + const char *p_ch = data; + const char ch = *p_ch; + size_t orig_alloc = buf->alloc; + size_t orig_len = buf->len; + + if (!check(assert_sane_strbuf(buf))) + return; + strbuf_addch(buf, ch); + if (!check(assert_sane_strbuf(buf))) + return; + if (!(check_uint(buf->len, ==, orig_len + 1) && + check_uint(buf->alloc, >=, orig_alloc))) + return; /* avoid de-referencing buf->buf */ + check_char(buf->buf[buf->len - 1], ==, ch); + check_char(buf->buf[buf->len], ==, '\0'); +} + +static void t_addstr(struct strbuf *buf, void *data) +{ + const char *text = data; + size_t len = strlen(text); + size_t orig_alloc = buf->alloc; + size_t orig_len = buf->len; + + if (!check(assert_sane_strbuf(buf))) + return; + strbuf_addstr(buf, text); + if (!check(assert_sane_strbuf(buf))) + return; + if (!(check_uint(buf->len, ==, orig_len + len) && + check_uint(buf->alloc, >=, orig_alloc) && + check_uint(buf->alloc, >, orig_len + len) && + check_char(buf->buf[orig_len + len], ==, '\0'))) + return; + check_str(buf->buf + orig_len, text); +} + +int cmd_main(int argc, const char **argv) +{ + if (!TEST(t_static_init(), "static initialization works")) + test_skip_all("STRBUF_INIT is broken"); + TEST(t_dynamic_init(), "dynamic initialization works"); + TEST(setup(t_addch, "a"), "strbuf_addch adds char"); + TEST(setup(t_addch, ""), "strbuf_addch adds NUL char"); + TEST(setup_populated(t_addch, "initial value", "a"), + "strbuf_addch appends to initial value"); + TEST(setup(t_addstr, "hello there"), "strbuf_addstr adds string"); + TEST(setup_populated(t_addstr, "initial value", "hello there"), + "strbuf_addstr appends string to initial value"); + + return test_done(); +} diff --git a/t/unit-tests/test-lib.c b/t/unit-tests/test-lib.c new file mode 100644 index 0000000000..7bf9dfdb95 --- /dev/null +++ b/t/unit-tests/test-lib.c @@ -0,0 +1,374 @@ +#include "test-lib.h" + +enum result { + RESULT_NONE, + RESULT_FAILURE, + RESULT_SKIP, + RESULT_SUCCESS, + RESULT_TODO +}; + +static struct { + enum result result; + int count; + unsigned failed :1; + unsigned lazy_plan :1; + unsigned running :1; + unsigned skip_all :1; + unsigned todo :1; +} ctx = { + .lazy_plan = 1, + .result = RESULT_NONE, +}; + +#ifndef _MSC_VER +#define make_relative(location) location +#else +/* + * Visual C interpolates the absolute Windows path for `__FILE__`, + * but we want to see relative paths, as verified by t0080. + */ +#include "dir.h" + +static const char *make_relative(const char *location) +{ + static char prefix[] = __FILE__, buf[PATH_MAX], *p; + static size_t prefix_len; + + if (!prefix_len) { + size_t len = strlen(prefix); + const char *needle = "\\t\\unit-tests\\test-lib.c"; + size_t needle_len = strlen(needle); + + if (len < needle_len || strcmp(needle, prefix + len - needle_len)) + die("unexpected suffix of '%s'", prefix); + + /* let it end in a directory separator */ + prefix_len = len - needle_len + 1; + } + + /* Does it not start with the expected prefix? */ + if (fspathncmp(location, prefix, prefix_len)) + return location; + + strlcpy(buf, location + prefix_len, sizeof(buf)); + /* convert backslashes to forward slashes */ + for (p = buf; *p; p++) + if (*p == '\\') + *p = '/'; + + return buf; +} +#endif + +static void msg_with_prefix(const char *prefix, const char *format, va_list ap) +{ + fflush(stderr); + if (prefix) + fprintf(stdout, "%s", prefix); + vprintf(format, ap); /* TODO: handle newlines */ + putc('\n', stdout); + fflush(stdout); +} + +void test_msg(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + msg_with_prefix("# ", format, ap); + va_end(ap); +} + +void test_plan(int count) +{ + assert(!ctx.running); + + fflush(stderr); + printf("1..%d\n", count); + fflush(stdout); + ctx.lazy_plan = 0; +} + +int test_done(void) +{ + assert(!ctx.running); + + if (ctx.lazy_plan) + test_plan(ctx.count); + + return ctx.failed; +} + +void test_skip(const char *format, ...) +{ + va_list ap; + + assert(ctx.running); + + ctx.result = RESULT_SKIP; + va_start(ap, format); + if (format) + msg_with_prefix("# skipping test - ", format, ap); + va_end(ap); +} + +void test_skip_all(const char *format, ...) +{ + va_list ap; + const char *prefix; + + if (!ctx.count && ctx.lazy_plan) { + /* We have not printed a test plan yet */ + prefix = "1..0 # SKIP "; + ctx.lazy_plan = 0; + } else { + /* We have already printed a test plan */ + prefix = "Bail out! # "; + ctx.failed = 1; + } + ctx.skip_all = 1; + ctx.result = RESULT_SKIP; + va_start(ap, format); + msg_with_prefix(prefix, format, ap); + va_end(ap); +} + +int test__run_begin(void) +{ + assert(!ctx.running); + + ctx.count++; + ctx.result = RESULT_NONE; + ctx.running = 1; + + return ctx.skip_all; +} + +static void print_description(const char *format, va_list ap) +{ + if (format) { + fputs(" - ", stdout); + vprintf(format, ap); + } +} + +int test__run_end(int was_run UNUSED, const char *location, const char *format, ...) +{ + va_list ap; + + assert(ctx.running); + assert(!ctx.todo); + + fflush(stderr); + va_start(ap, format); + if (!ctx.skip_all) { + switch (ctx.result) { + case RESULT_SUCCESS: + printf("ok %d", ctx.count); + print_description(format, ap); + break; + + case RESULT_FAILURE: + printf("not ok %d", ctx.count); + print_description(format, ap); + break; + + case RESULT_TODO: + printf("not ok %d", ctx.count); + print_description(format, ap); + printf(" # TODO"); + break; + + case RESULT_SKIP: + printf("ok %d", ctx.count); + print_description(format, ap); + printf(" # SKIP"); + break; + + case RESULT_NONE: + test_msg("BUG: test has no checks at %s", + make_relative(location)); + printf("not ok %d", ctx.count); + print_description(format, ap); + ctx.result = RESULT_FAILURE; + break; + } + } + va_end(ap); + ctx.running = 0; + if (ctx.skip_all) + return 1; + putc('\n', stdout); + fflush(stdout); + ctx.failed |= ctx.result == RESULT_FAILURE; + + return ctx.result != RESULT_FAILURE; +} + +static void test_fail(void) +{ + assert(ctx.result != RESULT_SKIP); + + ctx.result = RESULT_FAILURE; +} + +static void test_pass(void) +{ + assert(ctx.result != RESULT_SKIP); + + if (ctx.result == RESULT_NONE) + ctx.result = RESULT_SUCCESS; +} + +static void test_todo(void) +{ + assert(ctx.result != RESULT_SKIP); + + if (ctx.result != RESULT_FAILURE) + ctx.result = RESULT_TODO; +} + +int test_assert(const char *location, const char *check, int ok) +{ + assert(ctx.running); + + if (ctx.result == RESULT_SKIP) { + test_msg("skipping check '%s' at %s", check, + make_relative(location)); + return 1; + } + if (!ctx.todo) { + if (ok) { + test_pass(); + } else { + test_msg("check \"%s\" failed at %s", check, + make_relative(location)); + test_fail(); + } + } + + return !!ok; +} + +void test__todo_begin(void) +{ + assert(ctx.running); + assert(!ctx.todo); + + ctx.todo = 1; +} + +int test__todo_end(const char *location, const char *check, int res) +{ + assert(ctx.running); + assert(ctx.todo); + + ctx.todo = 0; + if (ctx.result == RESULT_SKIP) + return 1; + if (res) { + test_msg("todo check '%s' succeeded at %s", check, + make_relative(location)); + test_fail(); + } else { + test_todo(); + } + + return !res; +} + +int check_bool_loc(const char *loc, const char *check, int ok) +{ + return test_assert(loc, check, ok); +} + +union test__tmp test__tmp[2]; + +int check_int_loc(const char *loc, const char *check, int ok, + intmax_t a, intmax_t b) +{ + int ret = test_assert(loc, check, ok); + + if (!ret) { + test_msg(" left: %"PRIdMAX, a); + test_msg(" right: %"PRIdMAX, b); + } + + return ret; +} + +int check_uint_loc(const char *loc, const char *check, int ok, + uintmax_t a, uintmax_t b) +{ + int ret = test_assert(loc, check, ok); + + if (!ret) { + test_msg(" left: %"PRIuMAX, a); + test_msg(" right: %"PRIuMAX, b); + } + + return ret; +} + +static void print_one_char(char ch, char quote) +{ + if ((unsigned char)ch < 0x20u || ch == 0x7f) { + /* TODO: improve handling of \a, \b, \f ... */ + printf("\\%03o", (unsigned char)ch); + } else { + if (ch == '\\' || ch == quote) + putc('\\', stdout); + putc(ch, stdout); + } +} + +static void print_char(const char *prefix, char ch) +{ + printf("# %s: '", prefix); + print_one_char(ch, '\''); + fputs("'\n", stdout); +} + +int check_char_loc(const char *loc, const char *check, int ok, char a, char b) +{ + int ret = test_assert(loc, check, ok); + + if (!ret) { + fflush(stderr); + print_char(" left", a); + print_char(" right", b); + fflush(stdout); + } + + return ret; +} + +static void print_str(const char *prefix, const char *str) +{ + printf("# %s: ", prefix); + if (!str) { + fputs("NULL\n", stdout); + } else { + putc('"', stdout); + while (*str) + print_one_char(*str++, '"'); + fputs("\"\n", stdout); + } +} + +int check_str_loc(const char *loc, const char *check, + const char *a, const char *b) +{ + int ok = (!a && !b) || (a && b && !strcmp(a, b)); + int ret = test_assert(loc, check, ok); + + if (!ret) { + fflush(stderr); + print_str(" left", a); + print_str(" right", b); + fflush(stdout); + } + + return ret; +} diff --git a/t/unit-tests/test-lib.h b/t/unit-tests/test-lib.h new file mode 100644 index 0000000000..a8f07ae0b7 --- /dev/null +++ b/t/unit-tests/test-lib.h @@ -0,0 +1,149 @@ +#ifndef TEST_LIB_H +#define TEST_LIB_H + +#include "git-compat-util.h" + +/* + * Run a test function, returns 1 if the test succeeds, 0 if it + * fails. If test_skip_all() has been called then the test will not be + * run. The description for each test should be unique. For example: + * + * TEST(test_something(arg1, arg2), "something %d %d", arg1, arg2) + */ +#define TEST(t, ...) \ + test__run_end(test__run_begin() ? 0 : (t, 1), \ + TEST_LOCATION(), __VA_ARGS__) + +/* + * Print a test plan, should be called before any tests. If the number + * of tests is not known in advance test_done() will automatically + * print a plan at the end of the test program. + */ +void test_plan(int count); + +/* + * test_done() must be called at the end of main(). It will print the + * plan if plan() was not called at the beginning of the test program + * and returns the exit code for the test program. + */ +int test_done(void); + +/* Skip the current test. */ +__attribute__((format (printf, 1, 2))) +void test_skip(const char *format, ...); + +/* Skip all remaining tests. */ +__attribute__((format (printf, 1, 2))) +void test_skip_all(const char *format, ...); + +/* Print a diagnostic message to stdout. */ +__attribute__((format (printf, 1, 2))) +void test_msg(const char *format, ...); + +/* + * Test checks are built around test_assert(). checks return 1 on + * success, 0 on failure. If any check fails then the test will fail. To + * create a custom check define a function that wraps test_assert() and + * a macro to wrap that function to provide a source location and + * stringified arguments. Custom checks that take pointer arguments + * should be careful to check that they are non-NULL before + * dereferencing them. For example: + * + * static int check_oid_loc(const char *loc, const char *check, + * struct object_id *a, struct object_id *b) + * { + * int res = test_assert(loc, check, a && b && oideq(a, b)); + * + * if (!res) { + * test_msg(" left: %s", a ? oid_to_hex(a) : "NULL"; + * test_msg(" right: %s", b ? oid_to_hex(a) : "NULL"; + * + * } + * return res; + * } + * + * #define check_oid(a, b) \ + * check_oid_loc(TEST_LOCATION(), "oideq("#a", "#b")", a, b) + */ +int test_assert(const char *location, const char *check, int ok); + +/* Helper macro to pass the location to checks */ +#define TEST_LOCATION() TEST__MAKE_LOCATION(__LINE__) + +/* Check a boolean condition. */ +#define check(x) \ + check_bool_loc(TEST_LOCATION(), #x, x) +int check_bool_loc(const char *loc, const char *check, int ok); + +/* + * Compare two integers. Prints a message with the two values if the + * comparison fails. NB this is not thread safe. + */ +#define check_int(a, op, b) \ + (test__tmp[0].i = (a), test__tmp[1].i = (b), \ + check_int_loc(TEST_LOCATION(), #a" "#op" "#b, \ + test__tmp[0].i op test__tmp[1].i, \ + test__tmp[0].i, test__tmp[1].i)) +int check_int_loc(const char *loc, const char *check, int ok, + intmax_t a, intmax_t b); + +/* + * Compare two unsigned integers. Prints a message with the two values + * if the comparison fails. NB this is not thread safe. + */ +#define check_uint(a, op, b) \ + (test__tmp[0].u = (a), test__tmp[1].u = (b), \ + check_uint_loc(TEST_LOCATION(), #a" "#op" "#b, \ + test__tmp[0].u op test__tmp[1].u, \ + test__tmp[0].u, test__tmp[1].u)) +int check_uint_loc(const char *loc, const char *check, int ok, + uintmax_t a, uintmax_t b); + +/* + * Compare two chars. Prints a message with the two values if the + * comparison fails. NB this is not thread safe. + */ +#define check_char(a, op, b) \ + (test__tmp[0].c = (a), test__tmp[1].c = (b), \ + check_char_loc(TEST_LOCATION(), #a" "#op" "#b, \ + test__tmp[0].c op test__tmp[1].c, \ + test__tmp[0].c, test__tmp[1].c)) +int check_char_loc(const char *loc, const char *check, int ok, + char a, char b); + +/* Check whether two strings are equal. */ +#define check_str(a, b) \ + check_str_loc(TEST_LOCATION(), "!strcmp("#a", "#b")", a, b) +int check_str_loc(const char *loc, const char *check, + const char *a, const char *b); + +/* + * Wrap a check that is known to fail. If the check succeeds then the + * test will fail. Returns 1 if the check fails, 0 if it + * succeeds. For example: + * + * TEST_TODO(check(0)); + */ +#define TEST_TODO(check) \ + (test__todo_begin(), test__todo_end(TEST_LOCATION(), #check, check)) + +/* Private helpers */ + +#define TEST__STR(x) #x +#define TEST__MAKE_LOCATION(line) __FILE__ ":" TEST__STR(line) + +union test__tmp { + intmax_t i; + uintmax_t u; + char c; +}; + +extern union test__tmp test__tmp[2]; + +int test__run_begin(void); +__attribute__((format (printf, 3, 4))) +int test__run_end(int, const char *, const char *, ...); +void test__todo_begin(void); +int test__todo_end(const char *, const char *, int); + +#endif /* TEST_LIB_H */ diff --git a/t/valgrind/valgrind.sh b/t/valgrind/valgrind.sh index 669ebaf68b..3c8ee19975 100755 --- a/t/valgrind/valgrind.sh +++ b/t/valgrind/valgrind.sh @@ -23,7 +23,7 @@ memcheck) VALGRIND_MAJOR=$(expr "$VALGRIND_VERSION" : '[^0-9]*\([0-9]*\)') VALGRIND_MINOR=$(expr "$VALGRIND_VERSION" : '[^0-9]*[0-9]*\.\([0-9]*\)') test 3 -gt "$VALGRIND_MAJOR" || - test 3 -eq "$VALGRIND_MAJOR" -a 4 -gt "$VALGRIND_MINOR" || + { test 3 -eq "$VALGRIND_MAJOR" && test 4 -gt "$VALGRIND_MINOR"; } || TOOL_OPTIONS="$TOOL_OPTIONS --track-origins=yes" ;; *) |