diff options
Diffstat (limited to 't')
112 files changed, 3255 insertions, 589 deletions
diff --git a/t/.gitattributes b/t/.gitattributes index e7acedabe1..df05434d32 100644 --- a/t/.gitattributes +++ b/t/.gitattributes @@ -16,6 +16,7 @@ t[0-9][0-9][0-9][0-9]/* -whitespace /t4135/* eol=lf /t4211/* eol=lf /t4252/* eol=lf +/t4256/1/* eol=lf /t5100/* eol=lf /t5515/* eol=lf /t556x_common eol=lf @@ -154,6 +154,7 @@ appropriately before running "make". As the names depend on the tests' file names, it is safe to run the tests with this option in parallel. +-V:: --verbose-log:: Write verbose output to the same logfile as `--tee`, but do _not_ write it to stdout. Unlike `--tee --verbose`, this option @@ -301,6 +302,12 @@ that cannot be easily covered by a few specific test cases. These could be enabled by running the test suite with correct GIT_TEST_ environment set. +GIT_TEST_GETTEXT_POISON=<non-empty?> turns all strings marked for +translation into gibberish if non-empty (think "test -n"). Used for +spotting those tests that need to be marked with a C_LOCALE_OUTPUT +prerequisite when adding more strings for translation. See "Testing +marked strings" in po/README for details. + GIT_TEST_SPLIT_INDEX=<boolean> forces split-index mode on the whole test suite. Accept any boolean values that are accepted by git-config. @@ -338,11 +345,19 @@ for the index version specified. Can be set to any valid version GIT_TEST_PRELOAD_INDEX=<boolean> exercises the preload-index code path by overriding the minimum number of cache entries required per thread. +GIT_TEST_REBASE_USE_BUILTIN=<boolean>, when false, disables the +builtin version of git-rebase. See 'rebase.useBuiltin' in +git-config(1). + GIT_TEST_INDEX_THREADS=<n> enables exercising the multi-threaded loading of the index for the whole test suite by bypassing the default number of cache entries and thread minimums. Setting this to 1 will make the index loading single threaded. +GIT_TEST_MULTI_PACK_INDEX=<boolean>, when true, forces the multi-pack- +index to be written after every 'git repack' command, and overrides the +'core.multiPackIndex' setting to true. + Naming Tests ------------ diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c index 9cb8a0ea0f..47fee660b8 100644 --- a/t/helper/test-parse-options.c +++ b/t/helper/test-parse-options.c @@ -36,6 +36,7 @@ static int length_callback(const struct option *opt, const char *arg, int unset) static int number_callback(const struct option *opt, const char *arg, int unset) { + BUG_ON_OPT_NEG(unset); *(int *)opt->value = strtol(arg, NULL, 10); return 0; } @@ -119,7 +120,6 @@ int cmd__parse_options(int argc, const char **argv) OPT_INTEGER('j', NULL, &integer, "get a integer, too"), OPT_MAGNITUDE('m', "magnitude", &magnitude, "get a magnitude"), OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23), - OPT_DATE('t', NULL, ×tamp, "get timestamp of <time>"), OPT_CALLBACK('L', "length", &integer, "str", "get length of <str>", length_callback), OPT_FILENAME('F', "file", &file, "set file to <file>"), diff --git a/t/helper/test-prio-queue.c b/t/helper/test-prio-queue.c index 9807b649b1..5bc9c46ea5 100644 --- a/t/helper/test-prio-queue.c +++ b/t/helper/test-prio-queue.c @@ -22,14 +22,24 @@ int cmd__prio_queue(int argc, const char **argv) struct prio_queue pq = { intcmp }; while (*++argv) { - if (!strcmp(*argv, "get")) - show(prio_queue_get(&pq)); - else if (!strcmp(*argv, "dump")) { - int *v; - while ((v = prio_queue_get(&pq))) - show(v); - } - else { + if (!strcmp(*argv, "get")) { + void *peek = prio_queue_peek(&pq); + void *get = prio_queue_get(&pq); + if (peek != get) + BUG("peek and get results do not match"); + show(get); + } else if (!strcmp(*argv, "dump")) { + void *peek; + void *get; + while ((peek = prio_queue_peek(&pq))) { + get = prio_queue_get(&pq); + if (peek != get) + BUG("peek and get results do not match"); + show(get); + } + } else if (!strcmp(*argv, "stack")) { + pq.compare = NULL; + } else { int *v = malloc(sizeof(*v)); *v = atoi(*argv); prio_queue_put(&pq, v); diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c index 08d2ea68e8..a0272178b7 100644 --- a/t/helper/test-reach.c +++ b/t/helper/test-reach.c @@ -32,8 +32,8 @@ int cmd__reach(int ac, const char **av) struct commit *A, *B; struct commit_list *X, *Y; struct object_array X_obj = OBJECT_ARRAY_INIT; - struct commit **X_array; - int X_nr, X_alloc; + struct commit **X_array, **Y_array; + int X_nr, X_alloc, Y_nr, Y_alloc; struct strbuf buf = STRBUF_INIT; struct repository *r = the_repository; @@ -44,9 +44,10 @@ int cmd__reach(int ac, const char **av) A = B = NULL; X = Y = NULL; - X_nr = 0; - X_alloc = 16; + X_nr = Y_nr = 0; + X_alloc = Y_alloc = 16; ALLOC_ARRAY(X_array, X_alloc); + ALLOC_ARRAY(Y_array, Y_alloc); while (strbuf_getline(&buf, stdin) != EOF) { struct object_id oid; @@ -92,6 +93,8 @@ int cmd__reach(int ac, const char **av) case 'Y': commit_list_insert(c, &Y); + ALLOC_GROW(Y_array, Y_nr + 1, Y_alloc); + Y_array[Y_nr++] = c; break; default: @@ -136,6 +139,29 @@ int cmd__reach(int ac, const char **av) filter.with_commit_tag_algo = 0; printf("%s(_,A,X,_):%d\n", av[1], commit_contains(&filter, A, X, &cache)); + } else if (!strcmp(av[1], "get_reachable_subset")) { + const int reachable_flag = 1; + int i, count = 0; + struct commit_list *current; + struct commit_list *list = get_reachable_subset(X_array, X_nr, + Y_array, Y_nr, + reachable_flag); + printf("get_reachable_subset(X,Y)\n"); + for (current = list; current; current = current->next) { + if (!(list->item->object.flags & reachable_flag)) + die(_("commit %s is not marked reachable"), + oid_to_hex(&list->item->object.oid)); + count++; + } + for (i = 0; i < Y_nr; i++) { + if (Y_array[i]->object.flags & reachable_flag) + count--; + } + + if (count < 0) + die(_("too many commits marked reachable")); + + print_sorted_commit_ids(list); } exit(0); diff --git a/t/helper/test-submodule-nested-repo-config.c b/t/helper/test-submodule-nested-repo-config.c new file mode 100644 index 0000000000..a31e2a9bea --- /dev/null +++ b/t/helper/test-submodule-nested-repo-config.c @@ -0,0 +1,30 @@ +#include "test-tool.h" +#include "submodule-config.h" + +static void die_usage(int argc, const char **argv, const char *msg) +{ + fprintf(stderr, "%s\n", msg); + fprintf(stderr, "Usage: %s <submodulepath> <config name>\n", argv[0]); + exit(1); +} + +int cmd__submodule_nested_repo_config(int argc, const char **argv) +{ + struct repository submodule; + + if (argc < 3) + die_usage(argc, argv, "Wrong number of arguments."); + + setup_git_directory(); + + if (repo_submodule_init(&submodule, the_repository, argv[1])) { + die_usage(argc, argv, "Submodule not found."); + } + + /* Read the config of _child_ submodules. */ + print_config_from_gitmodules(&submodule, argv[2]); + + submodule_free(the_repository); + + return 0; +} diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c index 6b5836dc1b..bfb195b1a8 100644 --- a/t/helper/test-tool.c +++ b/t/helper/test-tool.c @@ -46,6 +46,7 @@ static struct test_cmd cmds[] = { { "strcmp-offset", cmd__strcmp_offset }, { "string-list", cmd__string_list }, { "submodule-config", cmd__submodule_config }, + { "submodule-nested-repo-config", cmd__submodule_nested_repo_config }, { "subprocess", cmd__subprocess }, { "urlmatch-normalization", cmd__urlmatch_normalization }, { "wildmatch", cmd__wildmatch }, @@ -55,13 +56,23 @@ static struct test_cmd cmds[] = { { "write-cache", cmd__write_cache }, }; +static NORETURN void die_usage(void) +{ + size_t i; + + fprintf(stderr, "usage: test-tool <toolname> [args]\n"); + for (i = 0; i < ARRAY_SIZE(cmds); i++) + fprintf(stderr, " %s\n", cmds[i].name); + exit(128); +} + int cmd_main(int argc, const char **argv) { int i; BUG_exit_code = 99; if (argc < 2) - die("I need a test name!"); + die_usage(); for (i = 0; i < ARRAY_SIZE(cmds); i++) { if (!strcmp(cmds[i].name, argv[1])) { @@ -70,5 +81,6 @@ int cmd_main(int argc, const char **argv) return cmds[i].fn(argc, argv); } } - die("There is no test named '%s'", argv[1]); + error("there is no tool named '%s'", argv[1]); + die_usage(); } diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h index e4890566da..042f12464b 100644 --- a/t/helper/test-tool.h +++ b/t/helper/test-tool.h @@ -1,5 +1,5 @@ -#ifndef __TEST_TOOL_H__ -#define __TEST_TOOL_H__ +#ifndef TEST_TOOL_H +#define TEST_TOOL_H #include "git-compat-util.h" @@ -42,6 +42,7 @@ int cmd__sigchain(int argc, const char **argv); int cmd__strcmp_offset(int argc, const char **argv); int cmd__string_list(int argc, const char **argv); int cmd__submodule_config(int argc, const char **argv); +int cmd__submodule_nested_repo_config(int argc, const char **argv); int cmd__subprocess(int argc, const char **argv); int cmd__urlmatch_normalization(int argc, const char **argv); int cmd__wildmatch(int argc, const char **argv); diff --git a/t/lib-gettext.sh b/t/lib-gettext.sh index eec757f104..2139b427ca 100644 --- a/t/lib-gettext.sh +++ b/t/lib-gettext.sh @@ -10,9 +10,14 @@ GIT_TEXTDOMAINDIR="$GIT_BUILD_DIR/po/build/locale" GIT_PO_PATH="$GIT_BUILD_DIR/po" export GIT_TEXTDOMAINDIR GIT_PO_PATH -. "$GIT_BUILD_DIR"/git-sh-i18n +if test -n "$GIT_TEST_INSTALLED" +then + . "$(git --exec-path)"/git-sh-i18n +else + . "$GIT_BUILD_DIR"/git-sh-i18n +fi -if test_have_prereq GETTEXT && ! test_have_prereq GETTEXT_POISON +if test_have_prereq GETTEXT && test_have_prereq C_LOCALE_OUTPUT then # is_IS.UTF-8 on Solaris and FreeBSD, is_IS.utf8 on Debian is_IS_locale=$(locale -a 2>/dev/null | diff --git a/t/lib-git-daemon.sh b/t/lib-git-daemon.sh index edbea2d986..f98de95c15 100644 --- a/t/lib-git-daemon.sh +++ b/t/lib-git-daemon.sh @@ -92,7 +92,7 @@ stop_git_daemon() { kill "$GIT_DAEMON_PID" wait "$GIT_DAEMON_PID" >&3 2>&4 ret=$? - if test_match_signal 15 $? + if ! test_match_signal 15 $ret then error "git daemon exited with status: $ret" fi diff --git a/t/lib-gpg/keyring.gpg b/t/lib-gpg/keyring.gpg index d4754a1f19..918dfce332 100644 --- a/t/lib-gpg/keyring.gpg +++ b/t/lib-gpg/keyring.gpg @@ -30,7 +30,6 @@ Cezx4Q2khACcCs+/LtE8Lb9hC+2cvr3uH5p82AI= =aEiU -----END PGP PRIVATE KEY BLOCK----- -----BEGIN PGP PRIVATE KEY BLOCK----- -Version: GnuPG v1 lQOYBFFMlkcBCADJi/xnAF8yI34PHilSCbM7VtOFO17oFMkpu4cgN2QpPuM5MVjy cvrzKSguZFvPCDLzeAFJW1uPxL4SHaHSkisCrFhijH7OJWcOPNPSFCwu+inAoAsv @@ -83,11 +82,43 @@ fn1sY/IG5atoKK+ypmV/TlBlMZqFQzuPIJQT8VLbmxtLlDhJG04LbI6c8axIZxOO ZKLy5nTTSy16ztqEeS7eifHLPZg1UFFyEEIQ1XW0CNDAeuWKh90ERjyl4Cg7PnWS Z9Ei+zj6JD5Pcdi3BJhQo9WOLOVEJ0NHmewTYqk9QVXH/0v1Hdl4LMJtgcbdbDWk 4UTkXbg9pn3umCgkNJ3Vs8fWnIWO9Izdr2/wrFY2JvUT7Yvl+wsNIWatvOEzGy7n -BOW78WUxzhu0YJTLKy+iKCjg5HS5dx6OC+e4aEEgfhNPCMkbvDsJjtQ= -=hieJ +BOW78WUxzhu0YJTLKy+iKCjg5HS5dx6OC+e4aEEgfhNPCMkbvDsJjtSdA5gEW967 +3AEIAKjseT0sTQjyN39fOn0fzxWp89REMUUKgLigb01MKuuNI3cedBZsz3hpFOKV +cii5rldw8uf3yS3Okht2DfHPSD4NrGzLGEzSTpQ10S8N2q0DUYwyLU6C0U8HnMZm +/n+lCGBbUoxvnruohAvKAjpHO3rmJ8D4De9hlWg/fwdAxQQ0Sve0kN8Vwk2p1GuO +OWQKV1SU9c+kBiou7dewQmbilPRanKmP5ZSU4emhpTOMlJFXF+kmYSODQk1cMvWW +Ob3ttll2llX0Gul7Sjf+haq/FcRyRk7Tw5MHwZjr5aWiCny0/0+byvfF6SBIfzyE +qlyWURQ2gHZUqSiG3QPMZiYr04cAEQEAAQAH/Am4rv/oQF6wodgz5y4zc6JJiTDA +4+nKdIuR7OKqUxk1oo7eZjJML/xvMumygNyUvJ9nodl1SlMKilOhdAswfkKj9gJY +BdDJLm1OufhW3pJwy6ahbjeqEgwJFVENtSPF0zkuyED9kElrpbD2ZTGfzwdM0e9D +10ZDFWtODCw8rzOFcijujgI8oilLtxSNrkkTKW+25WJFRNPSHgIkMIm8UlPAG+rj +3Yj9UqodeXTSvXwG2zceOxjFJadV77sOFJDgwWslN6J8El4+GcgwFVepJxoZEj7e +cKkmVr0Dc9/Q04D5dWATc1FYcIhZbTu3oImCAh45ep4u9WYLUV5PGyeMviEEAMwo +mJbYBxWuPjpNa722HQcbvMUiZWWDwHfLCib/SaP0AgfDahid8/PcZwxOPHPByBrm +GDi0z7ibn/pgJr07kpp1Cic9ntfc2FvkI0QMzG0EuiekzQyPEnzjoDHF+V4nJIj2 +GWVjLYYqlZWEmhsfKt1CnlPXBunKoDJ30ABPcHJ/BADT0WxAIVKF4lO2HlrDVP44 +bufBEG9Ct7dl/G08Qve4Ag3VEZpT82vEFp0LzX0mTCDIUKJUYAYLxAIPhP7IvIfc +EZXrwyDUxU7YSgKTHMKo9nFC6fIc1GeGPRalIF1gmTY32qlYJC6y5BTDhZNV5ydG +u8QL2P/orP7XuRrJyeyK+QP/XTekr/DS6Jkct826MPA52ciIkWVgYLatH5fO4HCq +ssDU8vz7FbbvGs0G1Xn7GA4m9dNYVOZtKwX++3nf2IEOpgPiZVTn/nP2u3HutpJb +/HMLlcfZGiGdxS6n/vdz6wsEobJoi6STkHkA+VFNOSZmdsw6eKl3X911tpCTYfOG +2U47/IkCbAQYAQgAIBYhBNS+IjEa0xMeXtoppGEJLoW3InGJBQJb3rvcAhsCAUAJ +EGEJLoW3InGJwHQgBBkBCAAdFiEE+DZKWeB//p9NYwBaZaDuoC4wytcFAlveu9wA +CgkQZaDuoC4wytcD9gf/WigtHl7lFyl8RaE/uqROFEelZyM00v1h55fd/IGRG88E +tN0Lr4FaqBqPkMZjU/LN9UMBaTd+748vHlHaweZqljXJu99CO9Id7Y4w7WzF3C3Y +yQsGZ92EGxthsPK0+rhHV0MbaINupI1oO9gATFglSxq17o83FJatGRjaXCZau8jr +57/By1MGtjk+Iq1NkzGkrX778LdRQGLKDw2Qa7lsdHY8d3lUPAH8mbb97ELmIc9t +PG2aM7ATJL7nBmFuTHo6hmEcIw32Ei9KK1zxM0ZylEYkjBjHAlklWmKb9MiayMC5 +uHW7Iyhjl+NbgbIEr2JTamW/9tL6UrIIxiDEdqaHNfCaB/9D+V31Upcohc9azwB4 +AF8diQwt5nfiVpnVeF/W8+eS1By2W6QrwLNthNRabYFnuSf9USHAY6atDWe+egId +MLIv4ce0i3ykoczSu0oMoUCMxdl9kQrsNHZCqWX/OiDDLSb05u/P/3he900y6tSB +15MbIPA6i5Bw/693nHguqxS1ASbBB/LiIu3vCXdFEs9RMvIJ+qkP3xQA96oImQiK +R3U6OGv593eONKijUINNqHRq6+UxIyJ+OCAi+L2QTidAhJLRCp6EZD96u02cthYq +8KA8j1+rx9BcbeacVVHepeG1JsgxsXX8BTJ7ZuS5VVndZOjag8URW/9nJMf01w/h +el64 +=Iv7W -----END PGP PRIVATE KEY BLOCK----- -----BEGIN PGP PUBLIC KEY BLOCK----- -Version: GnuPG v1 mQGiBEZnyykRBACzCPjIpTYNL7Y2tQqlEGTTDlvZcWNLjF5f7ZzuyOqNOidLUgFD 36qch1LZLSZkShdR3Gae+bsolyjxrlFuFP0eXRPMtqK20aLw7WZvPFpEV1ThMne+ @@ -137,6 +168,25 @@ bGPyBuWraCivsqZlf05QZTGahUM7jyCUE/FS25sbS5Q4SRtOC2yOnPGsSGcTjmSi 8uZ000stes7ahHku3onxyz2YNVBRchBCENV1tAjQwHrliofdBEY8peAoOz51kmfR Ivs4+iQ+T3HYtwSYUKPVjizlRCdDR5nsE2KpPUFVx/9L9R3ZeCzCbYHG3Ww1pOFE 5F24PaZ97pgoJDSd1bPH1pyFjvSM3a9v8KxWNib1E+2L5fsLDSFmrbzhMxsu5wTl -u/FlMc4btGCUyysvoigo4OR0uXcejgvnuGhBIH4TTwjJG7w7CY7U -=iYv/ +u/FlMc4btGCUyysvoigo4OR0uXcejgvnuGhBIH4TTwjJG7w7CY7UuQENBFveu9wB +CACo7Hk9LE0I8jd/Xzp9H88VqfPURDFFCoC4oG9NTCrrjSN3HnQWbM94aRTilXIo +ua5XcPLn98ktzpIbdg3xz0g+DaxsyxhM0k6UNdEvDdqtA1GMMi1OgtFPB5zGZv5/ +pQhgW1KMb567qIQLygI6Rzt65ifA+A3vYZVoP38HQMUENEr3tJDfFcJNqdRrjjlk +CldUlPXPpAYqLu3XsEJm4pT0Wpypj+WUlOHpoaUzjJSRVxfpJmEjg0JNXDL1ljm9 +7bZZdpZV9Brpe0o3/oWqvxXEckZO08OTB8GY6+Wlogp8tP9Pm8r3xekgSH88hKpc +llEUNoB2VKkoht0DzGYmK9OHABEBAAGJAmwEGAEIACAWIQTUviIxGtMTHl7aKaRh +CS6FtyJxiQUCW9673AIbAgFACRBhCS6FtyJxicB0IAQZAQgAHRYhBPg2Slngf/6f +TWMAWmWg7qAuMMrXBQJb3rvcAAoJEGWg7qAuMMrXA/YH/1ooLR5e5RcpfEWhP7qk +ThRHpWcjNNL9YeeX3fyBkRvPBLTdC6+BWqgaj5DGY1PyzfVDAWk3fu+PLx5R2sHm +apY1ybvfQjvSHe2OMO1sxdwt2MkLBmfdhBsbYbDytPq4R1dDG2iDbqSNaDvYAExY +JUsate6PNxSWrRkY2lwmWrvI6+e/wctTBrY5PiKtTZMxpK1++/C3UUBiyg8NkGu5 +bHR2PHd5VDwB/Jm2/exC5iHPbTxtmjOwEyS+5wZhbkx6OoZhHCMN9hIvSitc8TNG +cpRGJIwYxwJZJVpim/TImsjAubh1uyMoY5fjW4GyBK9iU2plv/bS+lKyCMYgxHam +hzXwmgf/Q/ld9VKXKIXPWs8AeABfHYkMLeZ34laZ1Xhf1vPnktQctlukK8CzbYTU +Wm2BZ7kn/VEhwGOmrQ1nvnoCHTCyL+HHtIt8pKHM0rtKDKFAjMXZfZEK7DR2Qqll +/zogwy0m9Obvz/94XvdNMurUgdeTGyDwOouQcP+vd5x4LqsUtQEmwQfy4iLt7wl3 +RRLPUTLyCfqpD98UAPeqCJkIikd1Ojhr+fd3jjSoo1CDTah0auvlMSMifjggIvi9 +kE4nQISS0QqehGQ/ertNnLYWKvCgPI9fq8fQXG3mnFVR3qXhtSbIMbF1/AUye2bk +uVVZ3WTo2oPFEVv/ZyTH9NcP4XpeuA== +=KRyT -----END PGP PUBLIC KEY BLOCK----- diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh index 2ca9fb69d6..7ea30e5006 100644 --- a/t/lib-rebase.sh +++ b/t/lib-rebase.sh @@ -47,9 +47,9 @@ set_fake_editor () { action=pick for line in $FAKE_LINES; do case $line in - pick|squash|fixup|edit|reword|drop) + pick|p|squash|s|fixup|f|edit|e|reword|r|drop|d) action="$line";; - exec*) + exec_*|x_*|break|b) echo "$line" | sed 's/_/ /g' >> "$1";; "#") echo '# comment' >> "$1";; diff --git a/t/perf/p3400-rebase.sh b/t/perf/p3400-rebase.sh index ce271ca4c1..d202aaed06 100755 --- a/t/perf/p3400-rebase.sh +++ b/t/perf/p3400-rebase.sh @@ -6,9 +6,9 @@ test_description='Tests rebase performance' test_perf_default_repo 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 && + git checkout -f -B base && + git checkout -B to-rebase && + git checkout -B upstream && for i in $(seq 100) do # simulate huge diffs @@ -35,8 +35,8 @@ test_perf 'rebase on top of a lot of unrelated changes' ' 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 + git checkout -B upstream2 to-rebase && + git checkout -B to-rebase2 upstream ' test_perf 'rebase a lot of unrelated changes without split-index' ' diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh index 11d1922cf5..2e33ab3ec3 100644 --- a/t/perf/perf-lib.sh +++ b/t/perf/perf-lib.sh @@ -82,7 +82,7 @@ test_perf_do_repo_symlink_config_ () { test_perf_create_repo_from () { test "$#" = 2 || - error "bug in the test script: not 2 parameters to test-create-repo" + BUG "not 2 parameters to test-create-repo" repo="$1" source="$2" source_git="$("$MODERN_GIT" -C "$source" rev-parse --git-dir)" @@ -184,7 +184,7 @@ test_wrapper_ () { test_start_ test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq= test "$#" = 2 || - error "bug in the test script: not 2 or 3 parameters to test-expect-success" + BUG "not 2 or 3 parameters to test-expect-success" export test_prereq if ! test_skip "$@" then diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index 4d23373526..b6566003dd 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -274,7 +274,7 @@ test_expect_success 'pretend we have a mix of all possible results' " EOF " -test_expect_success 'test --verbose' ' +test_expect_success C_LOCALE_OUTPUT 'test --verbose' ' test_must_fail run_sub_test_lib_test \ test-verbose "test verbose" --verbose <<-\EOF && test_expect_success "passing test" true diff --git a/t/t0001-init.sh b/t/t0001-init.sh index 182da069f1..42a263cada 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -319,14 +319,14 @@ test_lazy_prereq GETCWD_IGNORES_PERMS ' base=GETCWD_TEST_BASE_DIR && mkdir -p $base/dir && chmod 100 $base || - error "bug in test script: cannot prepare $base" + BUG "cannot prepare $base" (cd $base/dir && /bin/pwd -P) status=$? chmod 700 $base && rm -rf $base || - error "bug in test script: cannot clean $base" + BUG "cannot clean $base" return $status ' diff --git a/t/t0006-date.sh b/t/t0006-date.sh index 64ff86df8e..ffb2975e48 100755 --- a/t/t0006-date.sh +++ b/t/t0006-date.sh @@ -113,6 +113,8 @@ check_approxidate '3:00' '2009-08-30 03:00:00' check_approxidate '15:00' '2009-08-30 15:00:00' check_approxidate 'noon today' '2009-08-30 12:00:00' check_approxidate 'noon yesterday' '2009-08-29 12:00:00' +check_approxidate 'January 5th noon pm' '2009-01-05 12:00:00' +check_approxidate '10am noon' '2009-08-29 12:00:00' check_approxidate 'last tuesday' '2009-08-25 19:20:00' check_approxidate 'July 5th' '2009-07-05 19:20:00' diff --git a/t/t0009-prio-queue.sh b/t/t0009-prio-queue.sh index e56dfce668..3941ad2528 100755 --- a/t/t0009-prio-queue.sh +++ b/t/t0009-prio-queue.sh @@ -47,4 +47,18 @@ test_expect_success 'notice empty queue' ' test_cmp expect actual ' +cat >expect <<'EOF' +3 +2 +6 +4 +5 +1 +8 +EOF +test_expect_success 'stack order' ' + test-tool prio-queue stack 8 1 5 4 6 2 3 dump >actual && + test_cmp expect actual +' + test_done diff --git a/t/t0029-core-unsetenvvars.sh b/t/t0029-core-unsetenvvars.sh new file mode 100755 index 0000000000..24ce46a6ea --- /dev/null +++ b/t/t0029-core-unsetenvvars.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +test_description='test the Windows-only core.unsetenvvars setting' + +. ./test-lib.sh + +if ! test_have_prereq MINGW +then + skip_all='skipping Windows-specific tests' + test_done +fi + +test_expect_success 'setup' ' + mkdir -p "$TRASH_DIRECTORY/.git/hooks" && + write_script "$TRASH_DIRECTORY/.git/hooks/pre-commit" <<-\EOF + echo $HOBBES >&2 + EOF +' + +test_expect_success 'core.unsetenvvars works' ' + HOBBES=Calvin && + export HOBBES && + git commit --allow-empty -m with 2>err && + grep Calvin err && + git -c core.unsetenvvars=FINDUS,HOBBES,CALVIN \ + commit --allow-empty -m without 2>err && + ! grep Calvin err +' + +test_done diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index 17d0c18feb..b8f366c442 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -23,7 +23,6 @@ usage: test-tool parse-options <options> -j <n> get a integer, too -m, --magnitude <n> get a magnitude --set23 set integer to 23 - -t <time> get timestamp of <time> -L, --length <str> get length of <str> -F, --file <file> set file to <file> @@ -228,7 +227,7 @@ EOF test_expect_success 'detect possible typos' ' test_must_fail test-tool parse-options -boolean >output 2>output.err && test_must_be_empty output && - test_cmp typo.err output.err + test_i18ncmp typo.err output.err ' cat >typo.err <<\EOF @@ -238,7 +237,7 @@ EOF test_expect_success 'detect possible typos' ' test_must_fail test-tool parse-options -ambiguous >output 2>output.err && test_must_be_empty output && - test_cmp typo.err output.err + test_i18ncmp typo.err output.err ' test_expect_success 'keep some options as arguments' ' @@ -246,27 +245,6 @@ test_expect_success 'keep some options as arguments' ' ' cat >expect <<\EOF -boolean: 0 -integer: 0 -magnitude: 0 -timestamp: 1 -string: (not set) -abbrev: 7 -verbose: -1 -quiet: 1 -dry run: no -file: (not set) -arg 00: foo -EOF - -test_expect_success 'OPT_DATE() works' ' - test-tool parse-options -t "1970-01-01 00:00:01 +0000" \ - foo -q >output 2>output.err && - test_must_be_empty output.err && - test_cmp expect output -' - -cat >expect <<\EOF Callback: "four", 0 boolean: 5 integer: 4 diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh index cd74c0a471..c7b53e494b 100755 --- a/t/t0060-path-utils.sh +++ b/t/t0060-path-utils.sh @@ -306,6 +306,8 @@ test_git_path GIT_COMMON_DIR=bar hooks/me bar/hooks/me test_git_path GIT_COMMON_DIR=bar config bar/config test_git_path GIT_COMMON_DIR=bar packed-refs bar/packed-refs test_git_path GIT_COMMON_DIR=bar shallow bar/shallow +test_git_path GIT_COMMON_DIR=bar common bar/common +test_git_path GIT_COMMON_DIR=bar common/file bar/common/file # In the tests below, $(pwd) must be used because it is a native path on # Windows and avoids MSYS's path mangling (which simplifies "foo/../bar" and diff --git a/t/t0061-run-command.sh b/t/t0061-run-command.sh index 3e131c5325..96bf6d6a7d 100755 --- a/t/t0061-run-command.sh +++ b/t/t0061-run-command.sh @@ -12,8 +12,14 @@ cat >hello-script <<-EOF cat hello-script EOF -test_expect_success 'start_command reports ENOENT' ' - test-tool run-command start-command-ENOENT ./does-not-exist +test_expect_success 'start_command reports ENOENT (slash)' ' + test-tool run-command start-command-ENOENT ./does-not-exist 2>err && + test_i18ngrep "\./does-not-exist" err +' + +test_expect_success 'start_command reports ENOENT (no slash)' ' + test-tool run-command start-command-ENOENT does-not-exist 2>err && + test_i18ngrep "does-not-exist" err ' test_expect_success 'run_command can run a command' ' @@ -25,6 +31,14 @@ test_expect_success 'run_command can run a command' ' test_must_be_empty err ' +test_expect_success 'run_command is restricted to PATH' ' + write_script should-not-run <<-\EOF && + echo yikes + EOF + test_must_fail test-tool run-command run-command should-not-run 2>err && + test_i18ngrep "should-not-run" err +' + test_expect_success !MINGW 'run_command can run a script without a #! line' ' cat >hello <<-\EOF && cat hello-script diff --git a/t/t0205-gettext-poison.sh b/t/t0205-gettext-poison.sh index 438e778d6a..a06269f38a 100755 --- a/t/t0205-gettext-poison.sh +++ b/t/t0205-gettext-poison.sh @@ -5,13 +5,15 @@ test_description='Gettext Shell poison' +GIT_TEST_GETTEXT_POISON=YesPlease +export GIT_TEST_GETTEXT_POISON . ./lib-gettext.sh -test_expect_success GETTEXT_POISON 'sanity: $GIT_INTERNAL_GETTEXT_SH_SCHEME" is poison' ' +test_expect_success 'sanity: $GIT_INTERNAL_GETTEXT_SH_SCHEME" is poison' ' test "$GIT_INTERNAL_GETTEXT_SH_SCHEME" = "poison" ' -test_expect_success GETTEXT_POISON 'gettext: our gettext() fallback has poison semantics' ' +test_expect_success 'gettext: our gettext() fallback has poison semantics' ' printf "# GETTEXT POISON #" >expect && gettext "test" >actual && test_cmp expect actual && @@ -20,7 +22,7 @@ test_expect_success GETTEXT_POISON 'gettext: our gettext() fallback has poison s test_cmp expect actual ' -test_expect_success GETTEXT_POISON 'eval_gettext: our eval_gettext() fallback has poison semantics' ' +test_expect_success 'eval_gettext: our eval_gettext() fallback has poison semantics' ' printf "# GETTEXT POISON #" >expect && eval_gettext "test" >actual && test_cmp expect actual && diff --git a/t/t0410-partial-clone.sh b/t/t0410-partial-clone.sh index d446021bab..169f7f10a7 100755 --- a/t/t0410-partial-clone.sh +++ b/t/t0410-partial-clone.sh @@ -239,6 +239,51 @@ test_expect_success 'rev-list stops traversal at missing and promised commit' ' ! grep $FOO out ' +test_expect_success 'missing tree objects with --missing=allow-promisor and --exclude-promisor-objects' ' + rm -rf repo && + test_create_repo repo && + test_commit -C repo foo && + test_commit -C repo bar && + test_commit -C repo baz && + + promise_and_delete $(git -C repo rev-parse bar^{tree}) && + promise_and_delete $(git -C repo rev-parse foo^{tree}) && + + git -C repo config core.repositoryformatversion 1 && + git -C repo config extensions.partialclone "arbitrary string" && + + git -C repo rev-list --missing=allow-promisor --objects HEAD >objs 2>rev_list_err && + test_must_be_empty rev_list_err && + # 3 commits, 3 blobs, and 1 tree + test_line_count = 7 objs && + + # Do the same for --exclude-promisor-objects, but with all trees gone. + promise_and_delete $(git -C repo rev-parse baz^{tree}) && + git -C repo rev-list --exclude-promisor-objects --objects HEAD >objs 2>rev_list_err && + test_must_be_empty rev_list_err && + # 3 commits, no blobs or trees + test_line_count = 3 objs +' + +test_expect_success 'missing non-root tree object and rev-list' ' + rm -rf repo && + test_create_repo repo && + mkdir repo/dir && + echo foo >repo/dir/foo && + git -C repo add dir/foo && + git -C repo commit -m "commit dir/foo" && + + promise_and_delete $(git -C repo rev-parse HEAD:dir) && + + git -C repo config core.repositoryformatversion 1 && + git -C repo config extensions.partialclone "arbitrary string" && + + git -C repo rev-list --missing=allow-any --objects HEAD >objs 2>rev_list_err && + test_must_be_empty rev_list_err && + # 1 commit and 1 tree + test_line_count = 2 objs +' + test_expect_success 'rev-list stops traversal at missing and promised tree' ' rm -rf repo && test_create_repo repo && diff --git a/t/t1060-object-corruption.sh b/t/t1060-object-corruption.sh index ac1f189fd2..4feb65157d 100755 --- a/t/t1060-object-corruption.sh +++ b/t/t1060-object-corruption.sh @@ -117,8 +117,10 @@ test_expect_failure 'clone --local detects misnamed objects' ' ' test_expect_success 'fetch into corrupted repo with index-pack' ' + cp -R bit-error bit-error-cp && + test_when_finished "rm -rf bit-error-cp" && ( - cd bit-error && + cd bit-error-cp && test_must_fail git -c transfer.unpackLimit=1 \ fetch ../no-bit-error 2>stderr && test_i18ngrep ! -i collision stderr diff --git a/t/t1300-config.sh b/t/t1300-config.sh index e2cd50ecfc..9652b241c7 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -76,15 +76,11 @@ EOF test_expect_success 'non-match result' 'test_cmp expect .git/config' test_expect_success 'find mixed-case key by canonical name' ' - echo Second >expect && - git config cores.whatever >actual && - test_cmp expect actual + test_cmp_config Second cores.whatever ' test_expect_success 'find mixed-case key by non-canonical name' ' - echo Second >expect && - git config CoReS.WhAtEvEr >actual && - test_cmp expect actual + test_cmp_config Second CoReS.WhAtEvEr ' test_expect_success 'subsections are not canonicalized by git-config' ' @@ -94,12 +90,8 @@ test_expect_success 'subsections are not canonicalized by git-config' ' [section "SubSection"] key = two EOF - echo one >expect && - git config section.subsection.key >actual && - test_cmp expect actual && - echo two >expect && - git config section.SubSection.key >actual && - test_cmp expect actual + test_cmp_config one section.subsection.key && + test_cmp_config two section.SubSection.key ' cat > .git/config <<\EOF @@ -212,9 +204,7 @@ test_expect_success 'really really mean test' ' ' test_expect_success 'get value' ' - echo alpha >expect && - git config beta.haha >actual && - test_cmp expect actual + test_cmp_config alpha beta.haha ' cat > expect << EOF @@ -251,15 +241,11 @@ test_expect_success 'non-match' ' ' test_expect_success 'non-match value' ' - echo wow >expect && - git config --get nextsection.nonewline !for >actual && - test_cmp expect actual + test_cmp_config wow --get nextsection.nonewline !for ' test_expect_success 'multi-valued get returns final one' ' - echo "wow2 for me" >expect && - git config --get nextsection.nonewline >actual && - test_cmp expect actual + test_cmp_config "wow2 for me" --get nextsection.nonewline ' test_expect_success 'multi-valued get-all returns all' ' @@ -520,21 +506,11 @@ test_expect_success 'editing stdin is an error' ' test_expect_success 'refer config from subdirectory' ' mkdir x && - ( - cd x && - echo strasse >expect && - git config --get --file ../other-config ein.bahn >actual && - test_cmp expect actual - ) - + test_cmp_config -C x strasse --get --file ../other-config ein.bahn ' test_expect_success 'refer config from subdirectory via --file' ' - ( - cd x && - git config --file=../other-config --get ein.bahn >actual && - test_cmp expect actual - ) + test_cmp_config -C x strasse --file=../other-config --get ein.bahn ' cat > expect << EOF @@ -688,16 +664,13 @@ test_expect_success numbers ' test_expect_success '--int is at least 64 bits' ' git config giga.watts 121g && - echo 129922760704 >expect && - git config --int --get giga.watts >actual && - test_cmp expect actual + echo >expect && + test_cmp_config 129922760704 --int --get giga.watts ' test_expect_success 'invalid unit' ' git config aninvalid.unit "1auto" && - echo 1auto >expect && - git config aninvalid.unit >actual && - test_cmp expect actual && + test_cmp_config 1auto aninvalid.unit && test_must_fail git config --int --get aninvalid.unit 2>actual && test_i18ngrep "bad numeric config value .1auto. for .aninvalid.unit. in file .git/config: invalid unit" actual ' @@ -1039,9 +1012,7 @@ test_expect_success '--null --get-regexp' ' test_expect_success 'inner whitespace kept verbatim' ' git config section.val "foo bar" && - echo "foo bar" >expect && - git config section.val >actual && - test_cmp expect actual + test_cmp_config "foo bar" section.val ' test_expect_success SYMLINKS 'symlinked configuration' ' @@ -1809,21 +1780,15 @@ big = 1M EOF test_expect_success 'identical modern --type specifiers are allowed' ' - git config --type=int --type=int core.big >actual && - echo 1048576 >expect && - test_cmp expect actual + test_cmp_config 1048576 --type=int --type=int core.big ' test_expect_success 'identical legacy --type specifiers are allowed' ' - git config --int --int core.big >actual && - echo 1048576 >expect && - test_cmp expect actual + test_cmp_config 1048576 --int --int core.big ' test_expect_success 'identical mixed --type specifiers are allowed' ' - git config --int --type=int core.big >actual && - echo 1048576 >expect && - test_cmp expect actual + test_cmp_config 1048576 --int --type=int core.big ' test_expect_success 'non-identical modern --type specifiers are not allowed' ' @@ -1842,21 +1807,15 @@ test_expect_success 'non-identical mixed --type specifiers are not allowed' ' ' test_expect_success '--type allows valid type specifiers' ' - echo "true" >expect && - git config --type=bool core.foo >actual && - test_cmp expect actual + test_cmp_config true --type=bool core.foo ' test_expect_success '--no-type unsets type specifiers' ' - echo "10" >expect && - git config --type=bool --no-type core.number >actual && - test_cmp expect actual + test_cmp_config 10 --type=bool --no-type core.number ' test_expect_success 'unset type specifiers may be reset to conflicting ones' ' - echo 1048576 >expect && - git config --type=bool --no-type --type=int core.big >actual && - test_cmp expect actual + test_cmp_config 1048576 --type=bool --no-type --type=int core.big ' test_expect_success '--type rejects unknown specifiers' ' diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh index 388b0611d8..ae8a448e34 100755 --- a/t/t1410-reflog.sh +++ b/t/t1410-reflog.sh @@ -20,12 +20,12 @@ check_have () { } check_fsck () { - output=$(git fsck --full) + git fsck --full >fsck.output case "$1" in '') - test -z "$output" ;; + test_must_be_empty fsck.output ;; *) - echo "$output" | grep "$1" ;; + test_i18ngrep "$1" fsck.output ;; esac } @@ -368,4 +368,19 @@ test_expect_success 'continue walking past root commits' ' ) ' +test_expect_success 'expire with multiple worktrees' ' + git init main-wt && + ( + cd main-wt && + test_tick && + test_commit foo && + git worktree add link-wt && + test_tick && + test_commit -C link-wt foobar && + test_tick && + git reflog expire --verbose --all --expire=$test_tick && + test_must_be_empty .git/worktrees/link-wt/logs/HEAD + ) +' + test_done diff --git a/t/t1415-worktree-refs.sh b/t/t1415-worktree-refs.sh new file mode 100755 index 0000000000..b664e51250 --- /dev/null +++ b/t/t1415-worktree-refs.sh @@ -0,0 +1,79 @@ +#!/bin/sh + +test_description='per-worktree refs' + +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit initial && + test_commit wt1 && + test_commit wt2 && + git worktree add wt1 wt1 && + git worktree add wt2 wt2 && + git checkout initial && + git update-ref refs/worktree/foo HEAD && + git -C wt1 update-ref refs/worktree/foo HEAD && + git -C wt2 update-ref refs/worktree/foo HEAD +' + +test_expect_success 'refs/worktree must not be packed' ' + git pack-refs --all && + test_path_is_missing .git/refs/tags/wt1 && + test_path_is_file .git/refs/worktree/foo && + test_path_is_file .git/worktrees/wt1/refs/worktree/foo && + test_path_is_file .git/worktrees/wt2/refs/worktree/foo +' + +test_expect_success 'refs/worktree are per-worktree' ' + test_cmp_rev worktree/foo initial && + ( cd wt1 && test_cmp_rev worktree/foo wt1 ) && + ( cd wt2 && test_cmp_rev worktree/foo wt2 ) +' + +test_expect_success 'resolve main-worktree/HEAD' ' + test_cmp_rev main-worktree/HEAD initial && + ( cd wt1 && test_cmp_rev main-worktree/HEAD initial ) && + ( cd wt2 && test_cmp_rev main-worktree/HEAD initial ) +' + +test_expect_success 'ambiguous main-worktree/HEAD' ' + mkdir -p .git/refs/heads/main-worktree && + test_when_finished rm -f .git/refs/heads/main-worktree/HEAD && + cp .git/HEAD .git/refs/heads/main-worktree/HEAD && + git rev-parse main-worktree/HEAD 2>warn && + grep "main-worktree/HEAD.*ambiguous" warn +' + +test_expect_success 'resolve worktrees/xx/HEAD' ' + test_cmp_rev worktrees/wt1/HEAD wt1 && + ( cd wt1 && test_cmp_rev worktrees/wt1/HEAD wt1 ) && + ( cd wt2 && test_cmp_rev worktrees/wt1/HEAD wt1 ) +' + +test_expect_success 'ambiguous worktrees/xx/HEAD' ' + mkdir -p .git/refs/heads/worktrees/wt1 && + test_when_finished rm -f .git/refs/heads/worktrees/wt1/HEAD && + cp .git/HEAD .git/refs/heads/worktrees/wt1/HEAD && + git rev-parse worktrees/wt1/HEAD 2>warn && + grep "worktrees/wt1/HEAD.*ambiguous" warn +' + +test_expect_success 'reflog of main-worktree/HEAD' ' + git reflog HEAD | sed "s/HEAD/main-worktree\/HEAD/" >expected && + git reflog main-worktree/HEAD >actual && + test_cmp expected actual && + git -C wt1 reflog main-worktree/HEAD >actual.wt1 && + test_cmp expected actual.wt1 +' + +test_expect_success 'reflog of worktrees/xx/HEAD' ' + git -C wt2 reflog HEAD | sed "s/HEAD/worktrees\/wt2\/HEAD/" >expected && + git reflog worktrees/wt2/HEAD >actual && + test_cmp expected actual && + git -C wt1 reflog worktrees/wt2/HEAD >actual.wt1 && + test_cmp expected actual.wt1 && + git -C wt2 reflog worktrees/wt2/HEAD >actual.wt2 && + test_cmp expected actual.wt2 +' + +test_done diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index 0f2dd26f74..2e5e979336 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -70,7 +70,7 @@ test_expect_success 'object with bad sha1' ' test_must_fail git fsck 2>out && cat out && - grep "$sha.*corrupt" out + test_i18ngrep "$sha.*corrupt" out ' test_expect_success 'branch pointing to non-commit' ' @@ -78,7 +78,7 @@ test_expect_success 'branch pointing to non-commit' ' test_when_finished "git update-ref -d refs/heads/invalid" && test_must_fail git fsck 2>out && cat out && - grep "not a commit" out + test_i18ngrep "not a commit" out ' test_expect_success 'HEAD link pointing at a funny object' ' @@ -88,7 +88,7 @@ test_expect_success 'HEAD link pointing at a funny object' ' # avoid corrupt/broken HEAD from interfering with repo discovery test_must_fail env GIT_DIR=.git git fsck 2>out && cat out && - grep "detached HEAD points" out + test_i18ngrep "detached HEAD points" out ' test_expect_success 'HEAD link pointing at a funny place' ' @@ -98,7 +98,42 @@ test_expect_success 'HEAD link pointing at a funny place' ' # avoid corrupt/broken HEAD from interfering with repo discovery test_must_fail env GIT_DIR=.git git fsck 2>out && cat out && - grep "HEAD points to something strange" out + test_i18ngrep "HEAD points to something strange" out +' + +test_expect_success 'HEAD link pointing at a funny object (from different wt)' ' + test_when_finished "mv .git/SAVED_HEAD .git/HEAD" && + test_when_finished "rm -rf .git/worktrees wt" && + git worktree add wt && + mv .git/HEAD .git/SAVED_HEAD && + echo $ZERO_OID >.git/HEAD && + # avoid corrupt/broken HEAD from interfering with repo discovery + test_must_fail git -C wt fsck 2>out && + test_i18ngrep "main-worktree/HEAD: detached HEAD points" out +' + +test_expect_success 'other worktree HEAD link pointing at a funny object' ' + test_when_finished "rm -rf .git/worktrees other" && + git worktree add other && + echo $ZERO_OID >.git/worktrees/other/HEAD && + test_must_fail git fsck 2>out && + test_i18ngrep "worktrees/other/HEAD: detached HEAD points" out +' + +test_expect_success 'other worktree HEAD link pointing at missing object' ' + test_when_finished "rm -rf .git/worktrees other" && + git worktree add other && + echo "Contents missing from repo" | git hash-object --stdin >.git/worktrees/other/HEAD && + test_must_fail git fsck 2>out && + test_i18ngrep "worktrees/other/HEAD: invalid sha1 pointer" out +' + +test_expect_success 'other worktree HEAD link pointing at a funny place' ' + test_when_finished "rm -rf .git/worktrees other" && + git worktree add other && + echo "ref: refs/funny/place" >.git/worktrees/other/HEAD && + test_must_fail git fsck 2>out && + test_i18ngrep "worktrees/other/HEAD points to something strange" out ' test_expect_success 'email without @ is okay' ' @@ -122,7 +157,7 @@ test_expect_success 'email with embedded > is not okay' ' test_when_finished "git update-ref -d refs/heads/bogus" && test_must_fail git fsck 2>out && cat out && - grep "error in commit $new" out + test_i18ngrep "error in commit $new" out ' test_expect_success 'missing < email delimiter is reported nicely' ' @@ -134,7 +169,7 @@ test_expect_success 'missing < email delimiter is reported nicely' ' test_when_finished "git update-ref -d refs/heads/bogus" && test_must_fail git fsck 2>out && cat out && - grep "error in commit $new.* - bad name" out + test_i18ngrep "error in commit $new.* - bad name" out ' test_expect_success 'missing email is reported nicely' ' @@ -146,7 +181,7 @@ test_expect_success 'missing email is reported nicely' ' test_when_finished "git update-ref -d refs/heads/bogus" && test_must_fail git fsck 2>out && cat out && - grep "error in commit $new.* - missing email" out + test_i18ngrep "error in commit $new.* - missing email" out ' test_expect_success '> in name is reported' ' @@ -158,7 +193,7 @@ test_expect_success '> in name is reported' ' test_when_finished "git update-ref -d refs/heads/bogus" && test_must_fail git fsck 2>out && cat out && - grep "error in commit $new" out + test_i18ngrep "error in commit $new" out ' # date is 2^64 + 1 @@ -172,7 +207,7 @@ test_expect_success 'integer overflow in timestamps is reported' ' test_when_finished "git update-ref -d refs/heads/bogus" && test_must_fail git fsck 2>out && cat out && - grep "error in commit $new.*integer overflow" out + test_i18ngrep "error in commit $new.*integer overflow" out ' test_expect_success 'commit with NUL in header' ' @@ -184,7 +219,7 @@ test_expect_success 'commit with NUL in header' ' test_when_finished "git update-ref -d refs/heads/bogus" && test_must_fail git fsck 2>out && cat out && - grep "error in commit $new.*unterminated header: NUL at offset" out + test_i18ngrep "error in commit $new.*unterminated header: NUL at offset" out ' test_expect_success 'tree object with duplicate entries' ' @@ -205,7 +240,7 @@ test_expect_success 'tree object with duplicate entries' ' git hash-object -w -t tree --stdin ) && test_must_fail git fsck 2>out && - grep "error in tree .*contains duplicate file entries" out + test_i18ngrep "error in tree .*contains duplicate file entries" out ' test_expect_success 'unparseable tree object' ' @@ -259,7 +294,7 @@ test_expect_success 'tag pointing to nonexistent' ' test_when_finished "git update-ref -d refs/tags/invalid" && test_must_fail git fsck --tags >out && cat out && - grep "broken link" out + test_i18ngrep "broken link" out ' test_expect_success 'tag pointing to something else than its type' ' @@ -301,7 +336,7 @@ test_expect_success 'tag with incorrect tag name & missing tagger' ' warning in tag $tag: badTagName: invalid '\''tag'\'' name: wrong name format warning in tag $tag: missingTaggerEntry: invalid format - expected '\''tagger'\'' line EOF - test_cmp expect out + test_i18ncmp expect out ' test_expect_success 'tag with bad tagger' ' @@ -320,7 +355,7 @@ test_expect_success 'tag with bad tagger' ' echo $tag >.git/refs/tags/wrong && test_when_finished "git update-ref -d refs/tags/wrong" && test_must_fail git fsck --tags 2>out && - grep "error in tag .*: invalid author/committer" out + test_i18ngrep "error in tag .*: invalid author/committer" out ' test_expect_success 'tag with NUL in header' ' @@ -340,7 +375,7 @@ test_expect_success 'tag with NUL in header' ' test_when_finished "git update-ref -d refs/tags/wrong" && test_must_fail git fsck --tags 2>out && cat out && - grep "error in tag $tag.*unterminated header: NUL at offset" out + test_i18ngrep "error in tag $tag.*unterminated header: NUL at offset" out ' test_expect_success 'cleaned up' ' @@ -396,7 +431,7 @@ test_expect_success 'fsck notices blob entry pointing to null sha1' ' git hash-object -w --stdin -t tree) && git fsck 2>out && cat out && - grep "warning.*null sha1" out + test_i18ngrep "warning.*null sha1" out ) ' @@ -407,7 +442,7 @@ test_expect_success 'fsck notices submodule entry pointing to null sha1' ' git hash-object -w --stdin -t tree) && git fsck 2>out && cat out && - grep "warning.*null sha1" out + test_i18ngrep "warning.*null sha1" out ) ' @@ -428,7 +463,7 @@ while read name path pretty; do bad_tree=$(git mktree <bad) && git fsck 2>out && cat out && - grep "warning.*tree $bad_tree" out + test_i18ngrep "warning.*tree $bad_tree" out )' done <<-\EOF 100644 blob @@ -474,9 +509,9 @@ test_expect_success 'NUL in commit' ' git branch bad $(cat name) && test_must_fail git -c fsck.nulInCommit=error fsck 2>warn.1 && - grep nulInCommit warn.1 && + test_i18ngrep nulInCommit warn.1 && git fsck 2>warn.2 && - grep nulInCommit warn.2 + test_i18ngrep nulInCommit warn.2 ) ' @@ -594,7 +629,7 @@ test_expect_success 'fsck --name-objects' ' remove_object $(git rev-parse julius:caesar.t) && test_must_fail git fsck --name-objects >out && tree=$(git rev-parse --verify julius:) && - egrep "$tree \((refs/heads/master|HEAD)@\{[0-9]*\}:" out + test_i18ngrep -E "$tree \((refs/heads/master|HEAD)@\{[0-9]*\}:" out ) ' @@ -605,7 +640,7 @@ test_expect_success 'alternate objects are correctly blamed' ' mkdir alt.git/objects/12 && >alt.git/objects/12/34567890123456789012345678901234567890 && test_must_fail git fsck >out 2>&1 && - grep alt.git out + test_i18ngrep alt.git out ' test_expect_success 'fsck errors in packed objects' ' @@ -624,8 +659,8 @@ test_expect_success 'fsck errors in packed objects' ' remove_object $one && remove_object $two && test_must_fail git fsck 2>out && - grep "error in commit $one.* - bad name" out && - grep "error in commit $two.* - bad name" out && + test_i18ngrep "error in commit $one.* - bad name" out && + test_i18ngrep "error in commit $two.* - bad name" out && ! grep corrupt out ' @@ -673,16 +708,35 @@ test_expect_success 'fsck detects trailing loose garbage (commit)' ' test_i18ngrep "garbage.*$commit" out ' -test_expect_success 'fsck detects trailing loose garbage (blob)' ' +test_expect_success 'fsck detects trailing loose garbage (large blob)' ' blob=$(echo trailing | git hash-object -w --stdin) && file=$(sha1_file $blob) && test_when_finished "remove_object $blob" && chmod +w "$file" && echo garbage >>"$file" && - test_must_fail git fsck 2>out && + test_must_fail git -c core.bigfilethreshold=5 fsck 2>out && test_i18ngrep "garbage.*$blob" out ' +test_expect_success 'fsck detects truncated loose object' ' + # make it big enough that we know we will truncate in the data + # portion, not the header + test-tool genrandom truncate 4096 >file && + blob=$(git hash-object -w file) && + file=$(sha1_file $blob) && + test_when_finished "remove_object $blob" && + test_copy_bytes 1024 <"$file" >tmp && + rm "$file" && + mv -f tmp "$file" && + + # check both regular and streaming code paths + test_must_fail git fsck 2>out && + test_i18ngrep corrupt.*$blob out && + + test_must_fail git -c core.bigfilethreshold=128 fsck 2>out && + test_i18ngrep corrupt.*$blob out +' + # for each of type, we have one version which is referenced by another object # (and so while unreachable, not dangling), and another variant which really is # dangling. @@ -706,7 +760,7 @@ test_expect_success 'fsck notices dangling objects' ' git fsck >actual && # the output order is non-deterministic, as it comes from a hash sort <actual >actual.sorted && - test_cmp expect actual.sorted + test_i18ncmp expect actual.sorted ) ' @@ -754,7 +808,7 @@ test_expect_success 'detect corrupt index file in fsck' ' test_when_finished "mv .git/index.backup .git/index" && corrupt_index_checksum && test_must_fail git fsck --cache 2>errors && - grep "bad index file" errors + test_i18ngrep "bad index file" errors ' test_done diff --git a/t/t1700-split-index.sh b/t/t1700-split-index.sh index 2ac47aa0e4..4667e1a190 100755 --- a/t/t1700-split-index.sh +++ b/t/t1700-split-index.sh @@ -25,14 +25,17 @@ test_expect_success 'enable split index' ' git update-index --split-index && test-tool dump-split-index .git/index >actual && indexversion=$(test-tool index-version <.git/index) && + + # NEEDSWORK: Stop hard-coding checksums. if test "$indexversion" = "4" then - own=3527df833c6c100d3d1d921a9a782d62a8be4b58 - base=746f7ab2ed44fb839efdfbffcf399d0b113fb4cb + own=432ef4b63f32193984f339431fd50ca796493569 + base=508851a7f0dfa8691e9f69c7f055865389012491 else - own=5e9b60117ece18da410ddecc8b8d43766a0e4204 - base=4370042739b31cd17a5c5cd6043a77c9a00df113 + own=8299b0bcd1ac364e5f1d7768efb62fa2da79a339 + base=39d890139ee5356c7ef572216cebcd27aa41f9df fi && + cat >expect <<-EOF && own $own base $base @@ -381,6 +384,26 @@ test_expect_success 'check splitIndex.sharedIndexExpire set to "never" and "now" test $(ls .git/sharedindex.* | wc -l) -le 2 ' +test_expect_success POSIXPERM 'same mode for index & split index' ' + git init same-mode && + ( + cd same-mode && + test_commit A && + test_modebits .git/index >index_mode && + test_must_fail git config core.sharedRepository && + git -c core.splitIndex=true status && + shared=$(ls .git/sharedindex.*) && + case "$shared" in + *" "*) + # we have more than one??? + false ;; + *) + test_modebits "$shared" >split_index_mode && + test_cmp index_mode split_index_mode ;; + esac + ) +' + while read -r mode modebits do test_expect_success POSIXPERM "split index respects core.sharedrepository $mode" ' diff --git a/t/t2000-checkout-cache-clash.sh b/t/t2000-checkout-cache-clash.sh deleted file mode 100755 index de3edb5d57..0000000000 --- a/t/t2000-checkout-cache-clash.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2005 Junio C Hamano -# - -test_description='git checkout-index test. - -This test registers the following filesystem structure in the -cache: - - path0 - a file - path1/file1 - a file in a directory - -And then tries to checkout in a work tree that has the following: - - path0/file0 - a file in a directory - path1 - a file - -The git checkout-index command should fail when attempting to checkout -path0, finding it is occupied by a directory, and path1/file1, finding -path1 is occupied by a non-directory. With "-f" flag, it should remove -the conflicting paths and succeed. -' -. ./test-lib.sh - -date >path0 -mkdir path1 -date >path1/file1 - -test_expect_success \ - 'git update-index --add various paths.' \ - 'git update-index --add path0 path1/file1' - -rm -fr path0 path1 -mkdir path0 -date >path0/file0 -date >path1 - -test_expect_success \ - 'git checkout-index without -f should fail on conflicting work tree.' \ - 'test_must_fail git checkout-index -a' - -test_expect_success \ - 'git checkout-index with -f should succeed.' \ - 'git checkout-index -f -a' - -test_expect_success \ - 'git checkout-index conflicting paths.' \ - 'test -f path0 && test -d path1 && test -f path1/file1' - -test_expect_success SYMLINKS 'checkout-index -f twice with --prefix' ' - mkdir -p tar/get && - ln -s tar/get there && - echo first && - git checkout-index -a -f --prefix=there/ && - echo second && - git checkout-index -a -f --prefix=there/ -' - -test_done diff --git a/t/t2000-conflict-when-checking-files-out.sh b/t/t2000-conflict-when-checking-files-out.sh new file mode 100755 index 0000000000..f18616ad2b --- /dev/null +++ b/t/t2000-conflict-when-checking-files-out.sh @@ -0,0 +1,135 @@ +#!/bin/sh +# +# Copyright (c) 2005 Junio C Hamano +# + +test_description='git conflicts when checking files out test.' + +# The first test registers the following filesystem structure in the +# cache: +# +# path0 - a file +# path1/file1 - a file in a directory +# +# And then tries to checkout in a work tree that has the following: +# +# path0/file0 - a file in a directory +# path1 - a file +# +# The git checkout-index command should fail when attempting to checkout +# path0, finding it is occupied by a directory, and path1/file1, finding +# path1 is occupied by a non-directory. With "-f" flag, it should remove +# the conflicting paths and succeed. + +. ./test-lib.sh + +show_files() { + # show filesystem files, just [-dl] for type and name + find path? -ls | + sed -e 's/^[0-9]* * [0-9]* * \([-bcdl]\)[^ ]* *[0-9]* *[^ ]* *[^ ]* *[0-9]* [A-Z][a-z][a-z] [0-9][0-9] [^ ]* /fs: \1 /' + # what's in the cache, just mode and name + git ls-files --stage | + sed -e 's/^\([0-9]*\) [0-9a-f]* [0-3] /ca: \1 /' + # what's in the tree, just mode and name. + git ls-tree -r "$1" | + sed -e 's/^\([0-9]*\) [^ ]* [0-9a-f]* /tr: \1 /' +} + +date >path0 +mkdir path1 +date >path1/file1 + +test_expect_success \ + 'git update-index --add various paths.' \ + 'git update-index --add path0 path1/file1' + +rm -fr path0 path1 +mkdir path0 +date >path0/file0 +date >path1 + +test_expect_success \ + 'git checkout-index without -f should fail on conflicting work tree.' \ + 'test_must_fail git checkout-index -a' + +test_expect_success \ + 'git checkout-index with -f should succeed.' \ + 'git checkout-index -f -a' + +test_expect_success \ + 'git checkout-index conflicting paths.' \ + 'test -f path0 && test -d path1 && test -f path1/file1' + +test_expect_success SYMLINKS 'checkout-index -f twice with --prefix' ' + mkdir -p tar/get && + ln -s tar/get there && + echo first && + git checkout-index -a -f --prefix=there/ && + echo second && + git checkout-index -a -f --prefix=there/ +' + +# The second test registers the following filesystem structure in the cache: +# +# path2/file0 - a file in a directory +# path3/file1 - a file in a directory +# +# and attempts to check it out when the work tree has: +# +# path2/file0 - a file in a directory +# path3 - a symlink pointing at "path2" +# +# Checkout cache should fail to extract path3/file1 because the leading +# path path3 is occupied by a non-directory. With "-f" it should remove +# the symlink path3 and create directory path3 and file path3/file1. + +mkdir path2 +date >path2/file0 +test_expect_success \ + 'git update-index --add path2/file0' \ + 'git update-index --add path2/file0' +test_expect_success \ + 'writing tree out with git write-tree' \ + 'tree1=$(git write-tree)' +test_debug 'show_files $tree1' + +mkdir path3 +date >path3/file1 +test_expect_success \ + 'git update-index --add path3/file1' \ + 'git update-index --add path3/file1' +test_expect_success \ + 'writing tree out with git write-tree' \ + 'tree2=$(git write-tree)' +test_debug 'show_files $tree2' + +rm -fr path3 +test_expect_success \ + 'read previously written tree and checkout.' \ + 'git read-tree -m $tree1 && git checkout-index -f -a' +test_debug 'show_files $tree1' + +test_expect_success \ + 'add a symlink' \ + 'test_ln_s_add path2 path3' +test_expect_success \ + 'writing tree out with git write-tree' \ + 'tree3=$(git write-tree)' +test_debug 'show_files $tree3' + +# Morten says "Got that?" here. +# Test begins. + +test_expect_success \ + 'read previously written tree and checkout.' \ + 'git read-tree $tree2 && git checkout-index -f -a' +test_debug 'show_files $tree2' + +test_expect_success \ + 'checking out conflicting path with -f' \ + 'test ! -h path2 && test -d path2 && + test ! -h path3 && test -d path3 && + test ! -h path2/file0 && test -f path2/file0 && + test ! -h path3/file1 && test -f path3/file1' + +test_done diff --git a/t/t2001-checkout-cache-clash.sh b/t/t2001-checkout-cache-clash.sh deleted file mode 100755 index 1fc8e634b7..0000000000 --- a/t/t2001-checkout-cache-clash.sh +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2005 Junio C Hamano -# - -test_description='git checkout-index test. - -This test registers the following filesystem structure in the cache: - - path0/file0 - a file in a directory - path1/file1 - a file in a directory - -and attempts to check it out when the work tree has: - - path0/file0 - a file in a directory - path1 - a symlink pointing at "path0" - -Checkout cache should fail to extract path1/file1 because the leading -path path1 is occupied by a non-directory. With "-f" it should remove -the symlink path1 and create directory path1 and file path1/file1. -' -. ./test-lib.sh - -show_files() { - # show filesystem files, just [-dl] for type and name - find path? -ls | - sed -e 's/^[0-9]* * [0-9]* * \([-bcdl]\)[^ ]* *[0-9]* *[^ ]* *[^ ]* *[0-9]* [A-Z][a-z][a-z] [0-9][0-9] [^ ]* /fs: \1 /' - # what's in the cache, just mode and name - git ls-files --stage | - sed -e 's/^\([0-9]*\) [0-9a-f]* [0-3] /ca: \1 /' - # what's in the tree, just mode and name. - git ls-tree -r "$1" | - sed -e 's/^\([0-9]*\) [^ ]* [0-9a-f]* /tr: \1 /' -} - -mkdir path0 -date >path0/file0 -test_expect_success \ - 'git update-index --add path0/file0' \ - 'git update-index --add path0/file0' -test_expect_success \ - 'writing tree out with git write-tree' \ - 'tree1=$(git write-tree)' -test_debug 'show_files $tree1' - -mkdir path1 -date >path1/file1 -test_expect_success \ - 'git update-index --add path1/file1' \ - 'git update-index --add path1/file1' -test_expect_success \ - 'writing tree out with git write-tree' \ - 'tree2=$(git write-tree)' -test_debug 'show_files $tree2' - -rm -fr path1 -test_expect_success \ - 'read previously written tree and checkout.' \ - 'git read-tree -m $tree1 && git checkout-index -f -a' -test_debug 'show_files $tree1' - -test_expect_success \ - 'add a symlink' \ - 'test_ln_s_add path0 path1' -test_expect_success \ - 'writing tree out with git write-tree' \ - 'tree3=$(git write-tree)' -test_debug 'show_files $tree3' - -# Morten says "Got that?" here. -# Test begins. - -test_expect_success \ - 'read previously written tree and checkout.' \ - 'git read-tree $tree2 && git checkout-index -f -a' -test_debug 'show_files $tree2' - -test_expect_success \ - 'checking out conflicting path with -f' \ - 'test ! -h path0 && test -d path0 && - test ! -h path1 && test -d path1 && - test ! -h path0/file0 && test -f path0/file0 && - test ! -h path1/file1 && test -f path1/file1' - -test_done diff --git a/t/t2024-checkout-dwim.sh b/t/t2024-checkout-dwim.sh index 69b6774d10..fa0718c730 100755 --- a/t/t2024-checkout-dwim.sh +++ b/t/t2024-checkout-dwim.sh @@ -278,4 +278,35 @@ test_expect_success 'loosely defined local base branch is reported correctly' ' test_cmp expect actual ' +test_expect_success 'reject when arg could be part of dwim branch' ' + git remote add foo file://non-existent-place && + git update-ref refs/remotes/foo/dwim-arg HEAD && + echo foo >dwim-arg && + git add dwim-arg && + echo bar >dwim-arg && + test_must_fail git checkout dwim-arg && + test_must_fail git rev-parse refs/heads/dwim-arg -- && + grep bar dwim-arg +' + +test_expect_success 'disambiguate dwim branch and checkout path (1)' ' + git update-ref refs/remotes/foo/dwim-arg1 HEAD && + echo foo >dwim-arg1 && + git add dwim-arg1 && + echo bar >dwim-arg1 && + git checkout -- dwim-arg1 && + test_must_fail git rev-parse refs/heads/dwim-arg1 -- && + grep foo dwim-arg1 +' + +test_expect_success 'disambiguate dwim branch and checkout path (2)' ' + git update-ref refs/remotes/foo/dwim-arg2 HEAD && + echo foo >dwim-arg2 && + git add dwim-arg2 && + echo bar >dwim-arg2 && + git checkout dwim-arg2 -- && + git rev-parse refs/heads/dwim-arg2 -- && + grep bar dwim-arg2 +' + test_done diff --git a/t/t2029-worktree-config.sh b/t/t2029-worktree-config.sh new file mode 100755 index 0000000000..286121d8de --- /dev/null +++ b/t/t2029-worktree-config.sh @@ -0,0 +1,79 @@ +#!/bin/sh + +test_description="config file in multi worktree" + +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit start +' + +test_expect_success 'config --worktree in single worktree' ' + git config --worktree foo.bar true && + test_cmp_config true foo.bar +' + +test_expect_success 'add worktrees' ' + git worktree add wt1 && + git worktree add wt2 +' + +test_expect_success 'config --worktree without extension' ' + test_must_fail git config --worktree foo.bar false +' + +test_expect_success 'enable worktreeConfig extension' ' + git config extensions.worktreeConfig true && + test_cmp_config true extensions.worktreeConfig +' + +test_expect_success 'config is shared as before' ' + git config this.is shared && + test_cmp_config shared this.is && + test_cmp_config -C wt1 shared this.is && + test_cmp_config -C wt2 shared this.is +' + +test_expect_success 'config is shared (set from another worktree)' ' + git -C wt1 config that.is also-shared && + test_cmp_config also-shared that.is && + test_cmp_config -C wt1 also-shared that.is && + test_cmp_config -C wt2 also-shared that.is +' + +test_expect_success 'config private to main worktree' ' + git config --worktree this.is for-main && + test_cmp_config for-main this.is && + test_cmp_config -C wt1 shared this.is && + test_cmp_config -C wt2 shared this.is +' + +test_expect_success 'config private to linked worktree' ' + git -C wt1 config --worktree this.is for-wt1 && + test_cmp_config for-main this.is && + test_cmp_config -C wt1 for-wt1 this.is && + test_cmp_config -C wt2 shared this.is +' + +test_expect_success 'core.bare no longer for main only' ' + test_config core.bare true && + test "$(git rev-parse --is-bare-repository)" = true && + test "$(git -C wt1 rev-parse --is-bare-repository)" = true && + test "$(git -C wt2 rev-parse --is-bare-repository)" = true +' + +test_expect_success 'per-worktree core.bare is picked up' ' + git -C wt1 config --worktree core.bare true && + test "$(git rev-parse --is-bare-repository)" = false && + test "$(git -C wt1 rev-parse --is-bare-repository)" = true && + test "$(git -C wt2 rev-parse --is-bare-repository)" = false +' + +test_expect_success 'config.worktree no longer read without extension' ' + git config --unset extensions.worktreeConfig && + test_cmp_config shared this.is && + test_cmp_config -C wt1 shared this.is && + test_cmp_config -C wt2 shared this.is +' + +test_done diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh index 46aca0af10..891d4d7cb9 100755 --- a/t/t3070-wildmatch.sh +++ b/t/t3070-wildmatch.sh @@ -237,7 +237,7 @@ match 0 0 0 0 foobar 'foo\*bar' match 1 1 1 1 'f\oo' 'f\\oo' match 1 1 1 1 ball '*[al]?' match 0 0 0 0 ten '[ten]' -match 0 0 1 1 ten '**[!te]' +match 1 1 1 1 ten '**[!te]' match 0 0 0 0 ten '**[!ten]' match 1 1 1 1 ten 't[a-g]n' match 0 0 0 0 ten 't[!a-g]n' @@ -253,7 +253,7 @@ match 1 1 1 1 ']' ']' # Extended slash-matching features match 0 0 1 1 'foo/baz/bar' 'foo*bar' match 0 0 1 1 'foo/baz/bar' 'foo**bar' -match 0 0 1 1 'foobazbar' 'foo**bar' +match 1 1 1 1 'foobazbar' 'foo**bar' match 1 1 1 1 'foo/baz/bar' 'foo/**/bar' match 1 1 0 0 'foo/baz/bar' 'foo/**/**/bar' match 1 1 1 1 'foo/b/a/z/bar' 'foo/**/bar' diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh index 045aca1c18..048feaf6dd 100755 --- a/t/t3206-range-diff.sh +++ b/t/t3206-range-diff.sh @@ -122,6 +122,65 @@ test_expect_success 'changed commit' ' test_cmp expected actual ' +test_expect_success 'changed commit with --no-patch diff option' ' + git range-diff --no-color --no-patch topic...changed >actual && + cat >expected <<-EOF && + 1: 4de457d = 1: a4b3333 s/5/A/ + 2: fccce22 = 2: f51d370 s/4/A/ + 3: 147e64e ! 3: 0559556 s/11/B/ + 4: a63e992 ! 4: d966c5c s/12/B/ + EOF + test_cmp expected actual +' + +test_expect_success 'changed commit with --stat diff option' ' + git range-diff --no-color --stat topic...changed >actual && + cat >expected <<-EOF && + 1: 4de457d = 1: a4b3333 s/5/A/ + a => b | 0 + 1 file changed, 0 insertions(+), 0 deletions(-) + 2: fccce22 = 2: f51d370 s/4/A/ + a => b | 0 + 1 file changed, 0 insertions(+), 0 deletions(-) + 3: 147e64e ! 3: 0559556 s/11/B/ + a => b | 0 + 1 file changed, 0 insertions(+), 0 deletions(-) + 4: a63e992 ! 4: d966c5c s/12/B/ + a => b | 0 + 1 file changed, 0 insertions(+), 0 deletions(-) + EOF + test_cmp expected actual +' + +test_expect_success 'changed commit with sm config' ' + git range-diff --no-color --submodule=log topic...changed >actual && + cat >expected <<-EOF && + 1: 4de457d = 1: a4b3333 s/5/A/ + 2: fccce22 = 2: f51d370 s/4/A/ + 3: 147e64e ! 3: 0559556 s/11/B/ + @@ -10,7 +10,7 @@ + 9 + 10 + -11 + -+B + ++BB + 12 + 13 + 14 + 4: a63e992 ! 4: d966c5c s/12/B/ + @@ -8,7 +8,7 @@ + @@ + 9 + 10 + - B + + BB + -12 + +B + 13 + EOF + test_cmp expected actual +' + test_expect_success 'no commits on one side' ' git commit --amend -m "new message" && git range-diff master HEAD@{1} HEAD @@ -189,18 +248,24 @@ test_expect_success 'dual-coloring' ' for prev in topic master..topic do test_expect_success "format-patch --range-diff=$prev" ' - git format-patch --stdout --cover-letter --range-diff=$prev \ + git format-patch --cover-letter --range-diff=$prev \ master..unmodified >actual && - grep "= 1: .* s/5/A" actual && - grep "= 2: .* s/4/A" actual && - grep "= 3: .* s/11/B" actual && - grep "= 4: .* s/12/B" actual + test_when_finished "rm 000?-*" && + test_line_count = 5 actual && + test_i18ngrep "^Range-diff:$" 0000-* && + grep "= 1: .* s/5/A" 0000-* && + grep "= 2: .* s/4/A" 0000-* && + grep "= 3: .* s/11/B" 0000-* && + grep "= 4: .* s/12/B" 0000-* ' done test_expect_success 'format-patch --range-diff as commentary' ' - git format-patch --stdout --range-diff=HEAD~1 HEAD~1 >actual && - test_i18ngrep "^Range-diff:$" actual + git format-patch --range-diff=HEAD~1 HEAD~1 >actual && + test_when_finished "rm 0001-*" && + test_line_count = 1 actual && + test_i18ngrep "^Range-diff:$" 0001-* && + grep "> 1: .* new message" 0001-* ' test_done diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index ff89b6341a..7a440e08d8 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -75,6 +75,16 @@ test_expect_success 'rebase --keep-empty' ' test_line_count = 6 actual ' +cat > expect <<EOF +error: nothing to do +EOF + +test_expect_success 'rebase -i with empty HEAD' ' + set_fake_editor && + test_must_fail env FAKE_LINES="1 exec_true" git rebase -i HEAD^ >actual 2>&1 && + test_i18ncmp expect actual +' + test_expect_success 'rebase -i with the exec command' ' git checkout master && ( @@ -114,7 +124,7 @@ test_expect_success 'rebase -i with exec allows git commands in subdirs' ' git checkout master && mkdir subdir && (cd subdir && set_fake_editor && - FAKE_LINES="1 exec_cd_subdir_&&_git_rev-parse_--is-inside-work-tree" \ + FAKE_LINES="1 x_cd_subdir_&&_git_rev-parse_--is-inside-work-tree" \ git rebase -i HEAD^ ) ' @@ -312,7 +322,7 @@ test_expect_success 'retain authorship when squashing' ' git show HEAD | grep "^Author: Twerp Snog" ' -test_expect_success '-p handles "no changes" gracefully' ' +test_expect_success REBASE_P '-p handles "no changes" gracefully' ' HEAD=$(git rev-parse HEAD) && set_fake_editor && git rebase -i -p HEAD^ && @@ -322,7 +332,7 @@ test_expect_success '-p handles "no changes" gracefully' ' test $HEAD = $(git rev-parse HEAD) ' -test_expect_failure 'exchange two commits with -p' ' +test_expect_failure REBASE_P 'exchange two commits with -p' ' git checkout H && set_fake_editor && FAKE_LINES="2 1" git rebase -i -p HEAD~2 && @@ -330,7 +340,7 @@ test_expect_failure 'exchange two commits with -p' ' test G = $(git cat-file commit HEAD | sed -ne \$p) ' -test_expect_success 'preserve merges with -p' ' +test_expect_success REBASE_P 'preserve merges with -p' ' git checkout -b to-be-preserved master^ && : > unrelated-file && git add unrelated-file && @@ -373,7 +383,7 @@ test_expect_success 'preserve merges with -p' ' test $(git show HEAD:unrelated-file) = 1 ' -test_expect_success 'edit ancestor with -p' ' +test_expect_success REBASE_P 'edit ancestor with -p' ' set_fake_editor && FAKE_LINES="1 2 edit 3 4" git rebase -i -p HEAD~3 && echo 2 > unrelated-file && @@ -387,6 +397,7 @@ test_expect_success 'edit ancestor with -p' ' ' test_expect_success '--continue tries to commit' ' + git reset --hard D && test_tick && set_fake_editor && test_must_fail git rebase -i --onto new-branch1 HEAD^ && @@ -426,7 +437,7 @@ test_expect_success C_LOCALE_OUTPUT 'multi-fixup does not fire up editor' ' git rebase -i $base && test $base = $(git rev-parse HEAD^) && test 0 = $(git show | grep NEVER | wc -l) && - git checkout to-be-rebased && + git checkout @{-1} && git branch -D multi-fixup ' @@ -441,7 +452,7 @@ test_expect_success 'commit message used after conflict' ' git rebase --continue && test $base = $(git rev-parse HEAD^) && test 1 = $(git show | grep ONCE | wc -l) && - git checkout to-be-rebased && + git checkout @{-1} && git branch -D conflict-fixup ' @@ -456,7 +467,7 @@ test_expect_success 'commit message retained after conflict' ' git rebase --continue && test $base = $(git rev-parse HEAD^) && test 2 = $(git show | grep TWICE | wc -l) && - git checkout to-be-rebased && + git checkout @{-1} && git branch -D conflict-squash ' @@ -481,7 +492,7 @@ test_expect_success C_LOCALE_OUTPUT 'squash and fixup generate correct log messa grep "^# This is a combination of 3 commits\." && git cat-file commit HEAD@{3} | grep "^# This is a combination of 2 commits\." && - git checkout to-be-rebased && + git checkout @{-1} && git branch -D squash-fixup ' @@ -494,7 +505,7 @@ test_expect_success C_LOCALE_OUTPUT 'squash ignores comments' ' git rebase -i $base && test $base = $(git rev-parse HEAD^) && test 1 = $(git show | grep ONCE | wc -l) && - git checkout to-be-rebased && + git checkout @{-1} && git branch -D skip-comments ' @@ -507,7 +518,7 @@ test_expect_success C_LOCALE_OUTPUT 'squash ignores blank lines' ' git rebase -i $base && test $base = $(git rev-parse HEAD^) && test 1 = $(git show | grep ONCE | wc -l) && - git checkout to-be-rebased && + git checkout @{-1} && git branch -D skip-blank-lines ' @@ -515,7 +526,7 @@ test_expect_success 'squash works as expected' ' git checkout -b squash-works no-conflict-branch && one=$(git rev-parse HEAD~3) && set_fake_editor && - FAKE_LINES="1 squash 3 2" EXPECT_HEADER_COUNT=2 \ + FAKE_LINES="1 s 3 2" EXPECT_HEADER_COUNT=2 \ git rebase -i HEAD~3 && test $one = $(git rev-parse HEAD~2) ' @@ -648,7 +659,7 @@ test_expect_success 'rebase with a file named HEAD in worktree' ' ) && set_fake_editor && - FAKE_LINES="1 squash 2" git rebase -i to-be-rebased && + FAKE_LINES="1 squash 2" git rebase -i @{-1} && test "$(git show -s --pretty=format:%an)" = "Squashed Away" ' @@ -748,7 +759,7 @@ test_expect_success 'reword' ' git show HEAD^ | grep "D changed" && FAKE_LINES="reword 1 2 3 4" FAKE_COMMIT_MESSAGE="B changed" git rebase -i A && git show HEAD~3 | grep "B changed" && - FAKE_LINES="1 reword 2 3 4" FAKE_COMMIT_MESSAGE="C changed" git rebase -i A && + FAKE_LINES="1 r 2 pick 3 p 4" FAKE_COMMIT_MESSAGE="C changed" git rebase -i A && git show HEAD~2 | grep "C changed" ' @@ -774,7 +785,7 @@ test_expect_success 'rebase -i can copy notes over a fixup' ' git reset --hard n3 && git notes add -m"an earlier note" n2 && set_fake_editor && - GIT_NOTES_REWRITE_MODE=concatenate FAKE_LINES="1 fixup 2" git rebase -i n1 && + GIT_NOTES_REWRITE_MODE=concatenate FAKE_LINES="1 f 2" git rebase -i n1 && git notes show > output && test_cmp expect output ' @@ -1251,7 +1262,7 @@ rebase_setup_and_clean () { test_expect_success 'drop' ' rebase_setup_and_clean drop-test && set_fake_editor && - FAKE_LINES="1 drop 2 3 drop 4 5" git rebase -i --root && + FAKE_LINES="1 drop 2 3 d 4 5" git rebase -i --root && test E = $(git cat-file commit HEAD | sed -ne \$p) && test C = $(git cat-file commit HEAD^ | sed -ne \$p) && test A = $(git cat-file commit HEAD^^ | sed -ne \$p) diff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh index 0392e36d23..f64b130cb8 100755 --- a/t/t3406-rebase-message.sh +++ b/t/t3406-rebase-message.sh @@ -77,11 +77,54 @@ test_expect_success 'rebase -n overrides config rebase.stat config' ' # "Does not point to a valid commit: invalid-ref" # # NEEDSWORK: This "grep" is fine in real non-C locales, but -# GETTEXT_POISON poisons the refname along with the enclosing +# GIT_TEST_GETTEXT_POISON poisons the refname along with the enclosing # error message. test_expect_success 'rebase --onto outputs the invalid ref' ' test_must_fail git rebase --onto invalid-ref HEAD HEAD 2>err && test_i18ngrep "invalid-ref" err ' +test_expect_success 'error out early upon -C<n> or --whitespace=<bad>' ' + test_must_fail git rebase -Cnot-a-number HEAD 2>err && + test_i18ngrep "numerical value" err && + test_must_fail git rebase --whitespace=bad HEAD 2>err && + test_i18ngrep "Invalid whitespace option" err +' + +test_expect_success 'GIT_REFLOG_ACTION' ' + git checkout start && + test_commit reflog-onto && + git checkout -b reflog-topic start && + test_commit reflog-to-rebase && + + git rebase reflog-onto && + git log -g --format=%gs -3 >actual && + cat >expect <<-\EOF && + rebase finished: returning to refs/heads/reflog-topic + rebase: reflog-to-rebase + rebase: checkout reflog-onto + EOF + test_cmp expect actual && + + git checkout -b reflog-prefix reflog-to-rebase && + GIT_REFLOG_ACTION=change-the-reflog git rebase reflog-onto && + git log -g --format=%gs -3 >actual && + cat >expect <<-\EOF && + rebase finished: returning to refs/heads/reflog-prefix + change-the-reflog: reflog-to-rebase + change-the-reflog: checkout reflog-onto + EOF + test_cmp expect actual +' + +test_expect_success 'rebase -i onto unrelated history' ' + git init unrelated && + test_commit -C unrelated 1 && + git -C unrelated remote add -f origin "$PWD" && + git -C unrelated branch --set-upstream-to=origin/master && + git -C unrelated -c core.editor=true rebase -i -v --stat >actual && + test_i18ngrep "Changes to " actual && + test_i18ngrep "5 files changed" actual +' + test_done diff --git a/t/t3408-rebase-multi-line.sh b/t/t3408-rebase-multi-line.sh index e7292f5b9b..d2bd7c17b0 100755 --- a/t/t3408-rebase-multi-line.sh +++ b/t/t3408-rebase-multi-line.sh @@ -52,7 +52,7 @@ test_expect_success rebase ' test_cmp expect actual ' -test_expect_success rebasep ' +test_expect_success REBASE_P rebasep ' git checkout side-merge && git rebase -p side && diff --git a/t/t3409-rebase-preserve-merges.sh b/t/t3409-rebase-preserve-merges.sh index 8c251c57a6..3b340f1ece 100755 --- a/t/t3409-rebase-preserve-merges.sh +++ b/t/t3409-rebase-preserve-merges.sh @@ -8,6 +8,11 @@ Run "git rebase -p" and check that merges are properly carried along ' . ./test-lib.sh +if ! test_have_prereq REBASE_P; then + skip_all='skipping git rebase -p tests, as asked for' + test_done +fi + GIT_AUTHOR_EMAIL=bogus_email_address export GIT_AUTHOR_EMAIL diff --git a/t/t3410-rebase-preserve-dropped-merges.sh b/t/t3410-rebase-preserve-dropped-merges.sh index 6f73b95558..2e29866993 100755 --- a/t/t3410-rebase-preserve-dropped-merges.sh +++ b/t/t3410-rebase-preserve-dropped-merges.sh @@ -11,6 +11,11 @@ rewritten. ' . ./test-lib.sh +if ! test_have_prereq REBASE_P; then + skip_all='skipping git rebase -p tests, as asked for' + test_done +fi + # set up two branches like this: # # A - B - C - D - E diff --git a/t/t3411-rebase-preserve-around-merges.sh b/t/t3411-rebase-preserve-around-merges.sh index dc81bf27eb..fb45e7bf7b 100755 --- a/t/t3411-rebase-preserve-around-merges.sh +++ b/t/t3411-rebase-preserve-around-merges.sh @@ -10,6 +10,11 @@ a merge to before the merge. ' . ./test-lib.sh +if ! test_have_prereq REBASE_P; then + skip_all='skipping git rebase -p tests, as asked for' + test_done +fi + . "$TEST_DIRECTORY"/lib-rebase.sh set_fake_editor diff --git a/t/t3412-rebase-root.sh b/t/t3412-rebase-root.sh index 73a39f2923..21632a984e 100755 --- a/t/t3412-rebase-root.sh +++ b/t/t3412-rebase-root.sh @@ -86,14 +86,14 @@ test_expect_success 'pre-rebase got correct input (4)' ' test "z$(cat .git/PRE-REBASE-INPUT)" = z--root,work4 ' -test_expect_success 'rebase -i -p with linear history' ' +test_expect_success REBASE_P 'rebase -i -p with linear history' ' git checkout -b work5 other && git rebase -i -p --root --onto master && git log --pretty=tformat:"%s" > rebased5 && test_cmp expect rebased5 ' -test_expect_success 'pre-rebase got correct input (5)' ' +test_expect_success REBASE_P 'pre-rebase got correct input (5)' ' test "z$(cat .git/PRE-REBASE-INPUT)" = z--root, ' @@ -120,7 +120,7 @@ commit work6~4 1 EOF -test_expect_success 'rebase -i -p with merge' ' +test_expect_success REBASE_P 'rebase -i -p with merge' ' git checkout -b work6 other && git rebase -i -p --root --onto master && log_with_names work6 > rebased6 && @@ -155,7 +155,7 @@ commit work7~5 1 EOF -test_expect_success 'rebase -i -p with two roots' ' +test_expect_success REBASE_P 'rebase -i -p with two roots' ' git checkout -b work7 other && git rebase -i -p --root --onto master && log_with_names work7 > rebased7 && @@ -261,7 +261,7 @@ commit conflict3~6 1 EOF -test_expect_success 'rebase -i -p --root with conflict (first part)' ' +test_expect_success REBASE_P 'rebase -i -p --root with conflict (first part)' ' git checkout -b conflict3 other && test_must_fail git rebase -i -p --root --onto master && git ls-files -u | grep "B$" @@ -272,7 +272,7 @@ test_expect_success 'fix the conflict' ' git add B ' -test_expect_success 'rebase -i -p --root with conflict (second part)' ' +test_expect_success REBASE_P 'rebase -i -p --root with conflict (second part)' ' git rebase --continue && log_with_names conflict3 >out && test_cmp expect-conflict-p out diff --git a/t/t3414-rebase-preserve-onto.sh b/t/t3414-rebase-preserve-onto.sh index ee0a6cccfd..72e04b5386 100755 --- a/t/t3414-rebase-preserve-onto.sh +++ b/t/t3414-rebase-preserve-onto.sh @@ -10,6 +10,11 @@ aren'"'"'t on top of $ONTO, even if they are on top of $UPSTREAM. ' . ./test-lib.sh +if ! test_have_prereq REBASE_P; then + skip_all='skipping git rebase -p tests, as asked for' + test_done +fi + . "$TEST_DIRECTORY"/lib-rebase.sh # Set up branches like this: diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh index 25099d715c..0210b2ac6f 100755 --- a/t/t3418-rebase-continue.sh +++ b/t/t3418-rebase-continue.sh @@ -106,7 +106,7 @@ test_expect_success 'rebase -i --continue handles merge strategy and options' ' test -f funny.was.run ' -test_expect_success 'rebase passes merge strategy options correctly' ' +test_expect_success REBASE_P 'rebase passes merge strategy options correctly' ' rm -fr .git/rebase-* && git reset --hard commit-new-file-F3-on-topic-branch && test_commit theirs-to-merge && @@ -177,6 +177,7 @@ test_expect_success 'setup rerere database' ' git checkout master && test_commit "commit-new-file-F3" F3 3 && test_config rerere.enabled true && + git update-ref refs/heads/topic commit-new-file-F3-on-topic-branch && test_must_fail git rebase -m master topic && echo "Resolved" >F2 && cp F2 expected-F2 && @@ -240,6 +241,17 @@ test_rerere_autoupdate test_rerere_autoupdate -m GIT_SEQUENCE_EDITOR=: && export GIT_SEQUENCE_EDITOR test_rerere_autoupdate -i -test_rerere_autoupdate --preserve-merges +test_have_prereq !REBASE_P || test_rerere_autoupdate --preserve-merges +unset GIT_SEQUENCE_EDITOR + +test_expect_success 'the todo command "break" works' ' + rm -f execed && + FAKE_LINES="break b exec_>execed" git rebase -i HEAD && + test_path_is_missing execed && + git rebase --continue && + test_path_is_missing execed && + git rebase --continue && + test_path_is_file execed +' test_done diff --git a/t/t3420-rebase-autostash.sh b/t/t3420-rebase-autostash.sh index 0c4eefec76..4c7494cc8f 100755 --- a/t/t3420-rebase-autostash.sh +++ b/t/t3420-rebase-autostash.sh @@ -351,4 +351,22 @@ test_expect_success 'autostash is saved on editor failure with conflict' ' test_cmp expected file0 ' +test_expect_success 'autostash with dirty submodules' ' + test_when_finished "git reset --hard && git checkout master" && + git checkout -b with-submodule && + git submodule add ./ sub && + test_tick && + git commit -m add-submodule && + echo changed >sub/file0 && + git rebase -i --autostash HEAD +' + +test_expect_success 'branch is left alone when possible' ' + git checkout -b unchanged-branch && + echo changed >file0 && + git rebase --autostash unchanged-branch && + test changed = "$(cat file0)" && + test unchanged-branch = "$(git rev-parse --abbrev-ref HEAD)" +' + test_done diff --git a/t/t3421-rebase-topology-linear.sh b/t/t3421-rebase-topology-linear.sh index 99b2aac921..23ad4cff35 100755 --- a/t/t3421-rebase-topology-linear.sh +++ b/t/t3421-rebase-topology-linear.sh @@ -29,7 +29,7 @@ test_run_rebase () { test_run_rebase success '' test_run_rebase success -m test_run_rebase success -i -test_run_rebase success -p +test_have_prereq !REBASE_P || test_run_rebase success -p test_run_rebase () { result=$1 @@ -43,7 +43,7 @@ test_run_rebase () { test_run_rebase success '' test_run_rebase success -m test_run_rebase success -i -test_run_rebase success -p +test_have_prereq !REBASE_P || test_run_rebase success -p test_run_rebase () { result=$1 @@ -59,7 +59,7 @@ test_run_rebase () { test_run_rebase success '' test_run_rebase success -m test_run_rebase success -i -test_run_rebase failure -p +test_have_prereq !REBASE_P || test_run_rebase failure -p test_run_rebase () { result=$1 @@ -73,7 +73,7 @@ test_run_rebase () { test_run_rebase success '' test_run_rebase success -m test_run_rebase success -i -test_run_rebase success -p +test_have_prereq !REBASE_P || test_run_rebase success -p # f # / @@ -113,7 +113,7 @@ test_run_rebase () { test_run_rebase success '' test_run_rebase failure -m test_run_rebase success -i -test_run_rebase success -p +test_have_prereq !REBASE_P || test_run_rebase success -p test_run_rebase () { result=$1 @@ -128,7 +128,7 @@ test_run_rebase () { test_run_rebase success '' test_run_rebase failure -m test_run_rebase success -i -test_run_rebase success -p +test_have_prereq !REBASE_P || test_run_rebase success -p test_run_rebase () { result=$1 @@ -143,7 +143,7 @@ test_run_rebase () { test_run_rebase success '' test_run_rebase failure -m test_run_rebase success -i -test_run_rebase success -p +test_have_prereq !REBASE_P || test_run_rebase success -p test_run_rebase () { result=$1 @@ -158,7 +158,7 @@ test_run_rebase () { test_run_rebase success '' test_run_rebase success -m test_run_rebase success -i -test_run_rebase success -p +test_have_prereq !REBASE_P || test_run_rebase success -p # a---b---c---j! # \ @@ -186,7 +186,7 @@ test_run_rebase () { test_run_rebase success '' test_run_rebase success -m test_run_rebase success -i -test_run_rebase success -p +test_have_prereq !REBASE_P || test_run_rebase success -p test_run_rebase () { result=$1 @@ -201,7 +201,7 @@ test_run_rebase () { test_run_rebase success '' test_run_rebase success -m test_run_rebase success -i -test_run_rebase failure -p +test_have_prereq !REBASE_P || test_run_rebase failure -p test_run_rebase () { result=$1 @@ -216,7 +216,7 @@ test_run_rebase () { test_run_rebase success '' test_run_rebase success -m test_run_rebase success -i -test_run_rebase failure -p +test_have_prereq !REBASE_P || test_run_rebase failure -p test_run_rebase success --rebase-merges # m @@ -256,7 +256,7 @@ test_run_rebase () { test_run_rebase success '' test_run_rebase success -m test_run_rebase success -i -test_run_rebase success -p +test_have_prereq !REBASE_P || test_run_rebase success -p test_run_rebase () { result=$1 @@ -271,7 +271,7 @@ test_run_rebase () { test_run_rebase success '' test_run_rebase success -m test_run_rebase success -i -test_run_rebase failure -p +test_have_prereq !REBASE_P || test_run_rebase failure -p test_run_rebase () { result=$1 @@ -286,7 +286,7 @@ test_run_rebase () { test_run_rebase success '' test_run_rebase failure -m test_run_rebase success -i -test_run_rebase success -p +test_have_prereq !REBASE_P || test_run_rebase success -p test_run_rebase () { result=$1 @@ -302,7 +302,7 @@ test_run_rebase () { test_run_rebase success '' test_run_rebase success -m test_run_rebase success -i -test_run_rebase failure -p +test_have_prereq !REBASE_P || test_run_rebase failure -p test_run_rebase () { result=$1 @@ -317,7 +317,7 @@ test_run_rebase () { test_run_rebase success '' test_run_rebase failure -m test_run_rebase success -i -test_run_rebase failure -p +test_have_prereq !REBASE_P || test_run_rebase failure -p test_run_rebase () { result=$1 @@ -331,7 +331,7 @@ test_run_rebase () { test_run_rebase success '' test_run_rebase success -m test_run_rebase success -i -test_run_rebase failure -p +test_have_prereq !REBASE_P || test_run_rebase failure -p test_run_rebase () { result=$1 @@ -346,6 +346,6 @@ test_run_rebase () { test_run_rebase success '' test_run_rebase success -m test_run_rebase success -i -test_run_rebase success -p +test_have_prereq !REBASE_P || test_run_rebase success -p test_done diff --git a/t/t3425-rebase-topology-merges.sh b/t/t3425-rebase-topology-merges.sh index 846f85c27e..5f892e33d7 100755 --- a/t/t3425-rebase-topology-merges.sh +++ b/t/t3425-rebase-topology-merges.sh @@ -109,6 +109,11 @@ test_run_rebase success 'd e n o' '' test_run_rebase success 'd e n o' -m test_run_rebase success 'd n o e' -i +if ! test_have_prereq REBASE_P; then + skip_all='skipping git rebase -p tests, as asked for' + test_done +fi + test_expect_success "rebase -p is no-op in non-linear history" " reset_rebase && git rebase -p d w && diff --git a/t/t3430-rebase-merges.sh b/t/t3430-rebase-merges.sh index aa7bfc88ec..cc5646836f 100755 --- a/t/t3430-rebase-merges.sh +++ b/t/t3430-rebase-merges.sh @@ -396,4 +396,20 @@ test_expect_success 'with --autosquash and --exec' ' grep "G: +G" actual ' +test_expect_success '--continue after resolving conflicts after a merge' ' + git checkout -b already-has-g E && + git cherry-pick E..G && + test_commit H2 && + + git checkout -b conflicts-in-merge H && + test_commit H2 H2.t conflicts H2-conflict && + test_must_fail git rebase -r already-has-g && + grep conflicts H2.t && + echo resolved >H2.t && + git add -u && + git rebase --continue && + test_must_fail git rev-parse --verify HEAD^2 && + test_path_is_missing .git/MERGE_HEAD +' + test_done diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh index cd216655b9..5f8272b6f9 100755 --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@ -1096,4 +1096,32 @@ test_expect_success 'stash -- <subdir> works with binary files' ' test_path_is_file subdir/untracked ' +test_expect_success 'stash works when user.name and user.email are not set' ' + git reset && + >1 && + git add 1 && + echo "$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" >expect && + git stash && + git show -s --format="%an <%ae>" refs/stash >actual && + test_cmp expect actual && + >2 && + git add 2 && + test_config user.useconfigonly true && + test_config stash.usebuiltin true && + ( + sane_unset GIT_AUTHOR_NAME && + sane_unset GIT_AUTHOR_EMAIL && + sane_unset GIT_COMMITTER_NAME && + sane_unset GIT_COMMITTER_EMAIL && + test_unconfig user.email && + test_unconfig user.name && + test_must_fail git commit -m "should fail" && + echo "git stash <git@stash>" >expect && + >2 && + git stash && + git show -s --format="%an <%ae>" refs/stash >actual && + test_cmp expect actual + ) +' + test_done diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index 73f7038253..7d985ff6b1 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -129,7 +129,7 @@ do case "$magic" in noellipses) ;; *) - die "bug in t4103: unknown magic $magic" ;; + BUG "unknown magic $magic" ;; esac ;; *) cmd="$magic $cmd" magic= diff --git a/t/t4052-stat-output.sh b/t/t4052-stat-output.sh index 6e2cf933f7..28c053849a 100755 --- a/t/t4052-stat-output.sh +++ b/t/t4052-stat-output.sh @@ -44,42 +44,50 @@ show --stat log -1 --stat EOF -while read cmd args +cat >expect.60 <<-'EOF' + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + +EOF +cat >expect.6030 <<-'EOF' + ...aaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + +EOF +cat >expect2.60 <<-'EOF' + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + + ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + +EOF +cat >expect2.6030 <<-'EOF' + ...aaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + + ...aaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + +EOF +while read expect cmd args do - cat >expect <<-'EOF' - ...aaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + - EOF test_expect_success "$cmd --stat=width: a long name is given more room when the bar is short" ' git $cmd $args --stat=40 >output && grep " | " output >actual && - test_cmp expect actual + test_cmp $expect.60 actual ' test_expect_success "$cmd --stat-width=width with long name" ' git $cmd $args --stat-width=40 >output && grep " | " output >actual && - test_cmp expect actual + test_cmp $expect.60 actual ' - cat >expect <<-'EOF' - ...aaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 + - EOF test_expect_success "$cmd --stat=...,name-width with long name" ' git $cmd $args --stat=60,30 >output && grep " | " output >actual && - test_cmp expect actual + test_cmp $expect.6030 actual ' test_expect_success "$cmd --stat-name-width with long name" ' git $cmd $args --stat-name-width=30 >output && grep " | " output >actual && - test_cmp expect actual + test_cmp $expect.6030 actual ' done <<\EOF -format-patch -1 --stdout -diff HEAD^ HEAD --stat -show --stat -log -1 --stat +expect2 format-patch --cover-letter -1 --stdout +expect diff HEAD^ HEAD --stat +expect show --stat +expect log -1 --stat EOF @@ -97,6 +105,16 @@ test_expect_success 'preparation for big change tests' ' cat >expect72 <<'EOF' abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +EOF +test_expect_success "format-patch --cover-letter ignores COLUMNS (big change)" ' + COLUMNS=200 git format-patch -1 --stdout --cover-letter >output && + grep " | " output >actual && + test_cmp expect72 actual +' + +cat >expect72 <<'EOF' + abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ EOF cat >expect72-graph <<'EOF' | abcd | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh index 453e6c35eb..6e0dd6f9e5 100755 --- a/t/t4053-diff-no-index.sh +++ b/t/t4053-diff-no-index.sh @@ -127,4 +127,14 @@ test_expect_success 'diff --no-index from repo subdir respects config (implicit) test_cmp expect actual.head ' +test_expect_success 'diff --no-index from repo subdir with absolute paths' ' + cat <<-EOF >expect && + 1 1 $(pwd)/non/git/{a => b} + EOF + test_expect_code 1 \ + git -C repo/sub diff --numstat \ + "$(pwd)/non/git/a" "$(pwd)/non/git/b" >actual && + test_cmp expect actual +' + test_done diff --git a/t/t4136-apply-check.sh b/t/t4136-apply-check.sh index 6d92872318..4c3f264a63 100755 --- a/t/t4136-apply-check.sh +++ b/t/t4136-apply-check.sh @@ -29,6 +29,18 @@ test_expect_success 'apply exits non-zero with no-op patch' ' test_must_fail git apply --check input ' +test_expect_success '`apply --recount` allows no-op patch' ' + echo 1 >1 && + git apply --recount --check <<-\EOF + diff --get a/1 b/1 + index 6696ea4..606eddd 100644 + --- a/1 + +++ b/1 + @@ -1,1 +1,1 @@ + 1 + EOF +' + test_expect_success 'invalid combination: create and copy' ' test_must_fail git apply --check - <<-\EOF diff --git a/1 b/2 diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 153a506151..819c24d10e 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -1703,4 +1703,8 @@ test_expect_success 'log --source paints symmetric ranges' ' test_cmp expect actual ' +test_expect_success '--exclude-promisor-objects does not BUG-crash' ' + test_must_fail git log --exclude-promisor-objects source-a +' + test_done diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh index ef1322148e..bd5fe4d148 100755 --- a/t/t4211-line-log.sh +++ b/t/t4211-line-log.sh @@ -25,7 +25,7 @@ canned_test_failure () { test_bad_opts () { test_expect_success "invalid args: $1" " test_must_fail git log $1 2>errors && - grep '$2' errors + test_i18ngrep '$2' errors " } diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh index 2a97b27b0a..602bfd9574 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -206,6 +206,12 @@ test_expect_success 'git archive with --output, override inferred format' ' test_cmp_bin b.tar d4.zip ' +test_expect_success GZIP 'git archive with --output and --remote creates .tgz' ' + git archive --output=d5.tgz --remote=. HEAD && + gzip -d -c <d5.tgz >d5.tar && + test_cmp_bin b.tar d5.tar +' + test_expect_success 'git archive --list outside of a git repo' ' nongit git archive --list ' diff --git a/t/t5003-archive-zip.sh b/t/t5003-archive-zip.sh index 55c7870997..106eddbd85 100755 --- a/t/t5003-archive-zip.sh +++ b/t/t5003-archive-zip.sh @@ -158,11 +158,16 @@ test_expect_success 'git archive --format=zip with --output' \ 'git archive --format=zip --output=d2.zip HEAD && test_cmp_bin d.zip d2.zip' -test_expect_success 'git archive with --output, inferring format' ' +test_expect_success 'git archive with --output, inferring format (local)' ' git archive --output=d3.zip HEAD && test_cmp_bin d.zip d3.zip ' +test_expect_success 'git archive with --output, inferring format (remote)' ' + git archive --remote=. --output=d4.zip HEAD && + test_cmp_bin d.zip d4.zip +' + test_expect_success \ 'git archive --format=zip with prefix' \ 'git archive --format=zip --prefix=prefix/ HEAD >e.zip' diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh index 6c620cd540..410a09b0dd 100755 --- a/t/t5300-pack-object.sh +++ b/t/t5300-pack-object.sh @@ -468,29 +468,32 @@ test_expect_success 'pack-objects in too-many-packs mode' ' git fsck ' -# -# WARNING! -# -# The following test is destructive. Please keep the next -# two tests at the end of this file. -# - -test_expect_success \ - 'fake a SHA1 hash collision' \ - 'long_a=$(git hash-object a | sed -e "s!^..!&/!") && - long_b=$(git hash-object b | sed -e "s!^..!&/!") && - test -f .git/objects/$long_b && - cp -f .git/objects/$long_a \ - .git/objects/$long_b' +test_expect_success 'setup: fake a SHA1 hash collision' ' + git init corrupt && + ( + cd corrupt && + long_a=$(git hash-object -w ../a | sed -e "s!^..!&/!") && + long_b=$(git hash-object -w ../b | sed -e "s!^..!&/!") && + test -f .git/objects/$long_b && + cp -f .git/objects/$long_a \ + .git/objects/$long_b + ) +' -test_expect_success \ - 'make sure index-pack detects the SHA1 collision' \ - 'test_must_fail git index-pack -o bad.idx test-3.pack 2>msg && - test_i18ngrep "SHA1 COLLISION FOUND" msg' +test_expect_success 'make sure index-pack detects the SHA1 collision' ' + ( + cd corrupt && + test_must_fail git index-pack -o ../bad.idx ../test-3.pack 2>msg && + test_i18ngrep "SHA1 COLLISION FOUND" msg + ) +' -test_expect_success \ - 'make sure index-pack detects the SHA1 collision (large blobs)' \ - 'test_must_fail git -c core.bigfilethreshold=1 index-pack -o bad.idx test-3.pack 2>msg && - test_i18ngrep "SHA1 COLLISION FOUND" msg' +test_expect_success 'make sure index-pack detects the SHA1 collision (large blobs)' ' + ( + cd corrupt && + test_must_fail git -c core.bigfilethreshold=1 index-pack -o ../bad.idx ../test-3.pack 2>msg && + test_i18ngrep "SHA1 COLLISION FOUND" msg + ) +' test_done diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh index 1be3459c5b..82d7f7f6a5 100755 --- a/t/t5310-pack-bitmaps.sh +++ b/t/t5310-pack-bitmaps.sh @@ -191,6 +191,7 @@ test_expect_success 'pack-objects respects --honor-pack-keep (local bitmapped pa test_expect_success 'pack-objects respects --local (non-local bitmapped pack)' ' mv .git/objects/pack/$packbitmap.* alt.git/objects/pack/ && + rm -f .git/objects/pack/multi-pack-index && test_when_finished "mv alt.git/objects/pack/$packbitmap.* .git/objects/pack/" && echo HEAD | git pack-objects --local --stdout --revs >3b.pack && git index-pack 3b.pack && diff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh index 2e718f0bde..24541ea137 100755 --- a/t/t5317-pack-objects-filter-objects.sh +++ b/t/t5317-pack-objects-filter-objects.sh @@ -67,6 +67,47 @@ test_expect_success 'verify normal and blob:none packfiles have same commits/tre test_cmp expected observed ' +test_expect_success 'get an error for missing tree object' ' + git init r5 && + echo foo >r5/foo && + git -C r5 add foo && + git -C r5 commit -m "foo" && + del=$(git -C r5 rev-parse HEAD^{tree} | sed "s|..|&/|") && + rm r5/.git/objects/$del && + test_must_fail git -C r5 pack-objects --rev --stdout 2>bad_tree <<-EOF && + HEAD + EOF + grep "bad tree object" bad_tree +' + +test_expect_success 'setup for tests of tree:0' ' + mkdir r1/subtree && + echo "This is a file in a subtree" >r1/subtree/file && + git -C r1 add subtree/file && + git -C r1 commit -m subtree +' + +test_expect_success 'verify tree:0 packfile has no blobs or trees' ' + git -C r1 pack-objects --rev --stdout --filter=tree:0 >commitsonly.pack <<-EOF && + HEAD + EOF + git -C r1 index-pack ../commitsonly.pack && + git -C r1 verify-pack -v ../commitsonly.pack >objs && + ! grep -E "tree|blob" objs +' + +test_expect_success 'grab tree directly when using tree:0' ' + # We should get the tree specified directly but not its blobs or subtrees. + git -C r1 pack-objects --rev --stdout --filter=tree:0 >commitsonly.pack <<-EOF && + HEAD: + EOF + git -C r1 index-pack ../commitsonly.pack && + git -C r1 verify-pack -v ../commitsonly.pack >objs && + awk "/tree|blob/{print \$1}" objs >trees_and_blobs && + git -C r1 rev-parse HEAD: >expected && + test_cmp expected trees_and_blobs +' + # Test blob:limit=<n>[kmg] filter. # We boundary test around the size parameter. The filter is strictly less than # the value, so size 500 and 1000 should have the same results, but 1001 should diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh index bd8e841b81..70926b5bc0 100755 --- a/t/t5319-multi-pack-index.sh +++ b/t/t5319-multi-pack-index.sh @@ -271,7 +271,7 @@ test_expect_success 'git-fsck incorrect offset' ' test_expect_success 'repack removes multi-pack-index' ' test_path_is_file $objdir/pack/multi-pack-index && - git repack -adf && + GIT_TEST_MULTI_PACK_INDEX=0 git repack -adf && test_path_is_missing $objdir/pack/multi-pack-index ' diff --git a/t/t5321-pack-large-objects.sh b/t/t5321-pack-large-objects.sh new file mode 100755 index 0000000000..a75eab87d3 --- /dev/null +++ b/t/t5321-pack-large-objects.sh @@ -0,0 +1,32 @@ +#!/bin/sh +# +# Copyright (c) 2018 Johannes Schindelin +# + +test_description='git pack-object with "large" deltas + +' +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-pack.sh + +# Two similar-ish objects that we have computed deltas between. +A=01d7713666f4de822776c7622c10f1b07de280dc +B=e68fe8129b546b101aee9510c5328e7f21ca1d18 + +test_expect_success 'setup' ' + clear_packs && + { + pack_header 2 && + pack_obj $A $B && + pack_obj $B + } >ab.pack && + pack_trailer ab.pack && + git index-pack --stdin <ab.pack +' + +test_expect_success 'repack large deltas' ' + printf "%s\\n" $A $B | + GIT_TEST_OE_DELTA_SIZE=2 git pack-objects tmp-pack +' + +test_done diff --git a/t/t5410-receive-pack-alternates.sh b/t/t5410-receive-pack-alternates.sh index 457c20c2a5..f00d0da860 100755 --- a/t/t5410-receive-pack-alternates.sh +++ b/t/t5410-receive-pack-alternates.sh @@ -23,7 +23,7 @@ test_expect_success 'with core.alternateRefsCommand' ' --format="%(objectname)" \ refs/heads/public/ EOF - test_config -C fork core.alternateRefsCommand alternate-refs && + test_config -C fork core.alternateRefsCommand ./alternate-refs && git rev-parse public/branch >expect && printf "0000" | git receive-pack fork >actual && extract_haves <actual >actual.haves && diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index d2a2cdd453..883b32efa0 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -1222,4 +1222,59 @@ test_expect_success 'add remote matching the "insteadOf" URL' ' git remote add backup xyz@example.com ' +test_expect_success 'unqualified <dst> refspec DWIM and advice' ' + test_when_finished "(cd test && git tag -d some-tag)" && + ( + cd test && + git tag -a -m "Some tag" some-tag master && + exit_with=true && + for type in commit tag tree blob + do + if test "$type" = "blob" + then + oid=$(git rev-parse some-tag:file) + else + oid=$(git rev-parse some-tag^{$type}) + fi && + test_must_fail git push origin $oid:dst 2>err && + test_i18ngrep "error: The destination you" err && + test_i18ngrep "hint: Did you mean" err && + test_must_fail git -c advice.pushUnqualifiedRefName=false \ + push origin $oid:dst 2>err && + test_i18ngrep "error: The destination you" err && + test_i18ngrep ! "hint: Did you mean" err || + exit_with=false + done && + $exit_with + ) +' + +test_expect_success 'refs/remotes/* <src> refspec and unqualified <dst> DWIM and advice' ' + ( + cd two && + git tag -a -m "Some tag" my-tag master && + git update-ref refs/trees/my-head-tree HEAD^{tree} && + git update-ref refs/blobs/my-file-blob HEAD:file + ) && + ( + cd test && + git config --add remote.two.fetch "+refs/tags/*:refs/remotes/tags-from-two/*" && + git config --add remote.two.fetch "+refs/trees/*:refs/remotes/trees-from-two/*" && + git config --add remote.two.fetch "+refs/blobs/*:refs/remotes/blobs-from-two/*" && + git fetch --no-tags two && + + test_must_fail git push origin refs/remotes/two/another:dst 2>err && + test_i18ngrep "error: The destination you" err && + + test_must_fail git push origin refs/remotes/tags-from-two/my-tag:dst-tag 2>err && + test_i18ngrep "error: The destination you" err && + + test_must_fail git push origin refs/remotes/trees-from-two/my-head-tree:dst-tree 2>err && + test_i18ngrep "error: The destination you" err && + + test_must_fail git push origin refs/remotes/blobs-from-two/my-file-blob:dst-blob 2>err && + test_i18ngrep "error: The destination you" err + ) +' + test_done diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh index bc5703ff9b..32e722db2e 100755 --- a/t/t5512-ls-remote.sh +++ b/t/t5512-ls-remote.sh @@ -302,4 +302,28 @@ test_expect_success 'ls-remote works outside repository' ' nongit git ls-remote dst.git ' +test_expect_success 'ls-remote --sort fails gracefully outside repository' ' + # Use a sort key that requires access to the referenced objects. + nongit test_must_fail git ls-remote --sort=authordate "$TRASH_DIRECTORY" 2>err && + test_i18ngrep "^fatal: not a git repository, but the field '\''authordate'\'' requires access to object data" err +' + +test_expect_success 'ls-remote patterns work with all protocol versions' ' + git for-each-ref --format="%(objectname) %(refname)" \ + refs/heads/master refs/remotes/origin/master >expect && + git -c protocol.version=1 ls-remote . master >actual.v1 && + test_cmp expect actual.v1 && + git -c protocol.version=2 ls-remote . master >actual.v2 && + test_cmp expect actual.v2 +' + +test_expect_success 'ls-remote prefixes work with all protocol versions' ' + git for-each-ref --format="%(objectname) %(refname)" \ + refs/heads/ refs/tags/ >expect && + git -c protocol.version=1 ls-remote --heads --tags . >actual.v1 && + test_cmp expect actual.v1 && + git -c protocol.version=2 ls-remote --heads --tags . >actual.v2 && + test_cmp expect actual.v2 +' + test_done diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 7a8f56db53..37e8e80893 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -95,7 +95,7 @@ mk_child() { check_push_result () { test $# -ge 3 || - error "bug in the test script: check_push_result requires at least 3 parameters" + BUG "check_push_result requires at least 3 parameters" repo_name="$1" shift @@ -1577,7 +1577,13 @@ test_expect_success 'receive.denyCurrentBranch = updateInstead' ' test $(git -C .. rev-parse master) = $(git rev-parse HEAD) && git diff --quiet && git diff --cached --quiet - ) + ) && + + # (6) updateInstead intervened by fast-forward check + test_must_fail git push void master^:master && + test $(git -C void rev-parse HEAD) = $(git rev-parse master) && + git -C void diff --quiet && + git -C void diff --cached --quiet ' test_expect_success 'updateInstead with push-to-checkout hook' ' diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index 5e501c8b08..cf4cc32fd0 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -461,7 +461,8 @@ test_expect_success 'pull.rebase=1 is treated as true and flattens keep-merge' ' test file3 = "$(git show HEAD:file3.t)" ' -test_expect_success 'pull.rebase=preserve rebases and merges keep-merge' ' +test_expect_success REBASE_P \ + 'pull.rebase=preserve rebases and merges keep-merge' ' git reset --hard before-preserve-rebase && test_config pull.rebase preserve && git pull . copy && @@ -514,7 +515,8 @@ test_expect_success '--rebase=true rebases and flattens keep-merge' ' test file3 = "$(git show HEAD:file3.t)" ' -test_expect_success '--rebase=preserve rebases and merges keep-merge' ' +test_expect_success REBASE_P \ + '--rebase=preserve rebases and merges keep-merge' ' git reset --hard before-preserve-rebase && test_config pull.rebase true && git pull --rebase=preserve . copy && diff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh index 7045685e2d..6faf17e17a 100755 --- a/t/t5537-fetch-shallow.sh +++ b/t/t5537-fetch-shallow.sh @@ -186,6 +186,33 @@ EOF test_cmp expect actual ' +test_expect_success '.git/shallow is edited by repack' ' + git init shallow-server && + test_commit -C shallow-server A && + test_commit -C shallow-server B && + git -C shallow-server checkout -b branch && + test_commit -C shallow-server C && + test_commit -C shallow-server E && + test_commit -C shallow-server D && + d="$(git -C shallow-server rev-parse --verify D^0)" && + git -C shallow-server checkout master && + + git clone --depth=1 --no-tags --no-single-branch \ + "file://$PWD/shallow-server" shallow-client && + + : now remove the branch and fetch with prune && + git -C shallow-server branch -D branch && + git -C shallow-client fetch --prune --depth=1 \ + origin "+refs/heads/*:refs/remotes/origin/*" && + git -C shallow-client repack -adfl && + test_must_fail git -C shallow-client rev-parse --verify $d^0 && + ! grep $d shallow-client/.git/shallow && + + git -C shallow-server branch branch-orig $d && + git -C shallow-client fetch --prune --depth=2 \ + origin "+refs/heads/*:refs/remotes/origin/*" +' + . "$TEST_DIRECTORY"/lib-httpd.sh start_httpd diff --git a/t/t5562-http-backend-content-length.sh b/t/t5562-http-backend-content-length.sh index b24d8b05a4..90d890d02f 100755 --- a/t/t5562-http-backend-content-length.sh +++ b/t/t5562-http-backend-content-length.sh @@ -31,6 +31,7 @@ test_http_env() { PATH_TRANSLATED="$PWD/.git/git-$handler_type-pack" \ GIT_HTTP_EXPORT_ALL=TRUE \ REQUEST_METHOD=POST \ + "$PERL_PATH" \ "$TEST_DIRECTORY"/t5562/invoke-with-content-length.pl \ "$request_body" git http-backend >act.out 2>act.err } diff --git a/t/t5562/invoke-with-content-length.pl b/t/t5562/invoke-with-content-length.pl index 6c2aae7692..0943474af2 100755..100644 --- a/t/t5562/invoke-with-content-length.pl +++ b/t/t5562/invoke-with-content-length.pl @@ -1,4 +1,3 @@ -#!/usr/bin/perl use 5.008; use strict; use warnings; diff --git a/t/t5573-pull-verify-signatures.sh b/t/t5573-pull-verify-signatures.sh index 747775c147..3e9876e197 100755 --- a/t/t5573-pull-verify-signatures.sh +++ b/t/t5573-pull-verify-signatures.sh @@ -78,4 +78,11 @@ test_expect_success GPG 'pull commit with bad signature with --no-verify-signatu git pull --ff-only --no-verify-signatures bad 2>pullerror ' +test_expect_success GPG 'pull unsigned commit into unborn branch' ' + git init empty-repo && + test_must_fail \ + git -C empty-repo pull --verify-signatures .. 2>pullerror && + test_i18ngrep "does not have a GPG signature" pullerror +' + test_done diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index f1a49e94f5..8bbc7068ac 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -628,7 +628,7 @@ test_expect_success 'clone on case-insensitive fs' ' ) ' -test_expect_success !MINGW,!CYGWIN,CASE_INSENSITIVE_FS 'colliding file detection' ' +test_expect_success CASE_INSENSITIVE_FS 'colliding file detection' ' grep X icasefs/warning && grep x icasefs/warning && test_i18ngrep "the following paths have collided" icasefs/warning diff --git a/t/t5607-clone-bundle.sh b/t/t5607-clone-bundle.sh index 348d9b3bc7..cf39e9e243 100755 --- a/t/t5607-clone-bundle.sh +++ b/t/t5607-clone-bundle.sh @@ -71,4 +71,10 @@ test_expect_success 'prerequisites with an empty commit message' ' git bundle verify bundle ' +test_expect_success 'failed bundle creation does not leave cruft' ' + # This fails because the bundle would be empty. + test_must_fail git bundle create fail.bundle master..master && + test_path_is_missing fail.bundle.lock +' + test_done diff --git a/t/t5611-clone-config.sh b/t/t5611-clone-config.sh index 39329eb7a8..60c1ba951b 100755 --- a/t/t5611-clone-config.sh +++ b/t/t5611-clone-config.sh @@ -45,6 +45,53 @@ test_expect_success 'clone -c config is available during clone' ' test_cmp expect child/file ' +test_expect_success 'clone -c remote.origin.fetch=<refspec> works' ' + rm -rf child && + git update-ref refs/grab/it refs/heads/master && + git update-ref refs/leave/out refs/heads/master && + git clone -c "remote.origin.fetch=+refs/grab/*:refs/grab/*" . child && + git -C child for-each-ref --format="%(refname)" >actual && + + cat >expect <<-\EOF && + refs/grab/it + refs/heads/master + refs/remotes/origin/HEAD + refs/remotes/origin/master + EOF + test_cmp expect actual +' + +test_expect_success 'git -c remote.origin.fetch=<refspec> clone works' ' + rm -rf child && + git -c "remote.origin.fetch=+refs/grab/*:refs/grab/*" clone . child && + git -C child for-each-ref --format="%(refname)" >actual && + + cat >expect <<-\EOF && + refs/grab/it + refs/heads/master + refs/remotes/origin/HEAD + refs/remotes/origin/master + EOF + test_cmp expect actual +' + +test_expect_success 'clone -c remote.<remote>.fetch=<refspec> --origin=<name>' ' + rm -rf child && + git clone --origin=upstream \ + -c "remote.upstream.fetch=+refs/grab/*:refs/grab/*" \ + -c "remote.origin.fetch=+refs/leave/*:refs/leave/*" \ + . child && + git -C child for-each-ref --format="%(refname)" >actual && + + cat >expect <<-\EOF && + refs/grab/it + refs/heads/master + refs/remotes/upstream/HEAD + refs/remotes/upstream/master + EOF + test_cmp expect actual +' + # Tests for the hidden file attribute on windows is_hidden () { # Use the output of `attrib`, ignore the absolute path diff --git a/t/t5616-partial-clone.sh b/t/t5616-partial-clone.sh index 6391437529..9643acb161 100755 --- a/t/t5616-partial-clone.sh +++ b/t/t5616-partial-clone.sh @@ -166,6 +166,48 @@ test_expect_success 'partial clone with transfer.fsckobjects=1 uses index-pack - grep "git index-pack.*--fsck-objects" trace ' +test_expect_success 'use fsck before and after manually fetching a missing subtree' ' + # push new commit so server has a subtree + mkdir src/dir && + echo "in dir" >src/dir/file.txt && + git -C src add dir/file.txt && + git -C src commit -m "file in dir" && + git -C src push -u srv master && + SUBTREE=$(git -C src rev-parse HEAD:dir) && + + rm -rf dst && + git clone --no-checkout --filter=tree:0 "file://$(pwd)/srv.bare" dst && + git -C dst fsck && + + # Make sure we only have commits, and all trees and blobs are missing. + git -C dst rev-list --missing=allow-any --objects master \ + >fetched_objects && + awk -f print_1.awk fetched_objects | + xargs -n1 git -C dst cat-file -t >fetched_types && + + sort -u fetched_types >unique_types.observed && + echo commit >unique_types.expected && + test_cmp unique_types.expected unique_types.observed && + + # Auto-fetch a tree with cat-file. + git -C dst cat-file -p $SUBTREE >tree_contents && + grep file.txt tree_contents && + + # fsck still works after an auto-fetch of a tree. + git -C dst fsck && + + # Auto-fetch all remaining trees and blobs with --missing=error + git -C dst rev-list --missing=error --objects master >fetched_objects && + test_line_count = 70 fetched_objects && + + awk -f print_1.awk fetched_objects | + xargs -n1 git -C dst cat-file -t >fetched_types && + + sort -u fetched_types >unique_types.observed && + test_write_lines blob commit tree >unique_types.expected && + test_cmp unique_types.expected unique_types.observed +' + test_expect_success 'partial clone fetches blobs pointed to by refs even if normally filtered out' ' rm -rf src dst && git init src && @@ -239,7 +281,7 @@ test_expect_success 'upon cloning, check that all refs point to objects' ' test_must_fail git -c protocol.version=2 clone \ --filter=blob:none $HTTPD_URL/one_time_sed/server repo 2>err && - grep "did not send all necessary objects" err && + test_i18ngrep "did not send all necessary objects" err && # Ensure that the one-time-sed script was used. ! test -e "$HTTPD_ROOT_PATH/one-time-sed" diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index 8360188c01..0f2b09ebb8 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -446,6 +446,31 @@ test_expect_success 'fetch supports include-tag and tag following' ' git -C client cat-file -e $(git -C client rev-parse annotated_tag) ' +test_expect_success 'upload-pack respects client shallows' ' + rm -rf server client trace && + + git init server && + test_commit -C server base && + test_commit -C server client_has && + + git clone --depth=1 "file://$(pwd)/server" client && + + # Add extra commits to the client so that the whole fetch takes more + # than 1 request (due to negotiation) + for i in $(test_seq 1 32) + do + test_commit -C client c$i + done && + + git -C server checkout -b newbranch base && + test_commit -C server client_wants && + + GIT_TRACE_PACKET="$(pwd)/trace" git -C client -c protocol.version=2 \ + fetch origin newbranch && + # Ensure that protocol v2 is used + grep "fetch< version 2" trace +' + # Test protocol v2 with 'http://' transport # . "$TEST_DIRECTORY"/lib-httpd.sh @@ -512,6 +537,56 @@ test_expect_success 'push with http:// and a config of v2 does not request v2' ' ! grep "git< version 2" log ' +test_expect_success 'when server sends "ready", expect DELIM' ' + rm -rf "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" http_child && + + git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one && + + git clone "$HTTPD_URL/smart/http_parent" http_child && + + test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" two && + + # After "ready" in the acknowledgments section, pretend that a FLUSH + # (0000) was sent instead of a DELIM (0001). + printf "/ready/,$ s/0001/0000/" \ + >"$HTTPD_ROOT_PATH/one-time-sed" && + + test_must_fail git -C http_child -c protocol.version=2 \ + fetch "$HTTPD_URL/one_time_sed/http_parent" 2> err && + test_i18ngrep "expected packfile to be sent after .ready." err +' + +test_expect_success 'when server does not send "ready", expect FLUSH' ' + rm -rf "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" http_child log && + + git init "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" && + test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" one && + + git clone "$HTTPD_URL/smart/http_parent" http_child && + + test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" two && + + # Create many commits to extend the negotiation phase across multiple + # requests, so that the server does not send "ready" in the first + # request. + for i in $(test_seq 1 32) + do + test_commit -C http_child c$i + done && + + # After the acknowledgments section, pretend that a DELIM + # (0001) was sent instead of a FLUSH (0000). + printf "/acknowledgments/,$ s/0000/0001/" \ + >"$HTTPD_ROOT_PATH/one-time-sed" && + + test_must_fail env GIT_TRACE_PACKET="$(pwd)/log" git -C http_child \ + -c protocol.version=2 \ + fetch "$HTTPD_URL/one_time_sed/http_parent" 2> err && + grep "fetch< acknowledgments" log && + ! grep "fetch< ready" log && + test_i18ngrep "expected no other sections to be sent after no .ready." err +' stop_httpd diff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh index 3f58f05cbb..7053899cb5 100755 --- a/t/t5703-upload-pack-ref-in-want.sh +++ b/t/t5703-upload-pack-ref-in-want.sh @@ -208,7 +208,7 @@ test_expect_success 'server is initially ahead - no ref in want' ' cp -r "$LOCAL_PRISTINE" local && inconsistency master 1234567890123456789012345678901234567890 && test_must_fail git -C local fetch 2>err && - grep "ERR upload-pack: not our ref" err + test_i18ngrep "ERR upload-pack: not our ref" err ' test_expect_success 'server is initially ahead - ref in want' ' @@ -254,7 +254,7 @@ test_expect_success 'server loses a ref - ref in want' ' echo "s/master/raster/" >"$HTTPD_ROOT_PATH/one-time-sed" && test_must_fail git -C local fetch 2>err && - grep "ERR unknown ref refs/heads/raster" err + test_i18ngrep "ERR unknown ref refs/heads/raster" err ' stop_httpd diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh index fb4d295aa0..0507999729 100755 --- a/t/t6000-rev-list-misc.sh +++ b/t/t6000-rev-list-misc.sh @@ -90,11 +90,18 @@ test_expect_success 'rev-list can show index objects' ' 9200b628cf9dc883a85a7abc8d6e6730baee589c two EOF echo only-in-index >only-in-index && + test_when_finished "git reset --hard" && git add only-in-index && git rev-list --objects --indexed-objects >actual && test_cmp expect actual ' +test_expect_success 'rev-list can negate index objects' ' + git rev-parse HEAD >expect && + git rev-list -1 --objects HEAD --not --indexed-objects >actual && + test_cmp expect actual +' + test_expect_success '--bisect and --first-parent can not be combined' ' test_must_fail git rev-list --bisect --first-parent HEAD ' diff --git a/t/t6012-rev-list-simplify.sh b/t/t6012-rev-list-simplify.sh index b5a1190ffe..a10f0df02b 100755 --- a/t/t6012-rev-list-simplify.sh +++ b/t/t6012-rev-list-simplify.sh @@ -12,6 +12,22 @@ unnote () { git name-rev --tags --stdin | sed -e "s|$OID_REGEX (tags/\([^)]*\)) |\1 |g" } +# +# Create a test repo with interesting commit graph: +# +# A--B----------G--H--I--K--L +# \ \ / / +# \ \ / / +# C------E---F J +# \_/ +# +# The commits are laid out from left-to-right starting with +# the root commit A and terminating at the tip commit L. +# +# There are a few places where we adjust the commit date or +# author date to make the --topo-order, --date-order, and +# --author-date-order flags produce different output. + test_expect_success setup ' echo "Hi there" >file && echo "initial" >lost && @@ -21,10 +37,18 @@ test_expect_success setup ' git branch other-branch && + git symbolic-ref HEAD refs/heads/unrelated && + git rm -f "*" && + echo "Unrelated branch" >side && + git add side && + test_tick && git commit -m "Side root" && + note J && + git checkout master && + echo "Hello" >file && echo "second" >lost && git add file lost && - test_tick && git commit -m "Modified file and lost" && + test_tick && GIT_AUTHOR_DATE=$(($test_tick + 120)) git commit -m "Modified file and lost" && note B && git checkout other-branch && @@ -63,13 +87,6 @@ test_expect_success setup ' test_tick && git commit -a -m "Final change" && note I && - git symbolic-ref HEAD refs/heads/unrelated && - git rm -f "*" && - echo "Unrelated branch" >side && - git add side && - test_tick && git commit -m "Side root" && - note J && - git checkout master && test_tick && git merge --allow-unrelated-histories -m "Coolest" unrelated && note K && @@ -103,14 +120,24 @@ check_result () { check_outcome success "$@" } -check_result 'L K J I H G F E D C B A' --full-history +check_result 'L K J I H F E D C G B A' --full-history --topo-order +check_result 'L K I H G F E D C B J A' --full-history +check_result 'L K I H G F E D C B J A' --full-history --date-order +check_result 'L K I H G F E D B C J A' --full-history --author-date-order check_result 'K I H E C B A' --full-history -- file check_result 'K I H E C B A' --full-history --topo-order -- file check_result 'K I H E C B A' --full-history --date-order -- file +check_result 'K I H E B C A' --full-history --author-date-order -- file check_result 'I E C B A' --simplify-merges -- file +check_result 'I E C B A' --simplify-merges --topo-order -- file +check_result 'I E C B A' --simplify-merges --date-order -- file +check_result 'I E B C A' --simplify-merges --author-date-order -- file check_result 'I B A' -- file check_result 'I B A' --topo-order -- file +check_result 'I B A' --date-order -- file +check_result 'I B A' --author-date-order -- file check_result 'H' --first-parent -- another-file +check_result 'H' --first-parent --topo-order -- another-file check_result 'E C B A' --full-history E -- lost test_expect_success 'full history simplification without parent' ' diff --git a/t/t6018-rev-list-glob.sh b/t/t6018-rev-list-glob.sh index db8a7834d8..bb5aeac07f 100755 --- a/t/t6018-rev-list-glob.sh +++ b/t/t6018-rev-list-glob.sh @@ -36,7 +36,13 @@ test_expect_success 'setup' ' git tag foo/bar master && commit master3 && git update-ref refs/remotes/foo/baz master && - commit master4 + commit master4 && + git update-ref refs/remotes/upstream/one subspace/one && + git update-ref refs/remotes/upstream/two subspace/two && + git update-ref refs/remotes/upstream/x subspace-x && + git tag qux/one subspace/one && + git tag qux/two subspace/two && + git tag qux/x subspace-x ' test_expect_success 'rev-parse --glob=refs/heads/subspace/*' ' @@ -141,6 +147,66 @@ test_expect_success 'rev-parse accumulates multiple --exclude' ' compare rev-parse "--exclude=refs/remotes/* --exclude=refs/tags/* --all" --branches ' +test_expect_success 'rev-parse --branches clears --exclude' ' + compare rev-parse "--exclude=* --branches --branches" "--branches" +' + +test_expect_success 'rev-parse --tags clears --exclude' ' + compare rev-parse "--exclude=* --tags --tags" "--tags" +' + +test_expect_success 'rev-parse --all clears --exclude' ' + compare rev-parse "--exclude=* --all --all" "--all" +' + +test_expect_success 'rev-parse --exclude=glob with --branches=glob' ' + compare rev-parse "--exclude=subspace-* --branches=sub*" "subspace/one subspace/two" +' + +test_expect_success 'rev-parse --exclude=glob with --tags=glob' ' + compare rev-parse "--exclude=qux/? --tags=qux/*" "qux/one qux/two" +' + +test_expect_success 'rev-parse --exclude=glob with --remotes=glob' ' + compare rev-parse "--exclude=upstream/? --remotes=upstream/*" "upstream/one upstream/two" +' + +test_expect_success 'rev-parse --exclude=ref with --branches=glob' ' + compare rev-parse "--exclude=subspace-x --branches=sub*" "subspace/one subspace/two" +' + +test_expect_success 'rev-parse --exclude=ref with --tags=glob' ' + compare rev-parse "--exclude=qux/x --tags=qux/*" "qux/one qux/two" +' + +test_expect_success 'rev-parse --exclude=ref with --remotes=glob' ' + compare rev-parse "--exclude=upstream/x --remotes=upstream/*" "upstream/one upstream/two" +' + +test_expect_success 'rev-list --exclude=glob with --branches=glob' ' + compare rev-list "--exclude=subspace-* --branches=sub*" "subspace/one subspace/two" +' + +test_expect_success 'rev-list --exclude=glob with --tags=glob' ' + compare rev-list "--exclude=qux/? --tags=qux/*" "qux/one qux/two" +' + +test_expect_success 'rev-list --exclude=glob with --remotes=glob' ' + compare rev-list "--exclude=upstream/? --remotes=upstream/*" "upstream/one upstream/two" +' + +test_expect_success 'rev-list --exclude=ref with --branches=glob' ' + compare rev-list "--exclude=subspace-x --branches=sub*" "subspace/one subspace/two" +' + +test_expect_success 'rev-list --exclude=ref with --tags=glob' ' + compare rev-list "--exclude=qux/x --tags=qux/*" "qux/one qux/two" +' + +test_expect_success 'rev-list --exclude=ref with --remotes=glob' ' + compare rev-list "--exclude=upstream/x --remotes=upstream/*" "upstream/one upstream/two" +' + test_expect_success 'rev-list --glob=refs/heads/subspace/*' ' compare rev-list "subspace/one subspace/two" "--glob=refs/heads/subspace/*" @@ -233,7 +299,7 @@ test_expect_success 'rev-list --tags=foo' ' test_expect_success 'rev-list --tags' ' - compare rev-list "foo/bar" "--tags" + compare rev-list "foo/bar qux/x qux/two qux/one" "--tags" ' @@ -292,7 +358,7 @@ test_expect_success 'shortlog accepts --glob/--tags/--remotes' ' "master other/three someref subspace-x subspace/one subspace/two" \ "--glob=heads/*" && compare shortlog foo/bar --tags=foo && - compare shortlog foo/bar --tags && + compare shortlog "foo/bar qux/one qux/two qux/x" --tags && compare shortlog foo/baz --remotes=foo ' diff --git a/t/t6036-recursive-corner-cases.sh b/t/t6036-recursive-corner-cases.sh index 59e52c5a09..d23b948f27 100755 --- a/t/t6036-recursive-corner-cases.sh +++ b/t/t6036-recursive-corner-cases.sh @@ -64,15 +64,12 @@ test_expect_success 'merge simple rename+criss-cross with no modifications' ' git ls-files -u >out && test_line_count = 2 out && git ls-files -o >out && - test_line_count = 3 out && + test_line_count = 1 out && git rev-parse >expect \ - L2:three R2:three \ L2:three R2:three && git rev-parse >actual \ :2:three :3:three && - git hash-object >>actual \ - three~HEAD three~R2^0 && test_cmp expect actual ) ' @@ -140,15 +137,12 @@ test_expect_success 'merge criss-cross + rename merges with basic modification' git ls-files -u >out && test_line_count = 2 out && git ls-files -o >out && - test_line_count = 3 out && + test_line_count = 1 out && git rev-parse >expect \ - L2:three R2:three \ L2:three R2:three && git rev-parse >actual \ :2:three :3:three && - git hash-object >>actual \ - three~HEAD three~R2^0 && test_cmp expect actual ) ' @@ -185,7 +179,7 @@ test_expect_success 'setup differently handled merges of rename/add conflict' ' git branch B && git checkout -b C && echo 10 >>a && - echo "other content" >>new_a && + test_write_lines 0 1 2 3 4 5 6 7 foobar >new_a && git add a new_a && test_tick && git commit -m C && @@ -195,14 +189,14 @@ test_expect_success 'setup differently handled merges of rename/add conflict' ' git checkout B^0 && test_must_fail git merge C && - git clean -f && + git show :2:new_a >new_a && + git add new_a && test_tick && git commit -m D && git tag D && git checkout C^0 && test_must_fail git merge B && - rm new_a~HEAD new_a && - printf "Incorrectly merged content" >>new_a && + test_write_lines 0 1 2 3 4 5 6 7 bad_merge >new_a && git add -u && test_tick && git commit -m E && git tag E @@ -225,21 +219,74 @@ test_expect_success 'git detects differently handled merges conflict' ' test_line_count = 1 out && git rev-parse >expect \ - D:new_a E:new_a && + C:new_a D:new_a E:new_a && git rev-parse >actual \ - :2:new_a :3:new_a && + :1:new_a :2:new_a :3:new_a && test_cmp expect actual && - git cat-file -p B:new_a >ours && - git cat-file -p C:new_a >theirs && + # Test that the two-way merge in new_a is as expected + git cat-file -p D:new_a >ours && + git cat-file -p E:new_a >theirs && >empty && test_must_fail git merge-file \ - -L "Temporary merge branch 2" \ + -L "HEAD" \ -L "" \ - -L "Temporary merge branch 1" \ + -L "E^0" \ ours empty theirs && sed -e "s/^\([<=>]\)/\1\1\1/" ours >expect && - git cat-file -p :1:new_a >actual && + git hash-object new_a >actual && + git hash-object ours >expect && + test_cmp expect actual + ) +' + +# Repeat the above testcase with precisely the same setup, other than with +# the two merge bases having different orderings of commit timestamps so +# that they are reversed in the order they are provided to merge-recursive, +# so that we can improve code coverage. +test_expect_success 'git detects differently handled merges conflict, swapped' ' + ( + cd rename-add && + + # Difference #1: Do cleanup from previous testrun + git reset --hard && + git clean -fdqx && + + # Difference #2: Change commit timestamps + btime=$(git log --no-walk --date=raw --format=%cd B | awk "{print \$1}") && + ctime=$(git log --no-walk --date=raw --format=%cd C | awk "{print \$1}") && + newctime=$(($btime+1)) && + git fast-export --no-data --all | sed -e s/$ctime/$newctime/ | git fast-import --force --quiet && + # End of differences; rest is copy-paste of last test + + git checkout D^0 && + test_must_fail git merge -s recursive E^0 && + + git ls-files -s >out && + test_line_count = 3 out && + git ls-files -u >out && + test_line_count = 3 out && + git ls-files -o >out && + test_line_count = 1 out && + + git rev-parse >expect \ + C:new_a D:new_a E:new_a && + git rev-parse >actual \ + :1:new_a :2:new_a :3:new_a && + test_cmp expect actual && + + # Test that the two-way merge in new_a is as expected + git cat-file -p D:new_a >ours && + git cat-file -p E:new_a >theirs && + >empty && + test_must_fail git merge-file \ + -L "HEAD" \ + -L "" \ + -L "E^0" \ + ours empty theirs && + sed -e "s/^\([<=>]\)/\1\1\1/" ours >expect && + git hash-object new_a >actual && + git hash-object ours >expect && test_cmp expect actual ) ' @@ -1402,4 +1449,349 @@ test_expect_failure 'check conflicting modes for regular file' ' ) ' +# Setup: +# L1---L2 +# / \ / \ +# master X ? +# \ / \ / +# R1---R2 +# +# Where: +# master has two files, named 'b' and 'a' +# branches L1 and R1 both modify each of the two files in conflicting ways +# +# L2 is a merge of R1 into L1; more on it later. +# R2 is a merge of L1 into R1; more on it later. +# +# X is an auto-generated merge-base used when merging L2 and R2. +# since X is a merge of L1 and R1, it has conflicting versions of each file +# +# More about L2 and R2: +# - both resolve the conflicts in 'b' and 'a' differently +# - L2 renames 'b' to 'm' +# - R2 renames 'a' to 'm' +# +# In the end, in file 'm' we have four different conflicting files (from +# two versions of 'b' and two of 'a'). In addition, if +# merge.conflictstyle is diff3, then the base version also has +# conflict markers of its own, leading to a total of three levels of +# conflict markers. This is a pretty weird corner case, but we just want +# to ensure that we handle it as well as practical. + +test_expect_success 'setup nested conflicts' ' + test_create_repo nested_conflicts && + ( + cd nested_conflicts && + + # Create some related files now + for i in $(test_seq 1 10) + do + echo Random base content line $i + done >initial && + + cp initial b_L1 && + cp initial b_R1 && + cp initial b_L2 && + cp initial b_R2 && + cp initial a_L1 && + cp initial a_R1 && + cp initial a_L2 && + cp initial a_R2 && + + test_write_lines b b_L1 >>b_L1 && + test_write_lines b b_R1 >>b_R1 && + test_write_lines b b_L2 >>b_L2 && + test_write_lines b b_R2 >>b_R2 && + test_write_lines a a_L1 >>a_L1 && + test_write_lines a a_R1 >>a_R1 && + test_write_lines a a_L2 >>a_L2 && + test_write_lines a a_R2 >>a_R2 && + + # Setup original commit (or merge-base), consisting of + # files named "b" and "a" + cp initial b && + cp initial a && + echo b >>b && + echo a >>a && + git add b a && + test_tick && git commit -m initial && + + git branch L && + git branch R && + + # Handle the left side + git checkout L && + mv -f b_L1 b && + mv -f a_L1 a && + git add b a && + test_tick && git commit -m "version L1 of files" && + git tag L1 && + + # Handle the right side + git checkout R && + mv -f b_R1 b && + mv -f a_R1 a && + git add b a && + test_tick && git commit -m "verson R1 of files" && + git tag R1 && + + # Create first merge on left side + git checkout L && + test_must_fail git merge R1 && + mv -f b_L2 b && + mv -f a_L2 a && + git add b a && + git mv b m && + test_tick && git commit -m "left merge, rename b->m" && + git tag L2 && + + # Create first merge on right side + git checkout R && + test_must_fail git merge L1 && + mv -f b_R2 b && + mv -f a_R2 a && + git add b a && + git mv a m && + test_tick && git commit -m "right merge, rename a->m" && + git tag R2 + ) +' + +test_expect_success 'check nested conflicts' ' + ( + cd nested_conflicts && + + git clean -f && + git checkout L2^0 && + + # Merge must fail; there is a conflict + test_must_fail git -c merge.conflictstyle=diff3 merge -s recursive R2^0 && + + # Make sure the index has the right number of entries + git ls-files -s >out && + test_line_count = 2 out && + git ls-files -u >out && + test_line_count = 2 out && + # Ensure we have the correct number of untracked files + git ls-files -o >out && + test_line_count = 1 out && + + # Create a and b from virtual merge base X + git cat-file -p master:a >base && + git cat-file -p L1:a >ours && + git cat-file -p R1:a >theirs && + test_must_fail git merge-file --diff3 \ + -L "Temporary merge branch 1" \ + -L "merged common ancestors" \ + -L "Temporary merge branch 2" \ + ours \ + base \ + theirs && + sed -e "s/^\([<|=>]\)/\1\1/" ours >vmb_a && + + git cat-file -p master:b >base && + git cat-file -p L1:b >ours && + git cat-file -p R1:b >theirs && + test_must_fail git merge-file --diff3 \ + -L "Temporary merge branch 1" \ + -L "merged common ancestors" \ + -L "Temporary merge branch 2" \ + ours \ + base \ + theirs && + sed -e "s/^\([<|=>]\)/\1\1/" ours >vmb_b && + + # Compare :2:m to expected values + git cat-file -p L2:m >ours && + git cat-file -p R2:b >theirs && + test_must_fail git merge-file --diff3 \ + -L "HEAD:m" \ + -L "merged common ancestors:b" \ + -L "R2^0:b" \ + ours \ + vmb_b \ + theirs && + sed -e "s/^\([<|=>]\)/\1\1/" ours >m_stage_2 && + git cat-file -p :2:m >actual && + test_cmp m_stage_2 actual && + + # Compare :3:m to expected values + git cat-file -p L2:a >ours && + git cat-file -p R2:m >theirs && + test_must_fail git merge-file --diff3 \ + -L "HEAD:a" \ + -L "merged common ancestors:a" \ + -L "R2^0:m" \ + ours \ + vmb_a \ + theirs && + sed -e "s/^\([<|=>]\)/\1\1/" ours >m_stage_3 && + git cat-file -p :3:m >actual && + test_cmp m_stage_3 actual && + + # Compare m to expected contents + >empty && + cp m_stage_2 expected_final_m && + test_must_fail git merge-file --diff3 \ + -L "HEAD" \ + -L "merged common ancestors" \ + -L "R2^0" \ + expected_final_m \ + empty \ + m_stage_3 && + test_cmp expected_final_m m + ) +' + +# Setup: +# L1---L2---L3 +# / \ / \ / \ +# master X1 X2 ? +# \ / \ / \ / +# R1---R2---R3 +# +# Where: +# master has one file named 'content' +# branches L1 and R1 both modify each of the two files in conflicting ways +# +# L<n> (n>1) is a merge of R<n-1> into L<n-1> +# R<n> (n>1) is a merge of L<n-1> into R<n-1> +# L<n> and R<n> resolve the conflicts differently. +# +# X<n> is an auto-generated merge-base used when merging L<n+1> and R<n+1>. +# By construction, X1 has conflict markers due to conflicting versions. +# X2, due to using merge.conflictstyle=3, has nested conflict markers. +# +# So, merging R3 into L3 using merge.conflictstyle=3 should show the +# nested conflict markers from X2 in the base version -- that means we +# have three levels of conflict markers. Can we distinguish all three? + +test_expect_success 'setup virtual merge base with nested conflicts' ' + test_create_repo virtual_merge_base_has_nested_conflicts && + ( + cd virtual_merge_base_has_nested_conflicts && + + # Create some related files now + for i in $(test_seq 1 10) + do + echo Random base content line $i + done >content && + + # Setup original commit + git add content && + test_tick && git commit -m initial && + + git branch L && + git branch R && + + # Create L1 + git checkout L && + echo left >>content && + git add content && + test_tick && git commit -m "version L1 of content" && + git tag L1 && + + # Create R1 + git checkout R && + echo right >>content && + git add content && + test_tick && git commit -m "verson R1 of content" && + git tag R1 && + + # Create L2 + git checkout L && + test_must_fail git -c merge.conflictstyle=diff3 merge R1 && + git checkout L1 content && + test_tick && git commit -m "version L2 of content" && + git tag L2 && + + # Create R2 + git checkout R && + test_must_fail git -c merge.conflictstyle=diff3 merge L1 && + git checkout R1 content && + test_tick && git commit -m "version R2 of content" && + git tag R2 && + + # Create L3 + git checkout L && + test_must_fail git -c merge.conflictstyle=diff3 merge R2 && + git checkout L1 content && + test_tick && git commit -m "version L3 of content" && + git tag L3 && + + # Create R3 + git checkout R && + test_must_fail git -c merge.conflictstyle=diff3 merge L2 && + git checkout R1 content && + test_tick && git commit -m "version R3 of content" && + git tag R3 + ) +' + +test_expect_success 'check virtual merge base with nested conflicts' ' + ( + cd virtual_merge_base_has_nested_conflicts && + + git checkout L3^0 && + + # Merge must fail; there is a conflict + test_must_fail git -c merge.conflictstyle=diff3 merge -s recursive R3^0 && + + # Make sure the index has the right number of entries + git ls-files -s >out && + test_line_count = 3 out && + git ls-files -u >out && + test_line_count = 3 out && + # Ensure we have the correct number of untracked files + git ls-files -o >out && + test_line_count = 1 out && + + # Compare :[23]:content to expected values + git rev-parse L1:content R1:content >expect && + git rev-parse :2:content :3:content >actual && + test_cmp expect actual && + + # Imitate X1 merge base, except without long enough conflict + # markers because a subsequent sed will modify them. Put + # result into vmb. + git cat-file -p master:content >base && + git cat-file -p L:content >left && + git cat-file -p R:content >right && + cp left merged-once && + test_must_fail git merge-file --diff3 \ + -L "Temporary merge branch 1" \ + -L "merged common ancestors" \ + -L "Temporary merge branch 2" \ + merged-once \ + base \ + right && + sed -e "s/^\([<|=>]\)/\1\1\1/" merged-once >vmb && + + # Imitate X2 merge base, overwriting vmb. Note that we + # extend both sets of conflict markers to make them longer + # with the sed command. + cp left merged-twice && + test_must_fail git merge-file --diff3 \ + -L "Temporary merge branch 1" \ + -L "merged common ancestors" \ + -L "Temporary merge branch 2" \ + merged-twice \ + vmb \ + right && + sed -e "s/^\([<|=>]\)/\1\1\1/" merged-twice >vmb && + + # Compare :1:content to expected value + git cat-file -p :1:content >actual && + test_cmp vmb actual && + + # Determine expected content in final outer merge, compare to + # what the merge generated. + cp -f left expect && + test_must_fail git merge-file --diff3 \ + -L "HEAD" -L "merged common ancestors" -L "R3^0" \ + expect vmb right && + test_cmp expect content + ) +' + test_done diff --git a/t/t6042-merge-rename-corner-cases.sh b/t/t6042-merge-rename-corner-cases.sh index b97aca7fa2..7cc34e7579 100755 --- a/t/t6042-merge-rename-corner-cases.sh +++ b/t/t6042-merge-rename-corner-cases.sh @@ -464,17 +464,28 @@ test_expect_success 'handle rename/rename (2to1) conflict correctly' ' git ls-files -u c >out && test_line_count = 2 out && git ls-files -o >out && - test_line_count = 3 out && + test_line_count = 1 out && test_path_is_missing a && test_path_is_missing b && - test_path_is_file c~HEAD && - test_path_is_file c~C^0 && - git rev-parse >expect \ - C:a B:b && - git hash-object >actual \ - c~HEAD c~C^0 && + git rev-parse >expect \ + C:a B:b && + git rev-parse >actual \ + :2:c :3:c && + test_cmp expect actual && + + # Test that the two-way merge in new_a is as expected + git cat-file -p :2:c >>ours && + git cat-file -p :3:c >>theirs && + >empty && + test_must_fail git merge-file \ + -L "HEAD" \ + -L "" \ + -L "C^0" \ + ours empty theirs && + git hash-object c >actual && + git hash-object ours >expect && test_cmp expect actual ) ' @@ -673,7 +684,7 @@ test_expect_success 'rename/rename/add-dest merge still knows about conflicting git ls-files -u c >out && test_line_count = 2 out && git ls-files -o >out && - test_line_count = 5 out && + test_line_count = 1 out && git rev-parse >expect \ A:a C:b B:b C:c B:c && @@ -681,14 +692,27 @@ test_expect_success 'rename/rename/add-dest merge still knows about conflicting :1:a :2:b :3:b :2:c :3:c && test_cmp expect actual && - git rev-parse >expect \ - C:c B:c C:b B:b && - git hash-object >actual \ - c~HEAD c~B\^0 b~HEAD b~B\^0 && - test_cmp expect actual && + # Record some contents for re-doing merges + git cat-file -p A:a >stuff && + git cat-file -p C:b >important_info && + git cat-file -p B:c >precious_data && + >empty && - test_path_is_missing b && - test_path_is_missing c + # Test the merge in b + test_must_fail git merge-file \ + -L "HEAD" \ + -L "" \ + -L "B^0" \ + important_info empty stuff && + test_cmp important_info b && + + # Test the merge in c + test_must_fail git merge-file \ + -L "HEAD" \ + -L "" \ + -L "B^0" \ + stuff empty precious_data && + test_cmp stuff c ) ' @@ -937,4 +961,283 @@ test_expect_failure 'mod6-check: chains of rename/rename(1to2) and rename/rename ) ' +test_conflicts_with_adds_and_renames() { + sideL=$1 + sideR=$2 + + # Setup: + # L + # / \ + # master ? + # \ / + # R + # + # Where: + # Both L and R have files named 'three' which collide. Each of + # the colliding files could have been involved in a rename, in + # which case there was a file named 'one' or 'two' that was + # modified on the opposite side of history and renamed into the + # collision on this side of history. + # + # Questions: + # 1) The index should contain both a stage 2 and stage 3 entry + # for the colliding file. Does it? + # 2) When renames are involved, the content merges are clean, so + # the index should reflect the content merges, not merely the + # version of the colliding file from the prior commit. Does + # it? + # 3) There should be a file in the worktree named 'three' + # containing the two-way merged contents of the content-merged + # versions of 'three' from each of the two colliding + # files. Is it present? + # 4) There should not be any three~* files in the working + # tree + test_expect_success "setup simple $sideL/$sideR conflict" ' + test_create_repo simple_${sideL}_${sideR} && + ( + cd simple_${sideL}_${sideR} && + + # Create some related files now + for i in $(test_seq 1 10) + do + echo Random base content line $i + done >file_v1 && + cp file_v1 file_v2 && + echo modification >>file_v2 && + + cp file_v1 file_v3 && + echo more stuff >>file_v3 && + cp file_v3 file_v4 && + echo yet more stuff >>file_v4 && + + # Use a tag to record both these files for simple + # access, and clean out these untracked files + git tag file_v1 $(git hash-object -w file_v1) && + git tag file_v2 $(git hash-object -w file_v2) && + git tag file_v3 $(git hash-object -w file_v3) && + git tag file_v4 $(git hash-object -w file_v4) && + git clean -f && + + # Setup original commit (or merge-base), consisting of + # files named "one" and "two" if renames were involved. + touch irrelevant_file && + git add irrelevant_file && + if [ $sideL = "rename" ] + then + git show file_v1 >one && + git add one + fi && + if [ $sideR = "rename" ] + then + git show file_v3 >two && + git add two + fi && + test_tick && git commit -m initial && + + git branch L && + git branch R && + + # Handle the left side + git checkout L && + if [ $sideL = "rename" ] + then + git mv one three + else + git show file_v2 >three && + git add three + fi && + if [ $sideR = "rename" ] + then + git show file_v4 >two && + git add two + fi && + test_tick && git commit -m L && + + # Handle the right side + git checkout R && + if [ $sideL = "rename" ] + then + git show file_v2 >one && + git add one + fi && + if [ $sideR = "rename" ] + then + git mv two three + else + git show file_v4 >three && + git add three + fi && + test_tick && git commit -m R + ) + ' + + test_expect_success "check simple $sideL/$sideR conflict" ' + ( + cd simple_${sideL}_${sideR} && + + git checkout L^0 && + + # Merge must fail; there is a conflict + test_must_fail git merge -s recursive R^0 && + + # Make sure the index has the right number of entries + git ls-files -s >out && + test_line_count = 3 out && + git ls-files -u >out && + test_line_count = 2 out && + # Ensure we have the correct number of untracked files + git ls-files -o >out && + test_line_count = 1 out && + + # Nothing should have touched irrelevant_file + git rev-parse >actual \ + :0:irrelevant_file \ + :2:three \ + :3:three && + git rev-parse >expected \ + master:irrelevant_file \ + file_v2 \ + file_v4 && + test_cmp expected actual && + + # Make sure we have the correct merged contents for + # three + git show file_v1 >expected && + cat <<-\EOF >>expected && + <<<<<<< HEAD + modification + ======= + more stuff + yet more stuff + >>>>>>> R^0 + EOF + + test_cmp expected three + ) + ' +} + +test_conflicts_with_adds_and_renames rename rename +test_conflicts_with_adds_and_renames rename add +test_conflicts_with_adds_and_renames add rename +test_conflicts_with_adds_and_renames add add + +# Setup: +# L +# / \ +# master ? +# \ / +# R +# +# Where: +# master has two files, named 'one' and 'two'. +# branches L and R both modify 'one', in conflicting ways. +# branches L and R both modify 'two', in conflicting ways. +# branch L also renames 'one' to 'three'. +# branch R also renames 'two' to 'three'. +# +# So, we have four different conflicting files that all end up at path +# 'three'. +test_expect_success 'setup nested conflicts from rename/rename(2to1)' ' + test_create_repo nested_conflicts_from_rename_rename && + ( + cd nested_conflicts_from_rename_rename && + + # Create some related files now + for i in $(test_seq 1 10) + do + echo Random base content line $i + done >file_v1 && + + cp file_v1 file_v2 && + cp file_v1 file_v3 && + cp file_v1 file_v4 && + cp file_v1 file_v5 && + cp file_v1 file_v6 && + + echo one >>file_v1 && + echo uno >>file_v2 && + echo eins >>file_v3 && + + echo two >>file_v4 && + echo dos >>file_v5 && + echo zwei >>file_v6 && + + # Setup original commit (or merge-base), consisting of + # files named "one" and "two". + mv file_v1 one && + mv file_v4 two && + git add one two && + test_tick && git commit -m english && + + git branch L && + git branch R && + + # Handle the left side + git checkout L && + git mv one three && + mv -f file_v2 three && + mv -f file_v5 two && + git add two three && + test_tick && git commit -m spanish && + + # Handle the right side + git checkout R && + git mv two three && + mv -f file_v3 one && + mv -f file_v6 three && + git add one three && + test_tick && git commit -m german + ) +' + +test_expect_success 'check nested conflicts from rename/rename(2to1)' ' + ( + cd nested_conflicts_from_rename_rename && + + git checkout L^0 && + + # Merge must fail; there is a conflict + test_must_fail git merge -s recursive R^0 && + + # Make sure the index has the right number of entries + git ls-files -s >out && + test_line_count = 2 out && + git ls-files -u >out && + test_line_count = 2 out && + # Ensure we have the correct number of untracked files + git ls-files -o >out && + test_line_count = 1 out && + + # Compare :2:three to expected values + git cat-file -p master:one >base && + git cat-file -p L:three >ours && + git cat-file -p R:one >theirs && + test_must_fail git merge-file \ + -L "HEAD:three" -L "" -L "R^0:one" \ + ours base theirs && + sed -e "s/^\([<=>]\)/\1\1/" ours >L-three && + git cat-file -p :2:three >expect && + test_cmp expect L-three && + + # Compare :2:three to expected values + git cat-file -p master:two >base && + git cat-file -p L:two >ours && + git cat-file -p R:three >theirs && + test_must_fail git merge-file \ + -L "HEAD:two" -L "" -L "R^0:three" \ + ours base theirs && + sed -e "s/^\([<=>]\)/\1\1/" ours >R-three && + git cat-file -p :3:three >expect && + test_cmp expect R-three && + + # Compare three to expected contents + >empty && + test_must_fail git merge-file \ + -L "HEAD" -L "" -L "R^0" \ + L-three empty R-three && + test_cmp three L-three + ) +' + test_done diff --git a/t/t6043-merge-rename-directories.sh b/t/t6043-merge-rename-directories.sh index 4a71f17edd..62c564707b 100755 --- a/t/t6043-merge-rename-directories.sh +++ b/t/t6043-merge-rename-directories.sh @@ -278,7 +278,7 @@ test_expect_success '1d-check: Directory renames cause a rename/rename(2to1) con git ls-files -u >out && test_line_count = 2 out && git ls-files -o >out && - test_line_count = 3 out && + test_line_count = 1 out && git rev-parse >actual \ :0:x/b :0:x/c :0:x/d :0:x/e :0:x/m :0:x/n && @@ -293,15 +293,16 @@ test_expect_success '1d-check: Directory renames cause a rename/rename(2to1) con A:y/wham B:z/wham && test_cmp expect actual && - test_path_is_missing x/wham && - test_path_is_file x/wham~HEAD && - test_path_is_file x/wham~B^0 && - - git hash-object >actual \ - x/wham~HEAD x/wham~B^0 && - git rev-parse >expect \ - A:y/wham B:z/wham && - test_cmp expect actual + # Test that the two-way merge in x/wham is as expected + git cat-file -p :2:x/wham >expect && + git cat-file -p :3:x/wham >other && + >empty && + test_must_fail git merge-file \ + -L "HEAD" \ + -L "" \ + -L "B^0" \ + expect empty other && + test_cmp expect x/wham ) ' @@ -1077,7 +1078,7 @@ test_expect_success '5c-check: Transitive rename would cause rename/rename/renam git ls-files -u >out && test_line_count = 6 out && git ls-files -o >out && - test_line_count = 3 out && + test_line_count = 1 out && git rev-parse >actual \ :0:y/b :0:y/c :0:y/e && @@ -1093,9 +1094,9 @@ test_expect_success '5c-check: Transitive rename would cause rename/rename/renam test_cmp expect actual && git hash-object >actual \ - w/d~HEAD w/d~B^0 z/d && + z/d && git rev-parse >expect \ - O:x/d B:w/d O:x/d && + O:x/d && test_cmp expect actual && test_path_is_missing x/d && test_path_is_file y/d && @@ -1670,7 +1671,7 @@ test_expect_success '7b-check: rename/rename(2to1), but only due to transitive r git ls-files -u >out && test_line_count = 2 out && git ls-files -o >out && - test_line_count = 3 out && + test_line_count = 1 out && git rev-parse >actual \ :0:y/b :0:y/c :2:y/d :3:y/d && @@ -1678,15 +1679,16 @@ test_expect_success '7b-check: rename/rename(2to1), but only due to transitive r O:z/b O:z/c O:w/d O:x/d && test_cmp expect actual && - test_path_is_missing y/d && - test_path_is_file y/d~HEAD && - test_path_is_file y/d~B^0 && - - git hash-object >actual \ - y/d~HEAD y/d~B^0 && - git rev-parse >expect \ - O:w/d O:x/d && - test_cmp expect actual + # Test that the two-way merge in y/d is as expected + git cat-file -p :2:y/d >expect && + git cat-file -p :3:y/d >other && + >empty && + test_must_fail git merge-file \ + -L "HEAD" \ + -L "" \ + -L "B^0" \ + expect empty other && + test_cmp expect y/d ) ' @@ -3161,11 +3163,48 @@ test_expect_success '10c-check: Overwrite untracked with dir rename/rename(1to2) ) ' +test_expect_success '10c-check: Overwrite untracked with dir rename/rename(1to2), other direction' ' + ( + cd 10c && + + git reset --hard && + git clean -fdqx && + + git checkout B^0 && + mkdir y && + echo important >y/c && + + test_must_fail git merge -s recursive A^0 >out 2>err && + test_i18ngrep "CONFLICT (rename/rename)" out && + test_i18ngrep "Refusing to lose untracked file at y/c; adding as y/c~HEAD instead" out && + + git ls-files -s >out && + test_line_count = 6 out && + git ls-files -u >out && + test_line_count = 3 out && + git ls-files -o >out && + test_line_count = 3 out && + + git rev-parse >actual \ + :0:y/a :0:y/b :0:x/d :1:x/c :3:w/c :2:y/c && + git rev-parse >expect \ + O:z/a O:z/b O:x/d O:x/c O:x/c O:x/c && + test_cmp expect actual && + + git hash-object y/c~HEAD >actual && + git rev-parse O:x/c >expect && + test_cmp expect actual && + + echo important >expect && + test_cmp expect y/c + ) +' + # Testcase 10d, Delete untracked w/ dir rename/rename(2to1) # Commit O: z/{a,b,c_1}, x/{d,e,f_2} # Commit A: y/{a,b}, x/{d,e,f_2,wham_1} + untracked y/wham # Commit B: z/{a,b,c_1,wham_2}, y/{d,e} -# Expected: Failed Merge; y/{a,b,d,e} + untracked y/{wham,wham~B^0,wham~HEAD}+ +# Expected: Failed Merge; y/{a,b,d,e} + untracked y/{wham,wham~merged}+ # CONFLICT(rename/rename) z/c_1 vs x/f_2 -> y/wham # ERROR_MSG(Refusing to lose untracked file at y/wham) @@ -3219,7 +3258,7 @@ test_expect_success '10d-check: Delete untracked with dir rename/rename(2to1)' ' git ls-files -u >out && test_line_count = 2 out && git ls-files -o >out && - test_line_count = 4 out && + test_line_count = 3 out && git rev-parse >actual \ :0:y/a :0:y/b :0:y/d :0:y/e :2:y/wham :3:y/wham && @@ -3232,11 +3271,16 @@ test_expect_success '10d-check: Delete untracked with dir rename/rename(2to1)' ' echo important >expect && test_cmp expect y/wham && - git hash-object >actual \ - y/wham~B^0 y/wham~HEAD && - git rev-parse >expect \ - O:x/f O:z/c && - test_cmp expect actual + # Test that the two-way merge in y/wham~merged is as expected + git cat-file -p :2:y/wham >expect && + git cat-file -p :3:y/wham >other && + >empty && + test_must_fail git merge-file \ + -L "HEAD" \ + -L "" \ + -L "B^0" \ + expect empty other && + test_cmp expect y/wham~merged ) ' @@ -3665,7 +3709,7 @@ test_expect_success '11e-check: Avoid deleting not-uptodate with dir rename/rena git ls-files -u >out && test_line_count = 4 out && git ls-files -o >out && - test_line_count = 4 out && + test_line_count = 3 out && echo different >expected && echo mods >>expected && @@ -3677,11 +3721,17 @@ test_expect_success '11e-check: Avoid deleting not-uptodate with dir rename/rena O:z/a O:z/b O:x/d O:x/c O:x/c A:y/c O:x/c && test_cmp expect actual && - git hash-object >actual \ - y/c~B^0 y/c~HEAD && - git rev-parse >expect \ - O:x/c A:y/c && - test_cmp expect actual + # See if y/c~merged has expected contents; requires manually + # doing the expected file merge + git cat-file -p A:y/c >c1 && + git cat-file -p B:z/c >c2 && + >empty && + test_must_fail git merge-file \ + -L "HEAD" \ + -L "" \ + -L "B^0" \ + c1 empty c2 && + test_cmp c1 y/c~merged ) ' @@ -3689,7 +3739,7 @@ test_expect_success '11e-check: Avoid deleting not-uptodate with dir rename/rena # Commit O: z/{a,b}, x/{c_1,d_2} # Commit A: y/{a,b,wham_1}, x/d_2, except y/wham has uncommitted mods # Commit B: z/{a,b,wham_2}, x/c_1 -# Expected: Failed Merge; y/{a,b} + untracked y/{wham~B^0,wham~B^HEAD} + +# Expected: Failed Merge; y/{a,b} + untracked y/{wham~merged} + # y/wham with dirty changes from before merge + # CONFLICT(rename/rename) x/c vs x/d -> y/wham # ERROR_MSG(Refusing to lose dirty file at y/wham) @@ -3741,24 +3791,30 @@ test_expect_success '11f-check: Avoid deleting not-uptodate with dir rename/rena git ls-files -u >out && test_line_count = 2 out && git ls-files -o >out && - test_line_count = 4 out && + test_line_count = 3 out && test_seq 1 10 >expected && echo important >>expected && test_cmp expected y/wham && test_must_fail git rev-parse :1:y/wham && - git hash-object >actual \ - y/wham~B^0 y/wham~HEAD && - git rev-parse >expect \ - O:x/d O:x/c && - test_cmp expect actual && git rev-parse >actual \ :0:y/a :0:y/b :2:y/wham :3:y/wham && git rev-parse >expect \ O:z/a O:z/b O:x/c O:x/d && - test_cmp expect actual + test_cmp expect actual && + + # Test that the two-way merge in y/wham~merged is as expected + git cat-file -p :2:y/wham >expect && + git cat-file -p :3:y/wham >other && + >empty && + test_must_fail git merge-file \ + -L "HEAD" \ + -L "" \ + -L "B^0" \ + expect empty other && + test_cmp expect y/wham~merged ) ' diff --git a/t/t6050-replace.sh b/t/t6050-replace.sh index 86374a9c52..d638119750 100755 --- a/t/t6050-replace.sh +++ b/t/t6050-replace.sh @@ -133,8 +133,8 @@ test_expect_success 'tag replaced commit' ' test_expect_success '"git fsck" works' ' git fsck master >fsck_master.out && - grep "dangling commit $R" fsck_master.out && - grep "dangling tag $(cat .git/refs/tags/mytag)" fsck_master.out && + test_i18ngrep "dangling commit $R" fsck_master.out && + test_i18ngrep "dangling tag $(cat .git/refs/tags/mytag)" fsck_master.out && test -z "$(git fsck)" ' @@ -461,7 +461,10 @@ test_expect_success '--convert-graft-file' ' printf "%s\n%s %s\n\n# comment\n%s\n" \ $(git rev-parse HEAD^^ HEAD^ HEAD^^ HEAD^2) \ >.git/info/grafts && - git replace --convert-graft-file && + git status 2>stderr && + test_i18ngrep "hint:.*grafts is deprecated" stderr && + git replace --convert-graft-file 2>stderr && + test_i18ngrep ! "hint:.*grafts is deprecated" stderr && test_path_is_missing .git/info/grafts && : verify that the history is now "grafted" && diff --git a/t/t6112-rev-list-filters-objects.sh b/t/t6112-rev-list-filters-objects.sh index 53975c5724..eb32505a6e 100755 --- a/t/t6112-rev-list-filters-objects.sh +++ b/t/t6112-rev-list-filters-objects.sh @@ -34,6 +34,18 @@ test_expect_success 'verify blob:none omits all 5 blobs' ' test_cmp expected observed ' +test_expect_success 'specify blob explicitly prevents filtering' ' + file_3=$(git -C r1 ls-files -s file.3 | + awk -f print_2.awk) && + + file_4=$(git -C r1 ls-files -s file.4 | + awk -f print_2.awk) && + + git -C r1 rev-list --objects --filter=blob:none HEAD $file_3 >observed && + grep "$file_3" observed && + ! grep "$file_4" observed +' + test_expect_success 'verify emitted+omitted == all' ' git -C r1 rev-list --objects HEAD >revs && awk -f print_1.awk revs | @@ -232,6 +244,56 @@ test_expect_success 'verify sparse:oid=oid-ish omits top-level files' ' test_cmp expected observed ' +test_expect_success 'rev-list W/ --missing=print and --missing=allow-any for trees' ' + TREE=$(git -C r3 rev-parse HEAD:dir1) && + + # Create a spare repo because we will be deleting objects from this one. + git clone r3 r3.b && + + rm r3.b/.git/objects/$(echo $TREE | sed "s|^..|&/|") && + + git -C r3.b rev-list --quiet --missing=print --objects HEAD \ + >missing_objs 2>rev_list_err && + echo "?$TREE" >expected && + test_cmp expected missing_objs && + + # do not complain when a missing tree cannot be parsed + test_must_be_empty rev_list_err && + + git -C r3.b rev-list --missing=allow-any --objects HEAD \ + >objs 2>rev_list_err && + ! grep $TREE objs && + test_must_be_empty rev_list_err +' + +# Test tree:0 filter. + +test_expect_success 'verify tree:0 includes trees in "filtered" output' ' + git -C r3 rev-list --quiet --objects --filter-print-omitted \ + --filter=tree:0 HEAD >revs && + + awk -f print_1.awk revs | + sed s/~// | + xargs -n1 git -C r3 cat-file -t >unsorted_filtered_types && + + sort -u unsorted_filtered_types >filtered_types && + test_write_lines blob tree >expected && + test_cmp expected filtered_types +' + +# Make sure tree:0 does not iterate through any trees. + +test_expect_success 'filter a GIANT tree through tree:0' ' + GIT_TRACE=1 git -C r3 rev-list \ + --objects --filter=tree:0 HEAD 2>filter_trace && + grep "Skipping contents of tree [.][.][.]" filter_trace >actual && + # One line for each commit traversed. + test_line_count = 2 actual && + + # Make sure no other trees were considered besides the root. + ! grep "Skipping contents of tree [^.]" filter_trace +' + # Delete some loose objects and use rev-list, but WITHOUT any filtering. # This models previously omitted objects that we did not receive. diff --git a/t/t6132-pathspec-exclude.sh b/t/t6132-pathspec-exclude.sh index eb829fce97..2462b19ddd 100755 --- a/t/t6132-pathspec-exclude.sh +++ b/t/t6132-pathspec-exclude.sh @@ -194,4 +194,21 @@ test_expect_success 'multiple exclusions' ' test_cmp expect actual ' +test_expect_success 't_e_i() exclude case #8' ' + git init case8 && + ( + cd case8 && + echo file >file1 && + echo file >file2 && + git add file1 file2 && + git commit -m twofiles && + git grep -l file HEAD :^file2 >actual && + echo HEAD:file1 >expected && + test_cmp expected actual && + git grep -l file HEAD :^file1 >actual && + echo HEAD:file2 >expected && + test_cmp expected actual + ) +' + test_done diff --git a/t/t6600-test-reach.sh b/t/t6600-test-reach.sh index ae94b27f70..b24d850036 100755 --- a/t/t6600-test-reach.sh +++ b/t/t6600-test-reach.sh @@ -56,18 +56,22 @@ test_expect_success 'setup' ' git config core.commitGraph true ' -test_three_modes () { +run_three_modes () { test_when_finished rm -rf .git/objects/info/commit-graph && - test-tool reach $1 <input >actual && + "$@" <input >actual && test_cmp expect actual && cp commit-graph-full .git/objects/info/commit-graph && - test-tool reach $1 <input >actual && + "$@" <input >actual && test_cmp expect actual && cp commit-graph-half .git/objects/info/commit-graph && - test-tool reach $1 <input >actual && + "$@" <input >actual && test_cmp expect actual } +test_three_modes () { + run_three_modes test-tool reach "$@" +} + test_expect_success 'ref_newer:miss' ' cat >input <<-\EOF && A:commit-5-7 @@ -265,4 +269,140 @@ test_expect_success 'commit_contains:miss' ' test_three_modes commit_contains --tag ' +test_expect_success 'rev-list: basic topo-order' ' + git rev-parse \ + commit-6-6 commit-5-6 commit-4-6 commit-3-6 commit-2-6 commit-1-6 \ + commit-6-5 commit-5-5 commit-4-5 commit-3-5 commit-2-5 commit-1-5 \ + commit-6-4 commit-5-4 commit-4-4 commit-3-4 commit-2-4 commit-1-4 \ + commit-6-3 commit-5-3 commit-4-3 commit-3-3 commit-2-3 commit-1-3 \ + commit-6-2 commit-5-2 commit-4-2 commit-3-2 commit-2-2 commit-1-2 \ + commit-6-1 commit-5-1 commit-4-1 commit-3-1 commit-2-1 commit-1-1 \ + >expect && + run_three_modes git rev-list --topo-order commit-6-6 +' + +test_expect_success 'rev-list: first-parent topo-order' ' + git rev-parse \ + commit-6-6 \ + commit-6-5 \ + commit-6-4 \ + commit-6-3 \ + commit-6-2 \ + commit-6-1 commit-5-1 commit-4-1 commit-3-1 commit-2-1 commit-1-1 \ + >expect && + run_three_modes git rev-list --first-parent --topo-order commit-6-6 +' + +test_expect_success 'rev-list: range topo-order' ' + git rev-parse \ + commit-6-6 commit-5-6 commit-4-6 commit-3-6 commit-2-6 commit-1-6 \ + commit-6-5 commit-5-5 commit-4-5 commit-3-5 commit-2-5 commit-1-5 \ + commit-6-4 commit-5-4 commit-4-4 commit-3-4 commit-2-4 commit-1-4 \ + commit-6-3 commit-5-3 commit-4-3 \ + commit-6-2 commit-5-2 commit-4-2 \ + commit-6-1 commit-5-1 commit-4-1 \ + >expect && + run_three_modes git rev-list --topo-order commit-3-3..commit-6-6 +' + +test_expect_success 'rev-list: range topo-order' ' + git rev-parse \ + commit-6-6 commit-5-6 commit-4-6 \ + commit-6-5 commit-5-5 commit-4-5 \ + commit-6-4 commit-5-4 commit-4-4 \ + commit-6-3 commit-5-3 commit-4-3 \ + commit-6-2 commit-5-2 commit-4-2 \ + commit-6-1 commit-5-1 commit-4-1 \ + >expect && + run_three_modes git rev-list --topo-order commit-3-8..commit-6-6 +' + +test_expect_success 'rev-list: first-parent range topo-order' ' + git rev-parse \ + commit-6-6 \ + commit-6-5 \ + commit-6-4 \ + commit-6-3 \ + commit-6-2 \ + commit-6-1 commit-5-1 commit-4-1 \ + >expect && + run_three_modes git rev-list --first-parent --topo-order commit-3-8..commit-6-6 +' + +test_expect_success 'rev-list: ancestry-path topo-order' ' + git rev-parse \ + commit-6-6 commit-5-6 commit-4-6 commit-3-6 \ + commit-6-5 commit-5-5 commit-4-5 commit-3-5 \ + commit-6-4 commit-5-4 commit-4-4 commit-3-4 \ + commit-6-3 commit-5-3 commit-4-3 \ + >expect && + run_three_modes git rev-list --topo-order --ancestry-path commit-3-3..commit-6-6 +' + +test_expect_success 'rev-list: symmetric difference topo-order' ' + git rev-parse \ + commit-6-6 commit-5-6 commit-4-6 \ + commit-6-5 commit-5-5 commit-4-5 \ + commit-6-4 commit-5-4 commit-4-4 \ + commit-6-3 commit-5-3 commit-4-3 \ + commit-6-2 commit-5-2 commit-4-2 \ + commit-6-1 commit-5-1 commit-4-1 \ + commit-3-8 commit-2-8 commit-1-8 \ + commit-3-7 commit-2-7 commit-1-7 \ + >expect && + run_three_modes git rev-list --topo-order commit-3-8...commit-6-6 +' + +test_expect_success 'get_reachable_subset:all' ' + cat >input <<-\EOF && + X:commit-9-1 + X:commit-8-3 + X:commit-7-5 + X:commit-6-6 + X:commit-1-7 + Y:commit-3-3 + Y:commit-1-7 + Y:commit-5-6 + EOF + ( + echo "get_reachable_subset(X,Y)" && + git rev-parse commit-3-3 \ + commit-1-7 \ + commit-5-6 | sort + ) >expect && + test_three_modes get_reachable_subset +' + +test_expect_success 'get_reachable_subset:some' ' + cat >input <<-\EOF && + X:commit-9-1 + X:commit-8-3 + X:commit-7-5 + X:commit-1-7 + Y:commit-3-3 + Y:commit-1-7 + Y:commit-5-6 + EOF + ( + echo "get_reachable_subset(X,Y)" && + git rev-parse commit-3-3 \ + commit-1-7 | sort + ) >expect && + test_three_modes get_reachable_subset +' + +test_expect_success 'get_reachable_subset:none' ' + cat >input <<-\EOF && + X:commit-9-1 + X:commit-8-3 + X:commit-7-5 + X:commit-1-7 + Y:commit-9-3 + Y:commit-7-6 + Y:commit-2-8 + EOF + echo "get_reachable_subset(X,Y)" >expect && + test_three_modes get_reachable_subset +' + test_done diff --git a/t/t7201-co.sh b/t/t7201-co.sh index 826987ca80..72b9b375ba 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -254,9 +254,9 @@ test_expect_success 'checkout to detach HEAD (with advice declined)' ' test_expect_success 'checkout to detach HEAD' ' git config advice.detachedHead true && git checkout -f renamer && git clean -f && - git checkout renamer^ 2>messages && - test_i18ngrep "HEAD is now at 7329388" messages && - (test_line_count -gt 1 messages || test -n "$GETTEXT_POISON") && + GIT_TEST_GETTEXT_POISON= git checkout renamer^ 2>messages && + grep "HEAD is now at 7329388" messages && + test_line_count -gt 1 messages && H=$(git rev-parse --verify HEAD) && M=$(git show-ref -s --verify refs/heads/master) && test "z$H" = "z$M" && diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index c0ffc1022a..76a7cb0af7 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -1224,6 +1224,30 @@ test_expect_success 'submodule update and setting submodule.<name>.active' ' test_cmp expect actual ' +test_expect_success 'clone active submodule without submodule url set' ' + test_when_finished "rm -rf test/test" && + mkdir test && + # another dir breaks accidental relative paths still being correct + git clone file://"$pwd"/multisuper test/test && + ( + cd test/test && + git config submodule.active "." && + + # do not pass --init flag, as the submodule is already active: + git submodule update && + git submodule status >actual_raw && + + cut -c 1,43- actual_raw >actual && + cat >expect <<-\EOF && + sub0 (test2) + sub1 (test2) + sub2 (test2) + sub3 (test2) + EOF + test_cmp expect actual + ) +' + test_expect_success 'clone --recurse-submodules with a pathspec works' ' test_when_finished "rm -rf multisuper_clone" && cat >expected <<-\EOF && diff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh index 0bde5850ac..89690b7adb 100755 --- a/t/t7411-submodule-config.sh +++ b/t/t7411-submodule-config.sh @@ -82,29 +82,23 @@ Submodule name: 'a' for path 'b' Submodule name: 'submodule' for path 'submodule' EOF -test_expect_success 'error in one submodule config lets continue' ' +test_expect_success 'error in history of one submodule config lets continue, stderr message contains blob ref' ' + ORIG=$(git -C super rev-parse HEAD) && + test_when_finished "git -C super reset --hard $ORIG" && (cd super && cp .gitmodules .gitmodules.bak && echo " value = \"" >>.gitmodules && git add .gitmodules && mv .gitmodules.bak .gitmodules && git commit -m "add error" && - test-tool submodule-config \ - HEAD b \ - HEAD submodule \ - >actual && - test_cmp expect_error actual - ) -' - -test_expect_success 'error message contains blob reference' ' - (cd super && sha1=$(git rev-parse HEAD) && test-tool submodule-config \ HEAD b \ HEAD submodule \ - 2>actual_err && - test_i18ngrep "submodule-blob $sha1:.gitmodules" actual_err >/dev/null + >actual \ + 2>actual_stderr && + test_cmp expect_error actual && + test_i18ngrep "submodule-blob $sha1:.gitmodules" actual_stderr >/dev/null ) ' @@ -123,6 +117,8 @@ test_expect_success 'using different treeishs works' ' ' test_expect_success 'error in history in fetchrecursesubmodule lets continue' ' + ORIG=$(git -C super rev-parse HEAD) && + test_when_finished "git -C super reset --hard $ORIG" && (cd super && git config -f .gitmodules \ submodule.submodule.fetchrecursesubmodules blabla && @@ -134,8 +130,123 @@ test_expect_success 'error in history in fetchrecursesubmodule lets continue' ' HEAD b \ HEAD submodule \ >actual && - test_cmp expect_error actual && - git reset --hard HEAD^ + test_cmp expect_error actual + ) +' + +test_expect_success 'reading submodules config from the working tree with "submodule--helper config"' ' + (cd super && + echo "../submodule" >expect && + git submodule--helper config submodule.submodule.url >actual && + test_cmp expect actual + ) +' + +test_expect_success 'writing submodules config with "submodule--helper config"' ' + (cd super && + echo "new_url" >expect && + git submodule--helper config submodule.submodule.url "new_url" && + git submodule--helper config submodule.submodule.url >actual && + test_cmp expect actual + ) +' + +test_expect_success 'overwriting unstaged submodules config with "submodule--helper config"' ' + test_when_finished "git -C super checkout .gitmodules" && + (cd super && + echo "newer_url" >expect && + git submodule--helper config submodule.submodule.url "newer_url" && + git submodule--helper config submodule.submodule.url >actual && + test_cmp expect actual + ) +' + +test_expect_success 'writeable .gitmodules when it is in the working tree' ' + git -C super submodule--helper config --check-writeable +' + +test_expect_success 'writeable .gitmodules when it is nowhere in the repository' ' + ORIG=$(git -C super rev-parse HEAD) && + test_when_finished "git -C super reset --hard $ORIG" && + (cd super && + git rm .gitmodules && + git commit -m "remove .gitmodules from the current branch" && + git submodule--helper config --check-writeable + ) +' + +test_expect_success 'non-writeable .gitmodules when it is in the index but not in the working tree' ' + test_when_finished "git -C super checkout .gitmodules" && + (cd super && + rm -f .gitmodules && + test_must_fail git submodule--helper config --check-writeable + ) +' + +test_expect_success 'non-writeable .gitmodules when it is in the current branch but not in the index' ' + ORIG=$(git -C super rev-parse HEAD) && + test_when_finished "git -C super reset --hard $ORIG" && + (cd super && + git rm .gitmodules && + test_must_fail git submodule--helper config --check-writeable + ) +' + +test_expect_success 'reading submodules config from the index when .gitmodules is not in the working tree' ' + ORIG=$(git -C super rev-parse HEAD) && + test_when_finished "git -C super reset --hard $ORIG" && + (cd super && + git submodule--helper config submodule.submodule.url "staged_url" && + git add .gitmodules && + rm -f .gitmodules && + echo "staged_url" >expect && + git submodule--helper config submodule.submodule.url >actual && + test_cmp expect actual + ) +' + +test_expect_success 'reading submodules config from the current branch when .gitmodules is not in the index' ' + ORIG=$(git -C super rev-parse HEAD) && + test_when_finished "git -C super reset --hard $ORIG" && + (cd super && + git rm .gitmodules && + echo "../submodule" >expect && + git submodule--helper config submodule.submodule.url >actual && + test_cmp expect actual + ) +' + +test_expect_success 'reading nested submodules config' ' + (cd super && + git init submodule/nested_submodule && + echo "a" >submodule/nested_submodule/a && + git -C submodule/nested_submodule add a && + git -C submodule/nested_submodule commit -m "add a" && + git -C submodule submodule add ./nested_submodule && + git -C submodule add nested_submodule && + git -C submodule commit -m "added nested_submodule" && + git add submodule && + git commit -m "updated submodule" && + echo "./nested_submodule" >expect && + test-tool submodule-nested-repo-config \ + submodule submodule.nested_submodule.url >actual && + test_cmp expect actual + ) +' + +# When this test eventually passes, before turning it into +# test_expect_success, remember to replace the test_i18ngrep below with +# a "test_must_be_empty warning" to be sure that the warning is actually +# removed from the code. +test_expect_failure 'reading nested submodules config when .gitmodules is not in the working tree' ' + test_when_finished "git -C super/submodule checkout .gitmodules" && + (cd super && + echo "./nested_submodule" >expect && + rm submodule/.gitmodules && + test-tool submodule-nested-repo-config \ + submodule submodule.nested_submodule.url >actual 2>warning && + test_i18ngrep "nested submodules without %s in the working tree are not supported yet" warning && + test_cmp expect actual ) ' diff --git a/t/t7415-submodule-names.sh b/t/t7415-submodule-names.sh index 293e2e1963..49a37efe9c 100755 --- a/t/t7415-submodule-names.sh +++ b/t/t7415-submodule-names.sh @@ -154,7 +154,7 @@ test_expect_success 'fsck detects symlinked .gitmodules file' ' # symlink detector; this grep string comes from the config # variable name and will not be translated. test_must_fail git fsck 2>output && - grep gitmodulesSymlink output + test_i18ngrep gitmodulesSymlink output ) ' @@ -172,7 +172,7 @@ test_expect_success 'fsck detects non-blob .gitmodules' ' git ls-tree HEAD | sed s/subdir/.gitmodules/ | git mktree && test_must_fail git fsck 2>output && - grep gitmodulesBlob output + test_i18ngrep gitmodulesBlob output ) ' @@ -186,7 +186,7 @@ test_expect_success 'fsck detects corrupt .gitmodules' ' git commit -m "broken gitmodules" && git fsck 2>output && - grep gitmodulesParse output && + test_i18ngrep gitmodulesParse output && test_i18ngrep ! "bad config" output ) ' diff --git a/t/t7418-submodule-sparse-gitmodules.sh b/t/t7418-submodule-sparse-gitmodules.sh new file mode 100755 index 0000000000..3f7f271883 --- /dev/null +++ b/t/t7418-submodule-sparse-gitmodules.sh @@ -0,0 +1,122 @@ +#!/bin/sh +# +# Copyright (C) 2018 Antonio Ospite <ao2@ao2.it> +# + +test_description='Test reading/writing .gitmodules when not in the working tree + +This test verifies that, when .gitmodules is in the current branch but is not +in the working tree reading from it still works but writing to it does not. + +The test setup uses a sparse checkout, however the same scenario can be set up +also by committing .gitmodules and then just removing it from the filesystem. +' + +. ./test-lib.sh + +test_expect_success 'sparse checkout setup which hides .gitmodules' ' + git init upstream && + git init submodule && + (cd submodule && + echo file >file && + git add file && + test_tick && + git commit -m "Add file" + ) && + (cd upstream && + git submodule add ../submodule && + test_tick && + git commit -m "Add submodule" + ) && + git clone upstream super && + (cd super && + cat >.git/info/sparse-checkout <<-\EOF && + /* + !/.gitmodules + EOF + git config core.sparsecheckout true && + git read-tree -m -u HEAD && + test_path_is_missing .gitmodules + ) +' + +test_expect_success 'reading gitmodules config file when it is not checked out' ' + echo "../submodule" >expect && + git -C super submodule--helper config submodule.submodule.url >actual && + test_cmp expect actual +' + +test_expect_success 'not writing gitmodules config file when it is not checked out' ' + test_must_fail git -C super submodule--helper config submodule.submodule.url newurl && + test_path_is_missing super/.gitmodules +' + +test_expect_success 'initialising submodule when the gitmodules config is not checked out' ' + test_must_fail git -C super config submodule.submodule.url && + git -C super submodule init && + git -C super config submodule.submodule.url >actual && + echo "$(pwd)/submodule" >expect && + test_cmp expect actual +' + +test_expect_success 'updating submodule when the gitmodules config is not checked out' ' + test_path_is_missing super/submodule/file && + git -C super submodule update && + test_cmp submodule/file super/submodule/file +' + +ORIG_SUBMODULE=$(git -C submodule rev-parse HEAD) +ORIG_UPSTREAM=$(git -C upstream rev-parse HEAD) +ORIG_SUPER=$(git -C super rev-parse HEAD) + +test_expect_success 're-updating submodule when the gitmodules config is not checked out' ' + test_when_finished "git -C submodule reset --hard $ORIG_SUBMODULE; + git -C upstream reset --hard $ORIG_UPSTREAM; + git -C super reset --hard $ORIG_SUPER; + git -C upstream submodule update --remote; + git -C super pull; + git -C super submodule update --remote" && + (cd submodule && + echo file2 >file2 && + git add file2 && + test_tick && + git commit -m "Add file2 to submodule" + ) && + (cd upstream && + git submodule update --remote && + git add submodule && + test_tick && + git commit -m "Update submodule" + ) && + git -C super pull && + # The --for-status options reads the gitmodules config + git -C super submodule summary --for-status >actual && + rev1=$(git -C submodule rev-parse --short HEAD) && + rev2=$(git -C submodule rev-parse --short HEAD^) && + cat >expect <<-EOF && + * submodule ${rev1}...${rev2} (1): + < Add file2 to submodule + + EOF + test_cmp expect actual && + # Test that the update actually succeeds + test_path_is_missing super/submodule/file2 && + git -C super submodule update && + test_cmp submodule/file2 super/submodule/file2 && + git -C super status --short >output && + test_must_be_empty output +' + +test_expect_success 'not adding submodules when the gitmodules config is not checked out' ' + git clone submodule new_submodule && + test_must_fail git -C super submodule add ../new_submodule && + test_path_is_missing .gitmodules +' + +# This test checks that the previous "git submodule add" did not leave the +# repository in a spurious state when it failed. +test_expect_success 'init submodule still works even after the previous add failed' ' + git -C super submodule init +' + +test_done diff --git a/t/t7500-commit.sh b/t/t7500-commit-template-squash-signoff.sh index 31ab608b67..46a5cd4b73 100755 --- a/t/t7500-commit.sh +++ b/t/t7500-commit-template-squash-signoff.sh @@ -5,7 +5,7 @@ test_description='git commit -Tests for selected commit options.' +Tests for template, signoff, squash and -F functions.' . ./test-lib.sh diff --git a/t/t7501-commit.sh b/t/t7501-commit-basic-functionality.sh index f1349af56e..f1349af56e 100755 --- a/t/t7501-commit.sh +++ b/t/t7501-commit-basic-functionality.sh diff --git a/t/t7502-commit.sh b/t/t7502-commit-porcelain.sh index ca4a740da0..ca4a740da0 100755 --- a/t/t7502-commit.sh +++ b/t/t7502-commit-porcelain.sh diff --git a/t/t7505-prepare-commit-msg-hook.sh b/t/t7505-prepare-commit-msg-hook.sh index 1f43b3cd4c..ebfcad9c4c 100755 --- a/t/t7505-prepare-commit-msg-hook.sh +++ b/t/t7505-prepare-commit-msg-hook.sh @@ -253,7 +253,7 @@ test_rebase () { } test_rebase success -i -test_rebase success -p +test_have_prereq !REBASE_P || test_rebase success -p test_expect_success 'with hook (cherry-pick)' ' test_when_finished "git checkout -f master" && diff --git a/t/t7506-status-submodule.sh b/t/t7506-status-submodule.sh index 943708fb04..08629a6e70 100755 --- a/t/t7506-status-submodule.sh +++ b/t/t7506-status-submodule.sh @@ -325,7 +325,8 @@ test_expect_success 'setup superproject with untracked file in nested submodule' ( cd super && git clean -dfx && - rm .gitmodules && + git rm .gitmodules && + git commit -m "remove .gitmodules" && git submodule add -f ./sub1 && git submodule add -f ./sub2 && git submodule add -f ./sub1 sub3 && diff --git a/t/t7509-commit.sh b/t/t7509-commit-authorship.sh index ddef7ea6b0..500ab2fe72 100755 --- a/t/t7509-commit.sh +++ b/t/t7509-commit-authorship.sh @@ -3,7 +3,7 @@ # Copyright (c) 2009 Erick Mattos # -test_description='git commit --reset-author' +test_description='commit tests of various authorhip options. ' . ./test-lib.sh diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh index 4e37ff8f16..86d3f93fa2 100755 --- a/t/t7510-signed-commit.sh +++ b/t/t7510-signed-commit.sh @@ -175,8 +175,10 @@ test_expect_success GPG 'show good signature with custom format' ' G 13B6F51ECDDE430D C O Mitter <committer@example.com> + 73D758744BE721698EC54E8713B6F51ECDDE430D + 73D758744BE721698EC54E8713B6F51ECDDE430D EOF - git log -1 --format="%G?%n%GK%n%GS" sixth-signed >actual && + git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual && test_cmp expect actual ' @@ -185,28 +187,34 @@ test_expect_success GPG 'show bad signature with custom format' ' B 13B6F51ECDDE430D C O Mitter <committer@example.com> + + EOF - git log -1 --format="%G?%n%GK%n%GS" $(cat forged1.commit) >actual && + git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" $(cat forged1.commit) >actual && test_cmp expect actual ' test_expect_success GPG 'show untrusted signature with custom format' ' cat >expect <<-\EOF && U - 61092E85B7227189 + 65A0EEA02E30CAD7 Eris Discordia <discord@example.net> + F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7 + D4BE22311AD3131E5EDA29A461092E85B7227189 EOF - git log -1 --format="%G?%n%GK%n%GS" eighth-signed-alt >actual && + git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual && test_cmp expect actual ' test_expect_success GPG 'show unknown signature with custom format' ' cat >expect <<-\EOF && E - 61092E85B7227189 + 65A0EEA02E30CAD7 + + EOF - GNUPGHOME="$GNUPGHOME_NOT_USED" git log -1 --format="%G?%n%GK%n%GS" eighth-signed-alt >actual && + GNUPGHOME="$GNUPGHOME_NOT_USED" git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual && test_cmp expect actual ' @@ -215,8 +223,10 @@ test_expect_success GPG 'show lack of signature with custom format' ' N + + EOF - git log -1 --format="%G?%n%GK%n%GS" seventh-unsigned >actual && + git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" seventh-unsigned >actual && test_cmp expect actual ' @@ -234,4 +244,32 @@ test_expect_success GPG 'check config gpg.format values' ' test_must_fail git commit -S --amend -m "fail" ' +test_expect_success GPG 'detect fudged commit with double signature' ' + sed -e "/gpgsig/,/END PGP/d" forged1 >double-base && + sed -n -e "/gpgsig/,/END PGP/p" forged1 | \ + sed -e "s/^gpgsig//;s/^ //" | gpg --dearmor >double-sig1.sig && + gpg -o double-sig2.sig -u 29472784 --detach-sign double-base && + cat double-sig1.sig double-sig2.sig | gpg --enarmor >double-combined.asc && + sed -e "s/^\(-.*\)ARMORED FILE/\1SIGNATURE/;1s/^/gpgsig /;2,\$s/^/ /" \ + double-combined.asc > double-gpgsig && + sed -e "/committer/r double-gpgsig" double-base >double-commit && + git hash-object -w -t commit double-commit >double-commit.commit && + test_must_fail git verify-commit $(cat double-commit.commit) && + git show --pretty=short --show-signature $(cat double-commit.commit) >double-actual && + grep "BAD signature from" double-actual && + grep "Good signature from" double-actual +' + +test_expect_success GPG 'show double signature with custom format' ' + cat >expect <<-\EOF && + E + + + + + EOF + git log -1 --format="%G?%n%GK%n%GS%n%GF%n%GP" $(cat double-commit.commit) >actual && + test_cmp expect actual +' + test_done diff --git a/t/t7517-per-repo-email.sh b/t/t7517-per-repo-email.sh index 2a22fa7588..231b8cc19d 100755 --- a/t/t7517-per-repo-email.sh +++ b/t/t7517-per-repo-email.sh @@ -72,12 +72,14 @@ test_expect_success 'noop interactive rebase does not care about ident' ' git rebase -i HEAD^ ' -test_expect_success 'fast-forward rebase does not care about ident (preserve)' ' +test_expect_success REBASE_P \ + 'fast-forward rebase does not care about ident (preserve)' ' git checkout -B tmp side-without-commit && git rebase -p master ' -test_expect_success 'non-fast-forward rebase refuses to write commits (preserve)' ' +test_expect_success REBASE_P \ + 'non-fast-forward rebase refuses to write commits (preserve)' ' test_when_finished "git rebase --abort || true" && git checkout -B tmp side-with-commit && test_must_fail git rebase -p master diff --git a/t/t7612-merge-verify-signatures.sh b/t/t7612-merge-verify-signatures.sh index e2b1df817a..d99218a725 100755 --- a/t/t7612-merge-verify-signatures.sh +++ b/t/t7612-merge-verify-signatures.sh @@ -103,4 +103,11 @@ test_expect_success GPG 'merge commit with bad signature with merge.verifySignat git merge --no-verify-signatures $(cat forged.commit) ' +test_expect_success GPG 'merge unsigned commit into unborn branch' ' + test_when_finished "git checkout initial" && + git checkout --orphan unborn && + test_must_fail git merge --verify-signatures side-unsigned 2>mergeerror && + test_i18ngrep "does not have a GPG signature" mergeerror +' + test_done diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh index 562bd215a5..22b9199d59 100755 --- a/t/t7800-difftool.sh +++ b/t/t7800-difftool.sh @@ -332,7 +332,7 @@ test_expect_success 'difftool --extcmd cat arg1' ' test_expect_success 'difftool --extcmd cat arg2' ' echo branch >expect && git difftool --no-prompt \ - --extcmd sh\ -c\ \"cat\ \$2\" branch >actual && + --extcmd sh\ -c\ \"cat\ \\\"\$2\\\"\" branch >actual && test_cmp expect actual ' diff --git a/t/t7814-grep-recurse-submodules.sh b/t/t7814-grep-recurse-submodules.sh index 7184113b9b..fa475d52fa 100755 --- a/t/t7814-grep-recurse-submodules.sh +++ b/t/t7814-grep-recurse-submodules.sh @@ -380,4 +380,20 @@ test_expect_success 'grep --recurse-submodules should pass the pattern type alon fi ' +# Recursing down into nested submodules which do not have .gitmodules in their +# working tree does not work yet. This is because config_from_gitmodules() +# uses get_oid() and the latter is still not able to get objects from an +# arbitrary repository (the nested submodule, in this case). +test_expect_failure 'grep --recurse-submodules with submodules without .gitmodules in the working tree' ' + test_when_finished "git -C submodule checkout .gitmodules" && + rm submodule/.gitmodules && + git grep --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 +' + test_done diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh index 380e1c1054..eea048e52c 100755 --- a/t/t8002-blame.sh +++ b/t/t8002-blame.sh @@ -118,4 +118,8 @@ test_expect_success '--no-abbrev works like --abbrev=40' ' check_abbrev 40 --no-abbrev ' +test_expect_success '--exclude-promisor-objects does not BUG-crash' ' + test_must_fail git blame --exclude-promisor-objects one +' + test_done diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index 1ef1a19003..ee1efcc59d 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -492,6 +492,21 @@ do --validate \ $patches longline.patch ' + +done + +for enc in 7bit 8bit quoted-printable base64 +do + test_expect_success $PREREQ "--transfer-encoding=$enc produces correct header" ' + clean_fake_sendmail && + git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + --transfer-encoding=$enc \ + $patches && + grep "Content-Transfer-Encoding: $enc" msgtxt1 + ' done test_expect_success $PREREQ 'Invalid In-Reply-To' ' diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 40fe7e4976..59a13b6a77 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -1558,7 +1558,7 @@ test_expect_success 'O: blank lines not necessary after other commands' ' INPUT_END git fast-import <input && - test 8 = $(find .git/objects/pack -type f | wc -l) && + test 8 = $(find .git/objects/pack -type f | grep -v multi-pack-index | wc -l) && test $(git rev-parse refs/tags/O3-2nd) = $(git rev-parse O3^) && git log --reverse --pretty=oneline O3 | sed s/^.*z// >actual && test_cmp expect actual diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index 6a392e87bc..5690fe2810 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -66,6 +66,34 @@ test_expect_success 'fast-export master~2..master' ' ' +test_expect_success 'fast-export --reference-excluded-parents master~2..master' ' + + git fast-export --reference-excluded-parents master~2..master >actual && + grep commit.refs/heads/master actual >commit-count && + test_line_count = 2 commit-count && + sed "s/master/rewrite/" actual | + (cd new && + git fast-import && + test $MASTER = $(git rev-parse --verify refs/heads/rewrite)) +' + +test_expect_success 'fast-export --show-original-ids' ' + + git fast-export --show-original-ids master >output && + grep ^original-oid output| sed -e s/^original-oid.// | sort >actual && + git rev-list --objects master muss >objects-and-names && + awk "{print \$1}" objects-and-names | sort >commits-trees-blobs && + comm -23 actual commits-trees-blobs >unfound && + test_must_be_empty unfound +' + +test_expect_success 'fast-export --show-original-ids | git fast-import' ' + + git fast-export --show-original-ids master muss | git fast-import --quiet && + test $MASTER = $(git rev-parse --verify refs/heads/master) && + test $MUSS = $(git rev-parse --verify refs/tags/muss) +' + test_expect_success 'iso-8859-1' ' git config i18n.commitencoding ISO8859-1 && @@ -325,6 +353,22 @@ test_expect_success 'rewriting tag of filtered out object' ' ) ' +test_expect_success 'rewrite tag predating pathspecs to nothing' ' + test_create_repo rewrite_tag_predating_pathspecs && + ( + cd rewrite_tag_predating_pathspecs && + + test_commit initial && + + git tag -a -m "Some old tag" v0.0.0.0.0.0.1 && + + test_commit bar && + + git fast-export --tag-of-filtered-object=rewrite --all -- bar.t >output && + grep from.$ZERO_OID output + ) +' + cat > limit-by-paths/expected << EOF blob mark :1 @@ -366,6 +410,26 @@ test_expect_success 'path limiting with import-marks does not lose unmodified fi grep file0 actual ' +test_expect_success 'avoid corrupt stream with non-existent mark' ' + test_create_repo avoid_non_existent_mark && + ( + cd avoid_non_existent_mark && + + test_commit important-path && + + test_commit ignored && + + git branch A && + git branch B && + + echo foo >>important-path.t && + git add important-path.t && + test_commit more changes && + + git fast-export --all -- important-path.t | git fast-import --force + ) +' + test_expect_success 'full-tree re-shows unmodified files' ' git checkout -f simple && git fast-export --full-tree simple >actual && @@ -508,10 +572,20 @@ test_expect_success 'use refspec' ' test_cmp expected actual ' -test_expect_success 'delete refspec' ' +test_expect_success 'delete ref because entire history excluded' ' git branch to-delete && - git fast-export --refspec :refs/heads/to-delete to-delete ^to-delete > actual && - cat > expected <<-EOF && + git fast-export to-delete ^to-delete >actual && + cat >expected <<-EOF && + reset refs/heads/to-delete + from 0000000000000000000000000000000000000000 + + EOF + test_cmp expected actual +' + +test_expect_success 'delete refspec' ' + git fast-export --refspec :refs/heads/to-delete >actual && + cat >expected <<-EOF && reset refs/heads/to-delete from 0000000000000000000000000000000000000000 diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh index 175f83d704..6558eee499 100755 --- a/t/t9902-completion.sh +++ b/t/t9902-completion.sh @@ -1249,7 +1249,7 @@ test_expect_success 'teardown after ref completion' ' test_path_completion () { - test $# = 2 || error "bug in the test script: not 2 parameters to test_path_completion" + test $# = 2 || BUG "not 2 parameters to test_path_completion" local cur="$1" expected="$2" echo "$expected" >expected && @@ -1434,7 +1434,8 @@ test_expect_success 'double dash "git checkout"' ' --ignore-other-worktrees Z --recurse-submodules Z --progress Z - --no-quiet Z + --guess Z + --no-guess Z --no-... Z EOF ' @@ -1539,7 +1540,7 @@ test_expect_success 'complete tree filename with metacharacters' ' EOF ' -test_expect_success 'send-email' ' +test_expect_success PERL 'send-email' ' test_completion "git send-email --cov" "--cover-letter " && test_completion "git send-email ma" "master " ' @@ -1697,7 +1698,8 @@ test_expect_success 'sourcing the completion script clears cached commands' ' verbose test -z "$__git_all_commands" ' -test_expect_success !GETTEXT_POISON 'sourcing the completion script clears cached merge strategies' ' +test_expect_success 'sourcing the completion script clears cached merge strategies' ' + GIT_TEST_GETTEXT_POISON= && __git_compute_merge_strategies && verbose test -n "$__git_merge_strategies" && . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" && diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index 78d8c3783b..6b3bbf99e4 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -418,14 +418,14 @@ test_declared_prereq () { test_verify_prereq () { test -z "$test_prereq" || expr >/dev/null "$test_prereq" : '[A-Z0-9_,!]*$' || - error "bug in the test script: '$test_prereq' does not look like a prereq" + BUG "'$test_prereq' does not look like a prereq" } test_expect_failure () { test_start_ test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq= test "$#" = 2 || - error "bug in the test script: not 2 or 3 parameters to test-expect-failure" + BUG "not 2 or 3 parameters to test-expect-failure" test_verify_prereq export test_prereq if ! test_skip "$@" @@ -445,7 +445,7 @@ test_expect_success () { test_start_ test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq= test "$#" = 2 || - error "bug in the test script: not 2 or 3 parameters to test-expect-success" + BUG "not 2 or 3 parameters to test-expect-success" test_verify_prereq export test_prereq if ! test_skip "$@" @@ -472,7 +472,7 @@ test_expect_success () { test_external () { test "$#" = 4 && { test_prereq=$1; shift; } || test_prereq= test "$#" = 3 || - error >&5 "bug in the test script: not 3 or 4 parameters to test_external" + BUG "not 3 or 4 parameters to test_external" descr="$1" shift test_verify_prereq @@ -613,7 +613,7 @@ test_path_is_missing () { test_line_count () { if test $# != 3 then - error "bug in the test script: not 3 parameters to test_line_count" + BUG "not 3 parameters to test_line_count" elif ! test $(wc -l <"$3") "$1" "$2" then echo "test_line_count: line count for $3 !$1 $2" @@ -747,6 +747,29 @@ test_cmp() { $GIT_TEST_CMP "$@" } +# Check that the given config key has the expected value. +# +# test_cmp_config [-C <dir>] <expected-value> +# [<git-config-options>...] <config-key> +# +# for example to check that the value of core.bar is foo +# +# test_cmp_config foo core.bar +# +test_cmp_config() { + local GD && + if test "$1" = "-C" + then + shift && + GD="-C $1" && + shift + fi && + printf "%s\n" "$1" >expect.config && + shift && + git $GD config "$@" >actual.config && + test_cmp expect.config actual.config +} + # test_cmp_bin - helper to compare binary files test_cmp_bin() { @@ -755,31 +778,30 @@ test_cmp_bin() { # Use this instead of test_cmp to compare files that contain expected and # actual output from git commands that can be translated. When running -# under GETTEXT_POISON this pretends that the command produced expected +# under GIT_TEST_GETTEXT_POISON this pretends that the command produced expected # results. test_i18ncmp () { - test -n "$GETTEXT_POISON" || test_cmp "$@" + ! test_have_prereq C_LOCALE_OUTPUT || test_cmp "$@" } # Use this instead of "grep expected-string actual" to see if the # output from a git command that can be translated either contains an # expected string, or does not contain an unwanted one. When running -# under GETTEXT_POISON this pretends that the command produced expected +# under GIT_TEST_GETTEXT_POISON this pretends that the command produced expected # results. test_i18ngrep () { eval "last_arg=\${$#}" test -f "$last_arg" || - error "bug in the test script: test_i18ngrep requires a file" \ - "to read as the last parameter" + BUG "test_i18ngrep requires a file to read as the last parameter" if test $# -lt 2 || { test "x!" = "x$1" && test $# -lt 3 ; } then - error "bug in the test script: too few parameters to test_i18ngrep" + BUG "too few parameters to test_i18ngrep" fi - if test -n "$GETTEXT_POISON" + if test_have_prereq !C_LOCALE_OUTPUT then # pretend success return 0 @@ -831,9 +853,23 @@ test_must_be_empty () { # Tests that its two parameters refer to the same revision test_cmp_rev () { - git rev-parse --verify "$1" >expect.rev && - git rev-parse --verify "$2" >actual.rev && - test_cmp expect.rev actual.rev + if test $# != 2 + then + error "bug in the test script: test_cmp_rev requires two revisions, but got $#" + else + local r1 r2 + r1=$(git rev-parse --verify "$1") && + r2=$(git rev-parse --verify "$2") && + if test "$r1" != "$r2" + then + cat >&4 <<-EOF + error: two revisions point to different objects: + '$1': $r1 + '$2': $r2 + EOF + return 1 + fi + fi } # Print a sequence of integers in increasing order, either with @@ -848,7 +884,7 @@ test_seq () { case $# in 1) set 1 "$@" ;; 2) ;; - *) error "bug in the test script: not 1 or 2 parameters to test_seq" ;; + *) BUG "not 1 or 2 parameters to test_seq" ;; esac test_seq_counter__=$1 while test "$test_seq_counter__" -le "$2" @@ -886,7 +922,7 @@ test_when_finished () { # doing so on Bash is better than nothing (the test will # silently pass on other shells). test "${BASH_SUBSHELL-0}" = 0 || - error "bug in test script: test_when_finished does nothing in a subshell" + BUG "test_when_finished does nothing in a subshell" test_cleanup="{ $* } && (exit \"\$eval_ret\"); eval_ret=\$?; $test_cleanup" } @@ -895,12 +931,13 @@ test_when_finished () { # Usage: test_create_repo <directory> test_create_repo () { test "$#" = 1 || - error "bug in the test script: not 1 parameter to test-create-repo" + BUG "not 1 parameter to test-create-repo" repo="$1" mkdir -p "$repo" ( cd "$repo" || error "Cannot setup test environment" - "$GIT_EXEC_PATH/git-init" "--template=$GIT_BUILD_DIR/templates/blt/" >&3 2>&4 || + "${GIT_TEST_INSTALLED:-$GIT_EXEC_PATH}/git$X" init \ + "--template=$GIT_BUILD_DIR/templates/blt/" >&3 2>&4 || error "cannot run git init -- have you built things yet?" mv .git/hooks .git/hooks-disabled ) || exit @@ -1207,7 +1244,7 @@ test_oid_cache () { if ! expr "$k" : '[a-z0-9][a-z0-9]*$' >/dev/null then - error 'bug in the test script: bad hash algorithm' + BUG 'bad hash algorithm' fi && eval "test_oid_${k}_$tag=\"\$v\"" done @@ -1222,7 +1259,7 @@ test_oid () { # key-hash pair, so exit with an error. if eval "test -z \"\${$var+set}\"" then - error "bug in the test script: undefined key '$1'" >&2 + BUG "undefined key '$1'" fi && eval "printf '%s' \"\${$var}\"" } diff --git a/t/test-lib.sh b/t/test-lib.sh index 897e6fcc94..0f1faa24b2 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -49,25 +49,35 @@ export ASAN_OPTIONS : ${LSAN_OPTIONS=abort_on_error=1} export LSAN_OPTIONS +if test ! -f "$GIT_BUILD_DIR"/GIT-BUILD-OPTIONS +then + echo >&2 'error: GIT-BUILD-OPTIONS missing (has Git been built?).' + exit 1 +fi +. "$GIT_BUILD_DIR"/GIT-BUILD-OPTIONS +export PERL_PATH SHELL_PATH + ################################################################ # It appears that people try to run tests without building... -"$GIT_BUILD_DIR/git" >/dev/null +"${GIT_TEST_INSTALLED:-$GIT_BUILD_DIR}/git$X" >/dev/null if test $? != 1 then - echo >&2 'error: you do not seem to have built git yet.' + if test -n "$GIT_TEST_INSTALLED" + then + echo >&2 "error: there is no working Git at '$GIT_TEST_INSTALLED'" + else + echo >&2 'error: you do not seem to have built git yet.' + fi exit 1 fi -. "$GIT_BUILD_DIR"/GIT-BUILD-OPTIONS -export PERL_PATH SHELL_PATH - # if --tee was passed, write the output not only to the terminal, but # additionally to the file test-results/$BASENAME.out, too. case "$GIT_TEST_TEE_STARTED, $* " in done,*) # do not redirect again ;; -*' --tee '*|*' --va'*|*' --verbose-log '*) +*' --tee '*|*' --va'*|*' -V '*|*' --verbose-log '*) mkdir -p "$TEST_OUTPUT_DIRECTORY/test-results" BASE="$TEST_OUTPUT_DIRECTORY/test-results/$(basename "$0" .sh)" @@ -95,6 +105,16 @@ PAGER=cat TZ=UTC export LANG LC_ALL PAGER TZ EDITOR=: + +# GIT_TEST_GETTEXT_POISON should not influence git commands executed +# during initialization of test-lib and the test repo. Back it up, +# unset and then restore after initialization is finished. +if test -n "$GIT_TEST_GETTEXT_POISON" +then + GIT_TEST_GETTEXT_POISON_ORIG=$GIT_TEST_GETTEXT_POISON + unset GIT_TEST_GETTEXT_POISON +fi + # A call to "unset" with no arguments causes at least Solaris 10 # /usr/xpg4/bin/sh and /bin/ksh to bail out. So keep the unsets # deriving from the command substitution clustered with the other @@ -316,7 +336,7 @@ do echo >&2 "warning: ignoring -x; '$0' is untraceable without BASH_XTRACEFD" fi shift ;; - --verbose-log) + -V|--verbose-log) verbose_log=t shift ;; *) @@ -382,6 +402,10 @@ error () { exit 1 } +BUG () { + error >&7 "bug in the test script: $*" +} + say () { say_color info "$*" } @@ -709,7 +733,7 @@ test_run_ () { if $(printf '%s\n' "$1" | sed -f "$GIT_BUILD_DIR/t/chainlint.sed" | grep -q '?![A-Z][A-Z]*?!') || test "OK-117" != "$(test_eval_ "(exit 117) && $1${LF}${LF}echo OK-\$?" 3>&1)" then - error "bug in the test script: broken &&-chain or run-away HERE-DOC: $1" + BUG "broken &&-chain or run-away HERE-DOC: $1" fi trace=$trace_tmp fi @@ -957,7 +981,7 @@ elif test -n "$GIT_TEST_INSTALLED" then GIT_EXEC_PATH=$($GIT_TEST_INSTALLED/git --exec-path) || error "Cannot run git from $GIT_TEST_INSTALLED." - PATH=$GIT_TEST_INSTALLED:$GIT_BUILD_DIR:$PATH + PATH=$GIT_TEST_INSTALLED:$GIT_BUILD_DIR/t/helper:$PATH GIT_EXEC_PATH=${GIT_TEST_EXEC_PATH:-$GIT_EXEC_PATH} else # normal case, use ../bin-wrappers only unless $with_dashes: git_bin_dir="$GIT_BUILD_DIR/bin-wrappers" @@ -1104,13 +1128,15 @@ test -n "$USE_LIBPCRE1" && test_set_prereq LIBPCRE1 test -n "$USE_LIBPCRE2" && test_set_prereq LIBPCRE2 test -z "$NO_GETTEXT" && test_set_prereq GETTEXT +if test -n "$GIT_TEST_GETTEXT_POISON_ORIG" +then + GIT_TEST_GETTEXT_POISON=$GIT_TEST_GETTEXT_POISON_ORIG + unset GIT_TEST_GETTEXT_POISON_ORIG +fi + # Can we rely on git's output in the C locale? -if test -n "$GETTEXT_POISON" +if test -z "$GIT_TEST_GETTEXT_POISON" then - GIT_GETTEXT_POISON=YesPlease - export GIT_GETTEXT_POISON - test_set_prereq GETTEXT_POISON -else test_set_prereq C_LOCALE_OUTPUT fi @@ -1209,7 +1235,7 @@ test_lazy_prereq SANITY ' chmod -w SANETESTD.1 && chmod -r SANETESTD.1/x && chmod -rx SANETESTD.2 || - error "bug in test sript: cannot prepare SANETESTD" + BUG "cannot prepare SANETESTD" ! test -r SANETESTD.1/x && ! rm SANETESTD.1/x && ! test -f SANETESTD.2/x @@ -1217,7 +1243,7 @@ test_lazy_prereq SANITY ' chmod +rwx SANETESTD.1 SANETESTD.2 && rm -rf SANETESTD.1 SANETESTD.2 || - error "bug in test sript: cannot clean SANETESTD" + BUG "cannot clean SANETESTD" return $status ' @@ -1268,3 +1294,7 @@ test_lazy_prereq CURL ' test_lazy_prereq SHA1 ' test $(git hash-object /dev/null) = e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 ' + +test_lazy_prereq REBASE_P ' + test -z "$GIT_TEST_SKIP_REBASE_P" +' |