diff options
Diffstat (limited to 't')
101 files changed, 3126 insertions, 561 deletions
@@ -803,9 +803,9 @@ use these, and "test_set_prereq" for how to define your own. Test is not run by root user, and an attempt to write to an unwritable file is expected to fail correctly. - - LIBPCRE + - PCRE - Git was compiled with USE_LIBPCRE=YesPlease. Wrap any tests + Git was compiled with support for PCRE. Wrap any tests that use git-grep --perl-regexp or git-grep -P in these. - CASE_INSENSITIVE_FS @@ -817,6 +817,10 @@ use these, and "test_set_prereq" for how to define your own. Test is run on a filesystem which converts decomposed utf-8 (nfd) to precomposed utf-8 (nfc). + - PTHREADS + + Git wasn't compiled with NO_PTHREADS=YesPlease. + Tips for Writing Tests ---------------------- diff --git a/t/helper/test-config.c b/t/helper/test-config.c index 8e3ed6a76c..1a7b8bd3d6 100644 --- a/t/helper/test-config.c +++ b/t/helper/test-config.c @@ -1,4 +1,5 @@ #include "cache.h" +#include "config.h" #include "string-list.h" /* diff --git a/t/helper/test-date.c b/t/helper/test-date.c index 506054bcd5..f414a3ac67 100644 --- a/t/helper/test-date.c +++ b/t/helper/test-date.c @@ -4,7 +4,9 @@ static const char *usage_msg = "\n" " test-date relative [time_t]...\n" " test-date show:<format> [time_t]...\n" " test-date parse [date]...\n" -" test-date approxidate [date]...\n"; +" test-date approxidate [date]...\n" +" test-date is64bit\n" +" test-date time_t-is64bit\n"; static void show_relative_dates(const char **argv, struct timeval *now) { @@ -25,14 +27,14 @@ static void show_dates(const char **argv, const char *format) parse_date_format(format, &mode); for (; *argv; argv++) { char *arg; - time_t t; + timestamp_t t; int tz; /* * Do not use our normal timestamp parsing here, as the point * is to test the formatting code in isolation. */ - t = strtol(*argv, &arg, 10); + t = parse_timestamp(*argv, &arg, 10); while (*arg == ' ') arg++; tz = atoi(arg); @@ -46,12 +48,12 @@ static void parse_dates(const char **argv, struct timeval *now) struct strbuf result = STRBUF_INIT; for (; *argv; argv++) { - unsigned long t; + timestamp_t t; int tz; strbuf_reset(&result); parse_date(*argv, &result); - if (sscanf(result.buf, "%lu %d", &t, &tz) == 2) + if (sscanf(result.buf, "%"PRItime" %d", &t, &tz) == 2) printf("%s -> %s\n", *argv, show_date(t, tz, DATE_MODE(ISO8601))); else @@ -63,7 +65,7 @@ static void parse_dates(const char **argv, struct timeval *now) static void parse_approxidate(const char **argv, struct timeval *now) { for (; *argv; argv++) { - time_t t; + timestamp_t t; t = approxidate_relative(*argv, now); printf("%s -> %s\n", *argv, show_date(t, 0, DATE_MODE(ISO8601))); } @@ -93,6 +95,10 @@ int cmd_main(int argc, const char **argv) parse_dates(argv+1, &now); else if (!strcmp(*argv, "approxidate")) parse_approxidate(argv+1, &now); + else if (!strcmp(*argv, "is64bit")) + return sizeof(timestamp_t) == 8 ? 0 : 1; + else if (!strcmp(*argv, "time_t-is64bit")) + return sizeof(time_t) == 8 ? 0 : 1; else usage(usage_msg); return 0; diff --git a/t/helper/test-dump-cache-tree.c b/t/helper/test-dump-cache-tree.c index 7af116d49e..ebf3aab22d 100644 --- a/t/helper/test-dump-cache-tree.c +++ b/t/helper/test-dump-cache-tree.c @@ -10,7 +10,7 @@ static void dump_one(struct cache_tree *it, const char *pfx, const char *x) "invalid", x, pfx, it->subtree_nr); else printf("%s %s%s (%d entries, %d subtrees)\n", - sha1_to_hex(it->sha1), x, pfx, + oid_to_hex(&it->oid), x, pfx, it->entry_count, it->subtree_nr); } @@ -32,7 +32,7 @@ static int dump_cache_tree(struct cache_tree *it, } else { dump_one(it, pfx, ""); - if (hashcmp(it->sha1, ref->sha1) || + if (oidcmp(&it->oid, &ref->oid) || ref->entry_count != it->entry_count || ref->subtree_nr != it->subtree_nr) { /* claims to be valid but is lying */ diff --git a/t/helper/test-hashmap.c b/t/helper/test-hashmap.c index 7aa9440e27..6004c81f0b 100644 --- a/t/helper/test-hashmap.c +++ b/t/helper/test-hashmap.c @@ -13,16 +13,20 @@ static const char *get_value(const struct test_entry *e) return e->key + strlen(e->key) + 1; } -static int test_entry_cmp(const struct test_entry *e1, - const struct test_entry *e2, const char* key) +static int test_entry_cmp(const void *cmp_data, + const void *entry, + const void *entry_or_key, + const void *keydata) { - return strcmp(e1->key, key ? key : e2->key); -} - -static int test_entry_cmp_icase(const struct test_entry *e1, - const struct test_entry *e2, const char* key) -{ - return strcasecmp(e1->key, key ? key : e2->key); + const int ignore_case = cmp_data ? *((int *)cmp_data) : 0; + const struct test_entry *e1 = entry; + const struct test_entry *e2 = entry_or_key; + const char *key = keydata; + + if (ignore_case) + return strcasecmp(e1->key, key ? key : e2->key); + else + return strcmp(e1->key, key ? key : e2->key); } static struct test_entry *alloc_test_entry(int hash, char *key, int klen, @@ -92,7 +96,7 @@ static void perf_hashmap(unsigned int method, unsigned int rounds) if (method & TEST_ADD) { /* test adding to the map */ for (j = 0; j < rounds; j++) { - hashmap_init(&map, (hashmap_cmp_fn) test_entry_cmp, 0); + hashmap_init(&map, test_entry_cmp, NULL, 0); /* add entries */ for (i = 0; i < TEST_SIZE; i++) { @@ -104,7 +108,7 @@ static void perf_hashmap(unsigned int method, unsigned int rounds) } } else { /* test map lookups */ - hashmap_init(&map, (hashmap_cmp_fn) test_entry_cmp, 0); + hashmap_init(&map, test_entry_cmp, NULL, 0); /* fill the map (sparsely if specified) */ j = (method & TEST_SPARSE) ? TEST_SIZE / 10 : TEST_SIZE; @@ -146,8 +150,7 @@ int cmd_main(int argc, const char **argv) /* init hash map */ icase = argc > 1 && !strcmp("ignorecase", argv[1]); - hashmap_init(&map, (hashmap_cmp_fn) (icase ? test_entry_cmp_icase - : test_entry_cmp), 0); + hashmap_init(&map, test_entry_cmp, &icase, 0); /* process commands from stdin */ while (fgets(line, sizeof(line), stdin)) { diff --git a/t/helper/test-match-trees.c b/t/helper/test-match-trees.c index e939502863..356d8edef1 100644 --- a/t/helper/test-match-trees.c +++ b/t/helper/test-match-trees.c @@ -12,10 +12,10 @@ int cmd_main(int ac, const char **av) die("cannot parse %s as an object name", av[1]); if (get_oid(av[2], &hash2)) die("cannot parse %s as an object name", av[2]); - one = parse_tree_indirect(hash1.hash); + one = parse_tree_indirect(&hash1); if (!one) die("not a tree-ish %s", av[1]); - two = parse_tree_indirect(hash2.hash); + two = parse_tree_indirect(&hash2); if (!two) die("not a tree-ish %s", av[2]); diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c index a01430c24b..75fe883aac 100644 --- a/t/helper/test-parse-options.c +++ b/t/helper/test-parse-options.c @@ -5,7 +5,7 @@ static int boolean = 0; static int integer = 0; static unsigned long magnitude = 0; -static unsigned long timestamp; +static timestamp_t timestamp; static int abbrev = 7; static int verbose = -1; /* unspecified */ static int dry_run = 0, quiet = 0; @@ -161,7 +161,7 @@ int cmd_main(int argc, const char **argv) show(&expect, &ret, "boolean: %d", boolean); show(&expect, &ret, "integer: %d", integer); show(&expect, &ret, "magnitude: %lu", magnitude); - show(&expect, &ret, "timestamp: %lu", timestamp); + show(&expect, &ret, "timestamp: %"PRItime, timestamp); show(&expect, &ret, "string: %s", string ? string : "(not set)"); show(&expect, &ret, "abbrev: %d", abbrev); show(&expect, &ret, "verbose: %d", verbose); diff --git a/t/helper/test-ref-store.c b/t/helper/test-ref-store.c index 2d84c45ffe..05d8c4d8af 100644 --- a/t/helper/test-ref-store.c +++ b/t/helper/test-ref-store.c @@ -1,5 +1,6 @@ #include "cache.h" #include "refs.h" +#include "worktree.h" static const char *notnull(const char *arg, const char *name) { @@ -32,6 +33,23 @@ static const char **get_store(const char **argv, struct ref_store **refs) strbuf_release(&sb); *refs = get_submodule_ref_store(gitdir); + } else if (skip_prefix(argv[0], "worktree:", &gitdir)) { + struct worktree **p, **worktrees = get_worktrees(0); + + for (p = worktrees; *p; p++) { + struct worktree *wt = *p; + + if (!wt->id) { + /* special case for main worktree */ + if (!strcmp(gitdir, "main")) + break; + } else if (!strcmp(gitdir, wt->id)) + break; + } + if (!*p) + die("no such worktree: %s", gitdir); + + *refs = get_worktree_ref_store(*p); } else die("unknown backend %s", argv[0]); @@ -75,12 +93,13 @@ static int cmd_create_symref(struct ref_store *refs, const char **argv) static int cmd_delete_refs(struct ref_store *refs, const char **argv) { unsigned int flags = arg_flags(*argv++, "flags"); + const char *msg = *argv++; struct string_list refnames = STRING_LIST_INIT_NODUP; while (*argv) string_list_append(&refnames, *argv++); - return refs_delete_refs(refs, &refnames, flags); + return refs_delete_refs(refs, msg, &refnames, flags); } static int cmd_rename_ref(struct ref_store *refs, const char **argv) @@ -138,10 +157,10 @@ static int cmd_for_each_reflog(struct ref_store *refs, const char **argv) } static int each_reflog(struct object_id *old_oid, struct object_id *new_oid, - const char *committer, unsigned long timestamp, + const char *committer, timestamp_t timestamp, int tz, const char *msg, void *cb_data) { - printf("%s %s %s %lu %d %s\n", + printf("%s %s %s %"PRItime" %d %s\n", oid_to_hex(old_oid), oid_to_hex(new_oid), committer, timestamp, tz, msg); return 0; diff --git a/t/helper/test-strcmp-offset.c b/t/helper/test-strcmp-offset.c index 4a45a54e92..e159c9a127 100644 --- a/t/helper/test-strcmp-offset.c +++ b/t/helper/test-strcmp-offset.c @@ -11,7 +11,7 @@ int cmd_main(int argc, const char **argv) result = strcmp_offset(argv[1], argv[2], &offset); /* - * Because differnt CRTs behave differently, only rely on signs + * Because different CRTs behave differently, only rely on signs * of the result values. */ result = (result < 0 ? -1 : diff --git a/t/helper/test-submodule-config.c b/t/helper/test-submodule-config.c index 2f144d539a..e13fbcc1b5 100644 --- a/t/helper/test-submodule-config.c +++ b/t/helper/test-submodule-config.c @@ -1,4 +1,5 @@ #include "cache.h" +#include "config.h" #include "submodule-config.h" #include "submodule.h" @@ -40,7 +41,7 @@ int cmd_main(int argc, const char **argv) git_config(git_test_config, NULL); while (*arg) { - unsigned char commit_sha1[20]; + struct object_id commit_oid; const struct submodule *submodule; const char *commit; const char *path_or_name; @@ -49,14 +50,14 @@ int cmd_main(int argc, const char **argv) path_or_name = arg[1]; if (commit[0] == '\0') - hashclr(commit_sha1); - else if (get_sha1(commit, commit_sha1) < 0) + oidclr(&commit_oid); + else if (get_oid(commit, &commit_oid) < 0) die_usage(argc, argv, "Commit not found."); if (lookup_name) { - submodule = submodule_from_name(commit_sha1, path_or_name); + submodule = submodule_from_name(&commit_oid, path_or_name); } else - submodule = submodule_from_path(commit_sha1, path_or_name); + submodule = submodule_from_path(&commit_oid, path_or_name); if (!submodule) die_usage(argc, argv, "Submodule not found."); diff --git a/t/helper/test-wildmatch.c b/t/helper/test-wildmatch.c index 52be876fed..921d7b3e7e 100644 --- a/t/helper/test-wildmatch.c +++ b/t/helper/test-wildmatch.c @@ -11,11 +11,11 @@ int cmd_main(int argc, const char **argv) argv[i] += 3; } if (!strcmp(argv[1], "wildmatch")) - return !!wildmatch(argv[3], argv[2], WM_PATHNAME, NULL); + return !!wildmatch(argv[3], argv[2], WM_PATHNAME); else if (!strcmp(argv[1], "iwildmatch")) - return !!wildmatch(argv[3], argv[2], WM_PATHNAME | WM_CASEFOLD, NULL); + return !!wildmatch(argv[3], argv[2], WM_PATHNAME | WM_CASEFOLD); else if (!strcmp(argv[1], "pathmatch")) - return !!wildmatch(argv[3], argv[2], 0, NULL); + return !!wildmatch(argv[3], argv[2], 0); else return 1; } diff --git a/t/lib-gpg.sh b/t/lib-gpg.sh index ec2aa8f687..43679a4c64 100755 --- a/t/lib-gpg.sh +++ b/t/lib-gpg.sh @@ -31,6 +31,7 @@ then chmod 0700 ./gpghome && GNUPGHOME="$(pwd)/gpghome" && export GNUPGHOME && + (gpgconf --kill gpg-agent 2>&1 >/dev/null || : ) && gpg --homedir "${GNUPGHOME}" 2>/dev/null --import \ "$TEST_DIRECTORY"/lib-gpg/keyring.gpg && gpg --homedir "${GNUPGHOME}" 2>/dev/null --import-ownertrust \ diff --git a/t/lib-proto-disable.sh b/t/lib-proto-disable.sh index 02f49cb409..83babe57d9 100644 --- a/t/lib-proto-disable.sh +++ b/t/lib-proto-disable.sh @@ -147,29 +147,33 @@ test_config () { # Test clone/fetch/push with protocol.allow user defined default test_expect_success "clone $desc (enabled)" ' rm -rf tmp.git && - git config --global protocol.allow always && + test_config_global protocol.allow always && git clone --bare "$url" tmp.git ' test_expect_success "fetch $desc (enabled)" ' + test_config_global protocol.allow always && git -C tmp.git fetch ' test_expect_success "push $desc (enabled)" ' + test_config_global protocol.allow always && git -C tmp.git push origin HEAD:pushed ' test_expect_success "push $desc (disabled)" ' - git config --global protocol.allow never && + test_config_global protocol.allow never && test_must_fail git -C tmp.git push origin HEAD:pushed ' test_expect_success "fetch $desc (disabled)" ' + test_config_global protocol.allow never && test_must_fail git -C tmp.git fetch ' test_expect_success "clone $desc (disabled)" ' rm -rf tmp.git && + test_config_global protocol.allow never && test_must_fail git clone --bare "$url" tmp.git ' } diff --git a/t/lib-submodule-update.sh b/t/lib-submodule-update.sh index 2c17826e95..2d26f86800 100755 --- a/t/lib-submodule-update.sh +++ b/t/lib-submodule-update.sh @@ -73,6 +73,7 @@ create_lib_submodule_repo () { git checkout -b "add_sub1" && git submodule add ../submodule_update_sub1 sub1 && + git submodule add ../submodule_update_sub1 uninitialized_sub && git config -f .gitmodules submodule.sub1.ignore all && git config submodule.sub1.ignore all && git add .gitmodules && @@ -780,8 +781,9 @@ test_submodule_forced_switch () { # - Removing a submodule with a git directory absorbs the submodules # git directory first into the superproject. -test_submodule_switch_recursing () { - command="$1" +test_submodule_switch_recursing_with_args () { + cmd_args="$1" + command="git $cmd_args --recurse-submodules" RESULTDS=success if test "$KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS" = 1 then @@ -983,6 +985,18 @@ test_submodule_switch_recursing () { ) ' + test_expect_success "git -c submodule.recurse=true $cmd_args: modified submodule updates submodule work tree" ' + prolog && + reset_work_tree_to_interested add_sub1 && + ( + cd submodule_update && + git branch -t modify_sub1 origin/modify_sub1 && + git -c submodule.recurse=true $cmd_args modify_sub1 && + test_superproject_content origin/modify_sub1 && + test_submodule_content sub1 origin/modify_sub1 + ) + ' + # Updating a submodule to an invalid sha1 doesn't update the # superproject nor the submodule's work tree. test_expect_success "$command: updating to a missing submodule commit fails" ' @@ -1015,8 +1029,9 @@ test_submodule_switch_recursing () { # Test that submodule contents are updated when switching between commits # that change a submodule, but throwing away local changes in # the superproject as well as the submodule is allowed. -test_submodule_forced_switch_recursing () { - command="$1" +test_submodule_forced_switch_recursing_with_args () { + cmd_args="$1" + command="git $cmd_args --recurse-submodules" RESULT=success if test "$KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS" = 1 then @@ -1207,14 +1222,31 @@ test_submodule_forced_switch_recursing () { ) ' # Updating a submodule from an invalid sha1 updates - test_expect_success "$command: modified submodule does not update submodule work tree from invalid commit" ' + test_expect_success "$command: modified submodule does update submodule work tree from invalid commit" ' prolog && reset_work_tree_to_interested invalid_sub1 && ( cd submodule_update && git branch -t valid_sub1 origin/valid_sub1 && - test_must_fail $command valid_sub1 && - test_superproject_content origin/invalid_sub1 + $command valid_sub1 && + test_superproject_content origin/valid_sub1 && + test_submodule_content sub1 origin/valid_sub1 + ) + ' + + # Old versions of Git were buggy writing the .git link file + # (e.g. before f8eaa0ba98b and then moving the superproject repo + # whose submodules contained absolute paths) + test_expect_success "$command: updating submodules fixes .git links" ' + prolog && + reset_work_tree_to_interested add_sub1 && + ( + cd submodule_update && + git branch -t modify_sub1 origin/modify_sub1 && + echo "gitdir: bogus/path" >sub1/.git && + $command modify_sub1 && + test_superproject_content origin/modify_sub1 && + test_submodule_content sub1 origin/modify_sub1 ) ' } diff --git a/t/perf/README b/t/perf/README index 49ea4349be..21321a0f36 100644 --- a/t/perf/README +++ b/t/perf/README @@ -60,7 +60,22 @@ You can set the following variables (also in your config.mak): GIT_PERF_MAKE_OPTS Options to use when automatically building a git tree for - performance testing. E.g., -j6 would be useful. + performance testing. E.g., -j6 would be useful. Passed + directly to make as "make $GIT_PERF_MAKE_OPTS". + + GIT_PERF_MAKE_COMMAND + An arbitrary command that'll be run in place of the make + command, if set the GIT_PERF_MAKE_OPTS variable is + ignored. Useful in cases where source tree changes might + require issuing a different make command to different + revisions. + + This can be (ab)used to monkeypatch or otherwise change the + tree about to be built. Note that the build directory can be + re-used for subsequent runs so the make command might get + executed multiple times on the same tree, but don't count on + any of that, that's an implementation detail that might change + in the future. GIT_PERF_REPO GIT_PERF_LARGE_REPO @@ -106,6 +121,7 @@ sources perf-lib.sh: After that you will want to use some of the following: + test_perf_fresh_repo # sets up an empty repository test_perf_default_repo # sets up a "normal" repository test_perf_large_repo # sets up a "large" repository diff --git a/t/perf/p0100-globbing.sh b/t/perf/p0100-globbing.sh new file mode 100755 index 0000000000..dd18a9ce2b --- /dev/null +++ b/t/perf/p0100-globbing.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +test_description="Tests pathological globbing performance + +Shows how Git's globbing performance performs when given the sort of +pathological patterns described in at https://research.swtch.com/glob +" + +. ./perf-lib.sh + +test_globs_big='10 25 50 75 100' +test_globs_small='1 2 3 4 5 6' + +test_perf_fresh_repo + +test_expect_success 'setup' ' + for i in $(test_seq 1 100) + do + printf "a" >>refname && + for j in $(test_seq 1 $i) + do + printf "a*" >>refglob.$i + done && + echo b >>refglob.$i + done && + test_commit test $(cat refname).t "" $(cat refname).t +' + +for i in $test_globs_small +do + test_perf "refglob((a*)^nb) against tag (a^100).t; n = $i" ' + git for-each-ref "refs/tags/$(cat refglob.'$i')b" + ' +done + +for i in $test_globs_small +do + test_perf "fileglob((a*)^nb) against file (a^100).t; n = $i" ' + git ls-files "$(cat refglob.'$i')b" + ' +done + +test_done diff --git a/t/perf/p3400-rebase.sh b/t/perf/p3400-rebase.sh index b3e7d525d2..ce271ca4c1 100755 --- a/t/perf/p3400-rebase.sh +++ b/t/perf/p3400-rebase.sh @@ -5,7 +5,7 @@ test_description='Tests rebase performance' test_perf_default_repo -test_expect_success 'setup' ' +test_expect_success 'setup rebasing on top of a lot of changes' ' git checkout -f -b base && git checkout -b to-rebase && git checkout -b upstream && @@ -33,4 +33,24 @@ test_perf 'rebase on top of a lot of unrelated changes' ' git rebase --onto base HEAD^ ' +test_expect_success 'setup rebasing many changes without split-index' ' + git config core.splitIndex false && + git checkout -b upstream2 to-rebase && + git checkout -b to-rebase2 upstream +' + +test_perf 'rebase a lot of unrelated changes without split-index' ' + git rebase --onto upstream2 base && + git rebase --onto base upstream2 +' + +test_expect_success 'setup rebasing many changes with split-index' ' + git config core.splitIndex true +' + +test_perf 'rebase a lot of unrelated changes with split-index' ' + git rebase --onto upstream2 base && + git rebase --onto base upstream2 +' + test_done diff --git a/t/perf/p4205-log-pretty-formats.sh b/t/perf/p4205-log-pretty-formats.sh new file mode 100755 index 0000000000..7c26f4f337 --- /dev/null +++ b/t/perf/p4205-log-pretty-formats.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +test_description='Tests the performance of various pretty format placeholders' + +. ./perf-lib.sh + +test_perf_default_repo + +for format in %H %h %T %t %P %p %h-%h-%h +do + test_perf "log with $format" " + git log --format=\"$format\" >/dev/null + " +done + +test_done diff --git a/t/perf/p4220-log-grep-engines.sh b/t/perf/p4220-log-grep-engines.sh new file mode 100755 index 0000000000..2bc47ded4d --- /dev/null +++ b/t/perf/p4220-log-grep-engines.sh @@ -0,0 +1,53 @@ +#!/bin/sh + +test_description="Comparison of git-log's --grep regex engines + +Set GIT_PERF_4220_LOG_OPTS in the environment to pass options to +git-grep. Make sure to include a leading space, +e.g. GIT_PERF_4220_LOG_OPTS=' -i'. Some options to try: + + -i + --invert-grep + -i --invert-grep +" + +. ./perf-lib.sh + +test_perf_large_repo +test_checkout_worktree + +for pattern in \ + 'how.to' \ + '^how to' \ + '[how] to' \ + '\(e.t[^ ]*\|v.ry\) rare' \ + 'm\(ú\|u\)lt.b\(æ\|y\)te' +do + for engine in basic extended perl + do + if test $engine != "basic" + then + # Poor man's basic -> extended converter. + pattern=$(echo $pattern | sed 's/\\//g') + fi + if test $engine = "perl" && ! test_have_prereq PCRE + then + prereq="PCRE" + else + prereq="" + fi + test_perf $prereq "$engine log$GIT_PERF_4220_LOG_OPTS --grep='$pattern'" " + git -c grep.patternType=$engine log --pretty=format:%h$GIT_PERF_4220_LOG_OPTS --grep='$pattern' >'out.$engine' || : + " + done + + test_expect_success "assert that all engines found the same for$GIT_PERF_4220_LOG_OPTS '$pattern'" ' + test_cmp out.basic out.extended && + if test_have_prereq PCRE + then + test_cmp out.basic out.perl + fi + ' +done + +test_done diff --git a/t/perf/p4221-log-grep-engines-fixed.sh b/t/perf/p4221-log-grep-engines-fixed.sh new file mode 100755 index 0000000000..060971265a --- /dev/null +++ b/t/perf/p4221-log-grep-engines-fixed.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +test_description="Comparison of git-log's --grep regex engines with -F + +Set GIT_PERF_4221_LOG_OPTS in the environment to pass options to +git-grep. Make sure to include a leading space, +e.g. GIT_PERF_4221_LOG_OPTS=' -i'. Some options to try: + + -i + --invert-grep + -i --invert-grep +" + +. ./perf-lib.sh + +test_perf_large_repo +test_checkout_worktree + +for pattern in 'int' 'uncommon' 'æ' +do + for engine in fixed basic extended perl + do + if test $engine = "perl" && ! test_have_prereq PCRE + then + prereq="PCRE" + else + prereq="" + fi + test_perf $prereq "$engine log$GIT_PERF_4221_LOG_OPTS --grep='$pattern'" " + git -c grep.patternType=$engine log --pretty=format:%h$GIT_PERF_4221_LOG_OPTS --grep='$pattern' >'out.$engine' || : + " + done + + test_expect_success "assert that all engines found the same for$GIT_PERF_4221_LOG_OPTS '$pattern'" ' + test_cmp out.fixed out.basic && + test_cmp out.fixed out.extended && + if test_have_prereq PCRE + then + test_cmp out.fixed out.perl + fi + ' +done + +test_done diff --git a/t/perf/p7820-grep-engines.sh b/t/perf/p7820-grep-engines.sh new file mode 100755 index 0000000000..62aba19e76 --- /dev/null +++ b/t/perf/p7820-grep-engines.sh @@ -0,0 +1,56 @@ +#!/bin/sh + +test_description="Comparison of git-grep's regex engines + +Set GIT_PERF_7820_GREP_OPTS in the environment to pass options to +git-grep. Make sure to include a leading space, +e.g. GIT_PERF_7820_GREP_OPTS=' -i'. Some options to try: + + -i + -w + -v + -vi + -vw + -viw +" + +. ./perf-lib.sh + +test_perf_large_repo +test_checkout_worktree + +for pattern in \ + 'how.to' \ + '^how to' \ + '[how] to' \ + '\(e.t[^ ]*\|v.ry\) rare' \ + 'm\(ú\|u\)lt.b\(æ\|y\)te' +do + for engine in basic extended perl + do + if test $engine != "basic" + then + # Poor man's basic -> extended converter. + pattern=$(echo "$pattern" | sed 's/\\//g') + fi + if test $engine = "perl" && ! test_have_prereq PCRE + then + prereq="PCRE" + else + prereq="" + fi + test_perf $prereq "$engine grep$GIT_PERF_7820_GREP_OPTS '$pattern'" " + git -c grep.patternType=$engine grep$GIT_PERF_7820_GREP_OPTS -- '$pattern' >'out.$engine' || : + " + done + + test_expect_success "assert that all engines found the same for$GIT_PERF_7820_GREP_OPTS '$pattern'" ' + test_cmp out.basic out.extended && + if test_have_prereq PCRE + then + test_cmp out.basic out.perl + fi + ' +done + +test_done diff --git a/t/perf/p7821-grep-engines-fixed.sh b/t/perf/p7821-grep-engines-fixed.sh new file mode 100755 index 0000000000..c7ef1e198f --- /dev/null +++ b/t/perf/p7821-grep-engines-fixed.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +test_description="Comparison of git-grep's regex engines with -F + +Set GIT_PERF_7821_GREP_OPTS in the environment to pass options to +git-grep. Make sure to include a leading space, +e.g. GIT_PERF_7821_GREP_OPTS=' -w'. See p7820-grep-engines.sh for more +options to try. +" + +. ./perf-lib.sh + +test_perf_large_repo +test_checkout_worktree + +for pattern in 'int' 'uncommon' 'æ' +do + for engine in fixed basic extended perl + do + if test $engine = "perl" && ! test_have_prereq PCRE + then + prereq="PCRE" + else + prereq="" + fi + test_perf $prereq "$engine grep$GIT_PERF_7821_GREP_OPTS $pattern" " + git -c grep.patternType=$engine grep$GIT_PERF_7821_GREP_OPTS $pattern >'out.$engine' || : + " + done + + test_expect_success "assert that all engines found the same for$GIT_PERF_7821_GREP_OPTS $pattern" ' + test_cmp out.fixed out.basic && + test_cmp out.fixed out.extended && + if test_have_prereq PCRE + then + test_cmp out.fixed out.perl + fi + ' +done + +test_done diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh index ab4b8b06ae..b50211b259 100644 --- a/t/perf/perf-lib.sh +++ b/t/perf/perf-lib.sh @@ -78,6 +78,10 @@ if test -z "$GIT_PERF_LARGE_REPO"; then GIT_PERF_LARGE_REPO=$TEST_DIRECTORY/.. fi +test_perf_do_repo_symlink_config_ () { + test_have_prereq SYMLINKS || git config core.symlinks false +} + test_perf_create_repo_from () { test "$#" = 2 || error "bug in the test script: not 2 parameters to test-create-repo" @@ -102,15 +106,29 @@ test_perf_create_repo_from () { ) && ( cd "$repo" && - "$MODERN_GIT" init -q && { - test_have_prereq SYMLINKS || - git config core.symlinks false - } && - mv .git/hooks .git/hooks-disabled 2>/dev/null + "$MODERN_GIT" init -q && + test_perf_do_repo_symlink_config_ && + mv .git/hooks .git/hooks-disabled 2>/dev/null && + if test -f .git/index.lock + then + # We may be copying a repo that can't run "git + # status" due to a locked index. Since we have + # a copy it's fine to remove the lock. + rm .git/index.lock + fi ) || error "failed to copy repository '$source' to '$repo'" } # call at least one of these to establish an appropriately-sized repository +test_perf_fresh_repo () { + repo="${1:-$TRASH_DIRECTORY}" + "$MODERN_GIT" init -q "$repo" && + ( + cd "$repo" && + test_perf_do_repo_symlink_config_ + ) +} + test_perf_default_repo () { test_perf_create_repo_from "${1:-$TRASH_DIRECTORY}" "$GIT_PERF_REPO" } diff --git a/t/perf/run b/t/perf/run index c788d713ae..beb4acc0e4 100755 --- a/t/perf/run +++ b/t/perf/run @@ -24,6 +24,7 @@ run_one_dir () { unpack_git_rev () { rev=$1 + echo "=== Unpacking $rev in build/$rev ===" mkdir -p build/$rev (cd "$(git rev-parse --show-cdup)" && git archive --format=tar $rev) | (cd build/$rev && tar x) @@ -37,8 +38,16 @@ build_git_rev () { cp "../../$config" "build/$rev/" fi done - (cd build/$rev && make $GIT_PERF_MAKE_OPTS) || - die "failed to build revision '$mydir'" + echo "=== Building $rev ===" + ( + cd build/$rev && + if test -n "$GIT_PERF_MAKE_COMMAND" + then + sh -c "$GIT_PERF_MAKE_COMMAND" + else + make $GIT_PERF_MAKE_OPTS + fi + ) || die "failed to build revision '$mydir'" } run_dirs_helper () { diff --git a/t/t0006-date.sh b/t/t0006-date.sh index c0c910867d..7ac9466d50 100755 --- a/t/t0006-date.sh +++ b/t/t0006-date.sh @@ -31,9 +31,11 @@ check_show () { format=$1 time=$2 expect=$3 - test_expect_success $4 "show date ($format:$time)" ' + prereqs=$4 + zone=$5 + test_expect_success $prereqs "show date ($format:$time)" ' echo "$time -> $expect" >expect && - test-date show:$format "$time" >actual && + TZ=${zone:-$TZ} test-date show:"$format" "$time" >actual && test_cmp expect actual ' } @@ -51,10 +53,20 @@ check_show iso-local "$TIME" '2016-06-15 14:13:20 +0000' check_show raw-local "$TIME" '1466000000 +0000' check_show unix-local "$TIME" '1466000000' +check_show 'format:%z' "$TIME" '+0200' +check_show 'format-local:%z' "$TIME" '+0000' +check_show 'format:%Z' "$TIME" '' +check_show 'format-local:%Z' "$TIME" 'UTC' +check_show 'format:%%z' "$TIME" '%z' +check_show 'format-local:%%z' "$TIME" '%z' + +check_show 'format:%Y-%m-%d %H:%M:%S' "$TIME" '2016-06-15 16:13:20' +check_show 'format-local:%Y-%m-%d %H:%M:%S' "$TIME" '2016-06-15 09:13:20' '' EST5 + # arbitrary time absurdly far in the future FUTURE="5758122296 -0400" -check_show iso "$FUTURE" "2152-06-19 18:24:56 -0400" LONG_IS_64BIT -check_show iso-local "$FUTURE" "2152-06-19 22:24:56 +0000" LONG_IS_64BIT +check_show iso "$FUTURE" "2152-06-19 18:24:56 -0400" TIME_IS_64BIT,TIME_T_IS_64BIT +check_show iso-local "$FUTURE" "2152-06-19 22:24:56 +0000" TIME_IS_64BIT,TIME_T_IS_64BIT check_parse() { echo "$1 -> $2" >expect diff --git a/t/t0012-help.sh b/t/t0012-help.sh index 8faba2e8bc..487b92a5de 100755 --- a/t/t0012-help.sh +++ b/t/t0012-help.sh @@ -49,4 +49,16 @@ test_expect_success "--help does not work for guides" " test_i18ncmp expect actual " +test_expect_success 'generate builtin list' ' + git --list-builtins >builtins +' + +while read builtin +do + test_expect_success "$builtin can handle -h" ' + test_expect_code 129 git $builtin -h >output 2>&1 && + test_i18ngrep usage output + ' +done <builtins + test_done diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh index 161f560446..46f8e583c3 100755 --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@ -28,7 +28,7 @@ file_size () { } filter_git () { - rm -f rot13-filter.log && + rm -f *.log && git "$@" } @@ -42,10 +42,10 @@ test_cmp_count () { for FILE in "$expect" "$actual" do sort "$FILE" | uniq -c | - sed -e "s/^ *[0-9][0-9]*[ ]*IN: /x IN: /" >"$FILE.tmp" && - mv "$FILE.tmp" "$FILE" || return + sed -e "s/^ *[0-9][0-9]*[ ]*IN: /x IN: /" >"$FILE.tmp" done && - test_cmp "$expect" "$actual" + test_cmp "$expect.tmp" "$actual.tmp" && + rm "$expect.tmp" "$actual.tmp" } # Compare two files but exclude all `clean` invocations because Git can @@ -56,10 +56,10 @@ test_cmp_exclude_clean () { actual=$2 for FILE in "$expect" "$actual" do - grep -v "IN: clean" "$FILE" >"$FILE.tmp" && - mv "$FILE.tmp" "$FILE" + grep -v "IN: clean" "$FILE" >"$FILE.tmp" done && - test_cmp "$expect" "$actual" + test_cmp "$expect.tmp" "$actual.tmp" && + rm "$expect.tmp" "$actual.tmp" } # Check that the contents of two files are equal and that their rot13 version @@ -342,7 +342,7 @@ test_expect_success 'diff does not reuse worktree files that need cleaning' ' ' test_expect_success PERL 'required process filter should filter data' ' - test_config_global filter.protocol.process "rot13-filter.pl clean smudge" && + test_config_global filter.protocol.process "rot13-filter.pl debug.log clean smudge" && test_config_global filter.protocol.required true && rm -rf repo && mkdir repo && @@ -375,7 +375,7 @@ test_expect_success PERL 'required process filter should filter data' ' IN: clean testsubdir/test3 '\''sq'\'',\$x=.r $S3 [OK] -- OUT: $S3 . [OK] STOP EOF - test_cmp_count expected.log rot13-filter.log && + test_cmp_count expected.log debug.log && git commit -m "test commit 2" && rm -f test2.r "testsubdir/test3 '\''sq'\'',\$x=.r" && @@ -388,7 +388,7 @@ test_expect_success PERL 'required process filter should filter data' ' IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $S3 [OK] -- OUT: $S3 . [OK] STOP EOF - test_cmp_exclude_clean expected.log rot13-filter.log && + test_cmp_exclude_clean expected.log debug.log && filter_git checkout --quiet --no-progress empty-branch && cat >expected.log <<-EOF && @@ -397,7 +397,7 @@ test_expect_success PERL 'required process filter should filter data' ' IN: clean test.r $S [OK] -- OUT: $S . [OK] STOP EOF - test_cmp_exclude_clean expected.log rot13-filter.log && + test_cmp_exclude_clean expected.log debug.log && filter_git checkout --quiet --no-progress master && cat >expected.log <<-EOF && @@ -409,7 +409,7 @@ test_expect_success PERL 'required process filter should filter data' ' IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $S3 [OK] -- OUT: $S3 . [OK] STOP EOF - test_cmp_exclude_clean expected.log rot13-filter.log && + test_cmp_exclude_clean expected.log debug.log && test_cmp_committed_rot13 "$TEST_ROOT/test.o" test.r && test_cmp_committed_rot13 "$TEST_ROOT/test2.o" test2.r && @@ -419,7 +419,7 @@ test_expect_success PERL 'required process filter should filter data' ' test_expect_success PERL 'required process filter takes precedence' ' test_config_global filter.protocol.clean false && - test_config_global filter.protocol.process "rot13-filter.pl clean" && + test_config_global filter.protocol.process "rot13-filter.pl debug.log clean" && test_config_global filter.protocol.required true && rm -rf repo && mkdir repo && @@ -439,12 +439,12 @@ test_expect_success PERL 'required process filter takes precedence' ' IN: clean test.r $S [OK] -- OUT: $S . [OK] STOP EOF - test_cmp_count expected.log rot13-filter.log + test_cmp_count expected.log debug.log ) ' test_expect_success PERL 'required process filter should be used only for "clean" operation only' ' - test_config_global filter.protocol.process "rot13-filter.pl clean" && + test_config_global filter.protocol.process "rot13-filter.pl debug.log clean" && rm -rf repo && mkdir repo && ( @@ -462,7 +462,7 @@ test_expect_success PERL 'required process filter should be used only for "clean IN: clean test.r $S [OK] -- OUT: $S . [OK] STOP EOF - test_cmp_count expected.log rot13-filter.log && + test_cmp_count expected.log debug.log && rm test.r && @@ -474,12 +474,12 @@ test_expect_success PERL 'required process filter should be used only for "clean init handshake complete STOP EOF - test_cmp_exclude_clean expected.log rot13-filter.log + test_cmp_exclude_clean expected.log debug.log ) ' test_expect_success PERL 'required process filter should process multiple packets' ' - test_config_global filter.protocol.process "rot13-filter.pl clean smudge" && + test_config_global filter.protocol.process "rot13-filter.pl debug.log clean smudge" && test_config_global filter.protocol.required true && rm -rf repo && @@ -514,7 +514,7 @@ test_expect_success PERL 'required process filter should process multiple packet IN: clean 3pkt_2+1.file $(($S*2+1)) [OK] -- OUT: $(($S*2+1)) ... [OK] STOP EOF - test_cmp_count expected.log rot13-filter.log && + test_cmp_count expected.log debug.log && rm -f *.file && @@ -529,7 +529,7 @@ test_expect_success PERL 'required process filter should process multiple packet IN: smudge 3pkt_2+1.file $(($S*2+1)) [OK] -- OUT: $(($S*2+1)) ... [OK] STOP EOF - test_cmp_exclude_clean expected.log rot13-filter.log && + test_cmp_exclude_clean expected.log debug.log && for FILE in *.file do @@ -539,7 +539,7 @@ test_expect_success PERL 'required process filter should process multiple packet ' test_expect_success PERL 'required process filter with clean error should fail' ' - test_config_global filter.protocol.process "rot13-filter.pl clean smudge" && + test_config_global filter.protocol.process "rot13-filter.pl debug.log clean smudge" && test_config_global filter.protocol.required true && rm -rf repo && mkdir repo && @@ -558,7 +558,7 @@ test_expect_success PERL 'required process filter with clean error should fail' ' test_expect_success PERL 'process filter should restart after unexpected write failure' ' - test_config_global filter.protocol.process "rot13-filter.pl clean smudge" && + test_config_global filter.protocol.process "rot13-filter.pl debug.log clean smudge" && rm -rf repo && mkdir repo && ( @@ -579,7 +579,7 @@ test_expect_success PERL 'process filter should restart after unexpected write f git add . && rm -f *.r && - rm -f rot13-filter.log && + rm -f debug.log && git checkout --quiet --no-progress . 2>git-stderr.log && grep "smudge write error at" git-stderr.log && @@ -588,14 +588,14 @@ test_expect_success PERL 'process filter should restart after unexpected write f cat >expected.log <<-EOF && START init handshake complete - IN: smudge smudge-write-fail.r $SF [OK] -- OUT: $SF [WRITE FAIL] + IN: smudge smudge-write-fail.r $SF [OK] -- [WRITE FAIL] START init handshake complete IN: smudge test.r $S [OK] -- OUT: $S . [OK] IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK] STOP EOF - test_cmp_exclude_clean expected.log rot13-filter.log && + test_cmp_exclude_clean expected.log debug.log && test_cmp_committed_rot13 "$TEST_ROOT/test.o" test.r && test_cmp_committed_rot13 "$TEST_ROOT/test2.o" test2.r && @@ -609,7 +609,7 @@ test_expect_success PERL 'process filter should restart after unexpected write f ' test_expect_success PERL 'process filter should not be restarted if it signals an error' ' - test_config_global filter.protocol.process "rot13-filter.pl clean smudge" && + test_config_global filter.protocol.process "rot13-filter.pl debug.log clean smudge" && rm -rf repo && mkdir repo && ( @@ -634,12 +634,12 @@ test_expect_success PERL 'process filter should not be restarted if it signals a cat >expected.log <<-EOF && START init handshake complete - IN: smudge error.r $SE [OK] -- OUT: 0 [ERROR] + IN: smudge error.r $SE [OK] -- [ERROR] IN: smudge test.r $S [OK] -- OUT: $S . [OK] IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK] STOP EOF - test_cmp_exclude_clean expected.log rot13-filter.log && + test_cmp_exclude_clean expected.log debug.log && test_cmp_committed_rot13 "$TEST_ROOT/test.o" test.r && test_cmp_committed_rot13 "$TEST_ROOT/test2.o" test2.r && @@ -648,7 +648,7 @@ test_expect_success PERL 'process filter should not be restarted if it signals a ' test_expect_success PERL 'process filter abort stops processing of all further files' ' - test_config_global filter.protocol.process "rot13-filter.pl clean smudge" && + test_config_global filter.protocol.process "rot13-filter.pl debug.log clean smudge" && rm -rf repo && mkdir repo && ( @@ -673,10 +673,10 @@ test_expect_success PERL 'process filter abort stops processing of all further f cat >expected.log <<-EOF && START init handshake complete - IN: smudge abort.r $SA [OK] -- OUT: 0 [ABORT] + IN: smudge abort.r $SA [OK] -- [ABORT] STOP EOF - test_cmp_exclude_clean expected.log rot13-filter.log && + test_cmp_exclude_clean expected.log debug.log && test_cmp "$TEST_ROOT/test.o" test.r && test_cmp "$TEST_ROOT/test2.o" test2.r && @@ -697,8 +697,124 @@ test_expect_success PERL 'invalid process filter must fail (and not hang!)' ' cp "$TEST_ROOT/test.o" test.r && test_must_fail git add . 2>git-stderr.log && - grep "does not support filter protocol version" git-stderr.log + grep "expected git-filter-server" git-stderr.log ) ' +test_expect_success PERL 'delayed checkout in process filter' ' + test_config_global filter.a.process "rot13-filter.pl a.log clean smudge delay" && + test_config_global filter.a.required true && + test_config_global filter.b.process "rot13-filter.pl b.log clean smudge delay" && + test_config_global filter.b.required true && + + rm -rf repo && + mkdir repo && + ( + cd repo && + git init && + echo "*.a filter=a" >.gitattributes && + echo "*.b filter=b" >>.gitattributes && + cp "$TEST_ROOT/test.o" test.a && + cp "$TEST_ROOT/test.o" test-delay10.a && + cp "$TEST_ROOT/test.o" test-delay11.a && + cp "$TEST_ROOT/test.o" test-delay20.a && + cp "$TEST_ROOT/test.o" test-delay10.b && + git add . && + git commit -m "test commit" + ) && + + S=$(file_size "$TEST_ROOT/test.o") && + cat >a.exp <<-EOF && + START + init handshake complete + IN: smudge test.a $S [OK] -- OUT: $S . [OK] + IN: smudge test-delay10.a $S [OK] -- [DELAYED] + IN: smudge test-delay11.a $S [OK] -- [DELAYED] + IN: smudge test-delay20.a $S [OK] -- [DELAYED] + IN: list_available_blobs test-delay10.a test-delay11.a [OK] + IN: smudge test-delay10.a 0 [OK] -- OUT: $S . [OK] + IN: smudge test-delay11.a 0 [OK] -- OUT: $S . [OK] + IN: list_available_blobs test-delay20.a [OK] + IN: smudge test-delay20.a 0 [OK] -- OUT: $S . [OK] + IN: list_available_blobs [OK] + STOP + EOF + cat >b.exp <<-EOF && + START + init handshake complete + IN: smudge test-delay10.b $S [OK] -- [DELAYED] + IN: list_available_blobs test-delay10.b [OK] + IN: smudge test-delay10.b 0 [OK] -- OUT: $S . [OK] + IN: list_available_blobs [OK] + STOP + EOF + + rm -rf repo-cloned && + filter_git clone repo repo-cloned && + test_cmp_count a.exp repo-cloned/a.log && + test_cmp_count b.exp repo-cloned/b.log && + + ( + cd repo-cloned && + test_cmp_committed_rot13 "$TEST_ROOT/test.o" test.a && + test_cmp_committed_rot13 "$TEST_ROOT/test.o" test-delay10.a && + test_cmp_committed_rot13 "$TEST_ROOT/test.o" test-delay11.a && + test_cmp_committed_rot13 "$TEST_ROOT/test.o" test-delay20.a && + test_cmp_committed_rot13 "$TEST_ROOT/test.o" test-delay10.b && + + rm *.a *.b && + filter_git checkout . && + test_cmp_count ../a.exp a.log && + test_cmp_count ../b.exp b.log && + + test_cmp_committed_rot13 "$TEST_ROOT/test.o" test.a && + test_cmp_committed_rot13 "$TEST_ROOT/test.o" test-delay10.a && + test_cmp_committed_rot13 "$TEST_ROOT/test.o" test-delay11.a && + test_cmp_committed_rot13 "$TEST_ROOT/test.o" test-delay20.a && + test_cmp_committed_rot13 "$TEST_ROOT/test.o" test-delay10.b + ) +' + +test_expect_success PERL 'missing file in delayed checkout' ' + test_config_global filter.bug.process "rot13-filter.pl bug.log clean smudge delay" && + test_config_global filter.bug.required true && + + rm -rf repo && + mkdir repo && + ( + cd repo && + git init && + echo "*.a filter=bug" >.gitattributes && + cp "$TEST_ROOT/test.o" missing-delay.a + git add . && + git commit -m "test commit" + ) && + + rm -rf repo-cloned && + test_must_fail git clone repo repo-cloned 2>git-stderr.log && + cat git-stderr.log && + grep "error: .missing-delay\.a. was not filtered properly" git-stderr.log +' + +test_expect_success PERL 'invalid file in delayed checkout' ' + test_config_global filter.bug.process "rot13-filter.pl bug.log clean smudge delay" && + test_config_global filter.bug.required true && + + rm -rf repo && + mkdir repo && + ( + cd repo && + git init && + echo "*.a filter=bug" >.gitattributes && + cp "$TEST_ROOT/test.o" invalid-delay.a && + cp "$TEST_ROOT/test.o" unfiltered + git add . && + git commit -m "test commit" + ) && + + rm -rf repo-cloned && + test_must_fail git clone repo repo-cloned 2>git-stderr.log && + grep "error: external filter .* signaled that .unfiltered. is now available although it has not been delayed earlier" git-stderr.log +' + test_done diff --git a/t/t0021/rot13-filter.pl b/t/t0021/rot13-filter.pl index 617f581e56..ad685d92f8 100644 --- a/t/t0021/rot13-filter.pl +++ b/t/t0021/rot13-filter.pl @@ -2,8 +2,9 @@ # Example implementation for the Git filter protocol version 2 # See Documentation/gitattributes.txt, section "Filter Protocol" # -# The script takes the list of supported protocol capabilities as -# arguments ("clean", "smudge", etc). +# The first argument defines a debug log file that the script write to. +# All remaining arguments define a list of supported protocol +# capabilities ("clean", "smudge", etc). # # This implementation supports special test cases: # (1) If data with the pathname "clean-write-fail.r" is processed with @@ -17,6 +18,16 @@ # operation then the filter signals that it cannot or does not want # to process the file and any file after that is processed with the # same command. +# (5) If data with a pathname that is a key in the DELAY hash is +# requested (e.g. "test-delay10.a") then the filter responds with +# a "delay" status and sets the "requested" field in the DELAY hash. +# The filter will signal the availability of this object after +# "count" (field in DELAY hash) "list_available_blobs" commands. +# (6) If data with the pathname "missing-delay.a" is processed that the +# filter will drop the path from the "list_available_blobs" response. +# (7) If data with the pathname "invalid-delay.a" is processed that the +# filter will add the path "unfiltered" which was not delayed before +# to the "list_available_blobs" response. # use strict; @@ -24,9 +35,19 @@ use warnings; use IO::File; my $MAX_PACKET_CONTENT_SIZE = 65516; +my $log_file = shift @ARGV; my @capabilities = @ARGV; -open my $debug, ">>", "rot13-filter.log" or die "cannot open log file: $!"; +open my $debug, ">>", $log_file or die "cannot open log file: $!"; + +my %DELAY = ( + 'test-delay10.a' => { "requested" => 0, "count" => 1 }, + 'test-delay11.a' => { "requested" => 0, "count" => 1 }, + 'test-delay20.a' => { "requested" => 0, "count" => 2 }, + 'test-delay10.b' => { "requested" => 0, "count" => 1 }, + 'missing-delay.a' => { "requested" => 0, "count" => 1 }, + 'invalid-delay.a' => { "requested" => 0, "count" => 1 }, +); sub rot13 { my $str = shift; @@ -64,7 +85,7 @@ sub packet_bin_read { sub packet_txt_read { my ( $res, $buf ) = packet_bin_read(); - unless ( $buf =~ s/\n$// ) { + unless ( $buf eq '' or $buf =~ s/\n$// ) { die "A non-binary line MUST be terminated by an LF."; } return ( $res, $buf ); @@ -99,6 +120,7 @@ packet_flush(); ( packet_txt_read() eq ( 0, "capability=clean" ) ) || die "bad capability"; ( packet_txt_read() eq ( 0, "capability=smudge" ) ) || die "bad capability"; +( packet_txt_read() eq ( 0, "capability=delay" ) ) || die "bad capability"; ( packet_bin_read() eq ( 1, "" ) ) || die "bad capability end"; foreach (@capabilities) { @@ -109,88 +131,142 @@ print $debug "init handshake complete\n"; $debug->flush(); while (1) { - my ($command) = packet_txt_read() =~ /^command=(.+)$/; + my ( $command ) = packet_txt_read() =~ /^command=(.+)$/; print $debug "IN: $command"; $debug->flush(); - my ($pathname) = packet_txt_read() =~ /^pathname=(.+)$/; - print $debug " $pathname"; - $debug->flush(); - - if ( $pathname eq "" ) { - die "bad pathname '$pathname'"; - } + if ( $command eq "list_available_blobs" ) { + # Flush + packet_bin_read(); - # Flush - packet_bin_read(); - - my $input = ""; - { - binmode(STDIN); - my $buffer; - my $done = 0; - while ( !$done ) { - ( $done, $buffer ) = packet_bin_read(); - $input .= $buffer; + foreach my $pathname ( sort keys %DELAY ) { + if ( $DELAY{$pathname}{"requested"} >= 1 ) { + $DELAY{$pathname}{"count"} = $DELAY{$pathname}{"count"} - 1; + if ( $pathname eq "invalid-delay.a" ) { + # Send Git a pathname that was not delayed earlier + packet_txt_write("pathname=unfiltered"); + } + if ( $pathname eq "missing-delay.a" ) { + # Do not signal Git that this file is available + } elsif ( $DELAY{$pathname}{"count"} == 0 ) { + print $debug " $pathname"; + packet_txt_write("pathname=$pathname"); + } + } } - print $debug " " . length($input) . " [OK] -- "; - $debug->flush(); - } - - my $output; - if ( $pathname eq "error.r" or $pathname eq "abort.r" ) { - $output = ""; - } - elsif ( $command eq "clean" and grep( /^clean$/, @capabilities ) ) { - $output = rot13($input); - } - elsif ( $command eq "smudge" and grep( /^smudge$/, @capabilities ) ) { - $output = rot13($input); - } - else { - die "bad command '$command'"; - } - print $debug "OUT: " . length($output) . " "; - $debug->flush(); - - if ( $pathname eq "error.r" ) { - print $debug "[ERROR]\n"; - $debug->flush(); - packet_txt_write("status=error"); packet_flush(); - } - elsif ( $pathname eq "abort.r" ) { - print $debug "[ABORT]\n"; + + print $debug " [OK]\n"; $debug->flush(); - packet_txt_write("status=abort"); + packet_txt_write("status=success"); packet_flush(); } else { - packet_txt_write("status=success"); - packet_flush(); + my ( $pathname ) = packet_txt_read() =~ /^pathname=(.+)$/; + print $debug " $pathname"; + $debug->flush(); - if ( $pathname eq "${command}-write-fail.r" ) { - print $debug "[WRITE FAIL]\n"; + if ( $pathname eq "" ) { + die "bad pathname '$pathname'"; + } + + # Read until flush + my ( $done, $buffer ) = packet_txt_read(); + while ( $buffer ne '' ) { + if ( $buffer eq "can-delay=1" ) { + if ( exists $DELAY{$pathname} and $DELAY{$pathname}{"requested"} == 0 ) { + $DELAY{$pathname}{"requested"} = 1; + } + } else { + die "Unknown message '$buffer'"; + } + + ( $done, $buffer ) = packet_txt_read(); + } + + my $input = ""; + { + binmode(STDIN); + my $buffer; + my $done = 0; + while ( !$done ) { + ( $done, $buffer ) = packet_bin_read(); + $input .= $buffer; + } + print $debug " " . length($input) . " [OK] -- "; $debug->flush(); - die "${command} write error"; } - while ( length($output) > 0 ) { - my $packet = substr( $output, 0, $MAX_PACKET_CONTENT_SIZE ); - packet_bin_write($packet); - # dots represent the number of packets - print $debug "."; - if ( length($output) > $MAX_PACKET_CONTENT_SIZE ) { - $output = substr( $output, $MAX_PACKET_CONTENT_SIZE ); + my $output; + if ( exists $DELAY{$pathname} and exists $DELAY{$pathname}{"output"} ) { + $output = $DELAY{$pathname}{"output"} + } + elsif ( $pathname eq "error.r" or $pathname eq "abort.r" ) { + $output = ""; + } + elsif ( $command eq "clean" and grep( /^clean$/, @capabilities ) ) { + $output = rot13($input); + } + elsif ( $command eq "smudge" and grep( /^smudge$/, @capabilities ) ) { + $output = rot13($input); + } + else { + die "bad command '$command'"; + } + + if ( $pathname eq "error.r" ) { + print $debug "[ERROR]\n"; + $debug->flush(); + packet_txt_write("status=error"); + packet_flush(); + } + elsif ( $pathname eq "abort.r" ) { + print $debug "[ABORT]\n"; + $debug->flush(); + packet_txt_write("status=abort"); + packet_flush(); + } + elsif ( $command eq "smudge" and + exists $DELAY{$pathname} and + $DELAY{$pathname}{"requested"} == 1 + ) { + print $debug "[DELAYED]\n"; + $debug->flush(); + packet_txt_write("status=delayed"); + packet_flush(); + $DELAY{$pathname}{"requested"} = 2; + $DELAY{$pathname}{"output"} = $output; + } + else { + packet_txt_write("status=success"); + packet_flush(); + + if ( $pathname eq "${command}-write-fail.r" ) { + print $debug "[WRITE FAIL]\n"; + $debug->flush(); + die "${command} write error"; } - else { - $output = ""; + + print $debug "OUT: " . length($output) . " "; + $debug->flush(); + + while ( length($output) > 0 ) { + my $packet = substr( $output, 0, $MAX_PACKET_CONTENT_SIZE ); + packet_bin_write($packet); + # dots represent the number of packets + print $debug "."; + if ( length($output) > $MAX_PACKET_CONTENT_SIZE ) { + $output = substr( $output, $MAX_PACKET_CONTENT_SIZE ); + } + else { + $output = ""; + } } + packet_flush(); + print $debug " [OK]\n"; + $debug->flush(); + packet_flush(); } - packet_flush(); - print $debug " [OK]\n"; - $debug->flush(); - packet_flush(); } } diff --git a/t/t1013-read-tree-submodule.sh b/t/t1013-read-tree-submodule.sh index 7019d0a04f..91a6fafcb4 100755 --- a/t/t1013-read-tree-submodule.sh +++ b/t/t1013-read-tree-submodule.sh @@ -8,9 +8,9 @@ test_description='read-tree can handle submodules' KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS=1 KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED=1 -test_submodule_switch_recursing "git read-tree --recurse-submodules -u -m" +test_submodule_switch_recursing_with_args "read-tree -u -m" -test_submodule_forced_switch_recursing "git read-tree --recurse-submodules -u --reset" +test_submodule_forced_switch_recursing_with_args "read-tree -u --reset" test_submodule_switch "git read-tree -u -m" diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh index 933915ec06..d9d2f545a4 100755 --- a/t/t1305-config-include.sh +++ b/t/t1305-config-include.sh @@ -273,6 +273,29 @@ test_expect_success SYMLINKS 'conditional include, relative path with symlinks' ) ' +test_expect_success SYMLINKS 'conditional include, gitdir matching symlink' ' + ln -s foo bar && + ( + cd bar && + echo "[includeIf \"gitdir:bar/\"]path=bar7" >>.git/config && + echo "[test]seven=7" >.git/bar7 && + echo 7 >expect && + git config test.seven >actual && + test_cmp expect actual + ) +' + +test_expect_success SYMLINKS 'conditional include, gitdir matching symlink, icase' ' + ( + cd bar && + echo "[includeIf \"gitdir/i:BAR/\"]path=bar8" >>.git/config && + echo "[test]eight=8" >.git/bar8 && + echo 8 >expect && + git config test.eight >actual && + test_cmp expect actual + ) +' + test_expect_success 'include cycles are detected' ' cat >.gitconfig <<-\EOF && [test]value = gitconfig diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh index 69a0aa56d6..bafed5c9b8 100755 --- a/t/t1308-config-set.sh +++ b/t/t1308-config-set.sh @@ -183,11 +183,22 @@ test_expect_success 'proper error on non-existent files' ' test_cmp expect actual ' +test_expect_success 'proper error on directory "files"' ' + echo "Error (-1) reading configuration file a-directory." >expect && + mkdir a-directory && + test_expect_code 2 test-config configset_get_value foo.bar a-directory 2>output && + grep "^warning:" output && + grep "^Error" output >actual && + test_cmp expect actual +' + test_expect_success POSIXPERM,SANITY 'proper error on non-accessible files' ' chmod -r .git/config && test_when_finished "chmod +r .git/config" && echo "Error (-1) reading configuration file .git/config." >expect && - test_expect_code 2 test-config configset_get_value foo.bar .git/config 2>actual && + test_expect_code 2 test-config configset_get_value foo.bar .git/config 2>output && + grep "^warning:" output && + grep "^Error" output >actual && test_cmp expect actual ' diff --git a/t/t1405-main-ref-store.sh b/t/t1405-main-ref-store.sh index 490521f8cb..e8115df5ba 100755 --- a/t/t1405-main-ref-store.sh +++ b/t/t1405-main-ref-store.sh @@ -31,7 +31,7 @@ test_expect_success 'create_symref(FOO, refs/heads/master)' ' test_expect_success 'delete_refs(FOO, refs/tags/new-tag)' ' git rev-parse FOO -- && git rev-parse refs/tags/new-tag -- && - $RUN delete-refs 0 FOO refs/tags/new-tag && + $RUN delete-refs 0 nothing FOO refs/tags/new-tag && test_must_fail git rev-parse FOO -- && test_must_fail git rev-parse refs/tags/new-tag -- ' diff --git a/t/t1406-submodule-ref-store.sh b/t/t1406-submodule-ref-store.sh index 13b5454c56..c32d4cc465 100755 --- a/t/t1406-submodule-ref-store.sh +++ b/t/t1406-submodule-ref-store.sh @@ -31,7 +31,7 @@ test_expect_success 'create_symref() not allowed' ' ' test_expect_success 'delete_refs() not allowed' ' - test_must_fail $RUN delete-refs 0 FOO refs/tags/new-tag + test_must_fail $RUN delete-refs 0 nothing FOO refs/tags/new-tag ' test_expect_success 'rename_refs() not allowed' ' diff --git a/t/t1407-worktree-ref-store.sh b/t/t1407-worktree-ref-store.sh new file mode 100755 index 0000000000..5df06f3556 --- /dev/null +++ b/t/t1407-worktree-ref-store.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +test_description='test worktree ref store api' + +. ./test-lib.sh + +RWT="test-ref-store worktree:wt" +RMAIN="test-ref-store worktree:main" + +test_expect_success 'setup' ' + test_commit first && + git worktree add -b wt-master wt && + ( + cd wt && + test_commit second + ) +' + +test_expect_success 'resolve_ref(<shared-ref>)' ' + SHA1=`git rev-parse master` && + echo "$SHA1 refs/heads/master 0x0" >expected && + $RWT resolve-ref refs/heads/master 0 >actual && + test_cmp expected actual && + $RMAIN resolve-ref refs/heads/master 0 >actual && + test_cmp expected actual +' + +test_expect_success 'resolve_ref(<per-worktree-ref>)' ' + SHA1=`git -C wt rev-parse HEAD` && + echo "$SHA1 refs/heads/wt-master 0x1" >expected && + $RWT resolve-ref HEAD 0 >actual && + test_cmp expected actual && + + SHA1=`git rev-parse HEAD` && + echo "$SHA1 refs/heads/master 0x1" >expected && + $RMAIN resolve-ref HEAD 0 >actual && + test_cmp expected actual +' + +test_expect_success 'create_symref(FOO, refs/heads/master)' ' + $RWT create-symref FOO refs/heads/master nothing && + echo refs/heads/master >expected && + git -C wt symbolic-ref FOO >actual && + test_cmp expected actual && + + $RMAIN create-symref FOO refs/heads/wt-master nothing && + echo refs/heads/wt-master >expected && + git symbolic-ref FOO >actual && + test_cmp expected actual +' + +test_done diff --git a/t/t1411-reflog-show.sh b/t/t1411-reflog-show.sh index b9cb76654b..6ac7734d79 100755 --- a/t/t1411-reflog-show.sh +++ b/t/t1411-reflog-show.sh @@ -171,14 +171,4 @@ test_expect_success 'reflog exists works' ' ! git reflog exists refs/heads/nonexistent ' -# The behavior with two reflogs is buggy and the output is in flux; for now -# we're just checking that the program works at all without segfaulting. -test_expect_success 'showing multiple reflogs works' ' - git log -g HEAD HEAD >actual -' - -test_expect_success 'showing multiple reflogs with an old date' ' - git log -g HEAD@{1979-01-01} HEAD >actual -' - test_done diff --git a/t/t1414-reflog-walk.sh b/t/t1414-reflog-walk.sh new file mode 100755 index 0000000000..feb1efd8ff --- /dev/null +++ b/t/t1414-reflog-walk.sh @@ -0,0 +1,135 @@ +#!/bin/sh + +test_description='various tests of reflog walk (log -g) behavior' +. ./test-lib.sh + +test_expect_success 'set up some reflog entries' ' + test_commit one && + test_commit two && + git checkout -b side HEAD^ && + test_commit three && + git merge --no-commit master && + echo evil-merge-content >>one.t && + test_tick && + git commit --no-edit -a +' + +do_walk () { + git log -g --format="%gd %gs" "$@" +} + +sq="'" +test_expect_success 'set up expected reflog' ' + cat >expect.all <<-EOF + HEAD@{0} commit (merge): Merge branch ${sq}master${sq} into side + HEAD@{1} commit: three + HEAD@{2} checkout: moving from master to side + HEAD@{3} commit: two + HEAD@{4} commit (initial): one + EOF +' + +test_expect_success 'reflog walk shows expected logs' ' + do_walk >actual && + test_cmp expect.all actual +' + +test_expect_success 'reflog can limit with --no-merges' ' + grep -v merge expect.all >expect && + do_walk --no-merges >actual && + test_cmp expect actual +' + +test_expect_success 'reflog can limit with pathspecs' ' + grep two expect.all >expect && + do_walk -- two.t >actual && + test_cmp expect actual +' + +test_expect_success 'pathspec limiting handles merges' ' + # we pick up: + # - the initial commit of one + # - the checkout back to commit one + # - the evil merge which touched one + sed -n "1p;3p;5p" expect.all >expect && + do_walk -- one.t >actual && + test_cmp expect actual +' + +test_expect_success '--parents shows true parents' ' + # convert newlines to spaces + echo $(git rev-parse HEAD HEAD^1 HEAD^2) >expect && + git rev-list -g --parents -1 HEAD >actual && + test_cmp expect actual +' + +test_expect_success 'walking multiple reflogs shows all' ' + # We expect to see all entries for all reflogs, but interleaved by + # date, with order on the command line breaking ties. We + # can use "sort" on the separate lists to generate this, + # but note two tricks: + # + # 1. We use "{" as the delimiter, which lets us skip to the reflog + # date specifier as our second field, and then our "-n" numeric + # sort ignores the bits after the timestamp. + # + # 2. POSIX leaves undefined whether this is a stable sort or not. So + # we use "-k 1" to ensure that we see HEAD before master before + # side when breaking ties. + { + do_walk --date=unix HEAD && + do_walk --date=unix side && + do_walk --date=unix master + } >expect.raw && + sort -t "{" -k 2nr -k 1 <expect.raw >expect && + do_walk --date=unix HEAD master side >actual && + test_cmp expect actual +' + +test_expect_success 'date-limiting does not interfere with other logs' ' + do_walk HEAD@{1979-01-01} HEAD >actual && + test_cmp expect.all actual +' + +test_expect_success 'min/max age uses entry date to limit' ' + # Flip between commits one and two so each ref update actually + # does something (and does not get optimized out). We know + # that the timestamps of those commits will be before our "min". + + git update-ref -m before refs/heads/minmax one && + + test_tick && + min=$test_tick && + git update-ref -m min refs/heads/minmax two && + + test_tick && + max=$test_tick && + git update-ref -m max refs/heads/minmax one && + + test_tick && + git update-ref -m after refs/heads/minmax two && + + cat >expect <<-\EOF && + max + min + EOF + git log -g --since=$min --until=$max --format=%gs minmax >actual && + test_cmp expect actual +' + +test_expect_success 'walk prefers reflog to ref tip' ' + head=$(git rev-parse HEAD) && + one=$(git rev-parse one) && + ident="$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE" && + echo "$head $one $ident broken reflog entry" >>.git/logs/HEAD && + + echo $one >expect && + git log -g --format=%H -1 >actual && + test_cmp expect actual +' + +test_expect_success 'rev-list -g complains when there are no reflogs' ' + test_must_fail git rev-list -g +' + +test_done diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index bb89e1a5db..4087150db1 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -608,6 +608,22 @@ test_expect_success 'fsck errors in packed objects' ' ! grep corrupt out ' +test_expect_success 'fsck fails on corrupt packfile' ' + hsh=$(git commit-tree -m mycommit HEAD^{tree}) && + pack=$(echo $hsh | git pack-objects .git/objects/pack/pack) && + + # Corrupt the first byte of the first object. (It contains 3 type bits, + # at least one of which is not zero, so setting the first byte to 0 is + # sufficient.) + chmod a+w .git/objects/pack/pack-$pack.pack && + printf '\0' | dd of=.git/objects/pack/pack-$pack.pack bs=1 conv=notrunc seek=12 && + + 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_expect_success 'fsck finds problems in duplicate loose objects' ' rm -rf broken-duplicate && git init broken-duplicate && diff --git a/t/t1601-index-bogus.sh b/t/t1601-index-bogus.sh new file mode 100755 index 0000000000..73cc9323cd --- /dev/null +++ b/t/t1601-index-bogus.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +test_description='test handling of bogus index entries' +. ./test-lib.sh + +test_expect_success 'create tree with null sha1' ' + tree=$(printf "160000 commit $_z40\\tbroken\\n" | git mktree) +' + +test_expect_success 'read-tree refuses to read null sha1' ' + test_must_fail git read-tree $tree +' + +test_expect_success 'GIT_ALLOW_NULL_SHA1 overrides refusal' ' + GIT_ALLOW_NULL_SHA1=1 git read-tree $tree +' + +test_expect_success 'git write-tree refuses to write null sha1' ' + test_must_fail git write-tree +' + +test_done diff --git a/t/t2013-checkout-submodule.sh b/t/t2013-checkout-submodule.sh index aa35223369..6ef15738e4 100755 --- a/t/t2013-checkout-submodule.sh +++ b/t/t2013-checkout-submodule.sh @@ -64,9 +64,9 @@ test_expect_success '"checkout <submodule>" honors submodule.*.ignore from .git/ ' KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS=1 -test_submodule_switch_recursing "git checkout --recurse-submodules" +test_submodule_switch_recursing_with_args "checkout" -test_submodule_forced_switch_recursing "git checkout -f --recurse-submodules" +test_submodule_forced_switch_recursing_with_args "checkout -f" test_submodule_switch "git checkout" diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh index 84a9028c43..1bdf38e80d 100755 --- a/t/t2203-add-intent.sh +++ b/t/t2203-add-intent.sh @@ -129,10 +129,10 @@ test_expect_success 'cache-tree does skip dir that becomes empty' ' ) ' -test_expect_success 'commit: ita entries ignored in empty intial commit check' ' - git init empty-intial-commit && +test_expect_success 'commit: ita entries ignored in empty initial commit check' ' + git init empty-initial-commit && ( - cd empty-intial-commit && + cd empty-initial-commit && : >one && git add -N one && test_must_fail git commit -m nothing-new-here diff --git a/t/t3007-ls-files-recurse-submodules.sh b/t/t3007-ls-files-recurse-submodules.sh index ebb956fd16..318b5bce7e 100755 --- a/t/t3007-ls-files-recurse-submodules.sh +++ b/t/t3007-ls-files-recurse-submodules.sh @@ -135,6 +135,45 @@ test_expect_success '--recurse-submodules and pathspecs setup' ' test_cmp expect actual ' +test_expect_success 'inactive submodule' ' + test_when_finished "git config --bool submodule.submodule.active true" && + test_when_finished "git -C submodule config --bool submodule.subsub.active true" && + git config --bool submodule.submodule.active "false" && + + cat >expect <<-\EOF && + .gitmodules + a + b/b + h.txt + sib/file + sub/file + submodule + EOF + + git ls-files --recurse-submodules >actual && + test_cmp expect actual && + + git config --bool submodule.submodule.active "true" && + git -C submodule config --bool submodule.subsub.active "false" && + + cat >expect <<-\EOF && + .gitmodules + a + b/b + h.txt + sib/file + sub/file + submodule/.gitmodules + submodule/c + submodule/f.TXT + submodule/g.txt + submodule/subsub + EOF + + git ls-files --recurse-submodules >actual && + test_cmp expect actual +' + test_expect_success '--recurse-submodules and pathspecs' ' cat >expect <<-\EOF && h.txt diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh index 7ca69f4bed..163a14a1c2 100755 --- a/t/t3070-wildmatch.sh +++ b/t/t3070-wildmatch.sh @@ -82,6 +82,7 @@ match 1 0 'foo/bar' 'foo/**/bar' match 1 0 'foo/bar' 'foo/**/**/bar' match 0 0 'foo/bar' 'foo?bar' match 0 0 'foo/bar' 'foo[/]bar' +match 0 0 'foo/bar' 'foo[^a-z]bar' match 0 0 'foo/bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r' match 1 1 'foo-bar' 'f[^eiu][^eiu][^eiu][^eiu][^eiu]r' match 1 0 'foo' '**/foo' @@ -225,6 +226,7 @@ pathmatch 0 foo/bba/arr 'foo/*z' pathmatch 0 foo/bba/arr 'foo/**z' pathmatch 1 foo/bar 'foo?bar' pathmatch 1 foo/bar 'foo[/]bar' +pathmatch 1 foo/bar 'foo[^a-z]bar' pathmatch 0 foo '*/*/*' pathmatch 0 foo/bar '*/*/*' pathmatch 1 foo/bba/arr '*/*/*' @@ -233,7 +235,7 @@ pathmatch 1 abcXdefXghi '*X*i' pathmatch 1 ab/cXd/efXg/hi '*/*X*/*/*i' pathmatch 1 ab/cXd/efXg/hi '*Xg*i' -# Case-sensitivy features +# Case-sensitivity features match 0 x 'a' '[A-Z]' match 1 x 'A' '[A-Z]' match 0 x 'A' '[a-z]' diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index dd37ac47c5..9d707d2a40 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -166,10 +166,9 @@ test_expect_success 'resulting reflog can be shown by log -g' ' oid=$(git rev-parse HEAD) && cat >expect <<-EOF && HEAD@{0} $oid $msg - HEAD@{1} $oid $msg HEAD@{2} $oid checkout: moving from foo to baz EOF - git log -g --format="%gd %H %gs" -3 HEAD >actual && + git log -g --format="%gd %H %gs" -2 HEAD >actual && test_cmp expect actual ' diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh index a428ae6703..d2aec0f38b 100755 --- a/t/t3203-branch-output.sh +++ b/t/t3203-branch-output.sh @@ -2,6 +2,7 @@ test_description='git branch display tests' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-terminal.sh test_expect_success 'make commits' ' echo content >file && @@ -239,4 +240,34 @@ test_expect_success 'git branch --format option' ' test_i18ncmp expect actual ' +test_expect_success "set up color tests" ' + echo "<RED>master<RESET>" >expect.color && + echo "master" >expect.bare && + color_args="--format=%(color:red)%(refname:short) --list master" +' + +test_expect_success '%(color) omitted without tty' ' + TERM=vt100 git branch $color_args >actual.raw && + test_decode_color <actual.raw >actual && + test_cmp expect.bare actual +' + +test_expect_success TTY '%(color) present with tty' ' + test_terminal env TERM=vt100 git branch $color_args >actual.raw && + test_decode_color <actual.raw >actual && + test_cmp expect.color actual +' + +test_expect_success 'color.branch=always overrides auto-color' ' + git -c color.branch=always branch $color_args >actual.raw && + test_decode_color <actual.raw >actual && + test_cmp expect.color actual +' + +test_expect_success '--color overrides auto-color' ' + git branch --color $color_args >actual.raw && + test_decode_color <actual.raw >actual && + test_cmp expect.color actual +' + test_done diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh index 4428b9086e..fcfdd197bd 100755 --- a/t/t3418-rebase-continue.sh +++ b/t/t3418-rebase-continue.sh @@ -40,25 +40,6 @@ test_expect_success 'non-interactive rebase --continue works with touched file' git rebase --continue ' -test_expect_success 'non-interactive rebase --continue with rerere enabled' ' - test_config rerere.enabled true && - test_when_finished "test_might_fail git rebase --abort" && - git reset --hard commit-new-file-F2-on-topic-branch && - git checkout master && - rm -fr .git/rebase-* && - - test_must_fail git rebase --onto master master topic && - echo "Resolved" >F2 && - git add F2 && - cp F2 F2.expected && - git rebase --continue && - - git reset --hard commit-new-file-F2-on-topic-branch && - git checkout master && - test_must_fail git rebase --onto master master topic && - test_cmp F2.expected F2 -' - test_expect_success 'rebase --continue can not be used with other options' ' test_must_fail git rebase -v --continue && test_must_fail git rebase --continue -v @@ -93,25 +74,75 @@ test_expect_success 'rebase --continue remembers merge strategy and options' ' test -f funny.was.run ' -test_expect_success 'rebase --continue remembers --rerere-autoupdate' ' +test_expect_success 'setup rerere database' ' rm -fr .git/rebase-* && git reset --hard commit-new-file-F3-on-topic-branch && git checkout master && test_commit "commit-new-file-F3" F3 3 && - git config rerere.enabled true && + test_config rerere.enabled true && test_must_fail git rebase -m master topic && echo "Resolved" >F2 && + cp F2 expected-F2 && git add F2 && test_must_fail git rebase --continue && echo "Resolved" >F3 && + cp F3 expected-F3 && git add F3 && git rebase --continue && - git reset --hard topic@{1} && - test_must_fail git rebase -m --rerere-autoupdate master && - test "$(cat F2)" = "Resolved" && - test_must_fail git rebase --continue && - test "$(cat F3)" = "Resolved" && - git rebase --continue + git reset --hard topic@{1} ' +prepare () { + rm -fr .git/rebase-* && + git reset --hard commit-new-file-F3-on-topic-branch && + git checkout master && + test_config rerere.enabled true +} + +test_rerere_autoupdate () { + action=$1 && + test_expect_success "rebase $action --continue remembers --rerere-autoupdate" ' + prepare && + test_must_fail git rebase $action --rerere-autoupdate master topic && + test_cmp expected-F2 F2 && + git diff-files --quiet && + test_must_fail git rebase --continue && + test_cmp expected-F3 F3 && + git diff-files --quiet && + git rebase --continue + ' + + test_expect_success "rebase $action --continue honors rerere.autoUpdate" ' + prepare && + test_config rerere.autoupdate true && + test_must_fail git rebase $action master topic && + test_cmp expected-F2 F2 && + git diff-files --quiet && + test_must_fail git rebase --continue && + test_cmp expected-F3 F3 && + git diff-files --quiet && + git rebase --continue + ' + + test_expect_success "rebase $action --continue remembers --no-rerere-autoupdate" ' + prepare && + test_config rerere.autoupdate true && + test_must_fail git rebase $action --no-rerere-autoupdate master topic && + test_cmp expected-F2 F2 && + test_must_fail git diff-files --quiet && + git add F2 && + test_must_fail git rebase --continue && + test_cmp expected-F3 F3 && + test_must_fail git diff-files --quiet && + git add F3 && + git rebase --continue + ' +} + +test_rerere_autoupdate +test_rerere_autoupdate -m +GIT_SEQUENCE_EDITOR=: && export GIT_SEQUENCE_EDITOR +test_rerere_autoupdate -i +test_rerere_autoupdate --preserve-merges + test_done diff --git a/t/t3504-cherry-pick-rerere.sh b/t/t3504-cherry-pick-rerere.sh index e6a64816ef..a267b2d144 100755 --- a/t/t3504-cherry-pick-rerere.sh +++ b/t/t3504-cherry-pick-rerere.sh @@ -5,14 +5,13 @@ test_description='cherry-pick should rerere for conflicts' . ./test-lib.sh test_expect_success setup ' - echo foo >foo && - git add foo && test_tick && git commit -q -m 1 && - echo foo-master >foo && - git add foo && test_tick && git commit -q -m 2 && - - git checkout -b dev HEAD^ && - echo foo-dev >foo && - git add foo && test_tick && git commit -q -m 3 && + test_commit foo && + test_commit foo-master foo && + test_commit bar-master bar && + + git checkout -b dev foo && + test_commit foo-dev foo && + test_commit bar-dev bar && git config rerere.enabled true ' @@ -21,23 +20,80 @@ test_expect_success 'conflicting merge' ' ' test_expect_success 'fixup' ' - echo foo-dev >foo && - git add foo && test_tick && git commit -q -m 4 && - git reset --hard HEAD^ && - echo foo-dev >expect + echo foo-resolved >foo && + echo bar-resolved >bar && + git commit -am resolved && + cp foo foo-expect && + cp bar bar-expect && + git reset --hard HEAD^ ' -test_expect_success 'cherry-pick conflict' ' - test_must_fail git cherry-pick master && - test_cmp expect foo +test_expect_success 'cherry-pick conflict with --rerere-autoupdate' ' + test_must_fail git cherry-pick --rerere-autoupdate foo..bar-master && + test_cmp foo-expect foo && + git diff-files --quiet && + test_must_fail git cherry-pick --continue && + test_cmp bar-expect bar && + git diff-files --quiet && + git cherry-pick --continue && + git reset --hard bar-dev +' + +test_expect_success 'cherry-pick conflict repsects rerere.autoUpdate' ' + test_config rerere.autoUpdate true && + test_must_fail git cherry-pick foo..bar-master && + test_cmp foo-expect foo && + git diff-files --quiet && + test_must_fail git cherry-pick --continue && + test_cmp bar-expect bar && + git diff-files --quiet && + git cherry-pick --continue && + git reset --hard bar-dev +' + +test_expect_success 'cherry-pick conflict with --no-rerere-autoupdate' ' + test_config rerere.autoUpdate true && + test_must_fail git cherry-pick --no-rerere-autoupdate foo..bar-master && + test_cmp foo-expect foo && + test_must_fail git diff-files --quiet && + git add foo && + test_must_fail git cherry-pick --continue && + test_cmp bar-expect bar && + test_must_fail git diff-files --quiet && + git add bar && + git cherry-pick --continue && + git reset --hard bar-dev +' + +test_expect_success 'cherry-pick --continue rejects --rerere-autoupdate' ' + test_must_fail git cherry-pick --rerere-autoupdate foo..bar-master && + test_cmp foo-expect foo && + git diff-files --quiet && + test_must_fail git cherry-pick --continue --rerere-autoupdate >actual 2>&1 && + echo "fatal: cherry-pick: --rerere-autoupdate cannot be used with --continue" >expect && + test_i18ncmp expect actual && + test_must_fail git cherry-pick --continue --no-rerere-autoupdate >actual 2>&1 && + echo "fatal: cherry-pick: --no-rerere-autoupdate cannot be used with --continue" >expect && + test_i18ncmp expect actual && + git cherry-pick --abort ' -test_expect_success 'reconfigure' ' - git config rerere.enabled false && - git reset --hard +test_expect_success 'cherry-pick --rerere-autoupdate more than once' ' + test_must_fail git cherry-pick --rerere-autoupdate --rerere-autoupdate foo..bar-master && + test_cmp foo-expect foo && + git diff-files --quiet && + git cherry-pick --abort && + test_must_fail git cherry-pick --rerere-autoupdate --no-rerere-autoupdate --rerere-autoupdate foo..bar-master && + test_cmp foo-expect foo && + git diff-files --quiet && + git cherry-pick --abort && + test_must_fail git cherry-pick --rerere-autoupdate --no-rerere-autoupdate foo..bar-master && + test_must_fail git diff-files --quiet && + git cherry-pick --abort ' test_expect_success 'cherry-pick conflict without rerere' ' + test_config rerere.enabled false && test_must_fail git cherry-pick master && test_must_fail test_cmp expect foo ' diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh index 5f9913ba33..f8568f8841 100755 --- a/t/t3600-rm.sh +++ b/t/t3600-rm.sh @@ -97,9 +97,9 @@ test_expect_success FUNNYNAMES \ embedded'" test_expect_success SANITY 'Test that "git rm -f" fails if its rm fails' ' + test_when_finished "chmod 775 ." && chmod a-w . && - test_must_fail git rm -f baz && - chmod 775 . + test_must_fail git rm -f baz ' test_expect_success \ diff --git a/t/t4041-diff-submodule-option.sh b/t/t4041-diff-submodule-option.sh index 2d9731b52d..058ee0829d 100755 --- a/t/t4041-diff-submodule-option.sh +++ b/t/t4041-diff-submodule-option.sh @@ -430,9 +430,11 @@ test_expect_success 'deleted submodule' ' test_cmp expected actual ' -test_create_repo sm2 && -head7=$(add_file sm2 foo8 foo9) && -git add sm2 +test_expect_success 'create second submodule' ' + test_create_repo sm2 && + head7=$(add_file sm2 foo8 foo9) && + git add sm2 +' test_expect_success 'multiple submodules' ' git diff-index -p --submodule=log HEAD >actual && diff --git a/t/t4051-diff-function-context.sh b/t/t4051-diff-function-context.sh index 6154acb456..3e6b485ecb 100755 --- a/t/t4051-diff-function-context.sh +++ b/t/t4051-diff-function-context.sh @@ -72,7 +72,8 @@ test_expect_success 'setup' ' # overlap function context of 1st change and -u context of 2nd change grep -v "delete me from hello" <"$dir/hello.c" >file.c && - sed 2p <"$dir/dummy.c" >>file.c && + sed "2a\\ + extra line" <"$dir/dummy.c" >>file.c && commit_and_tag changed_hello_dummy file.c && git checkout initial && diff --git a/t/t4060-diff-submodule-option-diff-format.sh b/t/t4060-diff-submodule-option-diff-format.sh index d4a3ffa69c..4b168d0ed7 100755 --- a/t/t4060-diff-submodule-option-diff-format.sh +++ b/t/t4060-diff-submodule-option-diff-format.sh @@ -643,9 +643,11 @@ test_expect_success 'deleted submodule' ' test_cmp expected actual ' -test_create_repo sm2 && -head7=$(add_file sm2 foo8 foo9) && -git add sm2 +test_expect_success 'create second submodule' ' + test_create_repo sm2 && + head7=$(add_file sm2 foo8 foo9) && + git add sm2 +' test_expect_success 'multiple submodules' ' git diff-index -p --submodule=diff HEAD >actual && @@ -775,4 +777,45 @@ test_expect_success 'diff --submodule=diff with moved nested submodule HEAD' ' test_cmp expected actual ' +test_expect_success 'diff --submodule=diff recurses into nested submodules' ' + cat >expected <<-EOF && + Submodule sm2 contains modified content + Submodule sm2 a5a65c9..280969a: + diff --git a/sm2/.gitmodules b/sm2/.gitmodules + new file mode 100644 + index 0000000..3a816b8 + --- /dev/null + +++ b/sm2/.gitmodules + @@ -0,0 +1,3 @@ + +[submodule "nested"] + + path = nested + + url = ../sm2 + Submodule nested 0000000...b55928c (new submodule) + diff --git a/sm2/nested/file b/sm2/nested/file + new file mode 100644 + index 0000000..ca281f5 + --- /dev/null + +++ b/sm2/nested/file + @@ -0,0 +1 @@ + +nested content + diff --git a/sm2/nested/foo8 b/sm2/nested/foo8 + new file mode 100644 + index 0000000..db9916b + --- /dev/null + +++ b/sm2/nested/foo8 + @@ -0,0 +1 @@ + +foo8 + diff --git a/sm2/nested/foo9 b/sm2/nested/foo9 + new file mode 100644 + index 0000000..9c3b4f6 + --- /dev/null + +++ b/sm2/nested/foo9 + @@ -0,0 +1 @@ + +foo9 + EOF + git diff --submodule=diff >actual 2>err && + test_must_be_empty err && + test_cmp expected actual +' + test_done diff --git a/t/t4061-diff-indent.sh b/t/t4061-diff-indent.sh index 556450609b..2affd7a100 100755 --- a/t/t4061-diff-indent.sh +++ b/t/t4061-diff-indent.sh @@ -152,26 +152,28 @@ test_expect_success 'prepare' ' EOF ' +# --- diff tests ---------------------------------------------------------- + test_expect_success 'diff: ugly spaces' ' - git diff old new -- spaces.txt >out && + git diff --no-indent-heuristic old new -- spaces.txt >out && compare_diff spaces-expect out ' +test_expect_success 'diff: --no-indent-heuristic overrides config' ' + git -c diff.indentHeuristic=true diff --no-indent-heuristic old new -- spaces.txt >out2 && + compare_diff spaces-expect out2 +' + test_expect_success 'diff: nice spaces with --indent-heuristic' ' - git diff --indent-heuristic old new -- spaces.txt >out-compacted && + git -c diff.indentHeuristic=false diff --indent-heuristic old new -- spaces.txt >out-compacted && compare_diff spaces-compacted-expect out-compacted ' -test_expect_success 'diff: nice spaces with diff.indentHeuristic' ' +test_expect_success 'diff: nice spaces with diff.indentHeuristic=true' ' git -c diff.indentHeuristic=true diff old new -- spaces.txt >out-compacted2 && compare_diff spaces-compacted-expect out-compacted2 ' -test_expect_success 'diff: --no-indent-heuristic overrides config' ' - git -c diff.indentHeuristic=true diff --no-indent-heuristic old new -- spaces.txt >out2 && - compare_diff spaces-expect out2 -' - test_expect_success 'diff: --indent-heuristic with --patience' ' git diff --indent-heuristic --patience old new -- spaces.txt >out-compacted3 && compare_diff spaces-compacted-expect out-compacted3 @@ -183,7 +185,7 @@ test_expect_success 'diff: --indent-heuristic with --histogram' ' ' test_expect_success 'diff: ugly functions' ' - git diff old new -- functions.c >out && + git diff --no-indent-heuristic old new -- functions.c >out && compare_diff functions-expect out ' @@ -192,25 +194,175 @@ test_expect_success 'diff: nice functions with --indent-heuristic' ' compare_diff functions-compacted-expect out-compacted ' -test_expect_success 'blame: ugly spaces' ' - git blame old..new -- spaces.txt >out-blame && - compare_blame spaces-expect out-blame -' +# --- blame tests --------------------------------------------------------- test_expect_success 'blame: nice spaces with --indent-heuristic' ' git blame --indent-heuristic old..new -- spaces.txt >out-blame-compacted && compare_blame spaces-compacted-expect out-blame-compacted ' -test_expect_success 'blame: nice spaces with diff.indentHeuristic' ' +test_expect_success 'blame: nice spaces with diff.indentHeuristic=true' ' git -c diff.indentHeuristic=true blame old..new -- spaces.txt >out-blame-compacted2 && compare_blame spaces-compacted-expect out-blame-compacted2 ' +test_expect_success 'blame: ugly spaces with --no-indent-heuristic' ' + git blame --no-indent-heuristic old..new -- spaces.txt >out-blame && + compare_blame spaces-expect out-blame +' + +test_expect_success 'blame: ugly spaces with diff.indentHeuristic=false' ' + git -c diff.indentHeuristic=false blame old..new -- spaces.txt >out-blame2 && + compare_blame spaces-expect out-blame2 +' + test_expect_success 'blame: --no-indent-heuristic overrides config' ' - git -c diff.indentHeuristic=true blame --no-indent-heuristic old..new -- spaces.txt >out-blame2 && + git -c diff.indentHeuristic=true blame --no-indent-heuristic old..new -- spaces.txt >out-blame3 && git blame old..new -- spaces.txt >out-blame && - compare_blame spaces-expect out-blame2 + compare_blame spaces-expect out-blame3 +' + +test_expect_success 'blame: --indent-heuristic overrides config' ' + git -c diff.indentHeuristic=false blame --indent-heuristic old..new -- spaces.txt >out-blame-compacted3 && + compare_blame spaces-compacted-expect out-blame-compacted2 +' + +# --- diff-tree tests ----------------------------------------------------- + +test_expect_success 'diff-tree: nice spaces with --indent-heuristic' ' + git diff-tree --indent-heuristic -p old new -- spaces.txt >out-diff-tree-compacted && + compare_diff spaces-compacted-expect out-diff-tree-compacted +' + +test_expect_success 'diff-tree: nice spaces with diff.indentHeuristic=true' ' + git -c diff.indentHeuristic=true diff-tree -p old new -- spaces.txt >out-diff-tree-compacted2 && + compare_diff spaces-compacted-expect out-diff-tree-compacted2 +' + +test_expect_success 'diff-tree: ugly spaces with --no-indent-heuristic' ' + git diff-tree --no-indent-heuristic -p old new -- spaces.txt >out-diff-tree && + compare_diff spaces-expect out-diff-tree +' + +test_expect_success 'diff-tree: ugly spaces with diff.indentHeuristic=false' ' + git -c diff.indentHeuristic=false diff-tree -p old new -- spaces.txt >out-diff-tree2 && + compare_diff spaces-expect out-diff-tree2 +' + +test_expect_success 'diff-tree: --indent-heuristic overrides config' ' + git -c diff.indentHeuristic=false diff-tree --indent-heuristic -p old new -- spaces.txt >out-diff-tree-compacted3 && + compare_diff spaces-compacted-expect out-diff-tree-compacted3 +' + +test_expect_success 'diff-tree: --no-indent-heuristic overrides config' ' + git -c diff.indentHeuristic=true diff-tree --no-indent-heuristic -p old new -- spaces.txt >out-diff-tree3 && + compare_diff spaces-expect out-diff-tree3 +' + +# --- diff-index tests ---------------------------------------------------- + +test_expect_success 'diff-index: nice spaces with --indent-heuristic' ' + git checkout -B diff-index && + git reset --soft HEAD~ && + git diff-index --indent-heuristic -p old -- spaces.txt >out-diff-index-compacted && + compare_diff spaces-compacted-expect out-diff-index-compacted && + git checkout -f master +' + +test_expect_success 'diff-index: nice spaces with diff.indentHeuristic=true' ' + git checkout -B diff-index && + git reset --soft HEAD~ && + git -c diff.indentHeuristic=true diff-index -p old -- spaces.txt >out-diff-index-compacted2 && + compare_diff spaces-compacted-expect out-diff-index-compacted2 && + git checkout -f master +' + +test_expect_success 'diff-index: ugly spaces with --no-indent-heuristic' ' + git checkout -B diff-index && + git reset --soft HEAD~ && + git diff-index --no-indent-heuristic -p old -- spaces.txt >out-diff-index && + compare_diff spaces-expect out-diff-index && + git checkout -f master +' + +test_expect_success 'diff-index: ugly spaces with diff.indentHeuristic=false' ' + git checkout -B diff-index && + git reset --soft HEAD~ && + git -c diff.indentHeuristic=false diff-index -p old -- spaces.txt >out-diff-index2 && + compare_diff spaces-expect out-diff-index2 && + git checkout -f master +' + +test_expect_success 'diff-index: --indent-heuristic overrides config' ' + git checkout -B diff-index && + git reset --soft HEAD~ && + git -c diff.indentHeuristic=false diff-index --indent-heuristic -p old -- spaces.txt >out-diff-index-compacted3 && + compare_diff spaces-compacted-expect out-diff-index-compacted3 && + git checkout -f master +' + +test_expect_success 'diff-index: --no-indent-heuristic overrides config' ' + git checkout -B diff-index && + git reset --soft HEAD~ && + git -c diff.indentHeuristic=true diff-index --no-indent-heuristic -p old -- spaces.txt >out-diff-index3 && + compare_diff spaces-expect out-diff-index3 && + git checkout -f master +' + +# --- diff-files tests ---------------------------------------------------- + +test_expect_success 'diff-files: nice spaces with --indent-heuristic' ' + git checkout -B diff-files && + git reset HEAD~ && + git diff-files --indent-heuristic -p spaces.txt >out-diff-files-raw && + grep -v index out-diff-files-raw >out-diff-files-compacted && + compare_diff spaces-compacted-expect out-diff-files-compacted && + git checkout -f master +' + +test_expect_success 'diff-files: nice spaces with diff.indentHeuristic=true' ' + git checkout -B diff-files && + git reset HEAD~ && + git -c diff.indentHeuristic=true diff-files -p spaces.txt >out-diff-files-raw2 && + grep -v index out-diff-files-raw2 >out-diff-files-compacted2 && + compare_diff spaces-compacted-expect out-diff-files-compacted2 && + git checkout -f master +' + +test_expect_success 'diff-files: ugly spaces with --no-indent-heuristic' ' + git checkout -B diff-files && + git reset HEAD~ && + git diff-files --no-indent-heuristic -p spaces.txt >out-diff-files-raw && + grep -v index out-diff-files-raw >out-diff-files && + compare_diff spaces-expect out-diff-files && + git checkout -f master +' + +test_expect_success 'diff-files: ugly spaces with diff.indentHeuristic=false' ' + git checkout -B diff-files && + git reset HEAD~ && + git -c diff.indentHeuristic=false diff-files -p spaces.txt >out-diff-files-raw2 && + grep -v index out-diff-files-raw2 >out-diff-files && + compare_diff spaces-expect out-diff-files && + git checkout -f master +' + +test_expect_success 'diff-files: --indent-heuristic overrides config' ' + git checkout -B diff-files && + git reset HEAD~ && + git -c diff.indentHeuristic=false diff-files --indent-heuristic -p spaces.txt >out-diff-files-raw3 && + grep -v index out-diff-files-raw3 >out-diff-files-compacted && + compare_diff spaces-compacted-expect out-diff-files-compacted && + git checkout -f master +' + +test_expect_success 'diff-files: --no-indent-heuristic overrides config' ' + git checkout -B diff-files && + git reset HEAD~ && + git -c diff.indentHeuristic=true diff-files --no-indent-heuristic -p spaces.txt >out-diff-files-raw4 && + grep -v index out-diff-files-raw4 >out-diff-files && + compare_diff spaces-expect out-diff-files && + git checkout -f master ' test_done diff --git a/t/t4202-log.sh b/t/t4202-log.sh index e4441957e2..36d120c969 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -231,14 +231,47 @@ second initial EOF test_expect_success 'log --invert-grep --grep' ' - git log --pretty="tformat:%s" --invert-grep --grep=th --grep=Sec >actual && - test_cmp expect actual + # Fixed + git -c grep.patternType=fixed log --pretty="tformat:%s" --invert-grep --grep=th --grep=Sec >actual && + test_cmp expect actual && + + # POSIX basic + git -c grep.patternType=basic log --pretty="tformat:%s" --invert-grep --grep=t[h] --grep=S[e]c >actual && + test_cmp expect actual && + + # POSIX extended + git -c grep.patternType=basic log --pretty="tformat:%s" --invert-grep --grep=t[h] --grep=S[e]c >actual && + test_cmp expect actual && + + # PCRE + if test_have_prereq PCRE + then + git -c grep.patternType=perl log --pretty="tformat:%s" --invert-grep --grep=t[h] --grep=S[e]c >actual && + test_cmp expect actual + fi ' test_expect_success 'log --invert-grep --grep -i' ' echo initial >expect && - git log --pretty="tformat:%s" --invert-grep -i --grep=th --grep=Sec >actual && - test_cmp expect actual + + # Fixed + git -c grep.patternType=fixed log --pretty="tformat:%s" --invert-grep -i --grep=th --grep=Sec >actual && + test_cmp expect actual && + + # POSIX basic + git -c grep.patternType=basic log --pretty="tformat:%s" --invert-grep -i --grep=t[h] --grep=S[e]c >actual && + test_cmp expect actual && + + # POSIX extended + git -c grep.patternType=extended log --pretty="tformat:%s" --invert-grep -i --grep=t[h] --grep=S[e]c >actual && + test_cmp expect actual && + + # PCRE + if test_have_prereq PCRE + then + git -c grep.patternType=perl log --pretty="tformat:%s" --invert-grep -i --grep=t[h] --grep=S[e]c >actual && + test_cmp expect actual + fi ' test_expect_success 'log --grep option parsing' ' @@ -256,13 +289,53 @@ test_expect_success 'log -i --grep' ' test_expect_success 'log --grep -i' ' echo Second >expect && + + # Fixed git log -1 --pretty="tformat:%s" --grep=sec -i >actual && - test_cmp expect actual + test_cmp expect actual && + + # POSIX basic + git -c grep.patternType=basic log -1 --pretty="tformat:%s" --grep=s[e]c -i >actual && + test_cmp expect actual && + + # POSIX extended + git -c grep.patternType=extended log -1 --pretty="tformat:%s" --grep=s[e]c -i >actual && + test_cmp expect actual && + + # PCRE + if test_have_prereq PCRE + then + git -c grep.patternType=perl log -1 --pretty="tformat:%s" --grep=s[e]c -i >actual && + test_cmp expect actual + fi ' test_expect_success 'log -F -E --grep=<ere> uses ere' ' echo second >expect && - git log -1 --pretty="tformat:%s" -F -E --grep=s.c.nd >actual && + # basic would need \(s\) to do the same + git log -1 --pretty="tformat:%s" -F -E --grep="(s).c.nd" >actual && + test_cmp expect actual +' + +test_expect_success PCRE 'log -F -E --perl-regexp --grep=<pcre> uses PCRE' ' + test_when_finished "rm -rf num_commits" && + git init num_commits && + ( + cd num_commits && + test_commit 1d && + test_commit 2e + ) && + + # In PCRE \d in [\d] is like saying "0-9", and matches the 2 + # in 2e... + echo 2e >expect && + git -C num_commits log -1 --pretty="tformat:%s" -F -E --perl-regexp --grep="[\d]" >actual && + test_cmp expect actual && + + # ...in POSIX basic and extended it is the same as [d], + # i.e. "d", which matches 1d, but does not match 2e. + echo 1d >expect && + git -C num_commits log -1 --pretty="tformat:%s" -F -E --grep="[\d]" >actual && test_cmp expect actual ' @@ -280,6 +353,93 @@ test_expect_success 'log with grep.patternType configuration and command line' ' test_cmp expect actual ' +test_expect_success 'log with various grep.patternType configurations & command-lines' ' + git init pattern-type && + ( + cd pattern-type && + test_commit 1 file A && + + # The tagname is overridden here because creating a + # tag called "(1|2)" as test_commit would otherwise + # implicitly do would fail on e.g. MINGW. + test_commit "(1|2)" file B 2 && + + echo "(1|2)" >expect.fixed && + cp expect.fixed expect.basic && + cp expect.fixed expect.extended && + cp expect.fixed expect.perl && + + # A strcmp-like match with fixed. + git -c grep.patternType=fixed log --pretty=tformat:%s \ + --grep="(1|2)" >actual.fixed && + + # POSIX basic matches (, | and ) literally. + git -c grep.patternType=basic log --pretty=tformat:%s \ + --grep="(.|.)" >actual.basic && + + # POSIX extended needs to have | escaped to match it + # literally, whereas under basic this is the same as + # (|2), i.e. it would also match "1". This test checks + # for extended by asserting that it is not matching + # what basic would match. + git -c grep.patternType=extended log --pretty=tformat:%s \ + --grep="\|2" >actual.extended && + if test_have_prereq PCRE + then + # Only PCRE would match [\d]\| with only + # "(1|2)" due to [\d]. POSIX basic would match + # both it and "1" since similarly to the + # extended match above it is the same as + # \([\d]\|\). POSIX extended would + # match neither. + git -c grep.patternType=perl log --pretty=tformat:%s \ + --grep="[\d]\|" >actual.perl && + test_cmp expect.perl actual.perl + fi && + test_cmp expect.fixed actual.fixed && + test_cmp expect.basic actual.basic && + test_cmp expect.extended actual.extended && + + git log --pretty=tformat:%s -F \ + --grep="(1|2)" >actual.fixed.short-arg && + git log --pretty=tformat:%s -E \ + --grep="\|2" >actual.extended.short-arg && + if test_have_prereq PCRE + then + git log --pretty=tformat:%s -P \ + --grep="[\d]\|" >actual.perl.short-arg + else + test_must_fail git log -P \ + --grep="[\d]\|" + fi && + test_cmp expect.fixed actual.fixed.short-arg && + test_cmp expect.extended actual.extended.short-arg && + if test_have_prereq PCRE + then + test_cmp expect.perl actual.perl.short-arg + fi && + + git log --pretty=tformat:%s --fixed-strings \ + --grep="(1|2)" >actual.fixed.long-arg && + git log --pretty=tformat:%s --basic-regexp \ + --grep="(.|.)" >actual.basic.long-arg && + git log --pretty=tformat:%s --extended-regexp \ + --grep="\|2" >actual.extended.long-arg && + if test_have_prereq PCRE + then + git log --pretty=tformat:%s --perl-regexp \ + --grep="[\d]\|" >actual.perl.long-arg && + test_cmp expect.perl actual.perl.long-arg + else + test_must_fail git log --perl-regexp \ + --grep="[\d]\|" + fi && + test_cmp expect.fixed actual.fixed.long-arg && + test_cmp expect.basic actual.basic.long-arg && + test_cmp expect.extended actual.extended.long-arg + ) +' + cat > expect <<EOF * Second * sixth @@ -1363,6 +1523,12 @@ test_expect_success 'log diagnoses bogus HEAD' ' test_i18ngrep broken stderr ' +test_expect_success 'log does not default to HEAD when rev input is given' ' + >expect && + git log --branches=does-not-exist >actual && + test_cmp expect actual +' + test_expect_success 'set up --source tests' ' git checkout --orphan source-a && test_commit one && diff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh index b972296f06..60f040cab8 100755 --- a/t/t4207-log-decoration-colors.sh +++ b/t/t4207-log-decoration-colors.sh @@ -7,11 +7,6 @@ test_description='Test for "git log --decorate" colors' . ./test-lib.sh -get_color () -{ - git config --get-color no.such.slot "$1" -} - test_expect_success setup ' git config diff.color.commit yellow && git config color.decorate.branch green && @@ -20,14 +15,14 @@ test_expect_success setup ' git config color.decorate.stash magenta && git config color.decorate.HEAD cyan && - c_reset=$(get_color reset) && + c_reset="<RESET>" && - c_commit=$(get_color yellow) && - c_branch=$(get_color green) && - c_remoteBranch=$(get_color red) && - c_tag=$(get_color "reverse bold yellow") && - c_stash=$(get_color magenta) && - c_HEAD=$(get_color cyan) && + c_commit="<YELLOW>" && + c_branch="<GREEN>" && + c_remoteBranch="<RED>" && + c_tag="<BOLD;REVERSE;YELLOW>" && + c_stash="<MAGENTA>" && + c_HEAD="<CYAN>" && test_commit A && git clone . other && @@ -59,7 +54,8 @@ EOF # to this test since it does not contain any decoration, hence --first-parent test_expect_success 'Commit Decorations Colored Correctly' ' git log --first-parent --abbrev=10 --all --decorate --oneline --color=always | - sed "s/[0-9a-f]\{10,10\}/COMMIT_ID/" >out && + sed "s/[0-9a-f]\{10,10\}/COMMIT_ID/" | + test_decode_color >out && test_cmp expected out ' diff --git a/t/t4208-log-magic-pathspec.sh b/t/t4208-log-magic-pathspec.sh index 001343e2fc..935df6a65c 100755 --- a/t/t4208-log-magic-pathspec.sh +++ b/t/t4208-log-magic-pathspec.sh @@ -29,6 +29,12 @@ test_expect_success '"git log -- :/a" should not be ambiguous' ' git log -- :/a ' +# This differs from the ":/a" check above in that :/in looks like a pathspec, +# but doesn't match an actual file. +test_expect_success '"git log :/in" should not be ambiguous' ' + git log :/in +' + test_expect_success '"git log :" should be ambiguous' ' test_must_fail git log : 2>error && test_i18ngrep ambiguous error @@ -46,6 +52,32 @@ test_expect_success 'git log HEAD -- :/' ' test_cmp expected actual ' +test_expect_success '"git log :^sub" is not ambiguous' ' + git log :^sub +' + +test_expect_success '"git log :^does-not-exist" does not match anything' ' + test_must_fail git log :^does-not-exist +' + +test_expect_success '"git log :!" behaves the same as :^' ' + git log :!sub && + test_must_fail git log :!does-not-exist +' + +test_expect_success '"git log :(exclude)sub" is not ambiguous' ' + git log ":(exclude)sub" +' + +test_expect_success '"git log :(exclude)sub --" must resolve as an object' ' + test_must_fail git log ":(exclude)sub" -- +' + +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_expect_success 'command line pathspec parsing for "git log"' ' git reset --hard && >a && diff --git a/t/t4213-log-tabexpand.sh b/t/t4213-log-tabexpand.sh index e01a8f6ac9..7f90f58c03 100755 --- a/t/t4213-log-tabexpand.sh +++ b/t/t4213-log-tabexpand.sh @@ -37,7 +37,7 @@ count_expand () # Prefix the output with the command line arguments, and # replace SP with a dot both in the expecte and actual output - # so that test_cmp would show the differene together with the + # so that test_cmp would show the difference together with the # breakage in a way easier to consume by the debugging user. { echo "git show -s $*" diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh index 886b6953e4..fe2d4f15a7 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -390,7 +390,7 @@ test_expect_success TAR_HUGE,LONG_IS_64BIT 'system tar can read our huge size' ' test_cmp expect actual ' -test_expect_success LONG_IS_64BIT 'set up repository with far-future commit' ' +test_expect_success TIME_IS_64BIT 'set up repository with far-future commit' ' rm -f .git/index && echo content >file && git add file && @@ -398,11 +398,11 @@ test_expect_success LONG_IS_64BIT 'set up repository with far-future commit' ' git commit -m "tempori parendum" ' -test_expect_success LONG_IS_64BIT 'generate tar with future mtime' ' +test_expect_success TIME_IS_64BIT 'generate tar with future mtime' ' git archive HEAD >future.tar ' -test_expect_success TAR_HUGE,LONG_IS_64BIT 'system tar can read our future mtime' ' +test_expect_success TAR_HUGE,TIME_IS_64BIT,TIME_T_IS_64BIT 'system tar can read our future mtime' ' echo 4147 >expect && tar_info future.tar | cut -d" " -f2 >actual && test_cmp expect actual diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh index cca23383c5..f6207f42b5 100755 --- a/t/t5004-archive-corner-cases.sh +++ b/t/t5004-archive-corner-cases.sh @@ -27,6 +27,9 @@ check_dir() { test_cmp expect actual } +test_lazy_prereq UNZIP_ZIP64_SUPPORT ' + "$GIT_UNZIP" -v | grep ZIP64_SUPPORT +' # bsdtar/libarchive versions before 3.1.3 consider a tar file with a # global pax header that is not followed by a file record as corrupt. @@ -155,4 +158,51 @@ test_expect_success ZIPINFO 'zip archive with many entries' ' test_cmp expect actual ' +test_expect_success EXPENSIVE,UNZIP,UNZIP_ZIP64_SUPPORT \ + 'zip archive bigger than 4GB' ' + # build string containing 65536 characters + s=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef && + s=$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s && + s=$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s && + + # create blob with a length of 65536 + 1 bytes + blob=$(echo $s | git hash-object -w --stdin) && + + # create tree containing 65500 entries of that blob + for i in $(test_seq 1 65500) + do + echo "100644 blob $blob $i" + done >tree && + tree=$(git mktree <tree) && + + # zip it, creating an archive a bit bigger than 4GB + git archive -0 -o many-big.zip $tree && + + "$GIT_UNZIP" -t many-big.zip 9999 65500 && + "$GIT_UNZIP" -t many-big.zip +' + +test_expect_success EXPENSIVE,LONG_IS_64BIT,UNZIP,UNZIP_ZIP64_SUPPORT,ZIPINFO \ + 'zip archive with files bigger than 4GB' ' + # Pack created with: + # dd if=/dev/zero of=file bs=1M count=4100 && git hash-object -w file + mkdir -p .git/objects/pack && + ( + cd .git/objects/pack && + "$GIT_UNZIP" "$TEST_DIRECTORY"/t5004/big-pack.zip + ) && + blob=754a93d6fada4c6873360e6cb4b209132271ab0e && + size=$(expr 4100 "*" 1024 "*" 1024) && + + # create a tree containing the file + tree=$(echo "100644 blob $blob big-file" | git mktree) && + + # zip it, creating an archive with a file bigger than 4GB + git archive -o big.zip $tree && + + "$GIT_UNZIP" -t big.zip && + "$ZIPINFO" big.zip >big.lst && + grep $size big.lst +' + test_done diff --git a/t/t5004/big-pack.zip b/t/t5004/big-pack.zip Binary files differnew file mode 100644 index 0000000000..caaf614eee --- /dev/null +++ b/t/t5004/big-pack.zip diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh index 43a672c345..9c68b99251 100755 --- a/t/t5300-pack-object.sh +++ b/t/t5300-pack-object.sh @@ -421,6 +421,42 @@ test_expect_success 'index-pack <pack> works in non-repo' ' test_path_is_file foo.idx ' +test_expect_success !PTHREADS,C_LOCALE_OUTPUT 'index-pack --threads=N or pack.threads=N warns when no pthreads' ' + test_must_fail git index-pack --threads=2 2>err && + grep ^warning: err >warnings && + test_line_count = 1 warnings && + grep -F "no threads support, ignoring --threads=2" err && + + test_must_fail git -c pack.threads=2 index-pack 2>err && + grep ^warning: err >warnings && + test_line_count = 1 warnings && + grep -F "no threads support, ignoring pack.threads" err && + + test_must_fail git -c pack.threads=2 index-pack --threads=4 2>err && + grep ^warning: err >warnings && + test_line_count = 2 warnings && + grep -F "no threads support, ignoring --threads=4" err && + grep -F "no threads support, ignoring pack.threads" err +' + +test_expect_success !PTHREADS,C_LOCALE_OUTPUT 'pack-objects --threads=N or pack.threads=N warns when no pthreads' ' + git pack-objects --threads=2 --stdout --all </dev/null >/dev/null 2>err && + grep ^warning: err >warnings && + test_line_count = 1 warnings && + grep -F "no threads support, ignoring --threads" err && + + git -c pack.threads=2 pack-objects --stdout --all </dev/null >/dev/null 2>err && + grep ^warning: err >warnings && + test_line_count = 1 warnings && + grep -F "no threads support, ignoring pack.threads" err && + + git -c pack.threads=2 pack-objects --threads=4 --stdout --all </dev/null >/dev/null 2>err && + grep ^warning: err >warnings && + test_line_count = 2 warnings && + grep -F "no threads support, ignoring --threads" err && + grep -F "no threads support, ignoring pack.threads" err +' + # # WARNING! # diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh index b5865b385d..80a1a3239a 100755 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@ -547,6 +547,41 @@ test_expect_success 'fetch-pack can fetch a raw sha1' ' git fetch-pack hidden $(git -C hidden rev-parse refs/hidden/one) ' +test_expect_success 'fetch-pack can fetch a raw sha1 that is advertised as a ref' ' + rm -rf server client && + git init server && + test_commit -C server 1 && + + git init client && + git -C client fetch-pack ../server \ + $(git -C server rev-parse refs/heads/master) +' + +test_expect_success 'fetch-pack can fetch a raw sha1 overlapping a named ref' ' + rm -rf server client && + git init server && + test_commit -C server 1 && + test_commit -C server 2 && + + git init client && + git -C client fetch-pack ../server \ + $(git -C server rev-parse refs/tags/1) refs/tags/1 +' + +test_expect_success 'fetch-pack cannot fetch a raw sha1 that is not advertised as a ref' ' + rm -rf server && + + git init server && + test_commit -C server 5 && + git -C server tag -d 5 && + test_commit -C server 6 && + + git init client && + test_must_fail git -C client fetch-pack ../server \ + $(git -C server rev-parse refs/heads/master^) 2>err && + test_i18ngrep "Server does not allow request for unadvertised object" err +' + check_prot_path () { cat >expected <<-EOF && Diag: url=$1 diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh index 94fc9be9ce..02106c9226 100755 --- a/t/t5512-ls-remote.sh +++ b/t/t5512-ls-remote.sh @@ -85,8 +85,15 @@ test_expect_success 'use branch.<name>.remote if possible' ' ' test_expect_success 'confuses pattern as remote when no remote specified' ' - cat >exp <<-\EOF && - fatal: '\''refs*master'\'' does not appear to be a git repository + if test_have_prereq MINGW + then + # Windows does not like asterisks in pathname + does_not_exist=master + else + does_not_exist="refs*master" + fi && + cat >exp <<-EOF && + fatal: '\''$does_not_exist'\'' does not appear to be a git repository fatal: Could not read from remote repository. Please make sure you have the correct access rights @@ -98,7 +105,7 @@ test_expect_success 'confuses pattern as remote when no remote specified' ' # fetch <branch>. # We could just as easily have used "master"; the "*" emphasizes its # role as a pattern. - test_must_fail git ls-remote refs*master >actual 2>&1 && + test_must_fail git ls-remote "$does_not_exist" >actual 2>&1 && test_i18ncmp exp actual ' diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index f15f7a3329..59c4b778d3 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -305,7 +305,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 "When you have resolved this problem" out + test_i18ngrep "Resolve all conflicts manually" out ' test_expect_success 'failed --rebase shows advice' ' @@ -319,7 +319,7 @@ 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 "When you have resolved this problem" out + test_i18ngrep "Resolve all conflicts manually" out ' test_expect_success '--rebase fails with multiple branches' ' diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh index f3b0a8d30a..162baf101f 100755 --- a/t/t5526-fetch-submodules.sh +++ b/t/t5526-fetch-submodules.sh @@ -71,6 +71,16 @@ test_expect_success "fetch --recurse-submodules recurses into submodules" ' test_i18ncmp expect.err actual.err ' +test_expect_success "submodule.recurse option triggers recursive fetch" ' + add_upstream_commit && + ( + cd downstream && + git -c submodule.recurse fetch >../actual.out 2>../actual.err + ) && + test_must_be_empty actual.out && + test_i18ncmp expect.err actual.err +' + test_expect_success "fetch --recurse-submodules -j2 has the same output behaviour" ' add_upstream_commit && ( diff --git a/t/t5531-deep-submodule-push.sh b/t/t5531-deep-submodule-push.sh index 23c533e82e..0f84a53146 100755 --- a/t/t5531-deep-submodule-push.sh +++ b/t/t5531-deep-submodule-push.sh @@ -126,6 +126,27 @@ test_expect_success 'push succeeds if submodule commit not on remote but using o ) ' +test_expect_success 'push succeeds if submodule commit not on remote but using auto-on-demand via submodule.recurse config' ' + ( + cd work/gar/bage && + >recurse-on-demand-from-submodule-recurse-config && + git add recurse-on-demand-from-submodule-recurse-config && + git commit -m "Recurse submodule.recurse from config junk" + ) && + ( + cd work && + git add gar/bage && + git commit -m "Recurse submodule.recurse from config for gar/bage" && + git -c submodule.recurse push ../pub.git master && + # Check that the supermodule commit got there + git fetch ../pub.git && + git diff --quiet FETCH_HEAD master && + # Check that the submodule commit got there too + cd gar/bage && + git diff --quiet origin/master master + ) +' + test_expect_success 'push recurse-submodules on command line overrides config' ' ( cd work/gar/bage && @@ -512,7 +533,8 @@ test_expect_success 'push propagating refspec to a submodule' ' # Fails when refspec includes an object id test_must_fail git -C work push --recurse-submodules=on-demand origin \ "$(git -C work rev-parse branch2):refs/heads/branch2" && - # Fails when refspec includes 'HEAD' as it is unsupported at this time + # Fails when refspec includes HEAD and parent and submodule do not + # have the same named branch checked out test_must_fail git -C work push --recurse-submodules=on-demand origin \ HEAD:refs/heads/branch2 && @@ -527,4 +549,26 @@ test_expect_success 'push propagating refspec to a submodule' ' test_cmp expected_pub actual_pub ' +test_expect_success 'push propagating HEAD refspec to a submodule' ' + git -C work/gar/bage checkout branch2 && + > work/gar/bage/junk12 && + git -C work/gar/bage add junk12 && + git -C work/gar/bage commit -m "Twelfth junk" && + + git -C work checkout branch2 && + git -C work add gar/bage && + git -C work commit -m "updating gar/bage in branch2" && + + # Passes since the superproject and submodules HEAD are both on branch2 + git -C work push --recurse-submodules=on-demand origin \ + HEAD:refs/heads/branch2 && + + git -C submodule.git rev-parse branch2 >actual_submodule && + git -C pub.git rev-parse branch2 >actual_pub && + git -C work/gar/bage rev-parse branch2 >expected_submodule && + git -C work rev-parse branch2 >expected_pub && + test_cmp expected_submodule actual_submodule && + test_cmp expected_pub actual_pub +' + test_done diff --git a/t/t5532-fetch-proxy.sh b/t/t5532-fetch-proxy.sh index 51c9669398..9c2798603b 100755 --- a/t/t5532-fetch-proxy.sh +++ b/t/t5532-fetch-proxy.sh @@ -43,4 +43,9 @@ test_expect_success 'fetch through proxy works' ' test_cmp expect actual ' +test_expect_success 'funny hostnames are rejected before running proxy' ' + test_must_fail git fetch git://-remote/repo.git 2>stderr && + ! grep "proxying for" stderr +' + test_done diff --git a/t/t5572-pull-submodule.sh b/t/t5572-pull-submodule.sh index accfa5cc0c..077eb07e11 100755 --- a/t/t5572-pull-submodule.sh +++ b/t/t5572-pull-submodule.sh @@ -42,4 +42,62 @@ KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1 KNOWN_FAILURE_NOFF_MERGE_ATTEMPTS_TO_MERGE_REMOVED_SUBMODULE_FILES=1 test_submodule_switch "git_pull_noff" +test_expect_success 'pull --recurse-submodule setup' ' + test_create_repo child && + test_commit -C child bar && + + test_create_repo parent && + test_commit -C child foo && + + git -C parent submodule add ../child sub && + git -C parent commit -m "add submodule" && + + git clone --recurse-submodules parent super +' + +test_expect_success 'recursive pull updates working tree' ' + test_commit -C child merge_strategy && + git -C parent submodule update --remote && + git -C parent add sub && + git -C parent commit -m "update submodule" && + + git -C super pull --no-rebase --recurse-submodules && + test_path_is_file super/sub/merge_strategy.t +' + +test_expect_success 'recursive rebasing pull' ' + # change upstream + test_commit -C child rebase_strategy && + git -C parent submodule update --remote && + git -C parent add sub && + git -C parent commit -m "update submodule" && + + # also have local commits + test_commit -C super/sub local_stuff && + + git -C super pull --rebase --recurse-submodules && + test_path_is_file super/sub/rebase_strategy.t && + test_path_is_file super/sub/local_stuff.t +' + +test_expect_success 'pull rebase recursing fails with conflicts' ' + + # local changes in submodule recorded in superproject: + test_commit -C super/sub local_stuff_2 && + git -C super add sub && + git -C super commit -m "local update submodule" && + + # and in the remote as well: + test_commit -C child important_upstream_work && + git -C parent submodule update --remote && + git -C parent add sub && + git -C parent commit -m "remote update submodule" && + + # Unfortunately we fail here, despite no conflict in the + # 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_done diff --git a/t/t5580-clone-push-unc.sh b/t/t5580-clone-push-unc.sh index b195f71ea9..b322c2f722 100755 --- a/t/t5580-clone-push-unc.sh +++ b/t/t5580-clone-push-unc.sh @@ -1,10 +1,10 @@ #!/bin/sh -test_description='various UNC path tests (Windows-only)' +test_description='various Windows-only path tests' . ./test-lib.sh if ! test_have_prereq MINGW; then - skip_all='skipping UNC path tests, requires Windows' + skip_all='skipping Windows-only path tests' test_done fi @@ -45,4 +45,10 @@ test_expect_success push ' test "$rev" = "$(git rev-parse --verify refs/heads/to-push)" ' +test_expect_success 'remote nick cannot contain backslashes' ' + BACKSLASHED="$(pwd | tr / \\\\)" && + git ls-remote "$BACKSLASHED" >out 2>err && + test_i18ngrep ! "unable to access" err +' + test_done diff --git a/t/t5612-clone-refspec.sh b/t/t5612-clone-refspec.sh index 7ace2535c8..fac5a73851 100755 --- a/t/t5612-clone-refspec.sh +++ b/t/t5612-clone-refspec.sh @@ -17,13 +17,20 @@ test_expect_success 'setup' ' echo four >file && git commit -a -m four && git checkout master && + git tag five && # default clone git clone . dir_all && + # default clone --no-tags + git clone --no-tags . dir_all_no_tags && + # default --single that follows HEAD=master git clone --single-branch . dir_master && + # default --single that follows HEAD=master with no tags + git clone --single-branch --no-tags . dir_master_no_tags && + # default --single that follows HEAD=side git checkout side && git clone --single-branch . dir_side && @@ -45,6 +52,9 @@ test_expect_success 'setup' ' # explicit --single with tag git clone --single-branch --branch two . dir_tag && + # explicit --single with tag and --no-tags + git clone --single-branch --no-tags --branch two . dir_tag_no_tags && + # advance both "master" and "side" branches git checkout side && echo five >file && @@ -59,7 +69,8 @@ test_expect_success 'setup' ' test_expect_success 'by default all branches will be kept updated' ' ( - cd dir_all && git fetch && + cd dir_all && + git fetch && git for-each-ref refs/remotes/origin | sed -e "/HEAD$/d" \ -e "s|/remotes/origin/|/heads/|" >../actual @@ -71,28 +82,82 @@ test_expect_success 'by default all branches will be kept updated' ' test_expect_success 'by default no tags will be kept updated' ' ( - cd dir_all && git fetch && + cd dir_all && + git fetch && git for-each-ref refs/tags >../actual ) && git for-each-ref refs/tags >expect && - test_must_fail test_cmp expect actual + test_must_fail test_cmp expect actual && + test_line_count = 2 actual +' + +test_expect_success 'clone with --no-tags' ' + ( + cd dir_all_no_tags && + git fetch && + git for-each-ref refs/tags >../actual + ) && + >expect && + test_cmp expect actual ' test_expect_success '--single-branch while HEAD pointing at master' ' ( - cd dir_master && git fetch && + cd dir_master && + git fetch && git for-each-ref refs/remotes/origin | sed -e "/HEAD$/d" \ -e "s|/remotes/origin/|/heads/|" >../actual ) && # only follow master git for-each-ref refs/heads/master >expect && - test_cmp expect actual + # get & check latest tags + test_cmp expect actual && + ( + cd dir_master && + git fetch --tags && + git for-each-ref refs/tags >../actual + ) && + git for-each-ref refs/tags >expect && + test_cmp expect actual && + test_line_count = 2 actual +' + +test_expect_success '--single-branch while HEAD pointing at master and --no-tags' ' + ( + cd dir_master_no_tags && + git fetch && + git for-each-ref refs/remotes/origin | + sed -e "/HEAD$/d" \ + -e "s|/remotes/origin/|/heads/|" >../actual + ) && + # only follow master + git for-each-ref refs/heads/master >expect && + test_cmp expect actual && + # get tags (noop) + ( + cd dir_master_no_tags && + git fetch && + git for-each-ref refs/tags >../actual + ) && + >expect && + test_cmp expect actual && + test_line_count = 0 actual && + # get tags with --tags overrides tagOpt + ( + cd dir_master_no_tags && + git fetch --tags && + git for-each-ref refs/tags >../actual + ) && + git for-each-ref refs/tags >expect && + test_cmp expect actual && + test_line_count = 2 actual ' test_expect_success '--single-branch while HEAD pointing at side' ' ( - cd dir_side && git fetch && + cd dir_side && + git fetch && git for-each-ref refs/remotes/origin | sed -e "/HEAD$/d" \ -e "s|/remotes/origin/|/heads/|" >../actual @@ -104,7 +169,8 @@ test_expect_success '--single-branch while HEAD pointing at side' ' test_expect_success '--single-branch with explicit --branch side' ' ( - cd dir_side2 && git fetch && + cd dir_side2 && + git fetch && git for-each-ref refs/remotes/origin | sed -e "/HEAD$/d" \ -e "s|/remotes/origin/|/heads/|" >../actual @@ -116,16 +182,29 @@ test_expect_success '--single-branch with explicit --branch side' ' test_expect_success '--single-branch with explicit --branch with tag fetches updated tag' ' ( - cd dir_tag && git fetch && + cd dir_tag && + git fetch && git for-each-ref refs/tags >../actual ) && git for-each-ref refs/tags >expect && test_cmp expect actual ' +test_expect_success '--single-branch with explicit --branch with tag fetches updated tag despite --no-tags' ' + ( + cd dir_tag_no_tags && + git fetch && + git for-each-ref refs/tags >../actual + ) && + git for-each-ref refs/tags/two >expect && + test_cmp expect actual && + test_line_count = 1 actual +' + test_expect_success '--single-branch with --mirror' ' ( - cd dir_mirror && git fetch && + cd dir_mirror && + git fetch && git for-each-ref refs > ../actual ) && git for-each-ref refs >expect && @@ -134,7 +213,8 @@ test_expect_success '--single-branch with --mirror' ' test_expect_success '--single-branch with explicit --branch and --mirror' ' ( - cd dir_mirror_side && git fetch && + cd dir_mirror_side && + git fetch && git for-each-ref refs > ../actual ) && git for-each-ref refs >expect && @@ -143,7 +223,8 @@ test_expect_success '--single-branch with explicit --branch and --mirror' ' test_expect_success '--single-branch with detached' ' ( - cd dir_detached && git fetch && + cd dir_detached && + git fetch && git for-each-ref refs/remotes/origin | sed -e "/HEAD$/d" \ -e "s|/remotes/origin/|/heads/|" >../actual diff --git a/t/t5614-clone-submodules.sh b/t/t5614-clone-submodules-shallow.sh index a87d329656..e4e6ea4d52 100755 --- a/t/t5614-clone-submodules.sh +++ b/t/t5614-clone-submodules-shallow.sh @@ -71,7 +71,7 @@ test_expect_success 'clone follows shallow recommendation' ' test_when_finished "rm -rf super_clone" && git config -f .gitmodules submodule.sub.shallow true && git add .gitmodules && - git commit -m "recommed shallow for sub" && + git commit -m "recommend shallow for sub" && git clone --recurse-submodules --no-local "file://$pwd/." super_clone && ( cd super_clone && @@ -105,7 +105,7 @@ test_expect_success 'clone follows non shallow recommendation' ' test_when_finished "rm -rf super_clone" && git config -f .gitmodules submodule.sub.shallow false && git add .gitmodules && - git commit -m "recommed non shallow for sub" && + git commit -m "recommend non shallow for sub" && git clone --recurse-submodules --no-local "file://$pwd/." super_clone && ( cd super_clone && diff --git a/t/t5810-proto-disable-local.sh b/t/t5810-proto-disable-local.sh index 563592d8a8..c1ef99b85c 100755 --- a/t/t5810-proto-disable-local.sh +++ b/t/t5810-proto-disable-local.sh @@ -11,4 +11,27 @@ test_expect_success 'setup repository to clone' ' test_proto "file://" file "file://$PWD" test_proto "path" file . +test_expect_success 'setup repo with dash' ' + git init --bare repo.git && + git push repo.git HEAD && + mv repo.git "$PWD/-repo.git" +' + +# This will fail even without our rejection because upload-pack will +# complain about the bogus option. So let's make sure that GIT_TRACE +# doesn't show us even running upload-pack. +# +# We must also be sure to use "fetch" and not "clone" here, as the latter +# actually canonicalizes our input into an absolute path (which is fine +# to allow). +test_expect_success 'repo names starting with dash are rejected' ' + rm -f trace.out && + test_must_fail env GIT_TRACE="$PWD/trace.out" git fetch -- -repo.git && + ! grep upload-pack trace.out +' + +test_expect_success 'full paths still work' ' + git fetch "$PWD/-repo.git" +' + test_done diff --git a/t/t5813-proto-disable-ssh.sh b/t/t5813-proto-disable-ssh.sh index a954ead8af..3f084ee306 100755 --- a/t/t5813-proto-disable-ssh.sh +++ b/t/t5813-proto-disable-ssh.sh @@ -17,4 +17,27 @@ test_proto "host:path" ssh "remote:repo.git" test_proto "ssh://" ssh "ssh://remote$PWD/remote/repo.git" test_proto "git+ssh://" ssh "git+ssh://remote$PWD/remote/repo.git" +# Don't even bother setting up a "-remote" directory, as ssh would generally +# complain about the bogus option rather than completing our request. Our +# fake wrapper actually _can_ handle this case, but it's more robust to +# simply confirm from its output that it did not run at all. +test_expect_success 'hostnames starting with dash are rejected' ' + test_must_fail git clone ssh://-remote/repo.git dash-host 2>stderr && + ! grep ^ssh: stderr +' + +test_expect_success 'setup repo with dash' ' + git init --bare remote/-repo.git && + git push remote/-repo.git HEAD +' + +test_expect_success 'repo names starting with dash are rejected' ' + test_must_fail git clone remote:-repo.git dash-path 2>stderr && + ! grep ^ssh: stderr +' + +test_expect_success 'full paths still work' ' + git clone "remote:$PWD/remote/-repo.git" dash-path +' + test_done diff --git a/t/t6002-rev-list-bisect.sh b/t/t6002-rev-list-bisect.sh index 3bf2759eae..534903bbd2 100755 --- a/t/t6002-rev-list-bisect.sh +++ b/t/t6002-rev-list-bisect.sh @@ -235,4 +235,18 @@ test_sequence "--bisect" # # + +test_expect_success '--bisect can default to good/bad refs' ' + git update-ref refs/bisect/bad c3 && + good=$(git rev-parse b1) && + git update-ref refs/bisect/good-$good $good && + good=$(git rev-parse c1) && + git update-ref refs/bisect/good-$good $good && + + # the only thing between c3 and c1 is c2 + git rev-parse c2 >expect && + git rev-list --bisect >actual && + test_cmp expect actual +' + test_done diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh index a1dcdb81d7..b326d550f3 100755 --- a/t/t6006-rev-list-format.sh +++ b/t/t6006-rev-list-format.sh @@ -59,10 +59,14 @@ test_format () { } # Feed to --format to provide predictable colored sequences. +BASIC_COLOR='%Credfoo%Creset' +COLOR='%C(red)foo%C(reset)' AUTO_COLOR='%C(auto,red)foo%C(auto,reset)' +ALWAYS_COLOR='%C(always,red)foo%C(always,reset)' has_color () { - printf '\033[31mfoo\033[m\n' >expect && - test_cmp expect "$1" + test_decode_color <"$1" >decoded && + echo "<RED>foo<RESET>" >expect && + test_cmp expect decoded } has_no_color () { @@ -170,62 +174,84 @@ $added EOF -test_format colors %Credfoo%Cgreenbar%Cbluebaz%Cresetxyzzy <<EOF -commit $head2 -[31mfoo[32mbar[34mbaz[mxyzzy -commit $head1 -[31mfoo[32mbar[34mbaz[mxyzzy -EOF - -test_format advanced-colors '%C(red yellow bold)foo%C(reset)' <<EOF -commit $head2 -[1;31;43mfoo[m -commit $head1 -[1;31;43mfoo[m -EOF - -test_expect_success '%C(auto,...) does not enable color by default' ' - git log --format=$AUTO_COLOR -1 >actual && - has_no_color actual +test_expect_success 'basic colors' ' + cat >expect <<-EOF && + commit $head2 + <RED>foo<GREEN>bar<BLUE>baz<RESET>xyzzy + EOF + format="%Credfoo%Cgreenbar%Cbluebaz%Cresetxyzzy" && + git rev-list --color --format="$format" -1 master >actual.raw && + test_decode_color <actual.raw >actual && + test_cmp expect actual ' -test_expect_success '%C(auto,...) enables colors for color.diff' ' - git -c color.diff=always log --format=$AUTO_COLOR -1 >actual && - has_color actual +test_expect_success 'advanced colors' ' + cat >expect <<-EOF && + commit $head2 + <BOLD;RED;BYELLOW>foo<RESET> + EOF + format="%C(red yellow bold)foo%C(reset)" && + git rev-list --color --format="$format" -1 master >actual.raw && + test_decode_color <actual.raw >actual && + test_cmp expect actual ' -test_expect_success '%C(auto,...) enables colors for color.ui' ' - git -c color.ui=always log --format=$AUTO_COLOR -1 >actual && - has_color actual -' +for spec in \ + "%Cred:$BASIC_COLOR" \ + "%C(...):$COLOR" \ + "%C(auto,...):$AUTO_COLOR" +do + desc=${spec%%:*} + color=${spec#*:} + test_expect_success "$desc does not enable color by default" ' + git log --format=$color -1 >actual && + has_no_color actual + ' -test_expect_success '%C(auto,...) respects --color' ' - git log --format=$AUTO_COLOR -1 --color >actual && - has_color actual -' + test_expect_success "$desc enables colors for color.diff" ' + git -c color.diff=always log --format=$color -1 >actual && + has_color actual + ' -test_expect_success '%C(auto,...) respects --no-color' ' - git -c color.ui=always log --format=$AUTO_COLOR -1 --no-color >actual && - has_no_color actual -' + test_expect_success "$desc enables colors for color.ui" ' + git -c color.ui=always log --format=$color -1 >actual && + has_color actual + ' -test_expect_success TTY '%C(auto,...) respects --color=auto (stdout is tty)' ' - test_terminal env TERM=vt100 \ - git log --format=$AUTO_COLOR -1 --color=auto >actual && - has_color actual -' + test_expect_success "$desc respects --color" ' + git log --format=$color -1 --color >actual && + has_color actual + ' -test_expect_success '%C(auto,...) respects --color=auto (stdout not tty)' ' - ( - TERM=vt100 && export TERM && - git log --format=$AUTO_COLOR -1 --color=auto >actual && + test_expect_success "$desc respects --no-color" ' + git -c color.ui=always log --format=$color -1 --no-color >actual && has_no_color actual - ) + ' + + test_expect_success TTY "$desc respects --color=auto (stdout is tty)" ' + test_terminal env TERM=vt100 \ + git log --format=$color -1 --color=auto >actual && + has_color actual + ' + + test_expect_success "$desc respects --color=auto (stdout not tty)" ' + ( + TERM=vt100 && export TERM && + git log --format=$color -1 --color=auto >actual && + has_no_color actual + ) + ' +done + +test_expect_success '%C(always,...) enables color even without tty' ' + git log --format=$ALWAYS_COLOR -1 >actual && + has_color actual ' test_expect_success '%C(auto) respects --color' ' - git log --color --format="%C(auto)%H" -1 >actual && - printf "\\033[33m%s\\033[m\\n" $(git rev-parse HEAD) >expect && + git log --color --format="%C(auto)%H" -1 >actual.raw && + test_decode_color <actual.raw >actual && + echo "<YELLOW>$(git rev-parse HEAD)<RESET>" >expect && test_cmp expect actual ' @@ -235,6 +261,17 @@ test_expect_success '%C(auto) respects --no-color' ' test_cmp expect actual ' +test_expect_success 'rev-list %C(auto,...) respects --color' ' + git rev-list --color --format="%C(auto,green)foo%C(auto,reset)" \ + -1 HEAD >actual.raw && + test_decode_color <actual.raw >actual && + cat >expect <<-EOF && + commit $(git rev-parse HEAD) + <GREEN>foo<RESET> + EOF + test_cmp expect actual +' + iconv -f utf-8 -t $test_encoding > commit-msg <<EOF Test printing of complex bodies diff --git a/t/t6018-rev-list-glob.sh b/t/t6018-rev-list-glob.sh index 381f35ed16..d3453c583c 100755 --- a/t/t6018-rev-list-glob.sh +++ b/t/t6018-rev-list-glob.sh @@ -255,27 +255,19 @@ test_expect_success 'rev-list accumulates multiple --exclude' ' compare rev-list "--exclude=refs/remotes/* --exclude=refs/tags/* --all" --branches ' - -# "git rev-list<ENTER>" is likely to be a bug in the calling script and may -# deserve an error message, but do cases where set of refs programmatically -# given using globbing and/or --stdin need to fail with the same error, or -# are we better off reporting a success with no output? The following few -# tests document the current behaviour to remind us that we might want to -# think about this issue. - -test_expect_failure 'rev-list may want to succeed with empty output on no input (1)' ' +test_expect_failure 'rev-list should succeed with empty output on empty stdin' ' >expect && git rev-list --stdin <expect >actual && test_cmp expect actual ' -test_expect_failure 'rev-list may want to succeed with empty output on no input (2)' ' +test_expect_success 'rev-list should succeed with empty output with all refs excluded' ' >expect && git rev-list --exclude=* --all >actual && test_cmp expect actual ' -test_expect_failure 'rev-list may want to succeed with empty output on no input (3)' ' +test_expect_success 'rev-list should succeed with empty output with empty --all' ' ( test_create_repo empty && cd empty && @@ -285,6 +277,12 @@ test_expect_failure 'rev-list may want to succeed with empty output on no input ) ' +test_expect_success 'rev-list should succeed with empty output with empty glob' ' + >expect && + git rev-list --glob=does-not-match-anything >actual && + test_cmp expect actual +' + test_expect_success 'shortlog accepts --glob/--tags/--remotes' ' compare shortlog "subspace/one subspace/two" --branches=subspace && diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh index 16952e44fc..aa74eb8f0d 100755 --- a/t/t6120-describe.sh +++ b/t/t6120-describe.sh @@ -244,7 +244,7 @@ test_expect_success 'setup and absorb a submodule' ' test_cmp expect out ' -test_expect_success 'describe chokes on severly broken submodules' ' +test_expect_success 'describe chokes on severely broken submodules' ' mv .git/modules/sub1/ .git/modules/sub_moved && test_must_fail git describe --dirty ' diff --git a/t/t6134-pathspec-in-submodule.sh b/t/t6134-pathspec-in-submodule.sh index 99a8982ab1..c670668409 100755 --- a/t/t6134-pathspec-in-submodule.sh +++ b/t/t6134-pathspec-in-submodule.sh @@ -24,13 +24,9 @@ test_expect_success 'error message for path inside submodule' ' test_i18ncmp expect actual ' -cat <<EOF >expect -fatal: Pathspec '.' is in submodule 'sub' -EOF - test_expect_success 'error message for path inside submodule from within submodule' ' test_must_fail git -C sub add . 2>actual && - test_i18ncmp expect actual + test_i18ngrep "in unpopulated submodule" actual ' test_done diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index 834a9ed168..2274a4b733 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -7,6 +7,7 @@ test_description='for-each-ref test' . ./test-lib.sh . "$TEST_DIRECTORY"/lib-gpg.sh +. "$TEST_DIRECTORY"/lib-terminal.sh # Mon Jul 3 23:18:43 2006 +0000 datestamp=1151968723 @@ -412,21 +413,33 @@ test_expect_success 'Check for invalid refname format' ' test_must_fail git for-each-ref --format="%(refname:INVALID)" ' -get_color () -{ - git config --get-color no.such.slot "$1" -} +test_expect_success 'set up color tests' ' + cat >expected.color <<-EOF && + $(git rev-parse --short refs/heads/master) <GREEN>master<RESET> + $(git rev-parse --short refs/remotes/origin/master) <GREEN>origin/master<RESET> + $(git rev-parse --short refs/tags/testtag) <GREEN>testtag<RESET> + $(git rev-parse --short refs/tags/two) <GREEN>two<RESET> + EOF + sed "s/<[^>]*>//g" <expected.color >expected.bare && + color_format="%(objectname:short) %(color:green)%(refname:short)" +' -cat >expected <<EOF -$(git rev-parse --short refs/heads/master) $(get_color green)master$(get_color reset) -$(git rev-parse --short refs/remotes/origin/master) $(get_color green)origin/master$(get_color reset) -$(git rev-parse --short refs/tags/testtag) $(get_color green)testtag$(get_color reset) -$(git rev-parse --short refs/tags/two) $(get_color green)two$(get_color reset) -EOF +test_expect_success TTY '%(color) shows color with a tty' ' + test_terminal env TERM=vt100 \ + git for-each-ref --format="$color_format" >actual.raw && + test_decode_color <actual.raw >actual && + test_cmp expected.color actual +' -test_expect_success 'Check %(color:...) ' ' - git for-each-ref --format="%(objectname:short) %(color:green)%(refname:short)" >actual && - test_cmp expected actual +test_expect_success '%(color) does not show color without tty' ' + TERM=vt100 git for-each-ref --format="$color_format" >actual && + test_cmp expected.bare actual +' + +test_expect_success 'color.ui=always can override tty check' ' + git -c color.ui=always for-each-ref --format="$color_format" >actual.raw && + test_decode_color <actual.raw >actual && + test_cmp expected.color actual ' cat >expected <<\EOF diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index 0ef7b94394..dd5ba450ee 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -9,6 +9,7 @@ Tests for operations with tags.' . ./test-lib.sh . "$TEST_DIRECTORY"/lib-gpg.sh +. "$TEST_DIRECTORY"/lib-terminal.sh # creating and listing lightweight tags: @@ -1900,6 +1901,30 @@ test_expect_success '--format should list tags as per format given' ' test_cmp expect actual ' +test_expect_success "set up color tests" ' + echo "<RED>v1.0<RESET>" >expect.color && + echo "v1.0" >expect.bare && + color_args="--format=%(color:red)%(refname:short) --list v1.0" +' + +test_expect_success '%(color) omitted without tty' ' + TERM=vt100 git tag $color_args >actual.raw && + test_decode_color <actual.raw >actual && + test_cmp expect.bare actual +' + +test_expect_success TTY '%(color) present with tty' ' + test_terminal env TERM=vt100 git tag $color_args >actual.raw && + test_decode_color <actual.raw >actual && + test_cmp expect.color actual +' + +test_expect_success 'color.ui=always overrides auto-color' ' + git -c color.ui=always tag $color_args >actual.raw && + test_decode_color <actual.raw >actual && + test_cmp expect.color actual +' + test_expect_success 'setup --merged test tags' ' git tag mergetest-1 HEAD~2 && git tag mergetest-2 HEAD~1 && diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh index 20b4d83c28..9128ec5acd 100755 --- a/t/t7006-pager.sh +++ b/t/t7006-pager.sh @@ -134,6 +134,86 @@ test_expect_success TTY 'configuration can enable pager (from subdir)' ' } ' +test_expect_success TTY 'git tag -l defaults to paging' ' + rm -f paginated.out && + test_terminal git tag -l && + test -e paginated.out +' + +test_expect_success TTY 'git tag -l respects pager.tag' ' + rm -f paginated.out && + test_terminal git -c pager.tag=false tag -l && + ! test -e paginated.out +' + +test_expect_success TTY 'git tag -l respects --no-pager' ' + rm -f paginated.out && + test_terminal git -c pager.tag --no-pager tag -l && + ! test -e paginated.out +' + +test_expect_success TTY 'git tag with no args defaults to paging' ' + # no args implies -l so this should page like -l + rm -f paginated.out && + test_terminal git tag && + test -e paginated.out +' + +test_expect_success TTY 'git tag with no args respects pager.tag' ' + # no args implies -l so this should page like -l + rm -f paginated.out && + test_terminal git -c pager.tag=false tag && + ! test -e paginated.out +' + +test_expect_success TTY 'git tag --contains defaults to paging' ' + # --contains implies -l so this should page like -l + rm -f paginated.out && + test_terminal git tag --contains && + test -e paginated.out +' + +test_expect_success TTY 'git tag --contains respects pager.tag' ' + # --contains implies -l so this should page like -l + rm -f paginated.out && + test_terminal git -c pager.tag=false tag --contains && + ! test -e paginated.out +' + +test_expect_success TTY 'git tag -a defaults to not paging' ' + test_when_finished "git tag -d newtag" && + rm -f paginated.out && + test_terminal git tag -am message newtag && + ! test -e paginated.out +' + +test_expect_success TTY 'git tag -a ignores pager.tag' ' + test_when_finished "git tag -d newtag" && + rm -f paginated.out && + test_terminal git -c pager.tag tag -am message newtag && + ! test -e paginated.out +' + +test_expect_success TTY 'git tag -a respects --paginate' ' + test_when_finished "git tag -d newtag" && + rm -f paginated.out && + test_terminal git --paginate tag -am message newtag && + test -e paginated.out +' + +test_expect_success TTY 'git tag as alias ignores pager.tag with -a' ' + test_when_finished "git tag -d newtag" && + rm -f paginated.out && + test_terminal git -c pager.tag -c alias.t=tag t -am message newtag && + ! test -e paginated.out +' + +test_expect_success TTY 'git tag as alias respects pager.tag with -l' ' + rm -f paginated.out && + test_terminal git -c pager.tag=false -c alias.t=tag t -l && + ! test -e paginated.out +' + # A colored commit log will begin with an appropriate ANSI escape # for the first color; the text "commit" comes later. colorful() { diff --git a/t/t7008-grep-binary.sh b/t/t7008-grep-binary.sh index 9c9c378119..615e7e0162 100755 --- a/t/t7008-grep-binary.sh +++ b/t/t7008-grep-binary.sh @@ -4,8 +4,43 @@ test_description='git grep in binary files' . ./test-lib.sh +nul_match () { + matches=$1 + flags=$2 + pattern=$3 + pattern_human=$(echo "$pattern" | sed 's/Q/<NUL>/g') + + if test "$matches" = 1 + then + test_expect_success "git grep -f f $flags '$pattern_human' a" " + printf '$pattern' | q_to_nul >f && + git grep -f f $flags a + " + elif test "$matches" = 0 + then + test_expect_success "git grep -f f $flags '$pattern_human' a" " + printf '$pattern' | q_to_nul >f && + test_must_fail git grep -f f $flags a + " + elif test "$matches" = T1 + then + test_expect_failure "git grep -f f $flags '$pattern_human' a" " + printf '$pattern' | q_to_nul >f && + git grep -f f $flags a + " + elif test "$matches" = T0 + then + test_expect_failure "git grep -f f $flags '$pattern_human' a" " + printf '$pattern' | q_to_nul >f && + test_must_fail git grep -f f $flags a + " + else + test_expect_success "PANIC: Test framework error. Unknown matches value $matches" 'false' + fi +} + test_expect_success 'setup' " - echo 'binaryQfile' | q_to_nul >a && + echo 'binaryQfileQm[*]cQ*æQð' | q_to_nul >a && git add a && git commit -m. " @@ -69,35 +104,71 @@ test_expect_failure 'git grep .fi a' ' git grep .fi a ' -test_expect_success 'git grep -F y<NUL>f a' " - printf 'yQf' | q_to_nul >f && - git grep -f f -F a -" - -test_expect_success 'git grep -F y<NUL>x a' " - printf 'yQx' | q_to_nul >f && - test_must_fail git grep -f f -F a -" - -test_expect_success 'git grep -Fi Y<NUL>f a' " - printf 'YQf' | q_to_nul >f && - git grep -f f -Fi a -" - -test_expect_success 'git grep -Fi Y<NUL>x a' " - printf 'YQx' | q_to_nul >f && - test_must_fail git grep -f f -Fi a -" - -test_expect_success 'git grep y<NUL>f a' " - printf 'yQf' | q_to_nul >f && - git grep -f f a -" - -test_expect_success 'git grep y<NUL>x a' " - printf 'yQx' | q_to_nul >f && - test_must_fail git grep -f f a -" +nul_match 1 '-F' 'yQf' +nul_match 0 '-F' 'yQx' +nul_match 1 '-Fi' 'YQf' +nul_match 0 '-Fi' 'YQx' +nul_match 1 '' 'yQf' +nul_match 0 '' 'yQx' +nul_match 1 '' 'æQð' +nul_match 1 '-F' 'eQm[*]c' +nul_match 1 '-Fi' 'EQM[*]C' + +# Regex patterns that would match but shouldn't with -F +nul_match 0 '-F' 'yQ[f]' +nul_match 0 '-F' '[y]Qf' +nul_match 0 '-Fi' 'YQ[F]' +nul_match 0 '-Fi' '[Y]QF' +nul_match 0 '-F' 'æQ[ð]' +nul_match 0 '-F' '[æ]Qð' +nul_match 0 '-Fi' 'ÆQ[Ð]' +nul_match 0 '-Fi' '[Æ]QÐ' + +# kwset is disabled on -i & non-ASCII. No way to match non-ASCII \0 +# patterns case-insensitively. +nul_match T1 '-i' 'ÆQÐ' + +# \0 implicitly disables regexes. This is an undocumented internal +# limitation. +nul_match T1 '' 'yQ[f]' +nul_match T1 '' '[y]Qf' +nul_match T1 '-i' 'YQ[F]' +nul_match T1 '-i' '[Y]Qf' +nul_match T1 '' 'æQ[ð]' +nul_match T1 '' '[æ]Qð' +nul_match T1 '-i' 'ÆQ[Ð]' + +# ... because of \0 implicitly disabling regexes regexes that +# should/shouldn't match don't do the right thing. +nul_match T1 '' 'eQm.*cQ' +nul_match T1 '-i' 'EQM.*cQ' +nul_match T0 '' 'eQm[*]c' +nul_match T0 '-i' 'EQM[*]C' + +# Due to the REG_STARTEND extension when kwset() is disabled on -i & +# non-ASCII the string will be matched in its entirety, but the +# pattern will be cut off at the first \0. +nul_match 0 '-i' 'NOMATCHQð' +nul_match T0 '-i' '[Æ]QNOMATCH' +nul_match T0 '-i' '[æ]QNOMATCH' +# Matches, but for the wrong reasons, just stops at [æ] +nul_match 1 '-i' '[Æ]Qð' +nul_match 1 '-i' '[æ]Qð' + +# Ensure that the matcher doesn't regress to something that stops at +# \0 +nul_match 0 '-F' 'yQ[f]' +nul_match 0 '-Fi' 'YQ[F]' +nul_match 0 '' 'yQNOMATCH' +nul_match 0 '' 'QNOMATCH' +nul_match 0 '-i' 'YQNOMATCH' +nul_match 0 '-i' 'QNOMATCH' +nul_match 0 '-F' 'æQ[ð]' +nul_match 0 '-Fi' 'ÆQ[Ð]' +nul_match 0 '' 'yQNÓMATCH' +nul_match 0 '' 'QNÓMATCH' +nul_match 0 '-i' 'YQNÓMATCH' +nul_match 0 '-i' 'QNÓMATCH' test_expect_success 'grep respects binary diff attribute' ' echo text >t && @@ -162,7 +233,7 @@ test_expect_success 'grep does not honor textconv' ' ' test_expect_success 'grep --textconv honors textconv' ' - echo "a:binaryQfile" >expect && + echo "a:binaryQfileQm[*]cQ*æQð" >expect && git grep --textconv Qfile >actual && test_cmp expect actual ' @@ -172,7 +243,7 @@ test_expect_success 'grep --no-textconv does not honor textconv' ' ' test_expect_success 'grep --textconv blob honors textconv' ' - echo "HEAD:a:binaryQfile" >expect && + echo "HEAD:a:binaryQfileQm[*]cQ*æQð" >expect && git grep --textconv Qfile HEAD:a >actual && test_cmp expect actual ' diff --git a/t/t7009-filter-branch-null-sha1.sh b/t/t7009-filter-branch-null-sha1.sh index c27f90f285..a8d9ec4987 100755 --- a/t/t7009-filter-branch-null-sha1.sh +++ b/t/t7009-filter-branch-null-sha1.sh @@ -31,6 +31,12 @@ test_expect_success 'setup: bring HEAD and index in sync' ' git commit -a -m "back to normal" ' +test_expect_success 'noop filter-branch complains' ' + test_must_fail git filter-branch \ + --force --prune-empty \ + --index-filter "true" +' + test_expect_success 'filter commands are still checked' ' test_must_fail git filter-branch \ --force --prune-empty \ diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh index 0667bd9dd3..e5fb892f95 100755 --- a/t/t7063-status-untracked-cache.sh +++ b/t/t7063-status-untracked-cache.sh @@ -661,4 +661,26 @@ test_expect_success 'test ident field is working' ' test_i18ncmp ../expect ../err ' +test_expect_success 'untracked cache survives a checkout' ' + git commit --allow-empty -m empty && + test-dump-untracked-cache >../before && + test_when_finished "git checkout master" && + git checkout -b other_branch && + test-dump-untracked-cache >../after && + test_cmp ../before ../after && + test_commit test && + test-dump-untracked-cache >../before && + git checkout master && + test-dump-untracked-cache >../after && + test_cmp ../before ../after +' + +test_expect_success 'untracked cache survives a commit' ' + test-dump-untracked-cache >../before && + git add done/two && + git commit -m commit && + test-dump-untracked-cache >../after && + test_cmp ../before ../after +' + test_done diff --git a/t/t7112-reset-submodule.sh b/t/t7112-reset-submodule.sh index 2eda6adeb1..a1cb9ff858 100755 --- a/t/t7112-reset-submodule.sh +++ b/t/t7112-reset-submodule.sh @@ -5,6 +5,14 @@ test_description='reset can handle submodules' . ./test-lib.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh +KNOWN_FAILURE_SUBMODULE_RECURSIVE_NESTED=1 +KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS=1 +KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED=1 + +test_submodule_switch_recursing_with_args "reset --keep" + +test_submodule_forced_switch_recursing_with_args "reset --hard" + test_submodule_switch "git reset --keep" test_submodule_switch "git reset --merge" diff --git a/t/t7301-clean-interactive.sh b/t/t7301-clean-interactive.sh index 3ae394e934..556e1850e2 100755 --- a/t/t7301-clean-interactive.sh +++ b/t/t7301-clean-interactive.sh @@ -472,4 +472,14 @@ test_expect_success 'git clean -id with prefix and path (ask)' ' ' +test_expect_success 'git clean -i paints the header in HEADER color' ' + >a.out && + echo q | + git -c color.ui=always clean -i | + test_decode_color | + head -n 1 >header && + # not i18ngrep + grep "^<BOLD>" header +' + test_done diff --git a/t/t7401-submodule-summary.sh b/t/t7401-submodule-summary.sh index 366746f0d4..4e4c455502 100755 --- a/t/t7401-submodule-summary.sh +++ b/t/t7401-submodule-summary.sh @@ -241,9 +241,11 @@ EOF test_cmp expected actual " -test_create_repo sm2 && -head7=$(add_file sm2 foo8 foo9) && -git add sm2 +test_expect_success 'create second submodule' ' + test_create_repo sm2 && + head7=$(add_file sm2 foo8 foo9) && + git add sm2 +' test_expect_success 'multiple submodules' " git submodule summary >actual && diff --git a/t/t7412-submodule-absorbgitdirs.sh b/t/t7412-submodule-absorbgitdirs.sh index e2bbb449b6..ce74c12da2 100755 --- a/t/t7412-submodule-absorbgitdirs.sh +++ b/t/t7412-submodule-absorbgitdirs.sh @@ -33,7 +33,7 @@ test_expect_success 'absorb the git dir' ' test_cmp expect.2 actual.2 ' -test_expect_success 'absorbing does not fail for deinitalized submodules' ' +test_expect_success 'absorbing does not fail for deinitialized submodules' ' test_when_finished "git submodule update --init" && git submodule deinit --all && git submodule absorbgitdirs && diff --git a/t/t7413-submodule-is-active.sh b/t/t7413-submodule-is-active.sh index 9c785b07ec..c8e7e98331 100755 --- a/t/t7413-submodule-is-active.sh +++ b/t/t7413-submodule-is-active.sh @@ -2,7 +2,7 @@ test_description='Test submodule--helper is-active -This test verifies that `git submodue--helper is-active` correclty identifies +This test verifies that `git submodue--helper is-active` correctly identifies submodules which are "active" and interesting to the user. ' diff --git a/t/t7414-submodule-mistakes.sh b/t/t7414-submodule-mistakes.sh new file mode 100755 index 0000000000..f2e7df59cf --- /dev/null +++ b/t/t7414-submodule-mistakes.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +test_description='handling of common mistakes people may make with submodules' +. ./test-lib.sh + +test_expect_success 'create embedded repository' ' + git init embed && + test_commit -C embed one +' + +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_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_expect_success 'no warning when updating entry' ' + test_when_finished "git rm --cached -f embed" && + git add embed && + git -C embed commit --allow-empty -m two && + git add embed 2>stderr && + test_i18ngrep ! warning stderr +' + +test_expect_success 'submodule add does not warn' ' + test_when_finished "git rm -rf submodule .gitmodules" && + git submodule add ./embed submodule 2>stderr && + test_i18ngrep ! warning stderr +' + +test_done diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh index 116885a260..5739d3ed23 100755 --- a/t/t7500-commit.sh +++ b/t/t7500-commit.sh @@ -329,4 +329,27 @@ test_expect_success 'invalid message options when using --fixup' ' test_must_fail git commit --fixup HEAD~1 -F log ' +cat >expected-template <<EOF + +# Please enter the commit message for your changes. Lines starting +# with '#' will be ignored, and an empty message aborts the commit. +# +# Author: A U Thor <author@example.com> +# +# On branch commit-template-check +# Changes to be committed: +# new file: commit-template-check +# +# Untracked files not listed +EOF + +test_expect_success 'new line found before status message in commit template' ' + git checkout -b commit-template-check && + git reset --hard HEAD && + touch commit-template-check && + git add commit-template-check && + GIT_EDITOR="cat >editor-input" git commit --untracked-files=no --allow-empty-message && + test_i18ncmp expected-template editor-input +' + test_done diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh index 0b6da7ae1f..fa61b1a4ee 100755 --- a/t/t7501-commit.sh +++ b/t/t7501-commit.sh @@ -18,7 +18,7 @@ test_expect_success 'initial status' ' echo bongo bongo >file && git add file && git status >actual && - test_i18ngrep "Initial commit" actual + test_i18ngrep "No commits yet" actual ' test_expect_success 'fail initial amend' ' diff --git a/t/t7508-status.sh b/t/t7508-status.sh index 35ea0b7074..43d19a9b22 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -32,6 +32,17 @@ test_expect_success 'commit -h in broken repository' ' test_i18ngrep "[Uu]sage" broken/usage ' +test_expect_success 'create upstream branch' ' + git checkout -b upstream && + test_commit upstream1 && + test_commit upstream2 && + # leave the first commit on master as root because several + # tests depend on this case; for our upstream we only + # care about commit counts anyway, so a totally divergent + # history is OK + git checkout --orphan master +' + test_expect_success 'setup' ' : >tracked && : >modified && @@ -53,7 +64,9 @@ test_expect_success 'setup' ' echo 1 >dir1/modified && echo 2 >dir2/modified && echo 3 >dir2/added && - git add dir2/added + git add dir2/added && + + git branch --set-upstream-to=upstream ' test_expect_success 'status (1)' ' @@ -75,6 +88,10 @@ EOF test_expect_success 'status --column' ' cat >expect <<\EOF && # On branch master +# 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 reset HEAD <file>..." to unstage) # @@ -105,6 +122,10 @@ test_expect_success 'status --column status.displayCommentPrefix=false' ' cat >expect <<\EOF # On branch master +# 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 reset HEAD <file>..." to unstage) # @@ -178,6 +199,9 @@ test_expect_success 'commit ignores status.displayCommentPrefix=false in COMMIT_ cat >expect <<\EOF On branch master +Your branch and 'upstream' have diverged, +and have 1 and 2 different commits each, respectively. + Changes to be committed: new file: dir2/added @@ -248,6 +272,10 @@ test_expect_success 'status with gitignore' ' cat >expect <<\EOF && On branch master +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 reset HEAD <file>..." to unstage) @@ -313,6 +341,10 @@ test_expect_success 'status with gitignore (nothing untracked)' ' cat >expect <<\EOF && On branch master +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 reset HEAD <file>..." to unstage) @@ -348,7 +380,7 @@ output* EOF cat >expect <<\EOF -## master +## master...upstream [ahead 1, behind 2] M dir1/modified A dir2/added ?? dir1/untracked @@ -382,6 +414,10 @@ test_expect_success 'setup dir3' ' test_expect_success 'status -uno' ' cat >expect <<EOF && On branch master +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 reset HEAD <file>..." to unstage) @@ -408,6 +444,9 @@ test_expect_success 'status (status.showUntrackedFiles no)' ' test_expect_success 'status -uno (advice.statusHints false)' ' cat >expect <<EOF && On branch master +Your branch and '\''upstream'\'' have diverged, +and have 1 and 2 different commits each, respectively. + Changes to be committed: new file: dir2/added @@ -439,6 +478,10 @@ test_expect_success 'status -s (status.showUntrackedFiles no)' ' test_expect_success 'status -unormal' ' cat >expect <<EOF && On branch master +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 reset HEAD <file>..." to unstage) @@ -493,6 +536,10 @@ test_expect_success 'status -s (status.showUntrackedFiles normal)' ' test_expect_success 'status -uall' ' cat >expect <<EOF && On branch master +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 reset HEAD <file>..." to unstage) @@ -552,6 +599,10 @@ test_expect_success 'status -s (status.showUntrackedFiles all)' ' test_expect_success 'status with relative paths' ' cat >expect <<\EOF && On branch master +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 reset HEAD <file>..." to unstage) @@ -610,13 +661,19 @@ test_expect_success 'status --porcelain ignores relative paths setting' ' test_expect_success 'setup unique colors' ' git config status.color.untracked blue && - git config status.color.branch green + git config status.color.branch green && + git config status.color.localBranch yellow && + git config status.color.remoteBranch cyan ' test_expect_success 'status with color.ui' ' cat >expect <<\EOF && On branch <GREEN>master<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) + Changes to be committed: (use "git reset HEAD <file>..." to unstage) @@ -675,7 +732,7 @@ test_expect_success 'status -s with color.status' ' ' cat >expect <<\EOF -## <GREEN>master<RESET> +## <YELLOW>master<RESET>...<CYAN>upstream<RESET> [ahead <YELLOW>1<RESET>, behind <CYAN>2<RESET>] <RED>M<RESET> dir1/modified <GREEN>A<RESET> dir2/added <BLUE>??<RESET> dir1/untracked @@ -726,7 +783,7 @@ test_expect_success 'status --porcelain respects -b' ' git status --porcelain -b >output && { - echo "## master" && + echo "## master...upstream [ahead 1, behind 2]" && cat expect } >tmp && mv tmp expect && @@ -739,6 +796,10 @@ test_expect_success 'status --porcelain respects -b' ' test_expect_success 'status without relative paths' ' cat >expect <<\EOF && On branch master +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 reset HEAD <file>..." to unstage) @@ -785,6 +846,10 @@ test_expect_success 'status -s without relative paths' ' test_expect_success 'dry-run of partial commit excluding new file in index' ' cat >expect <<EOF && On branch master +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 reset HEAD <file>..." to unstage) @@ -825,6 +890,10 @@ test_expect_success 'setup status submodule summary' ' test_expect_success 'status submodule summary is disabled by default' ' cat >expect <<EOF && On branch master +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 reset HEAD <file>..." to unstage) @@ -881,6 +950,10 @@ head=$(cd sm && git rev-parse --short=7 --verify HEAD) test_expect_success 'status submodule summary' ' cat >expect <<EOF && On branch master +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 reset HEAD <file>..." to unstage) @@ -939,6 +1012,10 @@ test_expect_success 'status -s submodule summary' ' test_expect_success 'status submodule summary (clean submodule): commit' ' cat >expect <<EOF && On branch master +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 not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) @@ -985,6 +1062,10 @@ test_expect_success 'status -z implies porcelain' ' test_expect_success 'commit --dry-run submodule summary (--amend)' ' cat >expect <<EOF && On branch master +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 reset HEAD^1 <file>..." to unstage) @@ -1038,6 +1119,10 @@ touch .gitmodules test_expect_success '--ignore-submodules=untracked suppresses submodules with untracked content' ' cat > expect << EOF && On branch master +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 reset HEAD <file>..." to unstage) @@ -1146,6 +1231,10 @@ test_expect_success '.git/config ignore=dirty suppresses submodules with modifie test_expect_success "--ignore-submodules=untracked doesn't suppress submodules with modified content" ' cat > expect << EOF && On branch master +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 reset HEAD <file>..." to unstage) @@ -1202,6 +1291,10 @@ head2=$(cd sm && git commit -q -m "2nd commit" foo && git rev-parse --short=7 -- test_expect_success "--ignore-submodules=untracked doesn't suppress submodule summary" ' cat > expect << EOF && On branch master +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 reset HEAD <file>..." to unstage) @@ -1282,6 +1375,10 @@ test_expect_success ".git/config ignore=dirty doesn't suppress submodule summary cat > expect << EOF ; On branch master +; 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 reset HEAD <file>..." to unstage) ; @@ -1329,6 +1426,10 @@ test_expect_success "status (core.commentchar with two chars with submodule summ test_expect_success "--ignore-submodules=all suppresses submodule summary" ' cat > expect << EOF && On branch master +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 not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) @@ -1353,6 +1454,10 @@ EOF test_expect_success '.gitmodules ignore=all suppresses unstaged submodule summary' ' cat > expect << EOF && On branch master +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 reset HEAD <file>..." to unstage) @@ -1472,6 +1577,10 @@ test_expect_success 'git commit --dry-run will show a staged but ignored submodu git add sm && cat >expect << EOF && On branch master +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 reset HEAD <file>..." to unstage) @@ -1499,4 +1608,66 @@ test_expect_success 'git commit -m will commit a staged but ignored submodule' ' git config -f .gitmodules --remove-section submodule.subname ' +test_expect_success 'show stash info with "--show-stash"' ' + git reset --hard && + git stash clear && + echo 1 >file && + git add file && + 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_expect_success 'no stash info with "--show-stash --no-show-stash"' ' + git status --show-stash --no-show-stash >expected_without_stash && + test_cmp expected_default expected_without_stash +' + +test_expect_success '"status.showStash=false" weaker than "--show-stash"' ' + git -c status.showStash=false status --show-stash >actual && + test_cmp expected_with_stash actual +' + +test_expect_success '"status.showStash=true" weaker than "--no-show-stash"' ' + git -c status.showStash=true status --no-show-stash >actual && + test_cmp expected_without_stash actual +' + +test_expect_success 'no additionnal info if no stash entries' ' + git stash clear && + git -c status.showStash=true status >actual && + test_cmp expected_without_stash actual +' + +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_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_expect_success '"Initial commit" should be noted in commit template' ' + git checkout --orphan empty-branch-3 && + touch to_be_committed_1 && + git add to_be_committed_1 && + git commit --dry-run >output && + test_i18ngrep "Initial commit" output +' + +test_expect_success '"Initial commit" should not be noted in commit template' ' + git checkout --orphan empty-branch-4 && + test_commit test-commit-2 && + touch to_be_committed_2 && + git add to_be_committed_2 && + git commit --dry-run >output && + test_i18ngrep ! "Initial commit" output +' + test_done diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index cee42097b0..f106387820 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -275,12 +275,16 @@ do test_cmp expected actual ' - test_expect_success LIBPCRE "grep $L with grep.patterntype=perl" ' + test_expect_success PCRE "grep $L with grep.patterntype=perl" ' echo "${HC}ab:a+b*c" >expected && git -c grep.patterntype=perl grep "a\x{2b}b\x{2a}c" $H ab >actual && test_cmp expected actual ' + test_expect_success !PCRE "grep $L with grep.patterntype=perl errors without PCRE" ' + test_must_fail git -c grep.patterntype=perl grep "foo.*bar" + ' + test_expect_success "grep $L with grep.patternType=default and grep.extendedRegexp=true" ' echo "${HC}ab:abc" >expected && git \ @@ -771,6 +775,40 @@ test_expect_success 'grep -W with userdiff' ' test_cmp expected actual ' +for threads in $(test_seq 0 10) +do + test_expect_success "grep --threads=$threads & -c grep.threads=$threads" " + git grep --threads=$threads . >actual.$threads && + if test $threads -ge 1 + then + test_cmp actual.\$(($threads - 1)) actual.$threads + fi && + git -c grep.threads=$threads grep . >actual.$threads && + if test $threads -ge 1 + then + test_cmp actual.\$(($threads - 1)) actual.$threads + fi + " +done + +test_expect_success !PTHREADS,C_LOCALE_OUTPUT 'grep --threads=N or pack.threads=N warns when no pthreads' ' + git grep --threads=2 Hello hello_world 2>err && + grep ^warning: err >warnings && + test_line_count = 1 warnings && + grep -F "no threads support, ignoring --threads" err && + git -c grep.threads=2 grep Hello hello_world 2>err && + grep ^warning: err >warnings && + test_line_count = 1 warnings && + grep -F "no threads support, ignoring grep.threads" err && + git -c grep.threads=2 grep --threads=4 Hello hello_world 2>err && + grep ^warning: err >warnings && + test_line_count = 2 warnings && + grep -F "no threads support, ignoring --threads" err && + grep -F "no threads support, ignoring grep.threads" err && + git -c grep.threads=0 grep --threads=0 Hello hello_world 2>err && + test_line_count = 0 err +' + test_expect_success 'grep from a subdirectory to search wider area (1)' ' mkdir -p s && ( @@ -1053,16 +1091,24 @@ hello.c:int main(int argc, const char **argv) hello.c: printf("Hello world.\n"); EOF -test_expect_success LIBPCRE 'grep --perl-regexp pattern' ' +test_expect_success PCRE 'grep --perl-regexp pattern' ' git grep --perl-regexp "\p{Ps}.*?\p{Pe}" hello.c >actual && test_cmp expected actual ' -test_expect_success LIBPCRE 'grep -P pattern' ' +test_expect_success !PCRE 'grep --perl-regexp pattern errors without PCRE' ' + test_must_fail git grep --perl-regexp "foo.*bar" +' + +test_expect_success PCRE 'grep -P pattern' ' git grep -P "\p{Ps}.*?\p{Pe}" hello.c >actual && test_cmp expected actual ' +test_expect_success !PCRE 'grep -P pattern errors without PCRE' ' + test_must_fail git grep -P "foo.*bar" +' + test_expect_success 'grep pattern with grep.extendedRegexp=true' ' >empty && test_must_fail git -c grep.extendedregexp=true \ @@ -1070,13 +1116,13 @@ test_expect_success 'grep pattern with grep.extendedRegexp=true' ' test_cmp empty actual ' -test_expect_success LIBPCRE 'grep -P pattern with grep.extendedRegexp=true' ' +test_expect_success PCRE 'grep -P pattern with grep.extendedRegexp=true' ' git -c grep.extendedregexp=true \ grep -P "\p{Ps}.*?\p{Pe}" hello.c >actual && test_cmp expected actual ' -test_expect_success LIBPCRE 'grep -P -v pattern' ' +test_expect_success PCRE 'grep -P -v pattern' ' { echo "ab:a+b*c" echo "ab:a+bc" @@ -1085,7 +1131,7 @@ test_expect_success LIBPCRE 'grep -P -v pattern' ' test_cmp expected actual ' -test_expect_success LIBPCRE 'grep -P -i pattern' ' +test_expect_success PCRE 'grep -P -i pattern' ' cat >expected <<-EOF && hello.c: printf("Hello world.\n"); EOF @@ -1093,7 +1139,7 @@ test_expect_success LIBPCRE 'grep -P -i pattern' ' test_cmp expected actual ' -test_expect_success LIBPCRE 'grep -P -w pattern' ' +test_expect_success PCRE 'grep -P -w pattern' ' { echo "hello_world:Hello world" echo "hello_world:HeLLo world" @@ -1102,6 +1148,13 @@ test_expect_success LIBPCRE 'grep -P -w pattern' ' test_cmp expected actual ' +test_expect_success PCRE 'grep -P backreferences work (the PCRE NO_AUTO_CAPTURE flag is not set)' ' + git grep -P -h "(?P<one>.)(?P=one)" hello_world >actual && + test_cmp hello_world actual && + git grep -P -h "(.)\1" hello_world >actual && + test_cmp hello_world actual +' + test_expect_success 'grep -G invalidpattern properly dies ' ' test_must_fail git grep -G "a[" ' @@ -1118,11 +1171,11 @@ test_expect_success 'grep invalidpattern properly dies with grep.patternType=ext test_must_fail git -c grep.patterntype=extended grep "a[" ' -test_expect_success LIBPCRE 'grep -P invalidpattern properly dies ' ' +test_expect_success PCRE 'grep -P invalidpattern properly dies ' ' test_must_fail git grep -P "a[" ' -test_expect_success LIBPCRE 'grep invalidpattern properly dies with grep.patternType=perl' ' +test_expect_success PCRE 'grep invalidpattern properly dies with grep.patternType=perl' ' test_must_fail git -c grep.patterntype=perl grep "a[" ' @@ -1191,13 +1244,13 @@ test_expect_success 'grep pattern with grep.patternType=fixed, =basic, =perl, =e test_cmp expected actual ' -test_expect_success LIBPCRE 'grep -G -F -E -P pattern' ' +test_expect_success PCRE 'grep -G -F -E -P pattern' ' echo "d0:0" >expected && git grep -G -F -E -P "[\d]" d0 >actual && test_cmp expected actual ' -test_expect_success LIBPCRE 'grep pattern with grep.patternType=fixed, =basic, =extended, =perl' ' +test_expect_success PCRE 'grep pattern with grep.patternType=fixed, =basic, =extended, =perl' ' echo "d0:0" >expected && git \ -c grep.patterntype=fixed \ @@ -1208,7 +1261,7 @@ test_expect_success LIBPCRE 'grep pattern with grep.patternType=fixed, =basic, = test_cmp expected actual ' -test_expect_success LIBPCRE 'grep -P pattern with grep.patternType=fixed' ' +test_expect_success PCRE 'grep -P pattern with grep.patternType=fixed' ' echo "ab:a+b*c" >expected && git \ -c grep.patterntype=fixed \ @@ -1343,12 +1396,12 @@ space: line with leading space2 space: line with leading space3 EOF -test_expect_success LIBPCRE 'grep -E "^ "' ' +test_expect_success PCRE 'grep -E "^ "' ' git grep -E "^ " space >actual && test_cmp expected actual ' -test_expect_success LIBPCRE 'grep -P "^ "' ' +test_expect_success PCRE 'grep -P "^ "' ' git grep -P "^ " space >actual && test_cmp expected actual ' diff --git a/t/t7812-grep-icase-non-ascii.sh b/t/t7812-grep-icase-non-ascii.sh index 169fd8d706..0059a1f837 100755 --- a/t/t7812-grep-icase-non-ascii.sh +++ b/t/t7812-grep-icase-non-ascii.sh @@ -20,13 +20,13 @@ test_expect_success REGEX_LOCALE 'grep literal string, no -F' ' git grep -i "TILRAUN: HALLÓ HEIMUR!" ' -test_expect_success GETTEXT_LOCALE,LIBPCRE 'grep pcre utf-8 icase' ' +test_expect_success GETTEXT_LOCALE,PCRE 'grep pcre utf-8 icase' ' git grep --perl-regexp "TILRAUN: H.lló Heimur!" && git grep --perl-regexp -i "TILRAUN: H.lló Heimur!" && git grep --perl-regexp -i "TILRAUN: H.LLÓ HEIMUR!" ' -test_expect_success GETTEXT_LOCALE,LIBPCRE 'grep pcre utf-8 string with "+"' ' +test_expect_success GETTEXT_LOCALE,PCRE 'grep pcre utf-8 string with "+"' ' test_write_lines "TILRAUN: Hallóó Heimur!" >file2 && git add file2 && git grep -l --perl-regexp "TILRAUN: H.lló+ Heimur!" >actual && @@ -36,29 +36,14 @@ test_expect_success GETTEXT_LOCALE,LIBPCRE 'grep pcre utf-8 string with "+"' ' ' test_expect_success REGEX_LOCALE 'grep literal string, with -F' ' - git grep --debug -i -F "TILRAUN: Halló Heimur!" 2>&1 >/dev/null | - grep fixed >debug1 && - test_write_lines "fixed TILRAUN: Halló Heimur!" >expect1 && - test_cmp expect1 debug1 && - - git grep --debug -i -F "TILRAUN: HALLÓ HEIMUR!" 2>&1 >/dev/null | - grep fixed >debug2 && - test_write_lines "fixed TILRAUN: HALLÓ HEIMUR!" >expect2 && - test_cmp expect2 debug2 + git grep -i -F "TILRAUN: Halló Heimur!" && + git grep -i -F "TILRAUN: HALLÓ HEIMUR!" ' test_expect_success REGEX_LOCALE 'grep string with regex, with -F' ' - test_write_lines "^*TILR^AUN:.* \\Halló \$He[]imur!\$" >file && - - git grep --debug -i -F "^*TILR^AUN:.* \\Halló \$He[]imur!\$" 2>&1 >/dev/null | - grep fixed >debug1 && - test_write_lines "fixed \\^*TILR^AUN:\\.\\* \\\\Halló \$He\\[]imur!\\\$" >expect1 && - test_cmp expect1 debug1 && - - git grep --debug -i -F "^*TILR^AUN:.* \\HALLÓ \$HE[]IMUR!\$" 2>&1 >/dev/null | - grep fixed >debug2 && - test_write_lines "fixed \\^*TILR^AUN:\\.\\* \\\\HALLÓ \$HE\\[]IMUR!\\\$" >expect2 && - test_cmp expect2 debug2 + test_write_lines "TILRAUN: Halló Heimur [abc]!" >file3 && + git add file3 && + git grep -i -F "TILRAUN: Halló Heimur [abc]!" file3 ' test_expect_success REGEX_LOCALE 'pickaxe -i on non-ascii' ' diff --git a/t/t7813-grep-icase-iso.sh b/t/t7813-grep-icase-iso.sh index efef7fb81f..701e08a8e5 100755 --- a/t/t7813-grep-icase-iso.sh +++ b/t/t7813-grep-icase-iso.sh @@ -11,7 +11,7 @@ test_expect_success GETTEXT_ISO_LOCALE 'setup' ' export LC_ALL ' -test_expect_success GETTEXT_ISO_LOCALE,LIBPCRE 'grep pcre string' ' +test_expect_success GETTEXT_ISO_LOCALE,PCRE 'grep pcre string' ' git grep --perl-regexp -i "TILRAUN: H.ll Heimur!" && git grep --perl-regexp -i "TILRAUN: H.LL HEIMUR!" ' diff --git a/t/t7814-grep-recurse-submodules.sh b/t/t7814-grep-recurse-submodules.sh index 5b6eb3a65e..7184113b9b 100755 --- a/t/t7814-grep-recurse-submodules.sh +++ b/t/t7814-grep-recurse-submodules.sh @@ -9,13 +9,13 @@ submodules. . ./test-lib.sh test_expect_success 'setup directory structure and submodule' ' - echo "foobar" >a && + echo "(1|2)d(3|4)" >a && mkdir b && - echo "bar" >b/b && + echo "(3|4)" >b/b && git add a b && git commit -m "add a and b" && git init submodule && - echo "foobar" >submodule/a && + echo "(1|2)d(3|4)" >submodule/a && git -C submodule add a && git -C submodule commit -m "add a" && git submodule add ./submodule && @@ -24,18 +24,36 @@ test_expect_success 'setup directory structure and submodule' ' test_expect_success 'grep correctly finds patterns in a submodule' ' cat >expect <<-\EOF && - a:foobar - b/b:bar - submodule/a:foobar + a:(1|2)d(3|4) + b/b:(3|4) + submodule/a:(1|2)d(3|4) EOF - git grep -e "bar" --recurse-submodules >actual && + git grep -e "(3|4)" --recurse-submodules >actual && + test_cmp expect actual +' + +test_expect_success 'grep finds patterns in a submodule via config' ' + test_config submodule.recurse true && + # expect from previous test + git grep -e "(3|4)" >actual && + test_cmp expect actual +' + +test_expect_success 'grep --no-recurse-submodules overrides config' ' + test_config submodule.recurse true && + cat >expect <<-\EOF && + a:(1|2)d(3|4) + b/b:(3|4) + EOF + + git grep -e "(3|4)" --no-recurse-submodules >actual && test_cmp expect actual ' test_expect_success 'grep and basic pathspecs' ' cat >expect <<-\EOF && - submodule/a:foobar + submodule/a:(1|2)d(3|4) EOF git grep -e. --recurse-submodules -- submodule >actual && @@ -44,7 +62,7 @@ test_expect_success 'grep and basic pathspecs' ' test_expect_success 'grep and nested submodules' ' git init submodule/sub && - echo "foobar" >submodule/sub/a && + echo "(1|2)d(3|4)" >submodule/sub/a && git -C submodule/sub add a && git -C submodule/sub commit -m "add a" && git -C submodule submodule add ./sub && @@ -54,117 +72,117 @@ test_expect_success 'grep and nested submodules' ' git commit -m "updated submodule" && cat >expect <<-\EOF && - a:foobar - b/b:bar - submodule/a:foobar - submodule/sub/a:foobar + a:(1|2)d(3|4) + b/b:(3|4) + submodule/a:(1|2)d(3|4) + submodule/sub/a:(1|2)d(3|4) EOF - git grep -e "bar" --recurse-submodules >actual && + git grep -e "(3|4)" --recurse-submodules >actual && test_cmp expect actual ' test_expect_success 'grep and multiple patterns' ' cat >expect <<-\EOF && - a:foobar - submodule/a:foobar - submodule/sub/a:foobar + a:(1|2)d(3|4) + submodule/a:(1|2)d(3|4) + submodule/sub/a:(1|2)d(3|4) EOF - git grep -e "bar" --and -e "foo" --recurse-submodules >actual && + git grep -e "(3|4)" --and -e "(1|2)" --recurse-submodules >actual && test_cmp expect actual ' test_expect_success 'grep and multiple patterns' ' cat >expect <<-\EOF && - b/b:bar + b/b:(3|4) EOF - git grep -e "bar" --and --not -e "foo" --recurse-submodules >actual && + git grep -e "(3|4)" --and --not -e "(1|2)" --recurse-submodules >actual && test_cmp expect actual ' test_expect_success 'basic grep tree' ' cat >expect <<-\EOF && - HEAD:a:foobar - HEAD:b/b:bar - HEAD:submodule/a:foobar - HEAD:submodule/sub/a:foobar + HEAD:a:(1|2)d(3|4) + HEAD:b/b:(3|4) + HEAD:submodule/a:(1|2)d(3|4) + HEAD:submodule/sub/a:(1|2)d(3|4) EOF - git grep -e "bar" --recurse-submodules HEAD >actual && + git grep -e "(3|4)" --recurse-submodules HEAD >actual && test_cmp expect actual ' test_expect_success 'grep tree HEAD^' ' cat >expect <<-\EOF && - HEAD^:a:foobar - HEAD^:b/b:bar - HEAD^:submodule/a:foobar + HEAD^:a:(1|2)d(3|4) + HEAD^:b/b:(3|4) + HEAD^:submodule/a:(1|2)d(3|4) EOF - git grep -e "bar" --recurse-submodules HEAD^ >actual && + git grep -e "(3|4)" --recurse-submodules HEAD^ >actual && test_cmp expect actual ' test_expect_success 'grep tree HEAD^^' ' cat >expect <<-\EOF && - HEAD^^:a:foobar - HEAD^^:b/b:bar + HEAD^^:a:(1|2)d(3|4) + HEAD^^:b/b:(3|4) EOF - git grep -e "bar" --recurse-submodules HEAD^^ >actual && + git grep -e "(3|4)" --recurse-submodules HEAD^^ >actual && test_cmp expect actual ' test_expect_success 'grep tree and pathspecs' ' cat >expect <<-\EOF && - HEAD:submodule/a:foobar - HEAD:submodule/sub/a:foobar + HEAD:submodule/a:(1|2)d(3|4) + HEAD:submodule/sub/a:(1|2)d(3|4) EOF - git grep -e "bar" --recurse-submodules HEAD -- submodule >actual && + git grep -e "(3|4)" --recurse-submodules HEAD -- submodule >actual && test_cmp expect actual ' test_expect_success 'grep tree and pathspecs' ' cat >expect <<-\EOF && - HEAD:submodule/a:foobar - HEAD:submodule/sub/a:foobar + HEAD:submodule/a:(1|2)d(3|4) + HEAD:submodule/sub/a:(1|2)d(3|4) EOF - git grep -e "bar" --recurse-submodules HEAD -- "submodule*a" >actual && + git grep -e "(3|4)" --recurse-submodules HEAD -- "submodule*a" >actual && test_cmp expect actual ' test_expect_success 'grep tree and more pathspecs' ' cat >expect <<-\EOF && - HEAD:submodule/a:foobar + HEAD:submodule/a:(1|2)d(3|4) EOF - git grep -e "bar" --recurse-submodules HEAD -- "submodul?/a" >actual && + git grep -e "(3|4)" --recurse-submodules HEAD -- "submodul?/a" >actual && test_cmp expect actual ' test_expect_success 'grep tree and more pathspecs' ' cat >expect <<-\EOF && - HEAD:submodule/sub/a:foobar + HEAD:submodule/sub/a:(1|2)d(3|4) EOF - git grep -e "bar" --recurse-submodules HEAD -- "submodul*/sub/a" >actual && + git grep -e "(3|4)" --recurse-submodules HEAD -- "submodul*/sub/a" >actual && test_cmp expect actual ' test_expect_success !MINGW 'grep recurse submodule colon in name' ' git init parent && test_when_finished "rm -rf parent" && - echo "foobar" >"parent/fi:le" && + echo "(1|2)d(3|4)" >"parent/fi:le" && git -C parent add "fi:le" && git -C parent commit -m "add fi:le" && git init "su:b" && test_when_finished "rm -rf su:b" && - echo "foobar" >"su:b/fi:le" && + echo "(1|2)d(3|4)" >"su:b/fi:le" && git -C "su:b" add "fi:le" && git -C "su:b" commit -m "add fi:le" && @@ -172,30 +190,30 @@ test_expect_success !MINGW 'grep recurse submodule colon in name' ' git -C parent commit -m "add submodule" && cat >expect <<-\EOF && - fi:le:foobar - su:b/fi:le:foobar + fi:le:(1|2)d(3|4) + su:b/fi:le:(1|2)d(3|4) EOF - git -C parent grep -e "foobar" --recurse-submodules >actual && + git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual && test_cmp expect actual && cat >expect <<-\EOF && - HEAD:fi:le:foobar - HEAD:su:b/fi:le:foobar + HEAD:fi:le:(1|2)d(3|4) + HEAD:su:b/fi:le:(1|2)d(3|4) EOF - git -C parent grep -e "foobar" --recurse-submodules HEAD >actual && + git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules HEAD >actual && test_cmp expect actual ' test_expect_success 'grep history with moved submoules' ' git init parent && test_when_finished "rm -rf parent" && - echo "foobar" >parent/file && + echo "(1|2)d(3|4)" >parent/file && git -C parent add file && git -C parent commit -m "add file" && git init sub && test_when_finished "rm -rf sub" && - echo "foobar" >sub/file && + echo "(1|2)d(3|4)" >sub/file && git -C sub add file && git -C sub commit -m "add file" && @@ -203,82 +221,82 @@ test_expect_success 'grep history with moved submoules' ' git -C parent commit -m "add submodule" && cat >expect <<-\EOF && - dir/sub/file:foobar - file:foobar + dir/sub/file:(1|2)d(3|4) + file:(1|2)d(3|4) EOF - git -C parent grep -e "foobar" --recurse-submodules >actual && + git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual && test_cmp expect actual && git -C parent mv dir/sub sub-moved && git -C parent commit -m "moved submodule" && cat >expect <<-\EOF && - file:foobar - sub-moved/file:foobar + file:(1|2)d(3|4) + sub-moved/file:(1|2)d(3|4) EOF - git -C parent grep -e "foobar" --recurse-submodules >actual && + git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules >actual && test_cmp expect actual && cat >expect <<-\EOF && - HEAD^:dir/sub/file:foobar - HEAD^:file:foobar + HEAD^:dir/sub/file:(1|2)d(3|4) + HEAD^:file:(1|2)d(3|4) EOF - git -C parent grep -e "foobar" --recurse-submodules HEAD^ >actual && + git -C parent grep -e "(1|2)d(3|4)" --recurse-submodules HEAD^ >actual && test_cmp expect actual ' test_expect_success 'grep using relative path' ' test_when_finished "rm -rf parent sub" && git init sub && - echo "foobar" >sub/file && + echo "(1|2)d(3|4)" >sub/file && git -C sub add file && git -C sub commit -m "add file" && git init parent && - echo "foobar" >parent/file && + echo "(1|2)d(3|4)" >parent/file && git -C parent add file && mkdir parent/src && - echo "foobar" >parent/src/file2 && + echo "(1|2)d(3|4)" >parent/src/file2 && git -C parent add src/file2 && git -C parent submodule add ../sub && git -C parent commit -m "add files and submodule" && # From top works cat >expect <<-\EOF && - file:foobar - src/file2:foobar - sub/file:foobar + file:(1|2)d(3|4) + src/file2:(1|2)d(3|4) + sub/file:(1|2)d(3|4) EOF - git -C parent grep --recurse-submodules -e "foobar" >actual && + git -C parent grep --recurse-submodules -e "(1|2)d(3|4)" >actual && test_cmp expect actual && # Relative path to top cat >expect <<-\EOF && - ../file:foobar - file2:foobar - ../sub/file:foobar + ../file:(1|2)d(3|4) + file2:(1|2)d(3|4) + ../sub/file:(1|2)d(3|4) EOF - git -C parent/src grep --recurse-submodules -e "foobar" -- .. >actual && + git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" -- .. >actual && test_cmp expect actual && # Relative path to submodule cat >expect <<-\EOF && - ../sub/file:foobar + ../sub/file:(1|2)d(3|4) EOF - git -C parent/src grep --recurse-submodules -e "foobar" -- ../sub >actual && + git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" -- ../sub >actual && test_cmp expect actual ' test_expect_success 'grep from a subdir' ' test_when_finished "rm -rf parent sub" && git init sub && - echo "foobar" >sub/file && + echo "(1|2)d(3|4)" >sub/file && git -C sub add file && git -C sub commit -m "add file" && git init parent && mkdir parent/src && - echo "foobar" >parent/src/file && + echo "(1|2)d(3|4)" >parent/src/file && git -C parent add src/file && git -C parent submodule add ../sub src/sub && git -C parent submodule add ../sub sub && @@ -286,19 +304,19 @@ test_expect_success 'grep from a subdir' ' # Verify grep from root works cat >expect <<-\EOF && - src/file:foobar - src/sub/file:foobar - sub/file:foobar + src/file:(1|2)d(3|4) + src/sub/file:(1|2)d(3|4) + sub/file:(1|2)d(3|4) EOF - git -C parent grep --recurse-submodules -e "foobar" >actual && + git -C parent grep --recurse-submodules -e "(1|2)d(3|4)" >actual && test_cmp expect actual && # Verify grep from a subdir works cat >expect <<-\EOF && - file:foobar - sub/file:foobar + file:(1|2)d(3|4) + sub/file:(1|2)d(3|4) EOF - git -C parent/src grep --recurse-submodules -e "foobar" >actual && + git -C parent/src grep --recurse-submodules -e "(1|2)d(3|4)" >actual && test_cmp expect actual ' @@ -313,4 +331,53 @@ test_incompatible_with_recurse_submodules () test_incompatible_with_recurse_submodules --untracked test_incompatible_with_recurse_submodules --no-index +test_expect_success 'grep --recurse-submodules should pass the pattern type along' ' + # Fixed + test_must_fail git grep -F --recurse-submodules -e "(.|.)[\d]" && + test_must_fail git -c grep.patternType=fixed grep --recurse-submodules -e "(.|.)[\d]" && + + # Basic + git grep -G --recurse-submodules -e "(.|.)[\d]" >actual && + cat >expect <<-\EOF && + a:(1|2)d(3|4) + submodule/a:(1|2)d(3|4) + submodule/sub/a:(1|2)d(3|4) + EOF + test_cmp expect actual && + git -c grep.patternType=basic grep --recurse-submodules -e "(.|.)[\d]" >actual && + test_cmp expect actual && + + # Extended + git grep -E --recurse-submodules -e "(.|.)[\d]" >actual && + cat >expect <<-\EOF && + .gitmodules:[submodule "submodule"] + .gitmodules: path = submodule + .gitmodules: url = ./submodule + a:(1|2)d(3|4) + submodule/.gitmodules:[submodule "sub"] + submodule/a:(1|2)d(3|4) + submodule/sub/a:(1|2)d(3|4) + EOF + test_cmp expect actual && + git -c grep.patternType=extended grep --recurse-submodules -e "(.|.)[\d]" >actual && + test_cmp expect actual && + git -c grep.extendedRegexp=true grep --recurse-submodules -e "(.|.)[\d]" >actual && + test_cmp expect actual && + + # Perl + if test_have_prereq PCRE + then + git grep -P --recurse-submodules -e "(.|.)[\d]" >actual && + cat >expect <<-\EOF && + a:(1|2)d(3|4) + b/b:(3|4) + submodule/a:(1|2)d(3|4) + submodule/sub/a:(1|2)d(3|4) + EOF + test_cmp expect actual && + git -c grep.patternType=perl grep --recurse-submodules -e "(.|.)[\d]" >actual && + test_cmp expect actual + fi +' + test_done diff --git a/t/t8008-blame-formats.sh b/t/t8008-blame-formats.sh index 92c8e792d1..ae4b579d24 100755 --- a/t/t8008-blame-formats.sh +++ b/t/t8008-blame-formats.sh @@ -12,22 +12,25 @@ test_expect_success 'setup' ' echo c >>file && echo d >>file && test_tick && - git commit -a -m two + git commit -a -m two && + ID1=$(git rev-parse HEAD^) && + shortID1="^$(git rev-parse HEAD^ |cut -c 1-17)" && + ID2=$(git rev-parse HEAD) && + shortID2="$(git rev-parse HEAD |cut -c 1-18)" ' -cat >expect <<'EOF' -^baf5e0b (A U Thor 2005-04-07 15:13:13 -0700 1) a -8825379d (A U Thor 2005-04-07 15:14:13 -0700 2) b -8825379d (A U Thor 2005-04-07 15:14:13 -0700 3) c -8825379d (A U Thor 2005-04-07 15:14:13 -0700 4) d +cat >expect <<EOF +$shortID1 (A U Thor 2005-04-07 15:13:13 -0700 1) a +$shortID2 (A U Thor 2005-04-07 15:14:13 -0700 2) b +$shortID2 (A U Thor 2005-04-07 15:14:13 -0700 3) c +$shortID2 (A U Thor 2005-04-07 15:14:13 -0700 4) d EOF test_expect_success 'normal blame output' ' - git blame file >actual && + git blame --abbrev=17 file >actual && test_cmp expect actual ' -ID1=baf5e0b3869e0b2b2beb395a3720c7b51eac94fc -COMMIT1='author A U Thor +COMMIT1="author A U Thor author-mail <author@example.com> author-time 1112911993 author-tz -0700 @@ -37,9 +40,8 @@ committer-time 1112911993 committer-tz -0700 summary one boundary -filename file' -ID2=8825379dfb8a1267b58e8e5bcf69eec838f685ec -COMMIT2='author A U Thor +filename file" +COMMIT2="author A U Thor author-mail <author@example.com> author-time 1112912053 author-tz -0700 @@ -48,8 +50,8 @@ committer-mail <committer@example.com> committer-time 1112912053 committer-tz -0700 summary two -previous baf5e0b3869e0b2b2beb395a3720c7b51eac94fc file -filename file' +previous $ID1 file +filename file" cat >expect <<EOF $ID1 1 1 1 diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index 60a80f60b2..d1e4e8ad19 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -1913,4 +1913,52 @@ test_expect_success $PREREQ 'leading and trailing whitespaces are removed' ' test_cmp expected-list actual-list ' +test_expect_success $PREREQ 'invoke hook' ' + mkdir -p .git/hooks && + + write_script .git/hooks/sendemail-validate <<-\EOF && + # test that we have the correct environment variable, pwd, and + # argument + case "$GIT_DIR" in + *.git) + true + ;; + *) + false + ;; + esac && + test -f 0001-add-master.patch && + grep "add master" "$1" + EOF + + mkdir subdir && + ( + # Test that it works even if we are not at the root of the + # working tree + cd subdir && + git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/../fake.sendmail" \ + ../0001-add-master.patch && + + # Verify error message when a patch is rejected by the hook + sed -e "s/add master/x/" ../0001-add-master.patch >../another.patch && + git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/../fake.sendmail" \ + ../another.patch 2>err + test_i18ngrep "rejected by sendemail-validate hook" err + ) +' + +test_expect_success $PREREQ 'test that send-email works outside a repo' ' + nongit git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + "$(pwd)/0001-add-master.patch" +' + test_done diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 2e0ba3ebd8..67b8c50a5a 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -2822,7 +2822,7 @@ test_expect_success 'S: filemodify with garbage after sha1 must fail' ' # # notemodify, three ways to say dataref # -test_expect_success 'S: notemodify with garabge after mark dataref must fail' ' +test_expect_success 'S: notemodify with garbage after mark dataref must fail' ' test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && commit refs/heads/S committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE diff --git a/t/t9831-git-p4-triggers.sh b/t/t9831-git-p4-triggers.sh new file mode 100755 index 0000000000..bbcf14c664 --- /dev/null +++ b/t/t9831-git-p4-triggers.sh @@ -0,0 +1,103 @@ +#!/bin/sh + +test_description='git p4 with server triggers' + +. ./lib-git-p4.sh + +test_expect_success 'start p4d' ' + start_p4d +' + +test_expect_success 'init depot' ' + ( + cd "$cli" && + echo file1 >file1 && + p4 add file1 && + p4 submit -d "change 1" + echo file2 >file2 && + p4 add file2 && + p4 submit -d "change 2" + ) +' + +test_expect_success 'clone with extra info lines from verbose p4 trigger' ' + test_when_finished cleanup_git && + ( + p4 triggers -i <<-EOF + Triggers: p4triggertest-command command pre-user-change "echo verbose trigger" + EOF + ) && + ( + p4 change -o | grep -s "verbose trigger" + ) && + git p4 clone --dest="$git" //depot/@all && + ( + p4 triggers -i <<-EOF + Triggers: + EOF + ) +' + +test_expect_success 'import with extra info lines from verbose p4 trigger' ' + test_when_finished cleanup_git && + ( + cd "$cli" && + echo file3 >file3 && + p4 add file3 && + p4 submit -d "change 3" + ) && + ( + p4 triggers -i <<-EOF + Triggers: p4triggertest-command command pre-user-describe "echo verbose trigger" + EOF + ) && + ( + p4 describe 1 | grep -s "verbose trigger" + ) && + git p4 clone --dest="$git" //depot/@all && + ( + cd "$git" && + git p4 sync + )&& + ( + p4 triggers -i <<-EOF + Triggers: + EOF + ) +' + +test_expect_success 'submit description with extra info lines from verbose p4 change trigger' ' + test_when_finished cleanup_git && + ( + p4 triggers -i <<-EOF + Triggers: p4triggertest-command command pre-user-change "echo verbose trigger" + EOF + ) && + ( + p4 change -o | grep -s "verbose trigger" + ) && + git p4 clone --dest="$git" //depot && + ( + cd "$git" && + git config git-p4.skipSubmitEdit true && + echo file4 >file4 && + git add file4 && + git commit -m file4 && + git p4 submit + ) && + ( + p4 triggers -i <<-EOF + Triggers: + EOF + ) && + ( + cd "$cli" && + test_path_is_file file4 + ) +' + +test_expect_success 'kill p4d' ' + kill_p4d +' + +test_done diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index 50a9a1d1c4..1701fe2a06 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -42,6 +42,7 @@ test_decode_color () { function name(n) { if (n == 0) return "RESET"; if (n == 1) return "BOLD"; + if (n == 7) return "REVERSE"; if (n == 30) return "BLACK"; if (n == 31) return "RED"; if (n == 32) return "GREEN"; diff --git a/t/test-lib.sh b/t/test-lib.sh index 30eb743719..1b6e53f78a 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -36,6 +36,14 @@ then fi GIT_BUILD_DIR="$TEST_DIRECTORY"/.. +# If we were built with ASAN, it may complain about leaks +# of program-lifetime variables. Disable it by default to lower +# the noise level. This needs to happen at the start of the script, +# before we even do our "did we build git yet" check (since we don't +# want that one to complain to stderr). +: ${ASAN_OPTIONS=detect_leaks=0:abort_on_error=1} +export ASAN_OPTIONS + ################################################################ # It appears that people try to run tests without building... "$GIT_BUILD_DIR/git" >/dev/null @@ -148,9 +156,6 @@ else } fi -: ${ASAN_OPTIONS=detect_leaks=0} -export ASAN_OPTIONS - # Protect ourselves from common misconfiguration to export # CDPATH into the environment unset CDPATH @@ -766,10 +771,15 @@ test_done () { esac fi - test -d "$remove_trash" && - cd "$(dirname "$remove_trash")" && - rm -rf "$(basename "$remove_trash")" + if test -z "$debug" + then + test -d "$TRASH_DIRECTORY" || + error "Tests passed but trash directory already removed before test cleanup; aborting" + cd "$TRASH_DIRECTORY/.." && + rm -fr "$TRASH_DIRECTORY" || + error "Tests passed but test cleanup failed; aborting" + fi test_at_end_hook_ exit 0 ;; @@ -924,7 +934,6 @@ case "$TRASH_DIRECTORY" in /*) ;; # absolute path is good *) TRASH_DIRECTORY="$TEST_OUTPUT_DIRECTORY/$TRASH_DIRECTORY" ;; esac -test ! -z "$debug" || remove_trash=$TRASH_DIRECTORY rm -fr "$TRASH_DIRECTORY" || { GIT_EXIT_OK=t echo >&5 "FATAL: Cannot prepare test area" @@ -1014,8 +1023,9 @@ esac ( COLUMNS=1 && test $COLUMNS = 1 ) && test_set_prereq COLUMNS_CAN_BE_1 test -z "$NO_PERL" && test_set_prereq PERL +test -z "$NO_PTHREADS" && test_set_prereq PTHREADS test -z "$NO_PYTHON" && test_set_prereq PYTHON -test -n "$USE_LIBPCRE" && test_set_prereq LIBPCRE +test -n "$USE_LIBPCRE1$USE_LIBPCRE2" && test_set_prereq PCRE test -z "$NO_GETTEXT" && test_set_prereq GETTEXT # Can we rely on git's output in the C locale? @@ -1169,3 +1179,6 @@ build_option () { test_lazy_prereq LONG_IS_64BIT ' test 8 -le "$(build_option sizeof-long)" ' + +test_lazy_prereq TIME_IS_64BIT 'test-date is64bit' +test_lazy_prereq TIME_T_IS_64BIT 'test-date time_t-is64bit' |