diff options
Diffstat (limited to 't')
306 files changed, 13894 insertions, 3392 deletions
@@ -334,11 +334,20 @@ 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_FAIL_PREREQS=<boolean> fails all prerequisites. This is +useful for discovering issues with the tests where say a later test +implicitly depends on an optional earlier test. + +There's a "FAIL_PREREQS" prerequisite that can be used to test for +whether this mode is active, and e.g. skip some tests that are hard to +refactor to deal with it. The "SYMLINKS" prerequisite is currently +excluded as so much relies on it, but this might change in the future. + +GIT_TEST_GETTEXT_POISON=<boolean> turns all strings marked for +translation into gibberish if true. 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. @@ -388,6 +397,10 @@ GIT_TEST_STASH_USE_BUILTIN=<boolean>, when false, disables the built-in version of git-stash. See 'stash.useBuiltin' in git-config(1). +GIT_TEST_ADD_I_USE_BUILTIN=<boolean>, when true, enables the +built-in version of git add -i. See 'add.interactive.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 @@ -969,6 +982,15 @@ library for your script to use. output to the downstream---unlike the real version, it generates only up to 99 lines. + - test_bool_env <env-variable-name> <default-value> + + Given the name of an environment variable with a bool value, + normalize its value to a 0 (true) or 1 (false or empty string) + return code. Return with code corresponding to the given default + value if the variable is unset. + Abort the test script if either the value of the variable or the + default are not valid bool values. + Prerequisites ------------- diff --git a/t/gitweb-lib.sh b/t/gitweb-lib.sh index 006d2a8152..1f32ca66ea 100644 --- a/t/gitweb-lib.sh +++ b/t/gitweb-lib.sh @@ -58,10 +58,11 @@ gitweb_run () { GATEWAY_INTERFACE='CGI/1.1' HTTP_ACCEPT='*/*' REQUEST_METHOD='GET' - QUERY_STRING=""$1"" - PATH_INFO=""$2"" + QUERY_STRING=$1 + PATH_INFO=$2 + REQUEST_URI=/gitweb.cgi$PATH_INFO export GATEWAY_INTERFACE HTTP_ACCEPT REQUEST_METHOD \ - QUERY_STRING PATH_INFO + QUERY_STRING PATH_INFO REQUEST_URI GITWEB_CONFIG=$(pwd)/gitweb_config.perl export GITWEB_CONFIG diff --git a/t/helper/.gitignore b/t/helper/.gitignore index 2bad28af92..48c7bb0bbb 100644 --- a/t/helper/.gitignore +++ b/t/helper/.gitignore @@ -1,5 +1,4 @@ -* -!*.sh -!*.[ch] -!*.gitignore - +/test-tool +/test-fake-ssh +/test-line-buffer +/test-svn-fe diff --git a/t/helper/test-date.c b/t/helper/test-date.c index 585347ea48..099eff4f0f 100644 --- a/t/helper/test-date.c +++ b/t/helper/test-date.c @@ -12,13 +12,13 @@ static const char *usage_msg = "\n" " test-tool date is64bit\n" " test-tool date time_t-is64bit\n"; -static void show_relative_dates(const char **argv, struct timeval *now) +static void show_relative_dates(const char **argv) { struct strbuf buf = STRBUF_INIT; for (; *argv; argv++) { time_t t = atoi(*argv); - show_date_relative(t, now, &buf); + show_date_relative(t, &buf); printf("%s -> %s\n", *argv, buf.buf); } strbuf_release(&buf); @@ -74,20 +74,20 @@ static void parse_dates(const char **argv) strbuf_release(&result); } -static void parse_approxidate(const char **argv, struct timeval *now) +static void parse_approxidate(const char **argv) { for (; *argv; argv++) { timestamp_t t; - t = approxidate_relative(*argv, now); + t = approxidate_relative(*argv); printf("%s -> %s\n", *argv, show_date(t, 0, DATE_MODE(ISO8601))); } } -static void parse_approx_timestamp(const char **argv, struct timeval *now) +static void parse_approx_timestamp(const char **argv) { for (; *argv; argv++) { timestamp_t t; - t = approxidate_relative(*argv, now); + t = approxidate_relative(*argv); printf("%s -> %"PRItime"\n", *argv, t); } } @@ -103,22 +103,13 @@ static void getnanos(const char **argv) int cmd__date(int argc, const char **argv) { - struct timeval now; const char *x; - x = getenv("GIT_TEST_DATE_NOW"); - if (x) { - now.tv_sec = atoi(x); - now.tv_usec = 0; - } - else - gettimeofday(&now, NULL); - argv++; if (!*argv) usage(usage_msg); if (!strcmp(*argv, "relative")) - show_relative_dates(argv+1, &now); + show_relative_dates(argv+1); else if (!strcmp(*argv, "human")) show_human_dates(argv+1); else if (skip_prefix(*argv, "show:", &x)) @@ -126,9 +117,9 @@ int cmd__date(int argc, const char **argv) else if (!strcmp(*argv, "parse")) parse_dates(argv+1); else if (!strcmp(*argv, "approxidate")) - parse_approxidate(argv+1, &now); + parse_approxidate(argv+1); else if (!strcmp(*argv, "timestamp")) - parse_approx_timestamp(argv+1, &now); + parse_approx_timestamp(argv+1); else if (!strcmp(*argv, "getnanos")) getnanos(argv+1); else if (!strcmp(*argv, "is64bit")) diff --git a/t/helper/test-dir-iterator.c b/t/helper/test-dir-iterator.c new file mode 100644 index 0000000000..659b6bfa81 --- /dev/null +++ b/t/helper/test-dir-iterator.c @@ -0,0 +1,65 @@ +#include "test-tool.h" +#include "git-compat-util.h" +#include "strbuf.h" +#include "iterator.h" +#include "dir-iterator.h" + +static const char *error_name(int error_number) +{ + switch (error_number) { + case ENOENT: return "ENOENT"; + case ENOTDIR: return "ENOTDIR"; + default: return "ESOMETHINGELSE"; + } +} + +/* + * usage: + * tool-test dir-iterator [--follow-symlinks] [--pedantic] directory_path + */ +int cmd__dir_iterator(int argc, const char **argv) +{ + struct dir_iterator *diter; + unsigned int flags = 0; + int iter_status; + + for (++argv, --argc; *argv && starts_with(*argv, "--"); ++argv, --argc) { + if (strcmp(*argv, "--follow-symlinks") == 0) + flags |= DIR_ITERATOR_FOLLOW_SYMLINKS; + else if (strcmp(*argv, "--pedantic") == 0) + flags |= DIR_ITERATOR_PEDANTIC; + else + die("invalid option '%s'", *argv); + } + + if (!*argv || argc != 1) + die("dir-iterator needs exactly one non-option argument"); + + diter = dir_iterator_begin(*argv, flags); + + if (!diter) { + printf("dir_iterator_begin failure: %s\n", error_name(errno)); + exit(EXIT_FAILURE); + } + + while ((iter_status = dir_iterator_advance(diter)) == ITER_OK) { + if (S_ISDIR(diter->st.st_mode)) + printf("[d] "); + else if (S_ISREG(diter->st.st_mode)) + printf("[f] "); + else if (S_ISLNK(diter->st.st_mode)) + printf("[s] "); + else + printf("[?] "); + + printf("(%s) [%s] %s\n", diter->relative_path, diter->basename, + diter->path.buf); + } + + if (iter_status != ITER_DONE) { + printf("dir_iterator_advance failure\n"); + return 1; + } + + return 0; +} diff --git a/t/helper/test-drop-caches.c b/t/helper/test-drop-caches.c index f65e301f9d..7b4278462b 100644 --- a/t/helper/test-drop-caches.c +++ b/t/helper/test-drop-caches.c @@ -8,18 +8,21 @@ static int cmd_sync(void) { char Buffer[MAX_PATH]; DWORD dwRet; - char szVolumeAccessPath[] = "\\\\.\\X:"; + char szVolumeAccessPath[] = "\\\\.\\XXXX:"; HANDLE hVolWrite; - int success = 0; + int success = 0, dos_drive_prefix; dwRet = GetCurrentDirectory(MAX_PATH, Buffer); if ((0 == dwRet) || (dwRet > MAX_PATH)) return error("Error getting current directory"); - if (!has_dos_drive_prefix(Buffer)) + dos_drive_prefix = has_dos_drive_prefix(Buffer); + if (!dos_drive_prefix) return error("'%s': invalid drive letter", Buffer); - szVolumeAccessPath[4] = Buffer[0]; + memcpy(szVolumeAccessPath, Buffer, dos_drive_prefix); + szVolumeAccessPath[dos_drive_prefix] = '\0'; + hVolWrite = CreateFile(szVolumeAccessPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == hVolWrite) diff --git a/t/helper/test-example-decorate.c b/t/helper/test-example-decorate.c index a20a6161e4..c8a1cde7d2 100644 --- a/t/helper/test-example-decorate.c +++ b/t/helper/test-example-decorate.c @@ -26,8 +26,8 @@ int cmd__example_decorate(int argc, const char **argv) * Add 2 objects, one with a non-NULL decoration and one with a NULL * decoration. */ - one = lookup_unknown_object(one_oid.hash); - two = lookup_unknown_object(two_oid.hash); + one = lookup_unknown_object(&one_oid); + two = lookup_unknown_object(&two_oid); ret = add_decoration(&n, one, &decoration_a); if (ret) BUG("when adding a brand-new object, NULL should be returned"); @@ -56,7 +56,7 @@ int cmd__example_decorate(int argc, const char **argv) ret = lookup_decoration(&n, two); if (ret != &decoration_b) BUG("lookup should return added declaration"); - three = lookup_unknown_object(three_oid.hash); + three = lookup_unknown_object(&three_oid); ret = lookup_decoration(&n, three); if (ret) BUG("lookup for unknown object should return NULL"); diff --git a/t/helper/test-hashmap.c b/t/helper/test-hashmap.c index 23d2b172fe..f38706216f 100644 --- a/t/helper/test-hashmap.c +++ b/t/helper/test-hashmap.c @@ -5,6 +5,7 @@ struct test_entry { + int padding; /* hashmap entry no longer needs to be the first member */ struct hashmap_entry ent; /* key and value as two \0-terminated strings */ char key[FLEX_ARRAY]; @@ -16,15 +17,17 @@ static const char *get_value(const struct test_entry *e) } static int test_entry_cmp(const void *cmp_data, - const void *entry, - const void *entry_or_key, + const struct hashmap_entry *eptr, + const struct hashmap_entry *entry_or_key, const void *keydata) { const int ignore_case = cmp_data ? *((int *)cmp_data) : 0; - const struct test_entry *e1 = entry; - const struct test_entry *e2 = entry_or_key; + const struct test_entry *e1, *e2; const char *key = keydata; + e1 = container_of(eptr, const struct test_entry, ent); + e2 = container_of(entry_or_key, const struct test_entry, ent); + if (ignore_case) return strcasecmp(e1->key, key ? key : e2->key); else @@ -37,7 +40,7 @@ static struct test_entry *alloc_test_entry(unsigned int hash, size_t klen = strlen(key); size_t vlen = strlen(value); struct test_entry *entry = xmalloc(st_add4(sizeof(*entry), klen, vlen, 2)); - hashmap_entry_init(entry, hash); + hashmap_entry_init(&entry->ent, hash); memcpy(entry->key, key, klen + 1); memcpy(entry->key + klen + 1, value, vlen + 1); return entry; @@ -103,11 +106,11 @@ static void perf_hashmap(unsigned int method, unsigned int rounds) /* add entries */ for (i = 0; i < TEST_SIZE; i++) { - hashmap_entry_init(entries[i], hashes[i]); - hashmap_add(&map, entries[i]); + hashmap_entry_init(&entries[i]->ent, hashes[i]); + hashmap_add(&map, &entries[i]->ent); } - hashmap_free(&map, 0); + hashmap_free(&map); } } else { /* test map lookups */ @@ -116,8 +119,8 @@ static void perf_hashmap(unsigned int method, unsigned int rounds) /* fill the map (sparsely if specified) */ j = (method & TEST_SPARSE) ? TEST_SIZE / 10 : TEST_SIZE; for (i = 0; i < j; i++) { - hashmap_entry_init(entries[i], hashes[i]); - hashmap_add(&map, entries[i]); + hashmap_entry_init(&entries[i]->ent, hashes[i]); + hashmap_add(&map, &entries[i]->ent); } for (j = 0; j < rounds; j++) { @@ -127,7 +130,7 @@ static void perf_hashmap(unsigned int method, unsigned int rounds) } } - hashmap_free(&map, 0); + hashmap_free(&map); } } @@ -173,20 +176,13 @@ int cmd__hashmap(int argc, const char **argv) p2 = strtok(NULL, DELIM); } - if (!strcmp("hash", cmd) && p1) { - - /* print results of different hash functions */ - printf("%u %u %u %u\n", - strhash(p1), memhash(p1, strlen(p1)), - strihash(p1), memihash(p1, strlen(p1))); - - } else if (!strcmp("add", cmd) && p1 && p2) { + if (!strcmp("add", cmd) && p1 && p2) { /* create entry with key = p1, value = p2 */ entry = alloc_test_entry(hash, p1, p2); /* add to hashmap */ - hashmap_add(&map, entry); + hashmap_add(&map, &entry->ent); } else if (!strcmp("put", cmd) && p1 && p2) { @@ -194,43 +190,44 @@ int cmd__hashmap(int argc, const char **argv) entry = alloc_test_entry(hash, p1, p2); /* add / replace entry */ - entry = hashmap_put(&map, entry); + entry = hashmap_put_entry(&map, entry, ent); /* print and free replaced entry, if any */ puts(entry ? get_value(entry) : "NULL"); free(entry); } else if (!strcmp("get", cmd) && p1) { - /* lookup entry in hashmap */ - entry = hashmap_get_from_hash(&map, hash, p1); + entry = hashmap_get_entry_from_hash(&map, hash, p1, + struct test_entry, ent); /* print result */ if (!entry) puts("NULL"); - while (entry) { + hashmap_for_each_entry_from(&map, entry, ent) puts(get_value(entry)); - entry = hashmap_get_next(&map, entry); - } } else if (!strcmp("remove", cmd) && p1) { /* setup static key */ struct hashmap_entry key; + struct hashmap_entry *rm; hashmap_entry_init(&key, hash); /* remove entry from hashmap */ - entry = hashmap_remove(&map, &key, p1); + rm = hashmap_remove(&map, &key, p1); + entry = rm ? container_of(rm, struct test_entry, ent) + : NULL; /* print result and free entry*/ puts(entry ? get_value(entry) : "NULL"); free(entry); } else if (!strcmp("iterate", cmd)) { - struct hashmap_iter iter; - hashmap_iter_init(&map, &iter); - while ((entry = hashmap_iter_next(&iter))) + + hashmap_for_each_entry(&map, &iter, entry, + ent /* member name */) printf("%s %s\n", entry->key, get_value(entry)); } else if (!strcmp("size", cmd)) { @@ -265,6 +262,6 @@ int cmd__hashmap(int argc, const char **argv) } strbuf_release(&line); - hashmap_free(&map, 1); + hashmap_free_entries(&map, struct test_entry, ent); return 0; } diff --git a/t/helper/test-lazy-init-name-hash.c b/t/helper/test-lazy-init-name-hash.c index b99a37080d..cd1b4c9736 100644 --- a/t/helper/test-lazy-init-name-hash.c +++ b/t/helper/test-lazy-init-name-hash.c @@ -41,17 +41,13 @@ static void dump_run(void) die("non-threaded code path used"); } - dir = hashmap_iter_first(&the_index.dir_hash, &iter_dir); - while (dir) { + hashmap_for_each_entry(&the_index.dir_hash, &iter_dir, dir, + ent /* member name */) printf("dir %08x %7d %s\n", dir->ent.hash, dir->nr, dir->name); - dir = hashmap_iter_next(&iter_dir); - } - ce = hashmap_iter_first(&the_index.name_hash, &iter_cache); - while (ce) { + hashmap_for_each_entry(&the_index.name_hash, &iter_cache, ce, + ent /* member name */) printf("name %08x %s\n", ce->ent.hash, ce->name); - ce = hashmap_iter_next(&iter_cache); - } discard_cache(); } diff --git a/t/helper/test-match-trees.c b/t/helper/test-match-trees.c index 96857f26ac..b9fd427571 100644 --- a/t/helper/test-match-trees.c +++ b/t/helper/test-match-trees.c @@ -20,7 +20,7 @@ int cmd__match_trees(int ac, const char **av) if (!two) die("not a tree-ish %s", av[2]); - shift_tree(&one->object.oid, &two->object.oid, &shifted, -1); + shift_tree(the_repository, &one->object.oid, &two->object.oid, &shifted, -1); printf("shifted: %s\n", oid_to_hex(&shifted)); exit(0); diff --git a/t/helper/test-oidmap.c b/t/helper/test-oidmap.c new file mode 100644 index 0000000000..0acf99931e --- /dev/null +++ b/t/helper/test-oidmap.c @@ -0,0 +1,112 @@ +#include "test-tool.h" +#include "cache.h" +#include "oidmap.h" +#include "strbuf.h" + +/* key is an oid and value is a name (could be a refname for example) */ +struct test_entry { + struct oidmap_entry entry; + char name[FLEX_ARRAY]; +}; + +#define DELIM " \t\r\n" + +/* + * Read stdin line by line and print result of commands to stdout: + * + * hash oidkey -> sha1hash(oidkey) + * put oidkey namevalue -> NULL / old namevalue + * get oidkey -> NULL / namevalue + * remove oidkey -> NULL / old namevalue + * iterate -> oidkey1 namevalue1\noidkey2 namevalue2\n... + * + */ +int cmd__oidmap(int argc, const char **argv) +{ + struct strbuf line = STRBUF_INIT; + struct oidmap map = OIDMAP_INIT; + + setup_git_directory(); + + /* init oidmap */ + oidmap_init(&map, 0); + + /* process commands from stdin */ + while (strbuf_getline(&line, stdin) != EOF) { + char *cmd, *p1 = NULL, *p2 = NULL; + struct test_entry *entry; + struct object_id oid; + + /* break line into command and up to two parameters */ + cmd = strtok(line.buf, DELIM); + /* ignore empty lines */ + if (!cmd || *cmd == '#') + continue; + + p1 = strtok(NULL, DELIM); + if (p1) + p2 = strtok(NULL, DELIM); + + if (!strcmp("put", cmd) && p1 && p2) { + + if (get_oid(p1, &oid)) { + printf("Unknown oid: %s\n", p1); + continue; + } + + /* create entry with oid_key = p1, name_value = p2 */ + FLEX_ALLOC_STR(entry, name, p2); + oidcpy(&entry->entry.oid, &oid); + + /* add / replace entry */ + entry = oidmap_put(&map, entry); + + /* print and free replaced entry, if any */ + puts(entry ? entry->name : "NULL"); + free(entry); + + } else if (!strcmp("get", cmd) && p1) { + + if (get_oid(p1, &oid)) { + printf("Unknown oid: %s\n", p1); + continue; + } + + /* lookup entry in oidmap */ + entry = oidmap_get(&map, &oid); + + /* print result */ + puts(entry ? entry->name : "NULL"); + + } else if (!strcmp("remove", cmd) && p1) { + + if (get_oid(p1, &oid)) { + printf("Unknown oid: %s\n", p1); + continue; + } + + /* remove entry from oidmap */ + entry = oidmap_remove(&map, &oid); + + /* print result and free entry*/ + puts(entry ? entry->name : "NULL"); + free(entry); + + } else if (!strcmp("iterate", cmd)) { + + struct oidmap_iter iter; + oidmap_iter_init(&map, &iter); + while ((entry = oidmap_iter_next(&iter))) + printf("%s %s\n", oid_to_hex(&entry->entry.oid), entry->name); + + } else { + + printf("Unknown command %s\n", cmd); + + } + } + + strbuf_release(&line); + oidmap_free(&map, 1); + return 0; +} diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c index 5d543ad21f..409034cf4e 100644 --- a/t/helper/test-path-utils.c +++ b/t/helper/test-path-utils.c @@ -185,6 +185,99 @@ static int cmp_by_st_size(const void *a, const void *b) return x > y ? -1 : (x < y ? +1 : 0); } +/* + * A very simple, reproducible pseudo-random generator. Copied from + * `test-genrandom.c`. + */ +static uint64_t my_random_value = 1234; + +static uint64_t my_random(void) +{ + my_random_value = my_random_value * 1103515245 + 12345; + return my_random_value; +} + +/* + * A fast approximation of the square root, without requiring math.h. + * + * It uses Newton's method to approximate the solution of 0 = x^2 - value. + */ +static double my_sqrt(double value) +{ + const double epsilon = 1e-6; + double x = value; + + if (value == 0) + return 0; + + for (;;) { + double delta = (value / x - x) / 2; + if (delta < epsilon && delta > -epsilon) + return x + delta; + x += delta; + } +} + +static int protect_ntfs_hfs_benchmark(int argc, const char **argv) +{ + size_t i, j, nr, min_len = 3, max_len = 20; + char **names; + int repetitions = 15, file_mode = 0100644; + uint64_t begin, end; + double m[3][2], v[3][2]; + uint64_t cumul; + double cumul2; + + if (argc > 1 && !strcmp(argv[1], "--with-symlink-mode")) { + file_mode = 0120000; + argc--; + argv++; + } + + nr = argc > 1 ? strtoul(argv[1], NULL, 0) : 1000000; + ALLOC_ARRAY(names, nr); + + if (argc > 2) { + min_len = strtoul(argv[2], NULL, 0); + if (argc > 3) + max_len = strtoul(argv[3], NULL, 0); + if (min_len > max_len) + die("min_len > max_len"); + } + + for (i = 0; i < nr; i++) { + size_t len = min_len + (my_random() % (max_len + 1 - min_len)); + + names[i] = xmallocz(len); + while (len > 0) + names[i][--len] = (char)(' ' + (my_random() % ('\x7f' - ' '))); + } + + for (protect_ntfs = 0; protect_ntfs < 2; protect_ntfs++) + for (protect_hfs = 0; protect_hfs < 2; protect_hfs++) { + cumul = 0; + cumul2 = 0; + for (i = 0; i < repetitions; i++) { + begin = getnanotime(); + for (j = 0; j < nr; j++) + verify_path(names[j], file_mode); + end = getnanotime(); + printf("protect_ntfs = %d, protect_hfs = %d: %lfms\n", protect_ntfs, protect_hfs, (end-begin) / (double)1e6); + cumul += end - begin; + cumul2 += (end - begin) * (end - begin); + } + m[protect_ntfs][protect_hfs] = cumul / (double)repetitions; + v[protect_ntfs][protect_hfs] = my_sqrt(cumul2 / (double)repetitions - m[protect_ntfs][protect_hfs] * m[protect_ntfs][protect_hfs]); + printf("mean: %lfms, stddev: %lfms\n", m[protect_ntfs][protect_hfs] / (double)1e6, v[protect_ntfs][protect_hfs] / (double)1e6); + } + + for (protect_ntfs = 0; protect_ntfs < 2; protect_ntfs++) + for (protect_hfs = 0; protect_hfs < 2; protect_hfs++) + printf("ntfs=%d/hfs=%d: %lf%% slower\n", protect_ntfs, protect_hfs, (m[protect_ntfs][protect_hfs] - m[0][0]) * 100 / m[0][0]); + + return 0; +} + int cmd__path_utils(int argc, const char **argv) { if (argc == 3 && !strcmp(argv[1], "normalize_path_copy")) { @@ -355,6 +448,26 @@ int cmd__path_utils(int argc, const char **argv) return !!res; } + if (argc > 1 && !strcmp(argv[1], "protect_ntfs_hfs")) + return !!protect_ntfs_hfs_benchmark(argc - 1, argv + 1); + + if (argc > 1 && !strcmp(argv[1], "is_valid_path")) { + int res = 0, expect = 1, i; + + for (i = 2; i < argc; i++) + if (!strcmp("--not", argv[i])) + expect = 0; + else if (expect != is_valid_path(argv[i])) + res = error("'%s' is%s a valid path", + argv[i], expect ? " not" : ""); + else + fprintf(stderr, + "'%s' is%s a valid path\n", + argv[i], expect ? "" : " not"); + + return !!res; + } + fprintf(stderr, "%s: unknown function name: %s\n", argv[0], argv[1] ? argv[1] : "(there was none)"); return 1; diff --git a/t/helper/test-progress.c b/t/helper/test-progress.c new file mode 100644 index 0000000000..42b96cb103 --- /dev/null +++ b/t/helper/test-progress.c @@ -0,0 +1,81 @@ +/* + * A test helper to exercise the progress display. + * + * Reads instructions from standard input, one instruction per line: + * + * "progress <items>" - Call display_progress() with the given item count + * as parameter. + * "throughput <bytes> <millis> - Call display_throughput() with the given + * byte count as parameter. The 'millis' + * specify the time elapsed since the + * start_progress() call. + * "update" - Set the 'progress_update' flag. + * + * See 't0500-progress-display.sh' for examples. + */ +#include "test-tool.h" +#include "gettext.h" +#include "parse-options.h" +#include "progress.h" +#include "strbuf.h" + +/* + * These are defined in 'progress.c', but are not exposed in 'progress.h', + * because they are exclusively for testing. + */ +extern int progress_testing; +extern uint64_t progress_test_ns; +void progress_test_force_update(void); + +int cmd__progress(int argc, const char **argv) +{ + int total = 0; + const char *title; + struct strbuf line = STRBUF_INIT; + struct progress *progress; + + const char *usage[] = { + "test-tool progress [--total=<n>] <progress-title>", + NULL + }; + struct option options[] = { + OPT_INTEGER(0, "total", &total, "total number of items"), + OPT_END(), + }; + + argc = parse_options(argc, argv, NULL, options, usage, 0); + if (argc != 1) + die("need a title for the progress output"); + title = argv[0]; + + progress_testing = 1; + progress = start_progress(title, total); + while (strbuf_getline(&line, stdin) != EOF) { + char *end; + + if (skip_prefix(line.buf, "progress ", (const char **) &end)) { + uint64_t item_count = strtoull(end, &end, 10); + if (*end != '\0') + die("invalid input: '%s'\n", line.buf); + display_progress(progress, item_count); + } else if (skip_prefix(line.buf, "throughput ", + (const char **) &end)) { + uint64_t byte_count, test_ms; + + byte_count = strtoull(end, &end, 10); + if (*end != ' ') + die("invalid input: '%s'\n", line.buf); + test_ms = strtoull(end + 1, &end, 10); + if (*end != '\0') + die("invalid input: '%s'\n", line.buf); + progress_test_ns = test_ms * 1000 * 1000; + display_throughput(progress, byte_count); + } else if (!strcmp(line.buf, "update")) + progress_test_force_update(); + else + die("invalid input: '%s'\n", line.buf); + } + stop_progress(&progress); + + return 0; +} diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c index 7e79b555de..244977a29b 100644 --- a/t/helper/test-read-cache.c +++ b/t/helper/test-read-cache.c @@ -4,11 +4,10 @@ int cmd__read_cache(int argc, const char **argv) { - int i, cnt = 1, namelen; + int i, cnt = 1; const char *name = NULL; if (argc > 1 && skip_prefix(argv[1], "--print-and-refresh=", &name)) { - namelen = strlen(name); argc--; argv++; } @@ -24,7 +23,7 @@ int cmd__read_cache(int argc, const char **argv) refresh_index(&the_index, REFRESH_QUIET, NULL, NULL, NULL); - pos = index_name_pos(&the_index, name, namelen); + pos = index_name_pos(&the_index, name, strlen(name)); if (pos < 0) die("%s not in index", name); printf("%s is%s up to date\n", name, diff --git a/t/helper/test-read-graph.c b/t/helper/test-read-graph.c new file mode 100644 index 0000000000..d2884efe0a --- /dev/null +++ b/t/helper/test-read-graph.c @@ -0,0 +1,53 @@ +#include "test-tool.h" +#include "cache.h" +#include "commit-graph.h" +#include "repository.h" +#include "object-store.h" + +int cmd__read_graph(int argc, const char **argv) +{ + struct commit_graph *graph = NULL; + char *graph_name; + int open_ok; + int fd; + struct stat st; + const char *object_dir; + + setup_git_directory(); + object_dir = get_object_directory(); + + graph_name = get_commit_graph_filename(object_dir); + + open_ok = open_commit_graph(graph_name, &fd, &st); + if (!open_ok) + die_errno(_("Could not open commit-graph '%s'"), graph_name); + + graph = load_commit_graph_one_fd_st(fd, &st); + if (!graph) + return 1; + + FREE_AND_NULL(graph_name); + + printf("header: %08x %d %d %d %d\n", + ntohl(*(uint32_t*)graph->data), + *(unsigned char*)(graph->data + 4), + *(unsigned char*)(graph->data + 5), + *(unsigned char*)(graph->data + 6), + *(unsigned char*)(graph->data + 7)); + printf("num_commits: %u\n", graph->num_commits); + printf("chunks:"); + + if (graph->chunk_oid_fanout) + printf(" oid_fanout"); + if (graph->chunk_oid_lookup) + printf(" oid_lookup"); + if (graph->chunk_commit_data) + printf(" commit_metadata"); + if (graph->chunk_extra_edges) + printf(" extra_edges"); + printf("\n"); + + UNLEAK(graph); + + return 0; +} diff --git a/t/helper/test-run-command.c b/t/helper/test-run-command.c index 2cc93bb69c..1646aa25d8 100644 --- a/t/helper/test-run-command.c +++ b/t/helper/test-run-command.c @@ -10,11 +10,16 @@ #include "test-tool.h" #include "git-compat-util.h" +#include "cache.h" #include "run-command.h" #include "argv-array.h" #include "strbuf.h" -#include <string.h> -#include <errno.h> +#include "parse-options.h" +#include "string-list.h" +#include "thread-utils.h" +#include "wildmatch.h" +#include "gettext.h" +#include "parse-options.h" static int number_callbacks; static int parallel_next(struct child_process *cp, @@ -50,11 +55,337 @@ static int task_finished(int result, return 1; } +struct testsuite { + struct string_list tests, failed; + int next; + int quiet, immediate, verbose, verbose_log, trace, write_junit_xml; +}; +#define TESTSUITE_INIT \ + { STRING_LIST_INIT_DUP, STRING_LIST_INIT_DUP, -1, 0, 0, 0, 0, 0, 0 } + +static int next_test(struct child_process *cp, struct strbuf *err, void *cb, + void **task_cb) +{ + struct testsuite *suite = cb; + const char *test; + if (suite->next >= suite->tests.nr) + return 0; + + test = suite->tests.items[suite->next++].string; + argv_array_pushl(&cp->args, "sh", test, NULL); + if (suite->quiet) + argv_array_push(&cp->args, "--quiet"); + if (suite->immediate) + argv_array_push(&cp->args, "-i"); + if (suite->verbose) + argv_array_push(&cp->args, "-v"); + if (suite->verbose_log) + argv_array_push(&cp->args, "-V"); + if (suite->trace) + argv_array_push(&cp->args, "-x"); + if (suite->write_junit_xml) + argv_array_push(&cp->args, "--write-junit-xml"); + + strbuf_addf(err, "Output of '%s':\n", test); + *task_cb = (void *)test; + + return 1; +} + +static int test_finished(int result, struct strbuf *err, void *cb, + void *task_cb) +{ + struct testsuite *suite = cb; + const char *name = (const char *)task_cb; + + if (result) + string_list_append(&suite->failed, name); + + strbuf_addf(err, "%s: '%s'\n", result ? "FAIL" : "SUCCESS", name); + + return 0; +} + +static int test_failed(struct strbuf *out, void *cb, void *task_cb) +{ + struct testsuite *suite = cb; + const char *name = (const char *)task_cb; + + string_list_append(&suite->failed, name); + strbuf_addf(out, "FAILED TO START: '%s'\n", name); + + return 0; +} + +static const char * const testsuite_usage[] = { + "test-run-command testsuite [<options>] [<pattern>...]", + NULL +}; + +static int testsuite(int argc, const char **argv) +{ + struct testsuite suite = TESTSUITE_INIT; + int max_jobs = 1, i, ret; + DIR *dir; + struct dirent *d; + struct option options[] = { + OPT_BOOL('i', "immediate", &suite.immediate, + "stop at first failed test case(s)"), + OPT_INTEGER('j', "jobs", &max_jobs, "run <N> jobs in parallel"), + OPT_BOOL('q', "quiet", &suite.quiet, "be terse"), + OPT_BOOL('v', "verbose", &suite.verbose, "be verbose"), + OPT_BOOL('V', "verbose-log", &suite.verbose_log, + "be verbose, redirected to a file"), + OPT_BOOL('x', "trace", &suite.trace, "trace shell commands"), + OPT_BOOL(0, "write-junit-xml", &suite.write_junit_xml, + "write JUnit-style XML files"), + OPT_END() + }; + + memset(&suite, 0, sizeof(suite)); + suite.tests.strdup_strings = suite.failed.strdup_strings = 1; + + argc = parse_options(argc, argv, NULL, options, + testsuite_usage, PARSE_OPT_STOP_AT_NON_OPTION); + + if (max_jobs <= 0) + max_jobs = online_cpus(); + + dir = opendir("."); + if (!dir) + die("Could not open the current directory"); + while ((d = readdir(dir))) { + const char *p = d->d_name; + + if (*p != 't' || !isdigit(p[1]) || !isdigit(p[2]) || + !isdigit(p[3]) || !isdigit(p[4]) || p[5] != '-' || + !ends_with(p, ".sh")) + continue; + + /* No pattern: match all */ + if (!argc) { + string_list_append(&suite.tests, p); + continue; + } + + for (i = 0; i < argc; i++) + if (!wildmatch(argv[i], p, 0)) { + string_list_append(&suite.tests, p); + break; + } + } + closedir(dir); + + if (!suite.tests.nr) + die("No tests match!"); + if (max_jobs > suite.tests.nr) + max_jobs = suite.tests.nr; + + fprintf(stderr, "Running %d tests (%d at a time)\n", + suite.tests.nr, max_jobs); + + ret = run_processes_parallel(max_jobs, next_test, test_failed, + test_finished, &suite); + + if (suite.failed.nr > 0) { + ret = 1; + fprintf(stderr, "%d tests failed:\n\n", suite.failed.nr); + for (i = 0; i < suite.failed.nr; i++) + fprintf(stderr, "\t%s\n", suite.failed.items[i].string); + } + + string_list_clear(&suite.tests, 0); + string_list_clear(&suite.failed, 0); + + return !!ret; +} + +static uint64_t my_random_next = 1234; + +static uint64_t my_random(void) +{ + uint64_t res = my_random_next; + my_random_next = my_random_next * 1103515245 + 12345; + return res; +} + +static int quote_stress_test(int argc, const char **argv) +{ + /* + * We are running a quote-stress test. + * spawn a subprocess that runs quote-stress with a + * special option that echoes back the arguments that + * were passed in. + */ + char special[] = ".?*\\^_\"'`{}()[]<>@~&+:;$%"; // \t\r\n\a"; + int i, j, k, trials = 100, skip = 0, msys2 = 0; + struct strbuf out = STRBUF_INIT; + struct argv_array args = ARGV_ARRAY_INIT; + struct option options[] = { + OPT_INTEGER('n', "trials", &trials, "Number of trials"), + OPT_INTEGER('s', "skip", &skip, "Skip <n> trials"), + OPT_BOOL('m', "msys2", &msys2, "Test quoting for MSYS2's sh"), + OPT_END() + }; + const char * const usage[] = { + "test-tool run-command quote-stress-test <options>", + NULL + }; + + argc = parse_options(argc, argv, NULL, options, usage, 0); + + setenv("MSYS_NO_PATHCONV", "1", 0); + + for (i = 0; i < trials; i++) { + struct child_process cp = CHILD_PROCESS_INIT; + size_t arg_count, arg_offset; + int ret = 0; + + argv_array_clear(&args); + if (msys2) + argv_array_pushl(&args, "sh", "-c", + "printf %s\\\\0 \"$@\"", "skip", NULL); + else + argv_array_pushl(&args, "test-tool", "run-command", + "quote-echo", NULL); + arg_offset = args.argc; + + if (argc > 0) { + trials = 1; + arg_count = argc; + for (j = 0; j < arg_count; j++) + argv_array_push(&args, argv[j]); + } else { + arg_count = 1 + (my_random() % 5); + for (j = 0; j < arg_count; j++) { + char buf[20]; + size_t min_len = 1; + size_t arg_len = min_len + + (my_random() % (ARRAY_SIZE(buf) - min_len)); + + for (k = 0; k < arg_len; k++) + buf[k] = special[my_random() % + ARRAY_SIZE(special)]; + buf[arg_len] = '\0'; + + argv_array_push(&args, buf); + } + } + + if (i < skip) + continue; + + cp.argv = args.argv; + strbuf_reset(&out); + if (pipe_command(&cp, NULL, 0, &out, 0, NULL, 0) < 0) + return error("Failed to spawn child process"); + + for (j = 0, k = 0; j < arg_count; j++) { + const char *arg = args.argv[j + arg_offset]; + + if (strcmp(arg, out.buf + k)) + ret = error("incorrectly quoted arg: '%s', " + "echoed back as '%s'", + arg, out.buf + k); + k += strlen(out.buf + k) + 1; + } + + if (k != out.len) + ret = error("got %d bytes, but consumed only %d", + (int)out.len, (int)k); + + if (ret) { + fprintf(stderr, "Trial #%d failed. Arguments:\n", i); + for (j = 0; j < arg_count; j++) + fprintf(stderr, "arg #%d: '%s'\n", + (int)j, args.argv[j + arg_offset]); + + strbuf_release(&out); + argv_array_clear(&args); + + return ret; + } + + if (i && (i % 100) == 0) + fprintf(stderr, "Trials completed: %d\n", (int)i); + } + + strbuf_release(&out); + argv_array_clear(&args); + + return 0; +} + +static int quote_echo(int argc, const char **argv) +{ + while (argc > 1) { + fwrite(argv[1], strlen(argv[1]), 1, stdout); + fputc('\0', stdout); + argv++; + argc--; + } + + return 0; +} + +static int inherit_handle(const char *argv0) +{ + struct child_process cp = CHILD_PROCESS_INIT; + char path[PATH_MAX]; + int tmp; + + /* First, open an inheritable handle */ + xsnprintf(path, sizeof(path), "out-XXXXXX"); + tmp = xmkstemp(path); + + argv_array_pushl(&cp.args, + "test-tool", argv0, "inherited-handle-child", NULL); + cp.in = -1; + cp.no_stdout = cp.no_stderr = 1; + if (start_command(&cp) < 0) + die("Could not start child process"); + + /* Then close it, and try to delete it. */ + close(tmp); + if (unlink(path)) + die("Could not delete '%s'", path); + + if (close(cp.in) < 0 || finish_command(&cp) < 0) + die("Child did not finish"); + + return 0; +} + +static int inherit_handle_child(void) +{ + struct strbuf buf = STRBUF_INIT; + + if (strbuf_read(&buf, 0, 0) < 0) + die("Could not read stdin"); + printf("Received %s\n", buf.buf); + strbuf_release(&buf); + + return 0; +} + int cmd__run_command(int argc, const char **argv) { struct child_process proc = CHILD_PROCESS_INIT; int jobs; + if (argc > 1 && !strcmp(argv[1], "testsuite")) + exit(testsuite(argc - 1, argv + 1)); + if (!strcmp(argv[1], "inherited-handle")) + exit(inherit_handle(argv[0])); + if (!strcmp(argv[1], "inherited-handle-child")) + exit(inherit_handle_child()); + + if (argc >= 2 && !strcmp(argv[1], "quote-stress-test")) + return !!quote_stress_test(argc - 1, argv + 1); + + if (argc >= 2 && !strcmp(argv[1], "quote-echo")) + return !!quote_echo(argc - 1, argv + 1); + if (argc < 3) return 1; while (!strcmp(argv[1], "env")) { diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c index 087a8c0cc9..f20989d449 100644 --- a/t/helper/test-tool.c +++ b/t/helper/test-tool.c @@ -19,6 +19,7 @@ static struct test_cmd cmds[] = { { "ctype", cmd__ctype }, { "date", cmd__date }, { "delta", cmd__delta }, + { "dir-iterator", cmd__dir_iterator }, { "drop-caches", cmd__drop_caches }, { "dump-cache-tree", cmd__dump_cache_tree }, { "dump-fsmonitor", cmd__dump_fsmonitor }, @@ -35,13 +36,16 @@ static struct test_cmd cmds[] = { { "match-trees", cmd__match_trees }, { "mergesort", cmd__mergesort }, { "mktemp", cmd__mktemp }, + { "oidmap", cmd__oidmap }, { "online-cpus", cmd__online_cpus }, { "parse-options", cmd__parse_options }, { "path-utils", cmd__path_utils }, { "pkt-line", cmd__pkt_line }, { "prio-queue", cmd__prio_queue }, + { "progress", cmd__progress }, { "reach", cmd__reach }, { "read-cache", cmd__read_cache }, + { "read-graph", cmd__read_graph }, { "read-midx", cmd__read_midx }, { "ref-store", cmd__ref_store }, { "regex", cmd__regex }, diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h index 7e703f3038..8ed2af71d1 100644 --- a/t/helper/test-tool.h +++ b/t/helper/test-tool.h @@ -9,6 +9,7 @@ int cmd__config(int argc, const char **argv); int cmd__ctype(int argc, const char **argv); int cmd__date(int argc, const char **argv); int cmd__delta(int argc, const char **argv); +int cmd__dir_iterator(int argc, const char **argv); int cmd__drop_caches(int argc, const char **argv); int cmd__dump_cache_tree(int argc, const char **argv); int cmd__dump_fsmonitor(int argc, const char **argv); @@ -25,13 +26,16 @@ int cmd__lazy_init_name_hash(int argc, const char **argv); int cmd__match_trees(int argc, const char **argv); int cmd__mergesort(int argc, const char **argv); int cmd__mktemp(int argc, const char **argv); +int cmd__oidmap(int argc, const char **argv); int cmd__online_cpus(int argc, const char **argv); int cmd__parse_options(int argc, const char **argv); int cmd__path_utils(int argc, const char **argv); int cmd__pkt_line(int argc, const char **argv); int cmd__prio_queue(int argc, const char **argv); +int cmd__progress(int argc, const char **argv); int cmd__reach(int argc, const char **argv); int cmd__read_cache(int argc, const char **argv); +int cmd__read_graph(int argc, const char **argv); int cmd__read_midx(int argc, const char **argv); int cmd__ref_store(int argc, const char **argv); int cmd__regex(int argc, const char **argv); diff --git a/t/lib-git-daemon.sh b/t/lib-git-daemon.sh index 7b3407134e..e62569222b 100644 --- a/t/lib-git-daemon.sh +++ b/t/lib-git-daemon.sh @@ -15,8 +15,7 @@ # # test_done -test_tristate GIT_TEST_GIT_DAEMON -if test "$GIT_TEST_GIT_DAEMON" = false +if ! test_bool_env GIT_TEST_GIT_DAEMON true then skip_all="git-daemon testing disabled (unset GIT_TEST_GIT_DAEMON to enable)" test_done @@ -24,7 +23,7 @@ fi if test_have_prereq !PIPE then - test_skip_or_die $GIT_TEST_GIT_DAEMON "file system does not support FIFOs" + test_skip_or_die GIT_TEST_GIT_DAEMON "file system does not support FIFOs" fi test_set_port LIB_GIT_DAEMON_PORT @@ -73,7 +72,7 @@ start_git_daemon() { kill "$GIT_DAEMON_PID" wait "$GIT_DAEMON_PID" unset GIT_DAEMON_PID - test_skip_or_die $GIT_TEST_GIT_DAEMON \ + test_skip_or_die GIT_TEST_GIT_DAEMON \ "git daemon failed to start" fi } diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh index c1271d6863..7d248e6588 100644 --- a/t/lib-git-svn.sh +++ b/t/lib-git-svn.sh @@ -69,14 +69,12 @@ svn_cmd () { maybe_start_httpd () { loc=${1-svn} - test_tristate GIT_SVN_TEST_HTTPD - case $GIT_SVN_TEST_HTTPD in - true) + if test_bool_env GIT_TEST_SVN_HTTPD false + then . "$TEST_DIRECTORY"/lib-httpd.sh LIB_HTTPD_SVN="$loc" start_httpd - ;; - esac + fi } convert_to_rev_db () { @@ -106,8 +104,7 @@ EOF } require_svnserve () { - test_tristate GIT_TEST_SVNSERVE - if ! test "$GIT_TEST_SVNSERVE" = true + if ! test_bool_env GIT_TEST_SVNSERVE false then skip_all='skipping svnserve test. (set $GIT_TEST_SVNSERVE to enable)' test_done diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh index b3cc62bd36..656997b4d6 100644 --- a/t/lib-httpd.sh +++ b/t/lib-httpd.sh @@ -41,15 +41,14 @@ then test_done fi -test_tristate GIT_TEST_HTTPD -if test "$GIT_TEST_HTTPD" = false +if ! test_bool_env GIT_TEST_HTTPD true then skip_all="Network testing disabled (unset GIT_TEST_HTTPD to enable)" test_done fi if ! test_have_prereq NOT_ROOT; then - test_skip_or_die $GIT_TEST_HTTPD \ + test_skip_or_die GIT_TEST_HTTPD \ "Cannot run httpd tests as root" fi @@ -95,7 +94,7 @@ GIT_TRACE=$GIT_TRACE; export GIT_TRACE if ! test -x "$LIB_HTTPD_PATH" then - test_skip_or_die $GIT_TEST_HTTPD "no web server found at '$LIB_HTTPD_PATH'" + test_skip_or_die GIT_TEST_HTTPD "no web server found at '$LIB_HTTPD_PATH'" fi HTTPD_VERSION=$($LIB_HTTPD_PATH -v | \ @@ -107,19 +106,19 @@ then then if ! test $HTTPD_VERSION -ge 2 then - test_skip_or_die $GIT_TEST_HTTPD \ + test_skip_or_die GIT_TEST_HTTPD \ "at least Apache version 2 is required" fi if ! test -d "$DEFAULT_HTTPD_MODULE_PATH" then - test_skip_or_die $GIT_TEST_HTTPD \ + test_skip_or_die GIT_TEST_HTTPD \ "Apache module directory not found" fi LIB_HTTPD_MODULE_PATH="$DEFAULT_HTTPD_MODULE_PATH" fi else - test_skip_or_die $GIT_TEST_HTTPD \ + test_skip_or_die GIT_TEST_HTTPD \ "Could not identify web server at '$LIB_HTTPD_PATH'" fi @@ -184,7 +183,7 @@ start_httpd() { if test $? -ne 0 then cat "$HTTPD_ROOT_PATH"/error.log >&4 2>/dev/null - test_skip_or_die $GIT_TEST_HTTPD "web server setup failed" + test_skip_or_die GIT_TEST_HTTPD "web server setup failed" fi } diff --git a/t/lib-patch-mode.sh b/t/lib-patch-mode.sh index 06c3c91762..cfd76bf987 100644 --- a/t/lib-patch-mode.sh +++ b/t/lib-patch-mode.sh @@ -2,28 +2,40 @@ . ./test-lib.sh +# set_state <path> <worktree-content> <index-content> +# +# Prepare the content for path in worktree and the index as specified. set_state () { echo "$3" > "$1" && git add "$1" && echo "$2" > "$1" } +# save_state <path> +# +# Save index/worktree content of <path> in the files _worktree_<path> +# and _index_<path> save_state () { noslash="$(echo "$1" | tr / _)" && cat "$1" > _worktree_"$noslash" && git show :"$1" > _index_"$noslash" } +# set_and_save_state <path> <worktree-content> <index-content> set_and_save_state () { set_state "$@" && save_state "$1" } +# verify_state <path> <expected-worktree-content> <expected-index-content> verify_state () { test "$(cat "$1")" = "$2" && test "$(git show :"$1")" = "$3" } +# verify_saved_state <path> +# +# Call verify_state with expected contents from the last save_state verify_saved_state () { noslash="$(echo "$1" | tr / _)" && verify_state "$1" "$(cat _worktree_"$noslash")" "$(cat _index_"$noslash")" diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh index 7ea30e5006..b72c051f47 100644 --- a/t/lib-rebase.sh +++ b/t/lib-rebase.sh @@ -44,10 +44,10 @@ set_fake_editor () { rm -f "$1" echo 'rebase -i script before editing:' cat "$1".tmp - action=pick + action=\& for line in $FAKE_LINES; do case $line in - pick|p|squash|s|fixup|f|edit|e|reword|r|drop|d) + pick|p|squash|s|fixup|f|edit|e|reword|r|drop|d|label|l|reset|r|merge|m) action="$line";; exec_*|x_*|break|b) echo "$line" | sed 's/_/ /g' >> "$1";; @@ -58,11 +58,12 @@ set_fake_editor () { bad) action="badcmd";; fakesha) + test \& != "$action" || action=pick echo "$action XXXXXXX False commit" >> "$1" action=pick;; *) - sed -n "${line}s/^pick/$action/p" < "$1".tmp >> "$1" - action=pick;; + sed -n "${line}s/^[a-z][a-z]*/$action/p" < "$1".tmp >> "$1" + action=\&;; esac done echo 'rebase -i script after editing:' @@ -118,3 +119,31 @@ make_empty () { git commit --allow-empty -m "$1" && git tag "$1" } + +# Call this (inside test_expect_success) at the end of a test file to +# check that no tests have changed editor related environment +# variables or config settings +test_editor_unchanged () { + # We're only interested in exported variables hence 'sh -c' + sh -c 'cat >actual <<-EOF + EDITOR=$EDITOR + FAKE_COMMIT_AMEND=$FAKE_COMMIT_AMEND + FAKE_COMMIT_MESSAGE=$FAKE_COMMIT_MESSAGE + FAKE_LINES=$FAKE_LINES + GIT_EDITOR=$GIT_EDITOR + GIT_SEQUENCE_EDITOR=$GIT_SEQUENCE_EDITOR + core.editor=$(git config core.editor) + sequence.editor=$(git config sequence.editor) + EOF' + cat >expect <<-\EOF + EDITOR=: + FAKE_COMMIT_AMEND= + FAKE_COMMIT_MESSAGE= + FAKE_LINES= + GIT_EDITOR= + GIT_SEQUENCE_EDITOR= + core.editor= + sequence.editor= + EOF + test_cmp expect actual +} diff --git a/t/oid-info/hash-info b/t/oid-info/hash-info index ccdbfdf974..d0736dd1a0 100644 --- a/t/oid-info/hash-info +++ b/t/oid-info/hash-info @@ -6,3 +6,12 @@ hexsz sha256:64 zero sha1:0000000000000000000000000000000000000000 zero sha256:0000000000000000000000000000000000000000000000000000000000000000 + +algo sha1:sha1 +algo sha256:sha256 + +empty_blob sha1:e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 +empty_blob sha256:473a0f4c3be8a93681a267e3b1e9a7dcda1185436fe141f7749120a303721813 + +empty_tree sha1:4b825dc642cb6eb9a060e54bf8d69288fbee4904 +empty_tree sha256:6ef19b41225c5369f1c104d45d8d85efa9b057b53b14b4b9b939dd74decc5321 diff --git a/t/perf/aggregate.perl b/t/perf/aggregate.perl index 66554d2161..14e4cda287 100755 --- a/t/perf/aggregate.perl +++ b/t/perf/aggregate.perl @@ -4,7 +4,6 @@ use lib '../../perl/build/lib'; use strict; use warnings; use Getopt::Long; -use Git; use Cwd qw(realpath); sub get_times { @@ -85,6 +84,11 @@ sub format_size { return $out; } +sub sane_backticks { + open(my $fh, '-|', @_); + return <$fh>; +} + my (@dirs, %dirnames, %dirabbrevs, %prefixes, @tests, $codespeed, $sortby, $subsection, $reponame); @@ -102,7 +106,8 @@ while (scalar @ARGV) { my $prefix = ''; last if -f $arg or $arg eq "--"; if (! -d $arg) { - my $rev = Git::command_oneline(qw(rev-parse --verify), $arg); + my $rev = sane_backticks(qw(git rev-parse --verify), $arg); + chomp $rev; $dir = "build/".$rev; } elsif ($arg eq '.') { $dir = '.'; @@ -219,13 +224,7 @@ sub print_default_results { for my $i (0..$#dirs) { my $d = $dirs[$i]; my $base = "$resultsdir/$prefixes{$d}$t"; - $times{$prefixes{$d}.$t} = []; - foreach my $type (qw(times size)) { - if (-e "$base.$type") { - $times{$prefixes{$d}.$t} = [get_times("$base.$type")]; - last; - } - } + $times{$prefixes{$d}.$t} = [get_times("$base.result")]; my ($r,$u,$s) = @{$times{$prefixes{$d}.$t}}; my $w = length format_times($r,$u,$s,$firstr); $colwidth[$i] = $w if $w > $colwidth[$i]; @@ -267,7 +266,7 @@ sub print_sorted_results { my ($prevr, $prevu, $prevs, $prevrev); for my $i (0..$#dirs) { my $d = $dirs[$i]; - my ($r, $u, $s) = get_times("$resultsdir/$prefixes{$d}$t.times"); + my ($r, $u, $s) = get_times("$resultsdir/$prefixes{$d}$t.result"); if ($i > 0 and defined $r and defined $prevr and $prevr > 0) { my $percent = 100.0 * ($r - $prevr) / $prevr; push @evolutions, { "percent" => $percent, @@ -327,7 +326,7 @@ sub print_codespeed_results { my $commitid = $prefixes{$d}; $commitid =~ s/^build_//; $commitid =~ s/\.$//; - my ($result_value, $u, $s) = get_times("$resultsdir/$prefixes{$d}$t.times"); + my ($result_value, $u, $s) = get_times("$resultsdir/$prefixes{$d}$t.result"); my %vals = ( "commitid" => $commitid, diff --git a/t/perf/bisect_regression b/t/perf/bisect_regression index a94d9955d0..ce47e1662a 100755 --- a/t/perf/bisect_regression +++ b/t/perf/bisect_regression @@ -51,7 +51,7 @@ oldtime=$(echo "$oldtime" | sed -e 's/^\([0-9]\+\.[0-9]\+\).*$/\1/') newtime=$(echo "$newtime" | sed -e 's/^\([0-9]\+\.[0-9]\+\).*$/\1/') test $(echo "$newtime" "$oldtime" | awk '{ print ($1 > $2) }') = 1 || - die "New time '$newtime' shoud be greater than old time '$oldtime'" + die "New time '$newtime' should be greater than old time '$oldtime'" tmpdir=$(mktemp -d -t bisect_regression_XXXXXX) || die "Failed to create temp directory" echo "$oldtime" >"$tmpdir/oldtime" || die "Failed to write to '$tmpdir/oldtime'" diff --git a/t/perf/p5303-many-packs.sh b/t/perf/p5303-many-packs.sh index 3779851941..a369152c47 100755 --- a/t/perf/p5303-many-packs.sh +++ b/t/perf/p5303-many-packs.sh @@ -77,6 +77,7 @@ do # actual pack generation, without smudging the on-disk setup # between trials. test_perf "repack ($nr_packs)" ' + GIT_TEST_FULL_IN_PACK_ARRAY=1 \ git pack-objects --keep-true-parents \ --honor-pack-keep --non-empty --all \ --reflog --indexed-objects --delta-base-offset \ diff --git a/t/perf/p5601-clone-reference.sh b/t/perf/p5601-clone-reference.sh new file mode 100755 index 0000000000..68fed66347 --- /dev/null +++ b/t/perf/p5601-clone-reference.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +test_description='speed of clone --reference' +. ./perf-lib.sh + +test_perf_default_repo + +test_expect_success 'create shareable repository' ' + git clone --bare . shared.git +' + +test_expect_success 'advance base repository' ' + # Do not use test_commit here; its test_tick will + # use some ancient hard-coded date. The resulting clock + # skew will cause pack-objects to traverse in a very + # sub-optimal order, skewing the results. + echo content >new-file-that-does-not-exist && + git add new-file-that-does-not-exist && + git commit -m "new commit" +' + +test_perf 'clone --reference' ' + rm -rf dst.git && + git clone --no-local --bare --reference shared.git . dst.git +' + +test_done diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh index b58a43ea43..13e389367a 100644 --- a/t/perf/perf-lib.sh +++ b/t/perf/perf-lib.sh @@ -214,7 +214,7 @@ test_perf_ () { else test_ok_ "$1" fi - "$TEST_DIRECTORY"/perf/min_time.perl test_time.* >"$base".times + "$TEST_DIRECTORY"/perf/min_time.perl test_time.* >"$base".result } test_perf () { @@ -223,7 +223,7 @@ test_perf () { test_size_ () { say >&3 "running: $2" - if test_eval_ "$2" 3>"$base".size; then + if test_eval_ "$2" 3>"$base".result; then test_ok_ "$1" else test_failure_ "$@" diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index c03054c538..8a81a249d0 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -20,28 +20,27 @@ modification *should* take notice and update the test vectors here. . ./test-lib.sh -try_local_x () { - local x="local" && - echo "$x" +try_local_xy () { + local x="local" y="alsolocal" && + echo "$x $y" } -# This test is an experiment to check whether any Git users are using -# Shells that don't support the "local" keyword. "local" is not +# Check whether the shell supports the "local" keyword. "local" is not # POSIX-standard, but it is very widely supported by POSIX-compliant -# shells, and if it doesn't cause problems for people, we would like -# to be able to use it in Git code. +# shells, and we rely on it within Git's test framework. # -# For now, this is the only test that requires "local". If your shell -# fails this test, you can ignore the failure, but please report the -# problem to the Git mailing list <git@vger.kernel.org>, as it might -# convince us to continue avoiding the use of "local". +# If your shell fails this test, the results of other tests may be +# unreliable. You may wish to report the problem to the Git mailing +# list <git@vger.kernel.org>, as it could cause us to reconsider +# relying on "local". test_expect_success 'verify that the running shell supports "local"' ' x="notlocal" && - echo "local" >expected1 && - try_local_x >actual1 && + y="alsonotlocal" && + echo "local alsolocal" >expected1 && + try_local_xy >actual1 && test_cmp expected1 actual1 && - echo "notlocal" >expected2 && - echo "$x" >actual2 && + echo "notlocal alsonotlocal" >expected2 && + echo "$x $y" >actual2 && test_cmp expected2 actual2 ' @@ -128,7 +127,7 @@ check_sub_test_lib_test () { check_sub_test_lib_test_err () { name="$1" # stdin is the expected output from the test - # expected error output is in descriptior 3 + # expected error output is in descriptor 3 ( cd "$name" && sed -e 's/^> //' -e 's/Z$//' >expect.out && @@ -276,23 +275,23 @@ test_expect_success 'pretend we have a mix of all possible results' " test_expect_success C_LOCALE_OUTPUT 'test --verbose' ' test_must_fail run_sub_test_lib_test \ - test-verbose "test verbose" --verbose <<-\EOF && + t1234-verbose "test verbose" --verbose <<-\EOF && test_expect_success "passing test" true test_expect_success "test with output" "echo foo" test_expect_success "failing test" false test_done EOF - mv test-verbose/out test-verbose/out+ && - grep -v "^Initialized empty" test-verbose/out+ >test-verbose/out && - check_sub_test_lib_test test-verbose <<-\EOF - > expecting success: true + mv t1234-verbose/out t1234-verbose/out+ && + grep -v "^Initialized empty" t1234-verbose/out+ >t1234-verbose/out && + check_sub_test_lib_test t1234-verbose <<-\EOF + > expecting success of 1234.1 '\''passing test'\'': true > ok 1 - passing test > Z - > expecting success: echo foo + > expecting success of 1234.2 '\''test with output'\'': echo foo > foo > ok 2 - test with output > Z - > expecting success: false + > expecting success of 1234.3 '\''failing test'\'': false > not ok 3 - failing test > # false > Z @@ -303,17 +302,17 @@ test_expect_success C_LOCALE_OUTPUT 'test --verbose' ' test_expect_success 'test --verbose-only' ' test_must_fail run_sub_test_lib_test \ - test-verbose-only-2 "test verbose-only=2" \ + t2345-verbose-only-2 "test verbose-only=2" \ --verbose-only=2 <<-\EOF && test_expect_success "passing test" true test_expect_success "test with output" "echo foo" test_expect_success "failing test" false test_done EOF - check_sub_test_lib_test test-verbose-only-2 <<-\EOF + check_sub_test_lib_test t2345-verbose-only-2 <<-\EOF > ok 1 - passing test > Z - > expecting success: echo foo + > expecting success of 2345.2 '\''test with output'\'': echo foo > foo > ok 2 - test with output > Z @@ -393,6 +392,44 @@ test_expect_success 'GIT_SKIP_TESTS sh pattern' " ) " +test_expect_success 'GIT_SKIP_TESTS entire suite' " + ( + GIT_SKIP_TESTS='git' && export GIT_SKIP_TESTS && + run_sub_test_lib_test git-skip-tests-entire-suite \ + 'GIT_SKIP_TESTS entire suite' <<-\\EOF && + for i in 1 2 3 + do + test_expect_success \"passing test #\$i\" 'true' + done + test_done + EOF + check_sub_test_lib_test git-skip-tests-entire-suite <<-\\EOF + > 1..0 # SKIP skip all tests in git + EOF + ) +" + +test_expect_success 'GIT_SKIP_TESTS does not skip unmatched suite' " + ( + GIT_SKIP_TESTS='notgit' && export GIT_SKIP_TESTS && + run_sub_test_lib_test git-skip-tests-unmatched-suite \ + 'GIT_SKIP_TESTS does not skip unmatched suite' <<-\\EOF && + for i in 1 2 3 + do + test_expect_success \"passing test #\$i\" 'true' + done + test_done + EOF + check_sub_test_lib_test git-skip-tests-unmatched-suite <<-\\EOF + > ok 1 - passing test #1 + > ok 2 - passing test #2 + > ok 3 - passing test #3 + > # passed all 3 test(s) + > 1..3 + EOF + ) +" + test_expect_success '--run basic' " run_sub_test_lib_test run-basic \ '--run basic' --run='1 3 5' <<-\\EOF && @@ -726,7 +763,7 @@ donthaveit=yes test_expect_success DONTHAVEIT 'unmet prerequisite causes test to be skipped' ' donthaveit=no ' -if test $haveit$donthaveit != yesyes +if test -z "$GIT_TEST_FAIL_PREREQS_INTERNAL" -a $haveit$donthaveit != yesyes then say "bug in test framework: prerequisite tags do not work reliably" exit 1 @@ -747,7 +784,7 @@ donthaveiteither=yes test_expect_success DONTHAVEIT,HAVEIT 'unmet prerequisites causes test to be skipped' ' donthaveiteither=no ' -if test $haveit$donthaveit$donthaveiteither != yesyesyes +if test -z "$GIT_TEST_FAIL_PREREQS_INTERNAL" -a $haveit$donthaveit$donthaveiteither != yesyesyes then say "bug in test framework: multiple prerequisite tags do not work reliably" exit 1 @@ -763,7 +800,7 @@ test_expect_success !LAZY_TRUE 'missing lazy prereqs skip tests' ' donthavetrue=no ' -if test "$havetrue$donthavetrue" != yesyes +if test -z "$GIT_TEST_FAIL_PREREQS_INTERNAL" -a "$havetrue$donthavetrue" != yesyes then say 'bug in test framework: lazy prerequisites do not work' exit 1 @@ -779,7 +816,7 @@ test_expect_success LAZY_FALSE 'missing negative lazy prereqs will skip' ' havefalse=no ' -if test "$nothavefalse$havefalse" != yesyes +if test -z "$GIT_TEST_FAIL_PREREQS_INTERNAL" -a "$nothavefalse$havefalse" != yesyes then say 'bug in test framework: negative lazy prerequisites do not work' exit 1 @@ -790,7 +827,7 @@ test_expect_success 'tests clean up after themselves' ' test_when_finished clean=yes ' -if test $clean != yes +if test -z "$GIT_TEST_FAIL_PREREQS_INTERNAL" -a $clean != yes then say "bug in test framework: basic cleanup command does not work reliably" exit 1 @@ -880,6 +917,40 @@ test_expect_success 'test_oid can look up data for SHA-256' ' test "$hexsz" -eq 64 ' +test_expect_success 'test_bool_env' ' + ( + sane_unset envvar && + + test_bool_env envvar true && + ! test_bool_env envvar false && + + envvar= && + export envvar && + ! test_bool_env envvar true && + ! test_bool_env envvar false && + + envvar=true && + test_bool_env envvar true && + test_bool_env envvar false && + + envvar=false && + ! test_bool_env envvar true && + ! test_bool_env envvar false && + + envvar=invalid && + # When encountering an invalid bool value, test_bool_env + # prints its error message to the original stderr of the + # test script, hence the redirection of fd 7, and aborts + # with "exit 1", hence the subshell. + ! ( test_bool_env envvar true ) 7>err && + grep "error: test_bool_env requires bool values" err && + + envvar=true && + ! ( test_bool_env envvar invalid ) 7>err && + grep "error: test_bool_env requires bool values" err + ) +' + ################################################################ # Basics of the basics diff --git a/t/t0001-init.sh b/t/t0001-init.sh index 77c5ed6a18..26f8206326 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -467,8 +467,8 @@ test_expect_success MINGW 'redirect std handles' ' GIT_REDIRECT_STDOUT=output.txt \ GIT_REDIRECT_STDERR="2>&1" \ git rev-parse --git-dir --verify refs/invalid && - printf ".git\nfatal: Needed a single revision\n" >expect && - test_cmp expect output.txt + grep "^\\.git\$" output.txt && + grep "Needed a single revision" output.txt ' test_done diff --git a/t/t0007-git-var.sh b/t/t0007-git-var.sh index 5868a87352..1f600e2cae 100755 --- a/t/t0007-git-var.sh +++ b/t/t0007-git-var.sh @@ -17,7 +17,7 @@ test_expect_success 'get GIT_COMMITTER_IDENT' ' test_cmp expect actual ' -test_expect_success !AUTOIDENT 'requested identites are strict' ' +test_expect_success !FAIL_PREREQS,!AUTOIDENT 'requested identites are strict' ' ( sane_unset GIT_COMMITTER_NAME && sane_unset GIT_COMMITTER_EMAIL && diff --git a/t/t0011-hashmap.sh b/t/t0011-hashmap.sh index 3f1f505e89..5343ffd3f9 100755 --- a/t/t0011-hashmap.sh +++ b/t/t0011-hashmap.sh @@ -9,15 +9,6 @@ test_hashmap() { test_cmp expect actual } -test_expect_success 'hash functions' ' - -test_hashmap "hash key1" "2215982743 2215982743 116372151 116372151" && -test_hashmap "hash key2" "2215982740 2215982740 116372148 116372148" && -test_hashmap "hash fooBarFrotz" "1383912807 1383912807 3189766727 3189766727" && -test_hashmap "hash foobarfrotz" "2862305959 2862305959 3189766727 3189766727" - -' - test_expect_success 'put' ' test_hashmap "put key1 value1 @@ -179,31 +170,45 @@ NULL ' test_expect_success 'iterate' ' - -test_hashmap "put key1 value1 -put key2 value2 -put fooBarFrotz value3 -iterate" "NULL -NULL -NULL -key2 value2 -key1 value1 -fooBarFrotz value3" - + test-tool hashmap >actual.raw <<-\EOF && + put key1 value1 + put key2 value2 + put fooBarFrotz value3 + iterate + EOF + + cat >expect <<-\EOF && + NULL + NULL + NULL + fooBarFrotz value3 + key1 value1 + key2 value2 + EOF + + sort <actual.raw >actual && + test_cmp expect actual ' test_expect_success 'iterate (case insensitive)' ' - -test_hashmap "put key1 value1 -put key2 value2 -put fooBarFrotz value3 -iterate" "NULL -NULL -NULL -fooBarFrotz value3 -key2 value2 -key1 value1" ignorecase - + test-tool hashmap ignorecase >actual.raw <<-\EOF && + put key1 value1 + put key2 value2 + put fooBarFrotz value3 + iterate + EOF + + cat >expect <<-\EOF && + NULL + NULL + NULL + fooBarFrotz value3 + key1 value1 + key2 value2 + EOF + + sort <actual.raw >actual && + test_cmp expect actual ' test_expect_success 'grow / shrink' ' diff --git a/t/t0014-alias.sh b/t/t0014-alias.sh index a070e645d7..2694c81afd 100755 --- a/t/t0014-alias.sh +++ b/t/t0014-alias.sh @@ -37,4 +37,11 @@ test_expect_success 'looping aliases - internal execution' ' # test_i18ngrep "^fatal: alias loop detected: expansion of" output #' +test_expect_success 'run-command formats empty args properly' ' + GIT_TRACE=1 git frotz a "" b " " c 2>&1 | + sed -ne "/run_command:/s/.*trace: run_command: //p" >actual && + echo "git-frotz a '\'''\'' b '\'' '\'' c" >expect && + test_cmp expect actual +' + test_done diff --git a/t/t0016-oidmap.sh b/t/t0016-oidmap.sh new file mode 100755 index 0000000000..31f8276ba8 --- /dev/null +++ b/t/t0016-oidmap.sh @@ -0,0 +1,110 @@ +#!/bin/sh + +test_description='test oidmap' +. ./test-lib.sh + +# This purposefully is very similar to t0011-hashmap.sh + +test_oidmap () { + echo "$1" | test-tool oidmap $3 >actual && + echo "$2" >expect && + test_cmp expect actual +} + + +test_expect_success 'setup' ' + + test_commit one && + test_commit two && + test_commit three && + test_commit four + +' + +test_expect_success 'put' ' + +test_oidmap "put one 1 +put two 2 +put invalidOid 4 +put three 3" "NULL +NULL +Unknown oid: invalidOid +NULL" + +' + +test_expect_success 'replace' ' + +test_oidmap "put one 1 +put two 2 +put three 3 +put invalidOid 4 +put two deux +put one un" "NULL +NULL +NULL +Unknown oid: invalidOid +2 +1" + +' + +test_expect_success 'get' ' + +test_oidmap "put one 1 +put two 2 +put three 3 +get two +get four +get invalidOid +get one" "NULL +NULL +NULL +2 +NULL +Unknown oid: invalidOid +1" + +' + +test_expect_success 'remove' ' + +test_oidmap "put one 1 +put two 2 +put three 3 +remove one +remove two +remove invalidOid +remove four" "NULL +NULL +NULL +1 +2 +Unknown oid: invalidOid +NULL" + +' + +test_expect_success 'iterate' ' + test-tool oidmap >actual.raw <<-\EOF && + put one 1 + put two 2 + put three 3 + iterate + EOF + + # sort "expect" too so we do not rely on the order of particular oids + sort >expect <<-EOF && + NULL + NULL + NULL + $(git rev-parse one) 1 + $(git rev-parse two) 2 + $(git rev-parse three) 3 + EOF + + sort <actual.raw >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t0017-env-helper.sh b/t/t0017-env-helper.sh new file mode 100755 index 0000000000..c1ecf6aeac --- /dev/null +++ b/t/t0017-env-helper.sh @@ -0,0 +1,99 @@ +#!/bin/sh + +test_description='test env--helper' + +. ./test-lib.sh + + +test_expect_success 'env--helper usage' ' + test_must_fail git env--helper && + test_must_fail git env--helper --type=bool && + test_must_fail git env--helper --type=ulong && + test_must_fail git env--helper --type=bool && + test_must_fail git env--helper --type=bool --default && + test_must_fail git env--helper --type=bool --default= && + test_must_fail git env--helper --defaultxyz +' + +test_expect_success 'env--helper bad default values' ' + test_must_fail git env--helper --type=bool --default=1xyz MISSING && + test_must_fail git env--helper --type=ulong --default=1xyz MISSING +' + +test_expect_success 'env--helper --type=bool' ' + # Test various --default bool values + echo true >expected && + git env--helper --type=bool --default=1 MISSING >actual && + test_cmp expected actual && + git env--helper --type=bool --default=yes MISSING >actual && + test_cmp expected actual && + git env--helper --type=bool --default=true MISSING >actual && + test_cmp expected actual && + echo false >expected && + test_must_fail git env--helper --type=bool --default=0 MISSING >actual && + test_cmp expected actual && + test_must_fail git env--helper --type=bool --default=no MISSING >actual && + test_cmp expected actual && + test_must_fail git env--helper --type=bool --default=false MISSING >actual && + test_cmp expected actual && + + # No output with --exit-code + git env--helper --type=bool --default=true --exit-code MISSING >actual.out 2>actual.err && + test_must_be_empty actual.out && + test_must_be_empty actual.err && + test_must_fail git env--helper --type=bool --default=false --exit-code MISSING >actual.out 2>actual.err && + test_must_be_empty actual.out && + test_must_be_empty actual.err && + + # Existing variable + EXISTS=true git env--helper --type=bool --default=false --exit-code EXISTS >actual.out 2>actual.err && + test_must_be_empty actual.out && + test_must_be_empty actual.err && + test_must_fail \ + env EXISTS=false \ + git env--helper --type=bool --default=true --exit-code EXISTS >actual.out 2>actual.err && + test_must_be_empty actual.out && + test_must_be_empty actual.err +' + +test_expect_success 'env--helper --type=ulong' ' + echo 1234567890 >expected && + git env--helper --type=ulong --default=1234567890 MISSING >actual.out 2>actual.err && + test_cmp expected actual.out && + test_must_be_empty actual.err && + + echo 0 >expected && + test_must_fail git env--helper --type=ulong --default=0 MISSING >actual && + test_cmp expected actual && + + git env--helper --type=ulong --default=1234567890 --exit-code MISSING >actual.out 2>actual.err && + test_must_be_empty actual.out && + test_must_be_empty actual.err && + + EXISTS=1234567890 git env--helper --type=ulong --default=0 EXISTS --exit-code >actual.out 2>actual.err && + test_must_be_empty actual.out && + test_must_be_empty actual.err && + + echo 1234567890 >expected && + EXISTS=1234567890 git env--helper --type=ulong --default=0 EXISTS >actual.out 2>actual.err && + test_cmp expected actual.out && + test_must_be_empty actual.err +' + +test_expect_success 'env--helper reads config thanks to trace2' ' + mkdir home && + git config -f home/.gitconfig include.path cycle && + git config -f home/cycle include.path .gitconfig && + + test_must_fail \ + env HOME="$(pwd)/home" GIT_TEST_GETTEXT_POISON=false \ + git config -l 2>err && + grep "exceeded maximum include depth" err && + + test_must_fail \ + env HOME="$(pwd)/home" GIT_TEST_GETTEXT_POISON=true \ + git -C cycle env--helper --type=bool --default=0 --exit-code GIT_TEST_GETTEXT_POISON 2>err && + grep "# GETTEXT POISON #" err +' + +test_done diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh index e10f5f787f..6c6d77b51a 100755 --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@ -35,7 +35,7 @@ filter_git () { # Compare two files and ensure that `clean` and `smudge` respectively are # called at least once if specified in the `expect` file. The actual # invocation count is not relevant because their number can vary. -# c.f. http://public-inbox.org/git/xmqqshv18i8i.fsf@gitster.mtv.corp.google.com/ +# c.f. http://lore.kernel.org/git/xmqqshv18i8i.fsf@gitster.mtv.corp.google.com/ test_cmp_count () { expect=$1 actual=$2 @@ -50,7 +50,7 @@ test_cmp_count () { # Compare two files but exclude all `clean` invocations because Git can # call `clean` zero or more times. -# c.f. http://public-inbox.org/git/xmqqshv18i8i.fsf@gitster.mtv.corp.google.com/ +# c.f. http://lore.kernel.org/git/xmqqshv18i8i.fsf@gitster.mtv.corp.google.com/ test_cmp_exclude_clean () { expect=$1 actual=$2 @@ -390,6 +390,9 @@ test_expect_success PERL 'required process filter should filter data' ' EOF test_cmp_exclude_clean expected.log debug.log && + # Make sure that the file appears dirty, so checkout below has to + # run the configured filter. + touch test.r && filter_git checkout --quiet --no-progress empty-branch && cat >expected.log <<-EOF && START diff --git a/t/t0027-auto-crlf.sh b/t/t0027-auto-crlf.sh index 3587e454f1..9fcd56fab3 100755 --- a/t/t0027-auto-crlf.sh +++ b/t/t0027-auto-crlf.sh @@ -15,8 +15,10 @@ compare_ws_file () { pfx=$1 exp=$2.expect act=$pfx.actual.$3 - tr '\015\000abcdef0123456789' QN00000000000000000 <"$2" >"$exp" && - tr '\015\000abcdef0123456789' QN00000000000000000 <"$3" >"$act" && + tr '\015\000abcdef0123456789' QN00000000000000000 <"$2" | + sed -e "s/0000*/$ZERO_OID/" >"$exp" && + tr '\015\000abcdef0123456789' QN00000000000000000 <"$3" | + sed -e "s/0000*/$ZERO_OID/" >"$act" && test_cmp "$exp" "$act" && rm "$exp" "$act" } @@ -213,7 +215,7 @@ stats_ascii () { } -# contruct the attr/ returned by git ls-files --eol +# construct the attr/ returned by git ls-files --eol # Take none (=empty), one or two args # convert.c: eol=XX overrides text=auto attr_ascii () { diff --git a/t/t0028-working-tree-encoding.sh b/t/t0028-working-tree-encoding.sh index 1090e650ed..bfc4fb9af5 100755 --- a/t/t0028-working-tree-encoding.sh +++ b/t/t0028-working-tree-encoding.sh @@ -17,7 +17,7 @@ test_lazy_prereq NO_UTF32_BOM ' write_utf16 () { if test_have_prereq NO_UTF16_BOM then - printf '\xfe\xff' + printf '\376\377' fi && iconv -f UTF-8 -t UTF-16 } @@ -25,7 +25,7 @@ write_utf16 () { write_utf32 () { if test_have_prereq NO_UTF32_BOM then - printf '\x00\x00\xfe\xff' + printf '\0\0\376\377' fi && iconv -f UTF-8 -t UTF-32 } @@ -40,7 +40,7 @@ test_expect_success 'setup test files' ' printf "$text" | write_utf16 >test.utf16.raw && printf "$text" | write_utf32 >test.utf32.raw && printf "\377\376" >test.utf16lebom.raw && - printf "$text" | iconv -f UTF-8 -t UTF-32LE >>test.utf16lebom.raw && + printf "$text" | iconv -f UTF-8 -t UTF-16LE >>test.utf16lebom.raw && # Line ending tests printf "one\ntwo\nthree\n" >lf.utf8.raw && @@ -280,4 +280,43 @@ test_expect_success ICONV_SHIFT_JIS 'check roundtrip encoding' ' git reset ' +# $1: checkout encoding +# $2: test string +# $3: binary test string in checkout encoding +test_commit_utf8_checkout_other () { + encoding="$1" + orig_string="$2" + expect_bytes="$3" + + test_expect_success "Commit UTF-8, checkout $encoding" ' + test_when_finished "git checkout HEAD -- .gitattributes" && + + test_ext="commit_utf8_checkout_$encoding" && + test_file="test.$test_ext" && + + # Commit as UTF-8 + echo "*.$test_ext text working-tree-encoding=UTF-8" >.gitattributes && + printf "$orig_string" >$test_file && + git add $test_file && + git commit -m "Test data" && + + # Checkout in tested encoding + rm $test_file && + echo "*.$test_ext text working-tree-encoding=$encoding" >.gitattributes && + git checkout HEAD -- $test_file && + + # Test + printf $expect_bytes >$test_file.raw && + test_cmp_bin $test_file.raw $test_file + ' +} + +test_commit_utf8_checkout_other "UTF-8" "Test Тест" "\124\145\163\164\040\320\242\320\265\321\201\321\202" +test_commit_utf8_checkout_other "UTF-16LE" "Test Тест" "\124\000\145\000\163\000\164\000\040\000\042\004\065\004\101\004\102\004" +test_commit_utf8_checkout_other "UTF-16BE" "Test Тест" "\000\124\000\145\000\163\000\164\000\040\004\042\004\065\004\101\004\102" +test_commit_utf8_checkout_other "UTF-16LE-BOM" "Test Тест" "\377\376\124\000\145\000\163\000\164\000\040\000\042\004\065\004\101\004\102\004" +test_commit_utf8_checkout_other "UTF-16BE-BOM" "Test Тест" "\376\377\000\124\000\145\000\163\000\164\000\040\004\042\004\065\004\101\004\102" +test_commit_utf8_checkout_other "UTF-32LE" "Test Тест" "\124\000\000\000\145\000\000\000\163\000\000\000\164\000\000\000\040\000\000\000\042\004\000\000\065\004\000\000\101\004\000\000\102\004\000\000" +test_commit_utf8_checkout_other "UTF-32BE" "Test Тест" "\000\000\000\124\000\000\000\145\000\000\000\163\000\000\000\164\000\000\000\040\000\000\004\042\000\000\004\065\000\000\004\101\000\000\004\102" + test_done diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index cebc77fab0..705a136ed9 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -399,4 +399,11 @@ test_expect_success 'GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS works' ' test-tool parse-options --ye ' +test_expect_success '--end-of-options treats remainder as args' ' + test-tool parse-options \ + --expect="verbose: -1" \ + --expect="arg 00: --verbose" \ + --end-of-options --verbose +' + test_done diff --git a/t/t0050-filesystem.sh b/t/t0050-filesystem.sh index 192c94eccd..608673fb77 100755 --- a/t/t0050-filesystem.sh +++ b/t/t0050-filesystem.sh @@ -131,4 +131,24 @@ $test_unicode 'merge (silent unicode normalization)' ' git merge topic ' +test_expect_success CASE_INSENSITIVE_FS 'checkout with no pathspec and a case insensitive fs' ' + git init repo && + ( + cd repo && + + >Gitweb && + git add Gitweb && + git commit -m "add Gitweb" && + + git checkout --orphan todo && + git reset --hard && + mkdir -p gitweb/subdir && + >gitweb/subdir/file && + git add gitweb && + git commit -m "add gitweb/subdir/file" && + + git checkout master + ) +' + test_done diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh index c7b53e494b..de2df573a7 100755 --- a/t/t0060-path-utils.sh +++ b/t/t0060-path-utils.sh @@ -165,6 +165,15 @@ test_expect_success 'absolute path rejects the empty string' ' test_must_fail test-tool path-utils absolute_path "" ' +test_expect_success MINGW '<drive-letter>:\\abc is an absolute path' ' + for letter in : \" C Z 1 ä + do + path=$letter:\\abc && + absolute="$(test-tool path-utils absolute_path "$path")" && + test "$path" = "$absolute" || return 1 + done +' + test_expect_success 'real path rejects the empty string' ' test_must_fail test-tool path-utils real_path "" ' @@ -285,9 +294,13 @@ test_git_path GIT_OBJECT_DIRECTORY=foo objects/foo foo/foo test_git_path GIT_OBJECT_DIRECTORY=foo objects2 .git/objects2 test_expect_success 'setup common repository' 'git --git-dir=bar init' test_git_path GIT_COMMON_DIR=bar index .git/index +test_git_path GIT_COMMON_DIR=bar index.lock .git/index.lock test_git_path GIT_COMMON_DIR=bar HEAD .git/HEAD test_git_path GIT_COMMON_DIR=bar logs/HEAD .git/logs/HEAD +test_git_path GIT_COMMON_DIR=bar logs/HEAD.lock .git/logs/HEAD.lock test_git_path GIT_COMMON_DIR=bar logs/refs/bisect/foo .git/logs/refs/bisect/foo +test_git_path GIT_COMMON_DIR=bar logs/refs bar/logs/refs +test_git_path GIT_COMMON_DIR=bar logs/refs/ bar/logs/refs/ test_git_path GIT_COMMON_DIR=bar logs/refs/bisec/foo bar/logs/refs/bisec/foo test_git_path GIT_COMMON_DIR=bar logs/refs/bisec bar/logs/refs/bisec test_git_path GIT_COMMON_DIR=bar logs/refs/bisectfoo bar/logs/refs/bisectfoo @@ -423,6 +436,9 @@ test_expect_success 'match .gitmodules' ' ~1000000 \ ~9999999 \ \ + .gitmodules:\$DATA \ + "gitmod~4 . :\$DATA" \ + \ --not \ ".gitmodules x" \ ".gitmodules .x" \ @@ -447,7 +463,25 @@ test_expect_success 'match .gitmodules' ' \ GI7EB~1 \ GI7EB~01 \ - GI7EB~1X + GI7EB~1X \ + \ + .gitmodules,:\$DATA +' + +test_expect_success MINGW 'is_valid_path() on Windows' ' + test-tool path-utils is_valid_path \ + win32 \ + "win32 x" \ + ../hello.txt \ + C:\\git \ + \ + --not \ + "win32 " \ + "win32 /x " \ + "win32." \ + "win32 . ." \ + .../hello.txt \ + colon:test ' test_done diff --git a/t/t0061-run-command.sh b/t/t0061-run-command.sh index 015fac8b5d..7d599675e3 100755 --- a/t/t0061-run-command.sh +++ b/t/t0061-run-command.sh @@ -12,6 +12,10 @@ cat >hello-script <<-EOF cat hello-script EOF +test_expect_success MINGW 'subprocess inherits only std handles' ' + test-tool run-command inherited-handle +' + 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 @@ -210,10 +214,23 @@ test_expect_success MINGW 'verify curlies are quoted properly' ' test_cmp expect actual ' -test_expect_success MINGW 'can spawn with argv[0] containing spaces' ' - cp "$GIT_BUILD_DIR/t/helper/test-fake-ssh$X" ./ && - test_must_fail "$PWD/test-fake-ssh$X" 2>err && - grep TRASH_DIRECTORY err +test_expect_success MINGW 'can spawn .bat with argv[0] containing spaces' ' + bat="$TRASH_DIRECTORY/bat with spaces in name.bat" && + + # Every .bat invocation will log its arguments to file "out" + rm -f out && + echo "echo %* >>out" >"$bat" && + + # Ask git to invoke .bat; clone will fail due to fake SSH helper + test_must_fail env GIT_SSH="$bat" git clone myhost:src ssh-clone && + + # Spawning .bat can fail if there are two quoted cmd.exe arguments. + # .bat itself is first (due to spaces in name), so just one more is + # needed to verify. GIT_SSH will invoke .bat multiple times: + # 1) -G myhost + # 2) myhost "git-upload-pack src" + # First invocation will always succeed. Test the second one. + grep "git-upload-pack" out ' test_done diff --git a/t/t0066-dir-iterator.sh b/t/t0066-dir-iterator.sh new file mode 100755 index 0000000000..92910e4e6c --- /dev/null +++ b/t/t0066-dir-iterator.sh @@ -0,0 +1,148 @@ +#!/bin/sh + +test_description='Test the dir-iterator functionality' + +. ./test-lib.sh + +test_expect_success 'setup' ' + mkdir -p dir && + mkdir -p dir/a/b/c/ && + >dir/b && + >dir/c && + mkdir -p dir/d/e/d/ && + >dir/a/b/c/d && + >dir/a/e && + >dir/d/e/d/a && + + mkdir -p dir2/a/b/c/ && + >dir2/a/b/c/d +' + +test_expect_success 'dir-iterator should iterate through all files' ' + cat >expected-iteration-sorted-output <<-EOF && + [d] (a) [a] ./dir/a + [d] (a/b) [b] ./dir/a/b + [d] (a/b/c) [c] ./dir/a/b/c + [d] (d) [d] ./dir/d + [d] (d/e) [e] ./dir/d/e + [d] (d/e/d) [d] ./dir/d/e/d + [f] (a/b/c/d) [d] ./dir/a/b/c/d + [f] (a/e) [e] ./dir/a/e + [f] (b) [b] ./dir/b + [f] (c) [c] ./dir/c + [f] (d/e/d/a) [a] ./dir/d/e/d/a + EOF + + test-tool dir-iterator ./dir >out && + sort out >./actual-iteration-sorted-output && + + test_cmp expected-iteration-sorted-output actual-iteration-sorted-output +' + +test_expect_success 'dir-iterator should list files in the correct order' ' + cat >expected-pre-order-output <<-EOF && + [d] (a) [a] ./dir2/a + [d] (a/b) [b] ./dir2/a/b + [d] (a/b/c) [c] ./dir2/a/b/c + [f] (a/b/c/d) [d] ./dir2/a/b/c/d + EOF + + test-tool dir-iterator ./dir2 >actual-pre-order-output && + + test_cmp expected-pre-order-output actual-pre-order-output +' + +test_expect_success 'begin should fail upon inexistent paths' ' + test_must_fail test-tool dir-iterator ./inexistent-path \ + >actual-inexistent-path-output && + echo "dir_iterator_begin failure: ENOENT" >expected-inexistent-path-output && + test_cmp expected-inexistent-path-output actual-inexistent-path-output +' + +test_expect_success 'begin should fail upon non directory paths' ' + test_must_fail test-tool dir-iterator ./dir/b >actual-non-dir-output && + echo "dir_iterator_begin failure: ENOTDIR" >expected-non-dir-output && + test_cmp expected-non-dir-output actual-non-dir-output +' + +test_expect_success POSIXPERM,SANITY 'advance should not fail on errors by default' ' + cat >expected-no-permissions-output <<-EOF && + [d] (a) [a] ./dir3/a + EOF + + mkdir -p dir3/a && + >dir3/a/b && + chmod 0 dir3/a && + + test-tool dir-iterator ./dir3 >actual-no-permissions-output && + test_cmp expected-no-permissions-output actual-no-permissions-output && + chmod 755 dir3/a && + rm -rf dir3 +' + +test_expect_success POSIXPERM,SANITY 'advance should fail on errors, w/ pedantic flag' ' + cat >expected-no-permissions-pedantic-output <<-EOF && + [d] (a) [a] ./dir3/a + dir_iterator_advance failure + EOF + + mkdir -p dir3/a && + >dir3/a/b && + chmod 0 dir3/a && + + test_must_fail test-tool dir-iterator --pedantic ./dir3 \ + >actual-no-permissions-pedantic-output && + test_cmp expected-no-permissions-pedantic-output \ + actual-no-permissions-pedantic-output && + chmod 755 dir3/a && + rm -rf dir3 +' + +test_expect_success SYMLINKS 'setup dirs with symlinks' ' + mkdir -p dir4/a && + mkdir -p dir4/b/c && + >dir4/a/d && + ln -s d dir4/a/e && + ln -s ../b dir4/a/f && + + mkdir -p dir5/a/b && + mkdir -p dir5/a/c && + ln -s ../c dir5/a/b/d && + ln -s ../ dir5/a/b/e && + ln -s ../../ dir5/a/b/f +' + +test_expect_success SYMLINKS 'dir-iterator should not follow symlinks by default' ' + cat >expected-no-follow-sorted-output <<-EOF && + [d] (a) [a] ./dir4/a + [d] (b) [b] ./dir4/b + [d] (b/c) [c] ./dir4/b/c + [f] (a/d) [d] ./dir4/a/d + [s] (a/e) [e] ./dir4/a/e + [s] (a/f) [f] ./dir4/a/f + EOF + + test-tool dir-iterator ./dir4 >out && + sort out >actual-no-follow-sorted-output && + + test_cmp expected-no-follow-sorted-output actual-no-follow-sorted-output +' + +test_expect_success SYMLINKS 'dir-iterator should follow symlinks w/ follow flag' ' + cat >expected-follow-sorted-output <<-EOF && + [d] (a) [a] ./dir4/a + [d] (a/f) [f] ./dir4/a/f + [d] (a/f/c) [c] ./dir4/a/f/c + [d] (b) [b] ./dir4/b + [d] (b/c) [c] ./dir4/b/c + [f] (a/d) [d] ./dir4/a/d + [f] (a/e) [e] ./dir4/a/e + EOF + + test-tool dir-iterator --follow-symlinks ./dir4 >out && + sort out >actual-follow-sorted-output && + + test_cmp expected-follow-sorted-output actual-follow-sorted-output +' + +test_done diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh index 504334e552..ce9a4a5f32 100755 --- a/t/t0090-cache-tree.sh +++ b/t/t0090-cache-tree.sh @@ -162,8 +162,8 @@ test_expect_success PERL 'commit --interactive gives cache-tree on partial commi ' test_expect_success PERL 'commit -p with shrinking cache-tree' ' - mkdir -p deep/subdir && - echo content >deep/subdir/file && + mkdir -p deep/very-long-subdir && + echo content >deep/very-long-subdir/file && git add deep && git commit -m add && git rm -r deep && diff --git a/t/t0205-gettext-poison.sh b/t/t0205-gettext-poison.sh index a06269f38a..f9fa16ad83 100755 --- a/t/t0205-gettext-poison.sh +++ b/t/t0205-gettext-poison.sh @@ -5,7 +5,7 @@ test_description='Gettext Shell poison' -GIT_TEST_GETTEXT_POISON=YesPlease +GIT_TEST_GETTEXT_POISON=true export GIT_TEST_GETTEXT_POISON . ./lib-gettext.sh @@ -31,4 +31,9 @@ test_expect_success 'eval_gettext: our eval_gettext() fallback has poison semant test_cmp expect actual ' +test_expect_success "gettext: invalid GIT_TEST_GETTEXT_POISON value doesn't infinitely loop" " + test_must_fail env GIT_TEST_GETTEXT_POISON=xyz git version 2>error && + grep \"fatal: bad numeric config value 'xyz' for 'GIT_TEST_GETTEXT_POISON': invalid unit\" error +" + test_done diff --git a/t/t0211-trace2-perf.sh b/t/t0211-trace2-perf.sh index 2c3ad6e8c1..6ee8ee3b67 100755 --- a/t/t0211-trace2-perf.sh +++ b/t/t0211-trace2-perf.sh @@ -130,11 +130,11 @@ test_expect_success 'perf stream, child processes' ' d0|main|version|||||$V d0|main|start||_T_ABS_|||_EXE_ trace2 004child test-tool trace2 004child test-tool trace2 001return 0 d0|main|cmd_name|||||trace2 (trace2) - d0|main|child_start||_T_ABS_|||[ch0] class:? argv: test-tool trace2 004child test-tool trace2 001return 0 + d0|main|child_start||_T_ABS_|||[ch0] class:? argv:[test-tool trace2 004child test-tool trace2 001return 0] d1|main|version|||||$V d1|main|start||_T_ABS_|||_EXE_ trace2 004child test-tool trace2 001return 0 d1|main|cmd_name|||||trace2 (trace2/trace2) - d1|main|child_start||_T_ABS_|||[ch0] class:? argv: test-tool trace2 001return 0 + d1|main|child_start||_T_ABS_|||[ch0] class:? argv:[test-tool trace2 001return 0] d2|main|version|||||$V d2|main|start||_T_ABS_|||_EXE_ trace2 001return 0 d2|main|cmd_name|||||trace2 (trace2/trace2/trace2) diff --git a/t/t0212-trace2-event.sh b/t/t0212-trace2-event.sh index ff5b9cc729..7065a1b937 100755 --- a/t/t0212-trace2-event.sh +++ b/t/t0212-trace2-event.sh @@ -265,4 +265,23 @@ test_expect_success JSON_PP 'using global config, event stream, error event' ' test_cmp expect actual ' +test_expect_success 'discard traces when there are too many files' ' + mkdir trace_target_dir && + test_when_finished "rm -r trace_target_dir" && + ( + GIT_TRACE2_MAX_FILES=5 && + export GIT_TRACE2_MAX_FILES && + cd trace_target_dir && + test_seq $GIT_TRACE2_MAX_FILES >../expected_filenames.txt && + xargs touch <../expected_filenames.txt && + cd .. && + GIT_TRACE2_EVENT="$(pwd)/trace_target_dir" test-tool trace2 001return 0 + ) && + echo git-trace2-discard >>expected_filenames.txt && + ls trace_target_dir >ls_output.txt && + test_cmp expected_filenames.txt ls_output.txt && + head -n1 trace_target_dir/git-trace2-discard | grep \"event\":\"version\" && + head -n2 trace_target_dir/git-trace2-discard | tail -n1 | grep \"event\":\"too_many_files\" +' + test_done diff --git a/t/t0410-partial-clone.sh b/t/t0410-partial-clone.sh index 5bd892f2f7..a3988bd4b8 100755 --- a/t/t0410-partial-clone.sh +++ b/t/t0410-partial-clone.sh @@ -26,7 +26,7 @@ promise_and_delete () { test_expect_success 'extensions.partialclone without filter' ' test_create_repo server && git clone --filter="blob:none" "file://$(pwd)/server" client && - git -C client config --unset core.partialclonefilter && + git -C client config --unset remote.origin.partialclonefilter && git -C client fetch origin ' @@ -166,8 +166,9 @@ test_expect_success 'fetching of missing objects' ' # associated packfile contains the object ls repo/.git/objects/pack/pack-*.promisor >promisorlist && test_line_count = 1 promisorlist && - IDX=$(cat promisorlist | sed "s/promisor$/idx/") && - git verify-pack --verbose "$IDX" | grep "$HASH" + IDX=$(sed "s/promisor$/idx/" promisorlist) && + git verify-pack --verbose "$IDX" >out && + grep "$HASH" out ' test_expect_success 'fetching of missing objects works with ref-in-want enabled' ' @@ -182,8 +183,55 @@ test_expect_success 'fetching of missing objects works with ref-in-want enabled' grep "git< fetch=.*ref-in-want" trace ' +test_expect_success 'fetching of missing objects from another promisor remote' ' + git clone "file://$(pwd)/server" server2 && + test_commit -C server2 bar && + git -C server2 repack -a -d --write-bitmap-index && + HASH2=$(git -C server2 rev-parse bar) && + + git -C repo remote add server2 "file://$(pwd)/server2" && + git -C repo config remote.server2.promisor true && + git -C repo cat-file -p "$HASH2" && + + git -C repo fetch server2 && + rm -rf repo/.git/objects/* && + git -C repo cat-file -p "$HASH2" && + + # Ensure that the .promisor file is written, and check that its + # associated packfile contains the object + ls repo/.git/objects/pack/pack-*.promisor >promisorlist && + test_line_count = 1 promisorlist && + IDX=$(sed "s/promisor$/idx/" promisorlist) && + git verify-pack --verbose "$IDX" >out && + grep "$HASH2" out +' + +test_expect_success 'fetching of missing objects configures a promisor remote' ' + git clone "file://$(pwd)/server" server3 && + test_commit -C server3 baz && + git -C server3 repack -a -d --write-bitmap-index && + HASH3=$(git -C server3 rev-parse baz) && + git -C server3 config uploadpack.allowfilter 1 && + + rm repo/.git/objects/pack/pack-*.promisor && + + git -C repo remote add server3 "file://$(pwd)/server3" && + git -C repo fetch --filter="blob:none" server3 $HASH3 && + + test_cmp_config -C repo true remote.server3.promisor && + + # Ensure that the .promisor file is written, and check that its + # associated packfile contains the object + ls repo/.git/objects/pack/pack-*.promisor >promisorlist && + test_line_count = 1 promisorlist && + IDX=$(sed "s/promisor$/idx/" promisorlist) && + git verify-pack --verbose "$IDX" >out && + grep "$HASH3" out +' + test_expect_success 'fetching of missing blobs works' ' - rm -rf server repo && + rm -rf server server2 repo && + rm -rf server server3 repo && test_create_repo server && test_commit -C server foo && git -C server repack -a -d --write-bitmap-index && @@ -234,7 +282,7 @@ test_expect_success 'rev-list stops traversal at missing and promised commit' ' git -C repo config core.repositoryformatversion 1 && git -C repo config extensions.partialclone "arbitrary string" && - GIT_TEST_COMMIT_GRAPH=0 git -C repo rev-list --exclude-promisor-objects --objects bar >out && + GIT_TEST_COMMIT_GRAPH=0 git -C repo -c core.commitGraph=false rev-list --exclude-promisor-objects --objects bar >out && grep $(git -C repo rev-parse bar) out && ! grep $FOO out ' @@ -381,6 +429,19 @@ test_expect_success 'rev-list dies for missing objects on cmd line' ' done ' +test_expect_success 'single promisor remote can be re-initialized gracefully' ' + # ensure one promisor is in the promisors list + rm -rf repo && + test_create_repo repo && + test_create_repo other && + git -C repo remote add foo "file://$(pwd)/other" && + git -C repo config remote.foo.promisor true && + git -C repo config extensions.partialclone foo && + + # reinitialize the promisors list + git -C repo fetch --filter=blob:none foo +' + test_expect_success 'gc repacks promisor objects separately from non-promisor objects' ' rm -rf repo && test_create_repo repo && @@ -492,6 +553,20 @@ test_expect_success 'gc stops traversal when a missing but promised object is re ! grep "$TREE_HASH" out ' +test_expect_success 'do not fetch when checking existence of tree we construct ourselves' ' + rm -rf repo && + test_create_repo repo && + test_commit -C repo base && + test_commit -C repo side1 && + git -C repo checkout base && + test_commit -C repo side2 && + + git -C repo config core.repositoryformatversion 1 && + git -C repo config extensions.partialclone "arbitrary string" && + + git -C repo cherry-pick side1 +' + . "$TEST_DIRECTORY"/lib-httpd.sh start_httpd @@ -514,8 +589,12 @@ test_expect_success 'fetching of missing objects from an HTTP server' ' # associated packfile contains the object ls repo/.git/objects/pack/pack-*.promisor >promisorlist && test_line_count = 1 promisorlist && - IDX=$(cat promisorlist | sed "s/promisor$/idx/") && - git verify-pack --verbose "$IDX" | grep "$HASH" + IDX=$(sed "s/promisor$/idx/" promisorlist) && + git verify-pack --verbose "$IDX" >out && + grep "$HASH" out ' +# DO NOT add non-httpd-specific tests here, because the last part of this +# test script is only executed when httpd is available and enabled. + test_done diff --git a/t/t0500-progress-display.sh b/t/t0500-progress-display.sh new file mode 100755 index 0000000000..d2d088d9a0 --- /dev/null +++ b/t/t0500-progress-display.sh @@ -0,0 +1,286 @@ +#!/bin/sh + +test_description='progress display' + +. ./test-lib.sh + +show_cr () { + tr '\015' Q | sed -e "s/Q/<CR>\\$LF/g" +} + +test_expect_success 'simple progress display' ' + cat >expect <<-\EOF && + Working hard: 1<CR> + Working hard: 2<CR> + Working hard: 5<CR> + Working hard: 5, done. + EOF + + cat >in <<-\EOF && + update + progress 1 + update + progress 2 + progress 3 + progress 4 + update + progress 5 + EOF + test-tool progress "Working hard" <in 2>stderr && + + show_cr <stderr >out && + test_i18ncmp expect out +' + +test_expect_success 'progress display with total' ' + cat >expect <<-\EOF && + Working hard: 33% (1/3)<CR> + Working hard: 66% (2/3)<CR> + Working hard: 100% (3/3)<CR> + Working hard: 100% (3/3), done. + EOF + + cat >in <<-\EOF && + progress 1 + progress 2 + progress 3 + EOF + test-tool progress --total=3 "Working hard" <in 2>stderr && + + show_cr <stderr >out && + test_i18ncmp expect out +' + +test_expect_success 'progress display breaks long lines #1' ' + sed -e "s/Z$//" >expect <<\EOF && +Working hard.......2.........3.........4.........5.........6: 0% (100/100000)<CR> +Working hard.......2.........3.........4.........5.........6: 1% (1000/100000)<CR> +Working hard.......2.........3.........4.........5.........6: Z + 10% (10000/100000)<CR> + 100% (100000/100000)<CR> + 100% (100000/100000), done. +EOF + + cat >in <<-\EOF && + progress 100 + progress 1000 + progress 10000 + progress 100000 + EOF + test-tool progress --total=100000 \ + "Working hard.......2.........3.........4.........5.........6" \ + <in 2>stderr && + + show_cr <stderr >out && + test_i18ncmp expect out +' + +test_expect_success 'progress display breaks long lines #2' ' + # Note: we do not need that many spaces after the title to cover up + # the last line before breaking the progress line. + sed -e "s/Z$//" >expect <<\EOF && +Working hard.......2.........3.........4.........5.........6: 0% (1/100000)<CR> +Working hard.......2.........3.........4.........5.........6: 0% (2/100000)<CR> +Working hard.......2.........3.........4.........5.........6: Z + 10% (10000/100000)<CR> + 100% (100000/100000)<CR> + 100% (100000/100000), done. +EOF + + cat >in <<-\EOF && + update + progress 1 + update + progress 2 + progress 10000 + progress 100000 + EOF + test-tool progress --total=100000 \ + "Working hard.......2.........3.........4.........5.........6" \ + <in 2>stderr && + + show_cr <stderr >out && + test_i18ncmp expect out +' + +test_expect_success 'progress display breaks long lines #3 - even the first is too long' ' + # Note: we do not actually need any spaces at the end of the title + # line, because there is no previous progress line to cover up. + sed -e "s/Z$//" >expect <<\EOF && +Working hard.......2.........3.........4.........5.........6: Z + 25% (25000/100000)<CR> + 50% (50000/100000)<CR> + 75% (75000/100000)<CR> + 100% (100000/100000)<CR> + 100% (100000/100000), done. +EOF + + cat >in <<-\EOF && + progress 25000 + progress 50000 + progress 75000 + progress 100000 + EOF + test-tool progress --total=100000 \ + "Working hard.......2.........3.........4.........5.........6" \ + <in 2>stderr && + + show_cr <stderr >out && + test_i18ncmp expect out +' + +test_expect_success 'progress display breaks long lines #4 - title line matches terminal width' ' + cat >expect <<\EOF && +Working hard.......2.........3.........4.........5.........6.........7.........: + 25% (25000/100000)<CR> + 50% (50000/100000)<CR> + 75% (75000/100000)<CR> + 100% (100000/100000)<CR> + 100% (100000/100000), done. +EOF + + cat >in <<-\EOF && + progress 25000 + progress 50000 + progress 75000 + progress 100000 + EOF + test-tool progress --total=100000 \ + "Working hard.......2.........3.........4.........5.........6.........7........." \ + <in 2>stderr && + + show_cr <stderr >out && + test_i18ncmp expect out +' + +# Progress counter goes backwards, this should not happen in practice. +test_expect_success 'progress shortens - crazy caller' ' + cat >expect <<-\EOF && + Working hard: 10% (100/1000)<CR> + Working hard: 20% (200/1000)<CR> + Working hard: 0% (1/1000) <CR> + Working hard: 100% (1000/1000)<CR> + Working hard: 100% (1000/1000), done. + EOF + + cat >in <<-\EOF && + progress 100 + progress 200 + progress 1 + progress 1000 + EOF + test-tool progress --total=1000 "Working hard" <in 2>stderr && + + show_cr <stderr >out && + test_i18ncmp expect out +' + +test_expect_success 'progress display with throughput' ' + cat >expect <<-\EOF && + Working hard: 10<CR> + Working hard: 20, 200.00 KiB | 100.00 KiB/s<CR> + Working hard: 30, 300.00 KiB | 100.00 KiB/s<CR> + Working hard: 40, 400.00 KiB | 100.00 KiB/s<CR> + Working hard: 40, 400.00 KiB | 100.00 KiB/s, done. + EOF + + cat >in <<-\EOF && + throughput 102400 1000 + update + progress 10 + throughput 204800 2000 + update + progress 20 + throughput 307200 3000 + update + progress 30 + throughput 409600 4000 + update + progress 40 + EOF + test-tool progress "Working hard" <in 2>stderr && + + show_cr <stderr >out && + test_i18ncmp expect out +' + +test_expect_success 'progress display with throughput and total' ' + cat >expect <<-\EOF && + Working hard: 25% (10/40)<CR> + Working hard: 50% (20/40), 200.00 KiB | 100.00 KiB/s<CR> + Working hard: 75% (30/40), 300.00 KiB | 100.00 KiB/s<CR> + Working hard: 100% (40/40), 400.00 KiB | 100.00 KiB/s<CR> + Working hard: 100% (40/40), 400.00 KiB | 100.00 KiB/s, done. + EOF + + cat >in <<-\EOF && + throughput 102400 1000 + progress 10 + throughput 204800 2000 + progress 20 + throughput 307200 3000 + progress 30 + throughput 409600 4000 + progress 40 + EOF + test-tool progress --total=40 "Working hard" <in 2>stderr && + + show_cr <stderr >out && + test_i18ncmp expect out +' + +test_expect_success 'cover up after throughput shortens' ' + cat >expect <<-\EOF && + Working hard: 1<CR> + Working hard: 2, 800.00 KiB | 400.00 KiB/s<CR> + Working hard: 3, 1.17 MiB | 400.00 KiB/s <CR> + Working hard: 4, 1.56 MiB | 400.00 KiB/s<CR> + Working hard: 4, 1.56 MiB | 400.00 KiB/s, done. + EOF + + cat >in <<-\EOF && + throughput 409600 1000 + update + progress 1 + throughput 819200 2000 + update + progress 2 + throughput 1228800 3000 + update + progress 3 + throughput 1638400 4000 + update + progress 4 + EOF + test-tool progress "Working hard" <in 2>stderr && + + show_cr <stderr >out && + test_i18ncmp expect out +' + +test_expect_success 'cover up after throughput shortens a lot' ' + cat >expect <<-\EOF && + Working hard: 1<CR> + Working hard: 2, 1000.00 KiB | 1000.00 KiB/s<CR> + Working hard: 3, 3.00 MiB | 1.50 MiB/s <CR> + Working hard: 3, 3.00 MiB | 1024.00 KiB/s, done. + EOF + + cat >in <<-\EOF && + throughput 1 1000 + update + progress 1 + throughput 1024000 2000 + update + progress 2 + throughput 3145728 3000 + update + progress 3 + EOF + test-tool progress "Working hard" <in 2>stderr && + + show_cr <stderr >out && + test_i18ncmp expect out +' + +test_done diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh index 7099d33508..64b340f227 100755 --- a/t/t1007-hash-object.sh +++ b/t/t1007-hash-object.sh @@ -9,22 +9,19 @@ echo_without_newline() { } test_blob_does_not_exist() { - test_expect_success SHA1 'blob does not exist in database' " + test_expect_success 'blob does not exist in database' " test_must_fail git cat-file blob $1 " } test_blob_exists() { - test_expect_success SHA1 'blob exists in database' " + test_expect_success 'blob exists in database' " git cat-file blob $1 " } hello_content="Hello World" -hello_sha1=5e1c309dae7f45e0f39b1bf3ac3cd9db12e7d689 - example_content="This is an example" -example_sha1=ddd3f836d3e3fbb7ae289aa9ae83536f76956399 setup_repo() { echo_without_newline "$hello_content" > hello @@ -44,7 +41,16 @@ pop_repo() { rm -rf $test_repo } -setup_repo +test_expect_success 'setup' ' + setup_repo && + test_oid_cache <<-EOF + hello sha1:5e1c309dae7f45e0f39b1bf3ac3cd9db12e7d689 + hello sha256:1e3b6c04d2eeb2b3e45c8a330445404c0b7cc7b257e2b097167d26f5230090c4 + + example sha1:ddd3f836d3e3fbb7ae289aa9ae83536f76956399 + example sha256:b44fe1fe65589848253737db859bd490453510719d7424daab03daf0767b85ae + EOF +' # Argument checking @@ -73,23 +79,23 @@ test_expect_success "Can't use --path with --no-filters" ' push_repo -test_expect_success SHA1 'hash a file' ' - test $hello_sha1 = $(git hash-object hello) +test_expect_success 'hash a file' ' + test "$(test_oid hello)" = $(git hash-object hello) ' -test_blob_does_not_exist $hello_sha1 +test_blob_does_not_exist "$(test_oid hello)" -test_expect_success SHA1 'hash from stdin' ' - test $example_sha1 = $(git hash-object --stdin < example) +test_expect_success 'hash from stdin' ' + test "$(test_oid example)" = $(git hash-object --stdin < example) ' -test_blob_does_not_exist $example_sha1 +test_blob_does_not_exist "$(test_oid example)" -test_expect_success SHA1 'hash a file and write to database' ' - test $hello_sha1 = $(git hash-object -w hello) +test_expect_success 'hash a file and write to database' ' + test "$(test_oid hello)" = $(git hash-object -w hello) ' -test_blob_exists $hello_sha1 +test_blob_exists "$(test_oid hello)" test_expect_success 'git hash-object --stdin file1 <file0 first operates on file0, then file1' ' echo foo > file1 && @@ -161,11 +167,11 @@ pop_repo for args in "-w --stdin" "--stdin -w"; do push_repo - test_expect_success SHA1 "hash from stdin and write to database ($args)" ' - test $example_sha1 = $(git hash-object $args < example) + test_expect_success "hash from stdin and write to database ($args)" ' + test "$(test_oid example)" = $(git hash-object $args < example) ' - test_blob_exists $example_sha1 + test_blob_exists "$(test_oid example)" pop_repo done @@ -173,22 +179,22 @@ done filenames="hello example" -sha1s="$hello_sha1 -$example_sha1" +oids="$(test_oid hello) +$(test_oid example)" -test_expect_success SHA1 "hash two files with names on stdin" ' - test "$sha1s" = "$(echo_without_newline "$filenames" | git hash-object --stdin-paths)" +test_expect_success "hash two files with names on stdin" ' + test "$oids" = "$(echo_without_newline "$filenames" | git hash-object --stdin-paths)" ' for args in "-w --stdin-paths" "--stdin-paths -w"; do push_repo - test_expect_success SHA1 "hash two files with names on stdin and write to database ($args)" ' - test "$sha1s" = "$(echo_without_newline "$filenames" | git hash-object $args)" + test_expect_success "hash two files with names on stdin and write to database ($args)" ' + test "$oids" = "$(echo_without_newline "$filenames" | git hash-object $args)" ' - test_blob_exists $hello_sha1 - test_blob_exists $example_sha1 + test_blob_exists "$(test_oid hello)" + test_blob_exists "$(test_oid example)" pop_repo done diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh index ba71b159ba..eb44bafb59 100755 --- a/t/t1011-read-tree-sparse-checkout.sh +++ b/t/t1011-read-tree-sparse-checkout.sh @@ -215,7 +215,6 @@ test_expect_success 'read-tree adds to worktree, dirty case' ' ' test_expect_success 'index removal and worktree narrowing at the same time' ' - >empty && echo init.t >.git/info/sparse-checkout && echo sub/added >>.git/info/sparse-checkout && git checkout -f top && @@ -223,7 +222,7 @@ test_expect_success 'index removal and worktree narrowing at the same time' ' git checkout removed && git ls-files sub/added >result && test ! -f sub/added && - test_cmp empty result + test_must_be_empty result ' test_expect_success 'read-tree --reset removes outside worktree' ' diff --git a/t/t1014-read-tree-confusing.sh b/t/t1014-read-tree-confusing.sh index 2f5a25d503..da3376b3bb 100755 --- a/t/t1014-read-tree-confusing.sh +++ b/t/t1014-read-tree-confusing.sh @@ -49,6 +49,7 @@ git~1 .git.SPACE .git.{space} .\\\\.GIT\\\\foobar backslashes .git\\\\foobar backslashes2 +.git...:alternate-stream EOF test_expect_success 'utf-8 paths allowed with core.protectHFS off' ' diff --git a/t/t1050-large.sh b/t/t1050-large.sh index dcb4dbba67..d3b2adb28b 100755 --- a/t/t1050-large.sh +++ b/t/t1050-large.sh @@ -194,15 +194,15 @@ test_expect_success 'pack-objects with large loose object' ' test_cmp huge actual ' -test_expect_success 'tar achiving' ' +test_expect_success 'tar archiving' ' git archive --format=tar HEAD >/dev/null ' -test_expect_success 'zip achiving, store only' ' +test_expect_success 'zip archiving, store only' ' git archive --format=zip -0 HEAD >/dev/null ' -test_expect_success 'zip achiving, deflate' ' +test_expect_success 'zip archiving, deflate' ' git archive --format=zip HEAD >/dev/null ' diff --git a/t/t1090-sparse-checkout-scope.sh b/t/t1090-sparse-checkout-scope.sh index 090b7fc3d3..40cc004326 100755 --- a/t/t1090-sparse-checkout-scope.sh +++ b/t/t1090-sparse-checkout-scope.sh @@ -31,20 +31,6 @@ test_expect_success 'perform sparse checkout of master' ' test_path_is_file c ' -test_expect_success 'checkout -b checkout.optimizeNewBranch interaction' ' - cp .git/info/sparse-checkout .git/info/sparse-checkout.bak && - test_when_finished " - mv -f .git/info/sparse-checkout.bak .git/info/sparse-checkout - git checkout master - " && - echo "/b" >>.git/info/sparse-checkout && - test "$(git ls-files -t b)" = "S b" && - git -c checkout.optimizeNewBranch=true checkout -b fast && - test "$(git ls-files -t b)" = "S b" && - git checkout -b slow && - test "$(git ls-files -t b)" = "H b" -' - test_expect_success 'merge feature branch into sparse checkout of master' ' git merge feature && test_path_is_file a && diff --git a/t/t1300-config.sh b/t/t1300-config.sh index 428177c390..983a0a1583 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -1294,26 +1294,25 @@ test_expect_success 'git -c is not confused by empty environment' ' GIT_CONFIG_PARAMETERS="" git -c x.one=1 config --list ' -sq="'" test_expect_success 'detect bogus GIT_CONFIG_PARAMETERS' ' cat >expect <<-\EOF && env.one one env.two two EOF - GIT_CONFIG_PARAMETERS="${sq}env.one=one${sq} ${sq}env.two=two${sq}" \ + GIT_CONFIG_PARAMETERS="${SQ}env.one=one${SQ} ${SQ}env.two=two${SQ}" \ git config --get-regexp "env.*" >actual && test_cmp expect actual && cat >expect <<-EOF && - env.one one${sq} + env.one one${SQ} env.two two EOF - GIT_CONFIG_PARAMETERS="${sq}env.one=one${sq}\\$sq$sq$sq ${sq}env.two=two${sq}" \ + GIT_CONFIG_PARAMETERS="${SQ}env.one=one${SQ}\\$SQ$SQ$SQ ${SQ}env.two=two${SQ}" \ git config --get-regexp "env.*" >actual && test_cmp expect actual && test_must_fail env \ - GIT_CONFIG_PARAMETERS="${sq}env.one=one${sq}\\$sq ${sq}env.two=two${sq}" \ + GIT_CONFIG_PARAMETERS="${SQ}env.one=one${SQ}\\$SQ ${SQ}env.two=two${SQ}" \ git config --get-regexp "env.*" ' diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh index 579a86b7f8..f1e1b289f9 100755 --- a/t/t1305-config-include.sh +++ b/t/t1305-config-include.sh @@ -63,7 +63,7 @@ test_expect_success 'listing includes option and expansion' ' test.one=1 EOF git config --list >actual.full && - grep -v ^core actual.full >actual && + grep -v -e ^core -e ^extensions actual.full >actual && test_cmp expect actual ' @@ -309,21 +309,53 @@ test_expect_success SYMLINKS 'conditional include, gitdir matching symlink, icas ) ' +test_expect_success 'conditional include, onbranch' ' + echo "[includeIf \"onbranch:foo-branch\"]path=bar9" >>.git/config && + echo "[test]nine=9" >.git/bar9 && + git checkout -b master && + test_must_fail git config test.nine && + git checkout -b foo-branch && + echo 9 >expect && + git config test.nine >actual && + test_cmp expect actual +' + +test_expect_success 'conditional include, onbranch, wildcard' ' + echo "[includeIf \"onbranch:?oo-*/**\"]path=bar10" >>.git/config && + echo "[test]ten=10" >.git/bar10 && + git checkout -b not-foo-branch/a && + test_must_fail git config test.ten && + + echo 10 >expect && + git checkout -b foo-branch/a/b/c && + git config test.ten >actual && + test_cmp expect actual && + + git checkout -b moo-bar/a && + git config test.ten >actual && + test_cmp expect actual +' + +test_expect_success 'conditional include, onbranch, implicit /** for /' ' + echo "[includeIf \"onbranch:foo-dir/\"]path=bar11" >>.git/config && + echo "[test]eleven=11" >.git/bar11 && + git checkout -b not-foo-dir/a && + test_must_fail git config test.eleven && + + echo 11 >expect && + git checkout -b foo-dir/a/b/c && + git config test.eleven >actual && + test_cmp expect actual +' + test_expect_success 'include cycles are detected' ' - cat >.gitconfig <<-\EOF && - [test]value = gitconfig - [include]path = cycle - EOF - cat >cycle <<-\EOF && - [test]value = cycle - [include]path = .gitconfig - EOF - cat >expect <<-\EOF && - gitconfig - cycle - EOF - test_must_fail git config --get-all test.value 2>stderr && - test_i18ngrep "exceeded maximum include depth" stderr + git init --bare cycle && + git -C cycle config include.path cycle && + git config -f cycle/cycle include.path config && + test_must_fail \ + env GIT_TEST_GETTEXT_POISON=false \ + git -C cycle config --get-all test.value 2>stderr && + grep "exceeded maximum include depth" stderr ' test_done diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh index d0a2727b85..7b4e1a63eb 100755 --- a/t/t1308-config-set.sh +++ b/t/t1308-config-set.sh @@ -166,14 +166,14 @@ test_expect_success 'find value with highest priority from a configset' ' ' test_expect_success 'find value_list for a key from a configset' ' - cat >except <<-\EOF && + cat >expect <<-\EOF && + lama + ball sam bat hask - lama - ball EOF - test-tool config configset_get_value case.baz config2 .git/config >actual && + test-tool config configset_get_value_multi case.baz config2 .git/config >actual && test_cmp expect actual ' diff --git a/t/t1309-early-config.sh b/t/t1309-early-config.sh index 413642aa56..ebb8e1aecb 100755 --- a/t/t1309-early-config.sh +++ b/t/t1309-early-config.sh @@ -29,7 +29,7 @@ test_expect_success 'ceiling' ' cd sub && test-tool config read_early_config early.config ) >output && - test -z "$(cat output)" + test_must_be_empty output ' test_expect_success 'ceiling #2' ' @@ -89,4 +89,14 @@ test_expect_failure 'ignore .git/ with invalid config' ' test_with_config "[" ' +test_expect_success 'early config and onbranch' ' + echo "[broken" >broken && + test_with_config "[includeif \"onbranch:master\"]path=../broken" +' + +test_expect_success 'onbranch config outside of git repo' ' + test_config_global includeIf.onbranch:master.path non-existent && + nongit git help +' + test_done diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index 1fbd940408..b815cdd1b8 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -344,14 +344,16 @@ test_expect_success "verifying $m's log (logged by config)" ' test_cmp expect .git/logs/$m ' -git update-ref $m $D -cat >.git/logs/$m <<EOF -$Z $C $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500 -$C $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150350 -0500 -$A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150380 -0500 -$F $Z $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150680 -0500 -$Z $E $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150980 -0500 -EOF +test_expect_success 'set up for querying the reflog' ' + git update-ref $m $D && + cat >.git/logs/$m <<-EOF + $Z $C $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500 + $C $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150350 -0500 + $A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150380 -0500 + $F $Z $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150680 -0500 + $Z $E $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150980 -0500 + EOF +' ed="Thu, 26 May 2005 18:32:00 -0500" gd="Thu, 26 May 2005 18:33:00 -0500" @@ -378,13 +380,13 @@ test_expect_success 'Query "master@{May 26 2005 23:32:00}" (exactly history star test_when_finished "rm -f o e" && git rev-parse --verify "master@{May 26 2005 23:32:00}" >o 2>e && test $C = $(cat o) && - test "" = "$(cat e)" + test_must_be_empty e ' test_expect_success 'Query "master@{May 26 2005 23:32:30}" (first non-creation change)' ' test_when_finished "rm -f o e" && git rev-parse --verify "master@{May 26 2005 23:32:30}" >o 2>e && test $A = $(cat o) && - test "" = "$(cat e)" + test_must_be_empty e ' test_expect_success 'Query "master@{2005-05-26 23:33:01}" (middle of history with gap)' ' test_when_finished "rm -f o e" && @@ -396,13 +398,13 @@ test_expect_success 'Query "master@{2005-05-26 23:38:00}" (middle of history)' ' test_when_finished "rm -f o e" && git rev-parse --verify "master@{2005-05-26 23:38:00}" >o 2>e && test $Z = $(cat o) && - test "" = "$(cat e)" + test_must_be_empty e ' test_expect_success 'Query "master@{2005-05-26 23:43:00}" (exact end of history)' ' test_when_finished "rm -f o e" && git rev-parse --verify "master@{2005-05-26 23:43:00}" >o 2>e && test $E = $(cat o) && - test "" = "$(cat e)" + test_must_be_empty e ' test_expect_success 'Query "master@{2005-05-28}" (past end of history)' ' test_when_finished "rm -f o e" && diff --git a/t/t1404-update-ref-errors.sh b/t/t1404-update-ref-errors.sh index 970c5c36b9..2d142e5535 100755 --- a/t/t1404-update-ref-errors.sh +++ b/t/t1404-update-ref-errors.sh @@ -32,8 +32,6 @@ test_update_rejected () { test_cmp unchanged actual } -Q="'" - # Test adding and deleting D/F-conflicting references in a single # transaction. df_test() { @@ -93,7 +91,7 @@ df_test() { delname="$delref" fi && cat >expected-err <<-EOF && - fatal: cannot lock ref $Q$addname$Q: $Q$delref$Q exists; cannot create $Q$addref$Q + fatal: cannot lock ref $SQ$addname$SQ: $SQ$delref$SQ exists; cannot create $SQ$addref$SQ EOF $pack && if $add_del @@ -123,7 +121,7 @@ test_expect_success 'existing loose ref is a simple prefix of new' ' prefix=refs/1l && test_update_rejected "a c e" false "b c/x d" \ - "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x$Q" + "$SQ$prefix/c$SQ exists; cannot create $SQ$prefix/c/x$SQ" ' @@ -131,7 +129,7 @@ test_expect_success 'existing packed ref is a simple prefix of new' ' prefix=refs/1p && test_update_rejected "a c e" true "b c/x d" \ - "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x$Q" + "$SQ$prefix/c$SQ exists; cannot create $SQ$prefix/c/x$SQ" ' @@ -139,7 +137,7 @@ test_expect_success 'existing loose ref is a deeper prefix of new' ' prefix=refs/2l && test_update_rejected "a c e" false "b c/x/y d" \ - "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x/y$Q" + "$SQ$prefix/c$SQ exists; cannot create $SQ$prefix/c/x/y$SQ" ' @@ -147,7 +145,7 @@ test_expect_success 'existing packed ref is a deeper prefix of new' ' prefix=refs/2p && test_update_rejected "a c e" true "b c/x/y d" \ - "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x/y$Q" + "$SQ$prefix/c$SQ exists; cannot create $SQ$prefix/c/x/y$SQ" ' @@ -155,7 +153,7 @@ test_expect_success 'new ref is a simple prefix of existing loose' ' prefix=refs/3l && test_update_rejected "a c/x e" false "b c d" \ - "$Q$prefix/c/x$Q exists; cannot create $Q$prefix/c$Q" + "$SQ$prefix/c/x$SQ exists; cannot create $SQ$prefix/c$SQ" ' @@ -163,7 +161,7 @@ test_expect_success 'new ref is a simple prefix of existing packed' ' prefix=refs/3p && test_update_rejected "a c/x e" true "b c d" \ - "$Q$prefix/c/x$Q exists; cannot create $Q$prefix/c$Q" + "$SQ$prefix/c/x$SQ exists; cannot create $SQ$prefix/c$SQ" ' @@ -171,7 +169,7 @@ test_expect_success 'new ref is a deeper prefix of existing loose' ' prefix=refs/4l && test_update_rejected "a c/x/y e" false "b c d" \ - "$Q$prefix/c/x/y$Q exists; cannot create $Q$prefix/c$Q" + "$SQ$prefix/c/x/y$SQ exists; cannot create $SQ$prefix/c$SQ" ' @@ -179,7 +177,7 @@ test_expect_success 'new ref is a deeper prefix of existing packed' ' prefix=refs/4p && test_update_rejected "a c/x/y e" true "b c d" \ - "$Q$prefix/c/x/y$Q exists; cannot create $Q$prefix/c$Q" + "$SQ$prefix/c/x/y$SQ exists; cannot create $SQ$prefix/c$SQ" ' @@ -187,7 +185,7 @@ test_expect_success 'one new ref is a simple prefix of another' ' prefix=refs/5 && test_update_rejected "a e" false "b c c/x d" \ - "cannot process $Q$prefix/c$Q and $Q$prefix/c/x$Q at the same time" + "cannot process $SQ$prefix/c$SQ and $SQ$prefix/c/x$SQ at the same time" ' @@ -334,7 +332,7 @@ test_expect_success 'D/F conflict prevents indirect delete long packed + indirec test_expect_success 'missing old value blocks update' ' prefix=refs/missing-update && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/foo$Q: unable to resolve reference $Q$prefix/foo$Q + fatal: cannot lock ref $SQ$prefix/foo$SQ: unable to resolve reference $SQ$prefix/foo$SQ EOF printf "%s\n" "update $prefix/foo $E $D" | test_must_fail git update-ref --stdin 2>output.err && @@ -345,7 +343,7 @@ test_expect_success 'incorrect old value blocks update' ' prefix=refs/incorrect-update && git update-ref $prefix/foo $C && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/foo$Q: is at $C but expected $D + fatal: cannot lock ref $SQ$prefix/foo$SQ: is at $C but expected $D EOF printf "%s\n" "update $prefix/foo $E $D" | test_must_fail git update-ref --stdin 2>output.err && @@ -356,7 +354,7 @@ test_expect_success 'existing old value blocks create' ' prefix=refs/existing-create && git update-ref $prefix/foo $C && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/foo$Q: reference already exists + fatal: cannot lock ref $SQ$prefix/foo$SQ: reference already exists EOF printf "%s\n" "create $prefix/foo $E" | test_must_fail git update-ref --stdin 2>output.err && @@ -367,7 +365,7 @@ test_expect_success 'incorrect old value blocks delete' ' prefix=refs/incorrect-delete && git update-ref $prefix/foo $C && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/foo$Q: is at $C but expected $D + fatal: cannot lock ref $SQ$prefix/foo$SQ: is at $C but expected $D EOF printf "%s\n" "delete $prefix/foo $D" | test_must_fail git update-ref --stdin 2>output.err && @@ -378,7 +376,7 @@ test_expect_success 'missing old value blocks indirect update' ' prefix=refs/missing-indirect-update && git symbolic-ref $prefix/symref $prefix/foo && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/symref$Q: unable to resolve reference $Q$prefix/foo$Q + fatal: cannot lock ref $SQ$prefix/symref$SQ: unable to resolve reference $SQ$prefix/foo$SQ EOF printf "%s\n" "update $prefix/symref $E $D" | test_must_fail git update-ref --stdin 2>output.err && @@ -390,7 +388,7 @@ test_expect_success 'incorrect old value blocks indirect update' ' git symbolic-ref $prefix/symref $prefix/foo && git update-ref $prefix/foo $C && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/symref$Q: is at $C but expected $D + fatal: cannot lock ref $SQ$prefix/symref$SQ: is at $C but expected $D EOF printf "%s\n" "update $prefix/symref $E $D" | test_must_fail git update-ref --stdin 2>output.err && @@ -402,7 +400,7 @@ test_expect_success 'existing old value blocks indirect create' ' git symbolic-ref $prefix/symref $prefix/foo && git update-ref $prefix/foo $C && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/symref$Q: reference already exists + fatal: cannot lock ref $SQ$prefix/symref$SQ: reference already exists EOF printf "%s\n" "create $prefix/symref $E" | test_must_fail git update-ref --stdin 2>output.err && @@ -414,7 +412,7 @@ test_expect_success 'incorrect old value blocks indirect delete' ' git symbolic-ref $prefix/symref $prefix/foo && git update-ref $prefix/foo $C && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/symref$Q: is at $C but expected $D + fatal: cannot lock ref $SQ$prefix/symref$SQ: is at $C but expected $D EOF printf "%s\n" "delete $prefix/symref $D" | test_must_fail git update-ref --stdin 2>output.err && @@ -425,7 +423,7 @@ test_expect_success 'missing old value blocks indirect no-deref update' ' prefix=refs/missing-noderef-update && git symbolic-ref $prefix/symref $prefix/foo && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/symref$Q: reference is missing but expected $D + fatal: cannot lock ref $SQ$prefix/symref$SQ: reference is missing but expected $D EOF printf "%s\n" "option no-deref" "update $prefix/symref $E $D" | test_must_fail git update-ref --stdin 2>output.err && @@ -437,7 +435,7 @@ test_expect_success 'incorrect old value blocks indirect no-deref update' ' git symbolic-ref $prefix/symref $prefix/foo && git update-ref $prefix/foo $C && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/symref$Q: is at $C but expected $D + fatal: cannot lock ref $SQ$prefix/symref$SQ: is at $C but expected $D EOF printf "%s\n" "option no-deref" "update $prefix/symref $E $D" | test_must_fail git update-ref --stdin 2>output.err && @@ -449,7 +447,7 @@ test_expect_success 'existing old value blocks indirect no-deref create' ' git symbolic-ref $prefix/symref $prefix/foo && git update-ref $prefix/foo $C && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/symref$Q: reference already exists + fatal: cannot lock ref $SQ$prefix/symref$SQ: reference already exists EOF printf "%s\n" "option no-deref" "create $prefix/symref $E" | test_must_fail git update-ref --stdin 2>output.err && @@ -461,7 +459,7 @@ test_expect_success 'incorrect old value blocks indirect no-deref delete' ' git symbolic-ref $prefix/symref $prefix/foo && git update-ref $prefix/foo $C && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/symref$Q: is at $C but expected $D + fatal: cannot lock ref $SQ$prefix/symref$SQ: is at $C but expected $D EOF printf "%s\n" "option no-deref" "delete $prefix/symref $D" | test_must_fail git update-ref --stdin 2>output.err && @@ -474,13 +472,13 @@ test_expect_success 'non-empty directory blocks create' ' : >.git/$prefix/foo/bar/baz.lock && test_when_finished "rm -f .git/$prefix/foo/bar/baz.lock" && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/foo$Q: there is a non-empty directory $Q.git/$prefix/foo$Q blocking reference $Q$prefix/foo$Q + fatal: cannot lock ref $SQ$prefix/foo$SQ: there is a non-empty directory $SQ.git/$prefix/foo$SQ blocking reference $SQ$prefix/foo$SQ EOF printf "%s\n" "update $prefix/foo $C" | test_must_fail git update-ref --stdin 2>output.err && test_cmp expected output.err && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/foo$Q: unable to resolve reference $Q$prefix/foo$Q + fatal: cannot lock ref $SQ$prefix/foo$SQ: unable to resolve reference $SQ$prefix/foo$SQ EOF printf "%s\n" "update $prefix/foo $D $C" | test_must_fail git update-ref --stdin 2>output.err && @@ -493,13 +491,13 @@ test_expect_success 'broken reference blocks create' ' echo "gobbledigook" >.git/$prefix/foo && test_when_finished "rm -f .git/$prefix/foo" && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/foo$Q: unable to resolve reference $Q$prefix/foo$Q: reference broken + fatal: cannot lock ref $SQ$prefix/foo$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken EOF printf "%s\n" "update $prefix/foo $C" | test_must_fail git update-ref --stdin 2>output.err && test_cmp expected output.err && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/foo$Q: unable to resolve reference $Q$prefix/foo$Q: reference broken + fatal: cannot lock ref $SQ$prefix/foo$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken EOF printf "%s\n" "update $prefix/foo $D $C" | test_must_fail git update-ref --stdin 2>output.err && @@ -513,13 +511,13 @@ test_expect_success 'non-empty directory blocks indirect create' ' : >.git/$prefix/foo/bar/baz.lock && test_when_finished "rm -f .git/$prefix/foo/bar/baz.lock" && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/symref$Q: there is a non-empty directory $Q.git/$prefix/foo$Q blocking reference $Q$prefix/foo$Q + fatal: cannot lock ref $SQ$prefix/symref$SQ: there is a non-empty directory $SQ.git/$prefix/foo$SQ blocking reference $SQ$prefix/foo$SQ EOF printf "%s\n" "update $prefix/symref $C" | test_must_fail git update-ref --stdin 2>output.err && test_cmp expected output.err && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/symref$Q: unable to resolve reference $Q$prefix/foo$Q + fatal: cannot lock ref $SQ$prefix/symref$SQ: unable to resolve reference $SQ$prefix/foo$SQ EOF printf "%s\n" "update $prefix/symref $D $C" | test_must_fail git update-ref --stdin 2>output.err && @@ -532,13 +530,13 @@ test_expect_success 'broken reference blocks indirect create' ' echo "gobbledigook" >.git/$prefix/foo && test_when_finished "rm -f .git/$prefix/foo" && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/symref$Q: unable to resolve reference $Q$prefix/foo$Q: reference broken + fatal: cannot lock ref $SQ$prefix/symref$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken EOF printf "%s\n" "update $prefix/symref $C" | test_must_fail git update-ref --stdin 2>output.err && test_cmp expected output.err && cat >expected <<-EOF && - fatal: cannot lock ref $Q$prefix/symref$Q: unable to resolve reference $Q$prefix/foo$Q: reference broken + fatal: cannot lock ref $SQ$prefix/symref$SQ: unable to resolve reference $SQ$prefix/foo$SQ: reference broken EOF printf "%s\n" "update $prefix/symref $D $C" | test_must_fail git update-ref --stdin 2>output.err && @@ -614,7 +612,7 @@ test_expect_success 'delete fails cleanly if packed-refs file is locked' ' test_when_finished "rm -f .git/packed-refs.lock" && test_must_fail git update-ref -d $prefix/foo >out 2>err && git for-each-ref $prefix >actual && - test_i18ngrep "Unable to create $Q.*packed-refs.lock$Q: " err && + test_i18ngrep "Unable to create $SQ.*packed-refs.lock$SQ: " err && test_cmp unchanged actual ' diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh index 79f731db37..76d9b744a6 100755 --- a/t/t1410-reflog.sh +++ b/t/t1410-reflog.sh @@ -30,14 +30,13 @@ check_fsck () { } corrupt () { - aa=${1%??????????????????????????????????????} zz=${1#??} - mv .git/objects/$aa/$zz .git/$aa$zz + mv .git/objects/$(test_oid_to_path $1) .git/$1 } recover () { - aa=${1%??????????????????????????????????????} zz=${1#??} + aa=$(echo $1 | cut -c 1-2) mkdir -p .git/objects/$aa - mv .git/$aa$zz .git/objects/$aa/$zz + mv .git/$1 .git/objects/$(test_oid_to_path $1) } check_dont_have () { @@ -55,6 +54,7 @@ check_dont_have () { } test_expect_success setup ' + test_oid_init && mkdir -p A/B && echo rat >C && echo ox >A/D && @@ -195,7 +195,7 @@ test_expect_success 'delete' ' git reflog delete master@{1} && git reflog show master > output && - test $(($master_entry_count - 1)) = $(wc -l < output) && + test_line_count = $(($master_entry_count - 1)) output && test $HEAD_entry_count = $(git reflog | wc -l) && ! grep ox < output && @@ -209,7 +209,7 @@ test_expect_success 'delete' ' git reflog delete master@{07.04.2005.15:15:00.-0700} && git reflog show master > output && - test $(($master_entry_count - 1)) = $(wc -l < output) && + test_line_count = $(($master_entry_count - 1)) output && ! grep dragon < output ' @@ -313,12 +313,12 @@ test_expect_success 'stale dirs do not cause d/f conflicts (reflogs off)' ' # Each line is 114 characters, so we need 75 to still have a few before the # last 8K. The 89-character padding on the final entry lines up our # newline exactly. -test_expect_success 'parsing reverse reflogs at BUFSIZ boundaries' ' +test_expect_success SHA1 'parsing reverse reflogs at BUFSIZ boundaries' ' git checkout -b reflogskip && - z38=00000000000000000000000000000000000000 && + zf=$(test_oid zero_2) && ident="abc <xyz> 0000000001 +0000" && for i in $(test_seq 1 75); do - printf "$z38%02d $z38%02d %s\t" $i $(($i+1)) "$ident" && + printf "$zf%02d $zf%02d %s\t" $i $(($i+1)) "$ident" && if test $i = 75; then for j in $(test_seq 1 89); do printf X @@ -329,7 +329,7 @@ test_expect_success 'parsing reverse reflogs at BUFSIZ boundaries' ' printf "\n" done >.git/logs/refs/heads/reflogskip && git rev-parse reflogskip@{73} >actual && - echo ${z38}03 >expect && + echo ${zf}03 >expect && test_cmp expect actual ' diff --git a/t/t1414-reflog-walk.sh b/t/t1414-reflog-walk.sh index feb1efd8ff..1181a9fb28 100755 --- a/t/t1414-reflog-walk.sh +++ b/t/t1414-reflog-walk.sh @@ -18,10 +18,9 @@ do_walk () { git log -g --format="%gd %gs" "$@" } -sq="'" test_expect_success 'set up expected reflog' ' cat >expect.all <<-EOF - HEAD@{0} commit (merge): Merge branch ${sq}master${sq} into side + HEAD@{0} commit (merge): Merge branch ${SQ}master${SQ} into side HEAD@{1} commit: three HEAD@{2} checkout: moving from master to side HEAD@{3} commit: two diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index 0f268a3664..02478bc4ec 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -9,6 +9,7 @@ test_description='git fsck random collection of tests . ./test-lib.sh test_expect_success setup ' + test_oid_init && git config gc.auto 0 && git config i18n.commitencoding ISO-8859-1 && test_commit A fileA one && @@ -54,8 +55,8 @@ test_expect_success 'setup: helpers for corruption tests' ' test_expect_success 'object with bad sha1' ' sha=$(echo blob | git hash-object -w --stdin) && - old=$(echo $sha | sed "s+^..+&/+") && - new=$(dirname $old)/ffffffffffffffffffffffffffffffffffffff && + old=$(test_oid_to_path "$sha") && + new=$(dirname $old)/$(test_oid ff_2) && sha="$(dirname $new)$(basename $new)" && mv .git/objects/$old .git/objects/$new && test_when_finished "remove_object $sha" && @@ -69,7 +70,6 @@ test_expect_success 'object with bad sha1' ' test_when_finished "git update-ref -d refs/heads/bogus" && test_must_fail git fsck 2>out && - cat out && test_i18ngrep "$sha.*corrupt" out ' @@ -77,17 +77,15 @@ test_expect_success 'branch pointing to non-commit' ' git rev-parse HEAD^{tree} >.git/refs/heads/invalid && test_when_finished "git update-ref -d refs/heads/invalid" && test_must_fail git fsck 2>out && - cat out && test_i18ngrep "not a commit" out ' test_expect_success 'HEAD link pointing at a funny object' ' test_when_finished "mv .git/SAVED_HEAD .git/HEAD" && mv .git/HEAD .git/SAVED_HEAD && - echo 0000000000000000000000000000000000000000 >.git/HEAD && + echo $ZERO_OID >.git/HEAD && # avoid corrupt/broken HEAD from interfering with repo discovery test_must_fail env GIT_DIR=.git git fsck 2>out && - cat out && test_i18ngrep "detached HEAD points" out ' @@ -97,7 +95,6 @@ test_expect_success 'HEAD link pointing at a funny place' ' echo "ref: refs/funny/place" >.git/HEAD && # avoid corrupt/broken HEAD from interfering with repo discovery test_must_fail env GIT_DIR=.git git fsck 2>out && - cat out && test_i18ngrep "HEAD points to something strange" out ' @@ -156,7 +153,6 @@ test_expect_success 'email with embedded > is not okay' ' git update-ref refs/heads/bogus "$new" && test_when_finished "git update-ref -d refs/heads/bogus" && test_must_fail git fsck 2>out && - cat out && test_i18ngrep "error in commit $new" out ' @@ -168,7 +164,6 @@ test_expect_success 'missing < email delimiter is reported nicely' ' git update-ref refs/heads/bogus "$new" && test_when_finished "git update-ref -d refs/heads/bogus" && test_must_fail git fsck 2>out && - cat out && test_i18ngrep "error in commit $new.* - bad name" out ' @@ -180,7 +175,6 @@ test_expect_success 'missing email is reported nicely' ' git update-ref refs/heads/bogus "$new" && test_when_finished "git update-ref -d refs/heads/bogus" && test_must_fail git fsck 2>out && - cat out && test_i18ngrep "error in commit $new.* - missing email" out ' @@ -192,7 +186,6 @@ test_expect_success '> in name is reported' ' git update-ref refs/heads/bogus "$new" && test_when_finished "git update-ref -d refs/heads/bogus" && test_must_fail git fsck 2>out && - cat out && test_i18ngrep "error in commit $new" out ' @@ -206,7 +199,6 @@ test_expect_success 'integer overflow in timestamps is reported' ' git update-ref refs/heads/bogus "$new" && test_when_finished "git update-ref -d refs/heads/bogus" && test_must_fail git fsck 2>out && - cat out && test_i18ngrep "error in commit $new.*integer overflow" out ' @@ -218,7 +210,6 @@ test_expect_success 'commit with NUL in header' ' git update-ref refs/heads/bogus "$new" && test_when_finished "git update-ref -d refs/heads/bogus" && test_must_fail git fsck 2>out && - cat out && test_i18ngrep "error in commit $new.*unterminated header: NUL at offset" out ' @@ -244,10 +235,16 @@ test_expect_success 'tree object with duplicate entries' ' ' test_expect_success 'unparseable tree object' ' + test_oid_cache <<-\EOF && + junk sha1:twenty-bytes-of-junk + junk sha256:twenty-bytes-of-junk-twelve-more + EOF + test_when_finished "git update-ref -d refs/heads/wrong" && test_when_finished "remove_object \$tree_sha1" && test_when_finished "remove_object \$commit_sha1" && - tree_sha1=$(printf "100644 \0twenty-bytes-of-junk" | git hash-object -t tree --stdin -w --literally) && + junk=$(test_oid junk) && + tree_sha1=$(printf "100644 \0$junk" | git hash-object -t tree --stdin -w --literally) && commit_sha1=$(git commit-tree $tree_sha1) && git update-ref refs/heads/wrong $commit_sha1 && test_must_fail git fsck 2>out && @@ -275,8 +272,9 @@ test_expect_success 'tree entry with type mismatch' ' ' test_expect_success 'tag pointing to nonexistent' ' - cat >invalid-tag <<-\EOF && - object ffffffffffffffffffffffffffffffffffffffff + badoid=$(test_oid deadbeef) && + cat >invalid-tag <<-EOF && + object $badoid type commit tag invalid tagger T A Gger <tagger@example.com> 1234567890 -0000 @@ -289,7 +287,6 @@ test_expect_success 'tag pointing to nonexistent' ' echo $tag >.git/refs/tags/invalid && test_when_finished "git update-ref -d refs/tags/invalid" && test_must_fail git fsck --tags >out && - cat out && test_i18ngrep "broken link" out ' @@ -370,7 +367,6 @@ test_expect_success 'tag with NUL in header' ' echo $tag >.git/refs/tags/wrong && test_when_finished "git update-ref -d refs/tags/wrong" && test_must_fail git fsck --tags 2>out && - cat out && test_i18ngrep "error in tag $tag.*unterminated header: NUL at offset" out ' @@ -386,8 +382,8 @@ test_expect_success 'rev-list --verify-objects' ' test_expect_success 'rev-list --verify-objects with bad sha1' ' sha=$(echo blob | git hash-object -w --stdin) && - old=$(echo $sha | sed "s+^..+&/+") && - new=$(dirname $old)/ffffffffffffffffffffffffffffffffffffff && + old=$(test_oid_to_path $sha) && + new=$(dirname $old)/$(test_oid ff_2) && sha="$(dirname $new)$(basename $new)" && mv .git/objects/$old .git/objects/$new && test_when_finished "remove_object $sha" && @@ -401,8 +397,7 @@ test_expect_success 'rev-list --verify-objects with bad sha1' ' test_when_finished "git update-ref -d refs/heads/bogus" && test_might_fail git rev-list --verify-objects refs/heads/bogus >/dev/null 2>out && - cat out && - test_i18ngrep -q "error: hash mismatch 63ffffffffffffffffffffffffffffffffffffff" out + test_i18ngrep -q "error: hash mismatch $(dirname $new)$(test_oid ff_2)" out ' test_expect_success 'force fsck to ignore double author' ' @@ -417,16 +412,14 @@ test_expect_success 'force fsck to ignore double author' ' ' _bz='\0' -_bz5="$_bz$_bz$_bz$_bz$_bz" -_bz20="$_bz5$_bz5$_bz5$_bz5" +_bzoid=$(printf $ZERO_OID | sed -e 's/00/\\0/g') test_expect_success 'fsck notices blob entry pointing to null sha1' ' (git init null-blob && cd null-blob && - sha=$(printf "100644 file$_bz$_bz20" | + sha=$(printf "100644 file$_bz$_bzoid" | git hash-object -w --stdin -t tree) && git fsck 2>out && - cat out && test_i18ngrep "warning.*null sha1" out ) ' @@ -434,10 +427,9 @@ test_expect_success 'fsck notices blob entry pointing to null sha1' ' test_expect_success 'fsck notices submodule entry pointing to null sha1' ' (git init null-commit && cd null-commit && - sha=$(printf "160000 submodule$_bz$_bz20" | + sha=$(printf "160000 submodule$_bz$_bzoid" | git hash-object -w --stdin -t tree) && git fsck 2>out && - cat out && test_i18ngrep "warning.*null sha1" out ) ' @@ -449,6 +441,7 @@ while read name path pretty; do ( git init $name-$type && cd $name-$type && + git config core.protectNTFS false && echo content >file && git add file && git commit -m base && @@ -458,7 +451,6 @@ while read name path pretty; do printf "$mode $type %s\t%s" "$value" "$path" >bad && bad_tree=$(git mktree <bad) && git fsck 2>out && - cat out && test_i18ngrep "warning.*tree $bad_tree" out )' done <<-\EOF @@ -586,7 +578,7 @@ test_expect_success 'fsck --connectivity-only' ' # its type. That lets us see that --connectivity-only is # not actually looking at the contents, but leaves it # free to examine the type if it chooses. - empty=.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 && + empty=.git/objects/$(test_oid_to_path $EMPTY_BLOB) && blob=$(echo unrelated | git hash-object -w --stdin) && mv -f $(sha1_file $blob) $empty && @@ -625,16 +617,18 @@ 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:) && - test_i18ngrep -E "$tree \((refs/heads/master|HEAD)@\{[0-9]*\}:" out + test_i18ngrep "$tree (refs/tags/julius:" out ) ' test_expect_success 'alternate objects are correctly blamed' ' test_when_finished "rm -rf alt.git .git/objects/info/alternates" && + name=$(test_oid numeric) && + path=$(test_oid_to_path "$name") && git init --bare alt.git && echo "../../alt.git/objects" >.git/objects/info/alternates && - mkdir alt.git/objects/12 && - >alt.git/objects/12/34567890123456789012345678901234567890 && + mkdir alt.git/objects/$(dirname $path) && + >alt.git/objects/$(dirname $path)/$(basename $path) && test_must_fail git fsck >out 2>&1 && test_i18ngrep alt.git out ' diff --git a/t/t1500-rev-parse.sh b/t/t1500-rev-parse.sh index 01abee533d..603019b541 100755 --- a/t/t1500-rev-parse.sh +++ b/t/t1500-rev-parse.sh @@ -59,6 +59,7 @@ test_rev_parse () { ROOT=$(pwd) test_expect_success 'setup' ' + test_oid_init && mkdir -p sub/dir work && cp -R .git repo.git ' @@ -131,6 +132,30 @@ test_expect_success 'rev-parse --is-shallow-repository in non-shallow repo' ' test_cmp expect actual ' +test_expect_success 'rev-parse --show-object-format in repo' ' + echo "$(test_oid algo)" >expect && + git rev-parse --show-object-format >actual && + test_cmp expect actual && + git rev-parse --show-object-format=storage >actual && + test_cmp expect actual && + git rev-parse --show-object-format=input >actual && + test_cmp expect actual && + git rev-parse --show-object-format=output >actual && + test_cmp expect actual && + test_must_fail git rev-parse --show-object-format=squeamish-ossifrage 2>err && + grep "unknown mode for --show-object-format: squeamish-ossifrage" err +' + +test_expect_success '--show-toplevel from subdir of working tree' ' + pwd >expect && + git -C sub/dir rev-parse --show-toplevel >actual && + test_cmp expect actual +' + +test_expect_success '--show-toplevel from inside .git' ' + test_must_fail git -C .git rev-parse --show-toplevel +' + test_expect_success 'showing the superproject correctly' ' git rev-parse --show-superproject-working-tree >out && test_must_be_empty out && diff --git a/t/t1506-rev-parse-diagnosis.sh b/t/t1506-rev-parse-diagnosis.sh index 4ee009da66..6d951ca015 100755 --- a/t/t1506-rev-parse-diagnosis.sh +++ b/t/t1506-rev-parse-diagnosis.sh @@ -8,10 +8,9 @@ exec </dev/null test_did_you_mean () { - sq="'" && cat >expected <<-EOF && - fatal: Path '$2$3' $4, but not ${5:-$sq$3$sq}. - Did you mean '$1:$2$3'${2:+ aka $sq$1:./$3$sq}? + fatal: Path '$2$3' $4, but not ${5:-$SQ$3$SQ}. + Did you mean '$1:$2$3'${2:+ aka $SQ$1:./$3$SQ}? EOF test_cmp expected error } @@ -139,10 +138,10 @@ test_expect_success 'incorrect file in :path and :N:path' ' test_expect_success 'invalid @{n} reference' ' test_must_fail git rev-parse master@{99999} >output 2>error && - test -z "$(cat output)" && + test_must_be_empty output && grep "fatal: Log for [^ ]* only has [0-9][0-9]* entries." error && test_must_fail git rev-parse --verify master@{99999} >output 2>error && - test -z "$(cat output)" && + test_must_be_empty output && grep "fatal: Log for [^ ]* only has [0-9][0-9]* entries." error ' @@ -156,13 +155,13 @@ test_expect_success 'relative path not found' ' test_expect_success 'relative path outside worktree' ' test_must_fail git rev-parse HEAD:../file.txt >output 2>error && - test -z "$(cat output)" && + test_must_be_empty output && test_i18ngrep "outside repository" error ' test_expect_success 'relative path when cwd is outside worktree' ' test_must_fail git --git-dir=.git --work-tree=subdir rev-parse HEAD:./file.txt >output 2>error && - test -z "$(cat output)" && + test_must_be_empty output && grep "relative path syntax can.t be used outside working tree." error ' @@ -215,4 +214,12 @@ test_expect_success 'arg before dashdash must be a revision (ambiguous)' ' test_cmp expect actual ' +test_expect_success 'reject Nth parent if N is too high' ' + test_must_fail git rev-parse HEAD^100000000000000000000000000000000 +' + +test_expect_success 'reject Nth ancestor if N is too high' ' + test_must_fail git rev-parse HEAD~100000000000000000000000000000000 +' + test_done diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh index fa3e499641..8b4cf8a6e3 100755 --- a/t/t1507-rev-parse-upstream.sh +++ b/t/t1507-rev-parse-upstream.sh @@ -28,8 +28,6 @@ test_expect_success 'setup' ' ) ' -sq="'" - full_name () { (cd clone && git rev-parse --symbolic-full-name "$@") @@ -129,7 +127,7 @@ test_expect_success 'merge my-side@{u} records the correct name' ' git branch -t new my-side@{u} && git merge -s ours new@{u} && git show -s --pretty=tformat:%s >actual && - echo "Merge remote-tracking branch ${sq}origin/side${sq}" >expect && + echo "Merge remote-tracking branch ${SQ}origin/side${SQ}" >expect && test_cmp expect actual ) ' @@ -156,7 +154,7 @@ test_expect_success 'branch@{u} works when tracking a local branch' ' test_expect_success 'branch@{u} error message when no upstream' ' cat >expect <<-EOF && - fatal: no upstream configured for branch ${sq}non-tracking${sq} + fatal: no upstream configured for branch ${SQ}non-tracking${SQ} EOF error_message non-tracking@{u} && test_i18ncmp expect error @@ -164,7 +162,7 @@ test_expect_success 'branch@{u} error message when no upstream' ' test_expect_success '@{u} error message when no upstream' ' cat >expect <<-EOF && - fatal: no upstream configured for branch ${sq}master${sq} + fatal: no upstream configured for branch ${SQ}master${SQ} EOF test_must_fail git rev-parse --verify @{u} 2>actual && test_i18ncmp expect actual @@ -172,7 +170,7 @@ test_expect_success '@{u} error message when no upstream' ' test_expect_success 'branch@{u} error message with misspelt branch' ' cat >expect <<-EOF && - fatal: no such branch: ${sq}no-such-branch${sq} + fatal: no such branch: ${SQ}no-such-branch${SQ} EOF error_message no-such-branch@{u} && test_i18ncmp expect error @@ -189,7 +187,7 @@ test_expect_success '@{u} error message when not on a branch' ' test_expect_success 'branch@{u} error message if upstream branch not fetched' ' cat >expect <<-EOF && - fatal: upstream branch ${sq}refs/heads/side${sq} not stored as a remote-tracking branch + fatal: upstream branch ${SQ}refs/heads/side${SQ} not stored as a remote-tracking branch EOF error_message bad-upstream@{u} && test_i18ncmp expect error diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh index c19fb500cb..18fa6cf40d 100755 --- a/t/t1512-rev-parse-disambiguation.sh +++ b/t/t1512-rev-parse-disambiguation.sh @@ -282,7 +282,7 @@ test_expect_success 'rev-parse --disambiguate' ' # commits created by commit-tree in earlier tests share a # different prefix. git rev-parse --disambiguate=000000000 >actual && - test $(wc -l <actual) = 16 && + test_line_count = 16 actual && test "$(sed -e "s/^\(.........\).*/\1/" actual | sort -u)" = 000000000 ' @@ -339,7 +339,7 @@ test_expect_success C_LOCALE_OUTPUT 'ambiguity hints' ' test_expect_success C_LOCALE_OUTPUT 'ambiguity hints respect type' ' test_must_fail git rev-parse 000000000^{commit} 2>stderr && grep ^hint: stderr >hints && - # 5 commits, 1 tag (which is a commitish), plus intro line + # 5 commits, 1 tag (which is a committish), plus intro line test_line_count = 7 hints ' diff --git a/t/t1600-index.sh b/t/t1600-index.sh index 42962ed7d4..b7c31aa86a 100755 --- a/t/t1600-index.sh +++ b/t/t1600-index.sh @@ -59,17 +59,42 @@ test_expect_success 'out of bounds index.version issues warning' ' ) ' -test_expect_success 'GIT_INDEX_VERSION takes precedence over config' ' +test_index_version () { + INDEX_VERSION_CONFIG=$1 && + FEATURE_MANY_FILES=$2 && + ENV_VAR_VERSION=$3 + EXPECTED_OUTPUT_VERSION=$4 && ( rm -f .git/index && - GIT_INDEX_VERSION=4 && - export GIT_INDEX_VERSION && - git config --add index.version 2 && + rm -f .git/config && + if test "$INDEX_VERSION_CONFIG" -ne 0 + then + git config --add index.version $INDEX_VERSION_CONFIG + fi && + git config --add feature.manyFiles $FEATURE_MANY_FILES + if test "$ENV_VAR_VERSION" -ne 0 + then + GIT_INDEX_VERSION=$ENV_VAR_VERSION && + export GIT_INDEX_VERSION + else + unset GIT_INDEX_VERSION + fi && git add a 2>&1 && - echo 4 >expect && + echo $EXPECTED_OUTPUT_VERSION >expect && test-tool index-version <.git/index >actual && test_cmp expect actual ) +} + +test_expect_success 'index version config precedence' ' + test_index_version 0 false 0 2 && + test_index_version 2 false 0 2 && + test_index_version 3 false 0 2 && + test_index_version 4 false 0 4 && + test_index_version 2 false 4 4 && + test_index_version 2 true 0 2 && + test_index_version 0 true 0 4 && + test_index_version 0 true 2 2 ' test_done diff --git a/t/t1700-split-index.sh b/t/t1700-split-index.sh index 4f2f84f309..12a5568844 100755 --- a/t/t1700-split-index.sh +++ b/t/t1700-split-index.sh @@ -20,6 +20,22 @@ create_non_racy_file () { test-tool chmtime =-5 "$1" } +test_expect_success 'setup' ' + test_oid_cache <<-EOF + own_v3 sha1:8299b0bcd1ac364e5f1d7768efb62fa2da79a339 + own_v3 sha256:38a6d2925e3eceec33ad7b34cbff4e0086caa0daf28f31e51f5bd94b4a7af86b + + base_v3 sha1:39d890139ee5356c7ef572216cebcd27aa41f9df + base_v3 sha256:c9baeadf905112bf6c17aefbd7d02267afd70ded613c30cafed2d40cb506e1ed + + own_v4 sha1:432ef4b63f32193984f339431fd50ca796493569 + own_v4 sha256:6738ac6319c25b694afa7bcc313deb182d1a59b68bf7a47b4296de83478c0420 + + base_v4 sha1:508851a7f0dfa8691e9f69c7f055865389012491 + base_v4 sha256:3177d4adfdd4b6904f7e921d91d715a471c0dde7cf6a4bba574927f02b699508 + EOF +' + test_expect_success 'enable split index' ' git config splitIndex.maxPercentChange 100 && git update-index --split-index && @@ -29,11 +45,11 @@ test_expect_success 'enable split index' ' # NEEDSWORK: Stop hard-coding checksums. if test "$indexversion" = "4" then - own=432ef4b63f32193984f339431fd50ca796493569 - base=508851a7f0dfa8691e9f69c7f055865389012491 + own=$(test_oid own_v4) + base=$(test_oid base_v4) else - own=8299b0bcd1ac364e5f1d7768efb62fa2da79a339 - base=39d890139ee5356c7ef572216cebcd27aa41f9df + own=$(test_oid own_v3) + base=$(test_oid base_v3) fi && cat >expect <<-EOF && @@ -99,17 +115,18 @@ test_expect_success 'enable split index again, "one" now belongs to base index"' test_expect_success 'modify original file, base index untouched' ' echo modified | create_non_racy_file one && + file1_blob=$(git hash-object one) && git update-index one && git ls-files --stage >ls-files.actual && cat >ls-files.expect <<-EOF && - 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0 one + 100644 $file1_blob 0 one EOF test_cmp ls-files.expect ls-files.actual && test-tool dump-split-index .git/index | sed "/^own/d" >actual && q_to_tab >expect <<-EOF && $BASE - 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q + 100644 $file1_blob 0Q replacements: 0 deletions: EOF @@ -121,7 +138,7 @@ test_expect_success 'add another file, which stays index' ' git update-index --add two && git ls-files --stage >ls-files.actual && cat >ls-files.expect <<-EOF && - 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0 one + 100644 $file1_blob 0 one 100644 $EMPTY_BLOB 0 two EOF test_cmp ls-files.expect ls-files.actual && @@ -129,7 +146,7 @@ test_expect_success 'add another file, which stays index' ' test-tool dump-split-index .git/index | sed "/^own/d" >actual && q_to_tab >expect <<-EOF && $BASE - 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q + 100644 $file1_blob 0Q 100644 $EMPTY_BLOB 0 two replacements: 0 deletions: @@ -141,14 +158,14 @@ test_expect_success 'remove file not in base index' ' git update-index --force-remove two && git ls-files --stage >ls-files.actual && cat >ls-files.expect <<-EOF && - 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0 one + 100644 $file1_blob 0 one EOF test_cmp ls-files.expect ls-files.actual && test-tool dump-split-index .git/index | sed "/^own/d" >actual && q_to_tab >expect <<-EOF && $BASE - 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q + 100644 $file1_blob 0Q replacements: 0 deletions: EOF @@ -237,9 +254,9 @@ test_expect_success 'set core.splitIndex config variable to true' ' git update-index --add three && git ls-files --stage >ls-files.actual && cat >ls-files.expect <<-EOF && - 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one - 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 three - 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 two + 100644 $EMPTY_BLOB 0 one + 100644 $EMPTY_BLOB 0 three + 100644 $EMPTY_BLOB 0 two EOF test_cmp ls-files.expect ls-files.actual && BASE=$(test-tool dump-split-index .git/index | grep "^base") && @@ -257,8 +274,8 @@ test_expect_success 'set core.splitIndex config variable to false' ' git update-index --force-remove three && git ls-files --stage >ls-files.actual && cat >ls-files.expect <<-EOF && - 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one - 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 two + 100644 $EMPTY_BLOB 0 one + 100644 $EMPTY_BLOB 0 two EOF test_cmp ls-files.expect ls-files.actual && test-tool dump-split-index .git/index | sed "/^own/d" >actual && @@ -285,7 +302,7 @@ test_expect_success 'set core.splitIndex config variable back to true' ' test-tool dump-split-index .git/index | sed "/^own/d" >actual && cat >expect <<-EOF && $BASE - 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 four + 100644 $EMPTY_BLOB 0 four replacements: deletions: EOF @@ -309,7 +326,7 @@ test_expect_success 'check behavior with splitIndex.maxPercentChange unset' ' test-tool dump-split-index .git/index | sed "/^own/d" >actual && cat >expect <<-EOF && $BASE - 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 six + 100644 $EMPTY_BLOB 0 six replacements: deletions: EOF diff --git a/t/t2014-switch.sh b/t/t2014-checkout-switch.sh index ccfb147113..ccfb147113 100755 --- a/t/t2014-switch.sh +++ b/t/t2014-checkout-switch.sh diff --git a/t/t2020-checkout-detach.sh b/t/t2020-checkout-detach.sh index 1fa670625c..b748db9946 100755 --- a/t/t2020-checkout-detach.sh +++ b/t/t2020-checkout-detach.sh @@ -195,16 +195,22 @@ test_expect_success 'describe_detached_head prints no SHA-1 ellipsis when not as # The first detach operation is more chatty than the following ones. cat >1st_detach <<-EOF && - Note: checking out 'HEAD^'. + Note: switching to 'HEAD^'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this - state without impacting any branches by performing another checkout. + state without impacting any branches by switching back to a branch. If you want to create a new branch to retain commits you create, you may - do so (now or later) by using -b with the checkout command again. Example: + do so (now or later) by using -c with the switch command. Example: - git checkout -b <new-branch-name> + git switch -c <new-branch-name> + + Or undo this operation with: + + git switch - + + Turn off this advice by setting config variable advice.detachedHead to false HEAD is now at \$commit three EOF @@ -271,16 +277,22 @@ test_expect_success 'describe_detached_head does print SHA-1 ellipsis when asked # The first detach operation is more chatty than the following ones. cat >1st_detach <<-EOF && - Note: checking out 'HEAD^'. + Note: switching to 'HEAD^'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this - state without impacting any branches by performing another checkout. + state without impacting any branches by switching back to a branch. If you want to create a new branch to retain commits you create, you may - do so (now or later) by using -b with the checkout command again. Example: + do so (now or later) by using -c with the switch command. Example: + + git switch -c <new-branch-name> + + Or undo this operation with: + + git switch - - git checkout -b <new-branch-name> + Turn off this advice by setting config variable advice.detachedHead to false HEAD is now at \$commit... three EOF diff --git a/t/t2022-checkout-paths.sh b/t/t2022-checkout-paths.sh index fc3eb43b89..6844afafc0 100755 --- a/t/t2022-checkout-paths.sh +++ b/t/t2022-checkout-paths.sh @@ -78,4 +78,15 @@ test_expect_success 'do not touch files that are already up-to-date' ' test_cmp expect actual ' +test_expect_success 'checkout HEAD adds deleted intent-to-add file back to index' ' + echo "nonempty" >nonempty && + >empty && + git add nonempty empty && + git commit -m "create files to be deleted" && + git rm --cached nonempty empty && + git add -N nonempty empty && + git checkout HEAD nonempty empty && + git diff --cached --exit-code +' + test_done diff --git a/t/t2060-switch.sh b/t/t2060-switch.sh new file mode 100755 index 0000000000..f9efa29dfb --- /dev/null +++ b/t/t2060-switch.sh @@ -0,0 +1,96 @@ +#!/bin/sh + +test_description='switch basic functionality' + +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit first && + git branch first-branch && + test_commit second && + test_commit third && + git remote add origin nohost:/nopath && + git update-ref refs/remotes/origin/foo first-branch +' + +test_expect_success 'switch branch no arguments' ' + test_must_fail git switch +' + +test_expect_success 'switch branch' ' + git switch first-branch && + test_path_is_missing second.t +' + +test_expect_success 'switch and detach' ' + test_when_finished git switch master && + test_must_fail git switch master^{commit} && + git switch --detach master^{commit} && + test_must_fail git symbolic-ref HEAD +' + +test_expect_success 'switch and detach current branch' ' + test_when_finished git switch master && + git switch master && + git switch --detach && + test_must_fail git symbolic-ref HEAD +' + +test_expect_success 'switch and create branch' ' + test_when_finished git switch master && + git switch -c temp master^ && + test_cmp_rev master^ refs/heads/temp && + echo refs/heads/temp >expected-branch && + git symbolic-ref HEAD >actual-branch && + test_cmp expected-branch actual-branch +' + +test_expect_success 'force create branch from HEAD' ' + test_when_finished git switch master && + git switch --detach master && + test_must_fail git switch -c temp && + git switch -C temp && + test_cmp_rev master refs/heads/temp && + echo refs/heads/temp >expected-branch && + git symbolic-ref HEAD >actual-branch && + test_cmp expected-branch actual-branch +' + +test_expect_success 'new orphan branch from empty' ' + test_when_finished git switch master && + test_must_fail git switch --orphan new-orphan HEAD && + git switch --orphan new-orphan && + test_commit orphan && + git cat-file commit refs/heads/new-orphan >commit && + ! grep ^parent commit && + git ls-files >tracked-files && + echo orphan.t >expected && + test_cmp expected tracked-files +' + +test_expect_success 'switching ignores file of same branch name' ' + test_when_finished git switch master && + : >first-branch && + git switch first-branch && + echo refs/heads/first-branch >expected && + git symbolic-ref HEAD >actual && + test_cmp expected actual +' + +test_expect_success 'guess and create branch ' ' + test_when_finished git switch master && + test_must_fail git switch --no-guess foo && + git switch foo && + echo refs/heads/foo >expected && + git symbolic-ref HEAD >actual && + test_cmp expected actual +' + +test_expect_success 'not switching when something is in progress' ' + test_when_finished rm -f .git/MERGE_HEAD && + # fake a merge-in-progress + cp .git/HEAD .git/MERGE_HEAD && + test_must_fail git switch -d @^ +' + +test_done diff --git a/t/t2070-restore.sh b/t/t2070-restore.sh new file mode 100755 index 0000000000..21c3f84459 --- /dev/null +++ b/t/t2070-restore.sh @@ -0,0 +1,109 @@ +#!/bin/sh + +test_description='restore basic functionality' + +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit first && + echo first-and-a-half >>first.t && + git add first.t && + test_commit second && + echo one >one && + echo two >two && + echo untracked >untracked && + echo ignored >ignored && + echo /ignored >.gitignore && + git add one two .gitignore && + git update-ref refs/heads/one master +' + +test_expect_success 'restore without pathspec is not ok' ' + test_must_fail git restore && + test_must_fail git restore --source=first +' + +test_expect_success 'restore a file, ignoring branch of same name' ' + cat one >expected && + echo dirty >>one && + git restore one && + test_cmp expected one +' + +test_expect_success 'restore a file on worktree from another ref' ' + test_when_finished git reset --hard && + git cat-file blob first:./first.t >expected && + git restore --source=first first.t && + test_cmp expected first.t && + git cat-file blob HEAD:./first.t >expected && + git show :first.t >actual && + test_cmp expected actual +' + +test_expect_success 'restore a file in the index from another ref' ' + test_when_finished git reset --hard && + git cat-file blob first:./first.t >expected && + git restore --source=first --staged first.t && + git show :first.t >actual && + test_cmp expected actual && + git cat-file blob HEAD:./first.t >expected && + test_cmp expected first.t +' + +test_expect_success 'restore a file in both the index and worktree from another ref' ' + test_when_finished git reset --hard && + git cat-file blob first:./first.t >expected && + git restore --source=first --staged --worktree first.t && + git show :first.t >actual && + test_cmp expected actual && + test_cmp expected first.t +' + +test_expect_success 'restore --staged uses HEAD as source' ' + test_when_finished git reset --hard && + git cat-file blob :./first.t >expected && + echo index-dirty >>first.t && + git add first.t && + git restore --staged first.t && + git cat-file blob :./first.t >actual && + test_cmp expected actual +' + +test_expect_success 'restore --ignore-unmerged ignores unmerged entries' ' + git init unmerged && + ( + cd unmerged && + echo one >unmerged && + echo one >common && + git add unmerged common && + git commit -m common && + git switch -c first && + echo first >unmerged && + git commit -am first && + git switch -c second master && + echo second >unmerged && + git commit -am second && + test_must_fail git merge first && + + echo dirty >>common && + test_must_fail git restore . && + + git restore --ignore-unmerged --quiet . >output 2>&1 && + git diff common >diff-output && + test_must_be_empty output && + test_must_be_empty diff-output + ) +' + +test_expect_success 'restore --staged adds deleted intent-to-add file back to index' ' + echo "nonempty" >nonempty && + >empty && + git add nonempty empty && + git commit -m "create files to be deleted" && + git rm --cached nonempty empty && + git add -N nonempty empty && + git restore --staged nonempty empty && + git diff --cached --exit-code +' + +test_done diff --git a/t/t2071-restore-patch.sh b/t/t2071-restore-patch.sh new file mode 100755 index 0000000000..98b2476e7c --- /dev/null +++ b/t/t2071-restore-patch.sh @@ -0,0 +1,110 @@ +#!/bin/sh + +test_description='git restore --patch' + +. ./lib-patch-mode.sh + +test_expect_success PERL 'setup' ' + mkdir dir && + echo parent >dir/foo && + echo dummy >bar && + git add bar dir/foo && + git commit -m initial && + test_tick && + test_commit second dir/foo head && + set_and_save_state bar bar_work bar_index && + save_head +' + +test_expect_success PERL 'restore -p without pathspec is fine' ' + echo q >cmd && + git restore -p <cmd +' + +# note: bar sorts before dir/foo, so the first 'n' is always to skip 'bar' + +test_expect_success PERL 'saying "n" does nothing' ' + set_and_save_state dir/foo work head && + test_write_lines n n | git restore -p && + verify_saved_state bar && + verify_saved_state dir/foo +' + +test_expect_success PERL 'git restore -p' ' + set_and_save_state dir/foo work head && + test_write_lines n y | git restore -p && + verify_saved_state bar && + verify_state dir/foo head head +' + +test_expect_success PERL 'git restore -p with staged changes' ' + set_state dir/foo work index && + test_write_lines n y | git restore -p && + verify_saved_state bar && + verify_state dir/foo index index +' + +test_expect_success PERL 'git restore -p --source=HEAD' ' + set_state dir/foo work index && + # the third n is to get out in case it mistakenly does not apply + test_write_lines n y n | git restore -p --source=HEAD && + verify_saved_state bar && + verify_state dir/foo head index +' + +test_expect_success PERL 'git restore -p --source=HEAD^' ' + set_state dir/foo work index && + # the third n is to get out in case it mistakenly does not apply + test_write_lines n y n | git restore -p --source=HEAD^ && + verify_saved_state bar && + verify_state dir/foo parent index +' + +test_expect_success PERL 'git restore -p handles deletion' ' + set_state dir/foo work index && + rm dir/foo && + test_write_lines n y | git restore -p && + verify_saved_state bar && + verify_state dir/foo index index +' + +# The idea in the rest is that bar sorts first, so we always say 'y' +# first and if the path limiter fails it'll apply to bar instead of +# dir/foo. There's always an extra 'n' to reject edits to dir/foo in +# the failure case (and thus get out of the loop). + +test_expect_success PERL 'path limiting works: dir' ' + set_state dir/foo work head && + test_write_lines y n | git restore -p dir && + verify_saved_state bar && + verify_state dir/foo head head +' + +test_expect_success PERL 'path limiting works: -- dir' ' + set_state dir/foo work head && + test_write_lines y n | git restore -p -- dir && + verify_saved_state bar && + verify_state dir/foo head head +' + +test_expect_success PERL 'path limiting works: HEAD^ -- dir' ' + set_state dir/foo work head && + # the third n is to get out in case it mistakenly does not apply + test_write_lines y n n | git restore -p --source=HEAD^ -- dir && + verify_saved_state bar && + verify_state dir/foo parent head +' + +test_expect_success PERL 'path limiting works: foo inside dir' ' + set_state dir/foo work head && + # the third n is to get out in case it mistakenly does not apply + test_write_lines y n n | (cd dir && git restore -p foo) && + verify_saved_state bar && + verify_state dir/foo head head +' + +test_expect_success PERL 'none of this moved HEAD' ' + verify_saved_head +' + +test_done diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh index 68e54d5c44..5bbe8dcce4 100755 --- a/t/t2203-add-intent.sh +++ b/t/t2203-add-intent.sh @@ -247,12 +247,14 @@ test_expect_success 'diff-files/diff-cached shows ita as new/not-new files' ' test_expect_success '"diff HEAD" includes ita as new files' ' git reset --hard && echo new >new-ita && + oid=$(git hash-object new-ita) && + oid=$(git rev-parse --short $oid) && git add -N new-ita && git diff HEAD >actual && - cat >expected <<-\EOF && + cat >expected <<-EOF && diff --git a/new-ita b/new-ita new file mode 100644 - index 0000000..3e75765 + index 0000000..$oid --- /dev/null +++ b/new-ita @@ -0,0 +1 @@ diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh index d83a9f0fdc..b5ece19460 100755 --- a/t/t2400-worktree-add.sh +++ b/t/t2400-worktree-add.sh @@ -438,7 +438,7 @@ test_expect_success 'git worktree add does not match remote' ' cd foo && test_must_fail git config "branch.foo.remote" && test_must_fail git config "branch.foo.merge" && - ! test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo + test_cmp_rev ! refs/remotes/repo_a/foo refs/heads/foo ) ' @@ -483,7 +483,7 @@ test_expect_success 'git worktree --no-guess-remote option overrides config' ' cd foo && test_must_fail git config "branch.foo.remote" && test_must_fail git config "branch.foo.merge" && - ! test_cmp_rev refs/remotes/repo_a/foo refs/heads/foo + test_cmp_rev ! refs/remotes/repo_a/foo refs/heads/foo ) ' @@ -570,6 +570,11 @@ test_expect_success '"add" an existing locked but missing worktree' ' git worktree add --force --force --detach gnoo ' +test_expect_success FUNNYNAMES 'sanitize generated worktree name' ' + git worktree add --detach ". weird*..?.lock.lock" && + test -d .git/worktrees/---weird-.- +' + test_expect_success '"add" should not fail because of another bad worktree' ' git init add-fail && ( @@ -582,4 +587,28 @@ test_expect_success '"add" should not fail because of another bad worktree' ' ) ' +test_expect_success '"add" with uninitialized submodule, with submodule.recurse unset' ' + test_create_repo submodule && + test_commit -C submodule first && + test_create_repo project && + git -C project submodule add ../submodule && + git -C project add submodule && + test_tick && + git -C project commit -m add_sub && + git clone project project-clone && + git -C project-clone worktree add ../project-2 +' +test_expect_success '"add" with uninitialized submodule, with submodule.recurse set' ' + git -C project-clone -c submodule.recurse worktree add ../project-3 +' + +test_expect_success '"add" with initialized submodule, with submodule.recurse unset' ' + git -C project-clone submodule update --init && + git -C project-clone worktree add ../project-4 +' + +test_expect_success '"add" with initialized submodule, with submodule.recurse set' ' + git -C project-clone -c submodule.recurse worktree add ../project-5 +' + test_done diff --git a/t/t3005-ls-files-relative.sh b/t/t3005-ls-files-relative.sh index 209b4c7cd8..2ec69a8a26 100755 --- a/t/t3005-ls-files-relative.sh +++ b/t/t3005-ls-files-relative.sh @@ -7,10 +7,6 @@ This test runs git ls-files with various relative path arguments. . ./test-lib.sh -new_line=' -' -sq=\' - test_expect_success 'prepare' ' : >never-mind-me && git add never-mind-me && @@ -44,9 +40,9 @@ test_expect_success 'ls-files -c' ' cd top/sub && for f in ../y* do - echo "error: pathspec $sq$f$sq did not match any file(s) known to git" + echo "error: pathspec $SQ$f$SQ did not match any file(s) known to git" done >expect.err && - echo "Did you forget to ${sq}git add${sq}?" >>expect.err && + echo "Did you forget to ${SQ}git add${SQ}?" >>expect.err && ls ../x* >expect.out && test_must_fail git ls-files -c --error-unmatch ../[xy]* >actual.out 2>actual.err && test_cmp expect.out actual.out && @@ -59,9 +55,9 @@ test_expect_success 'ls-files -o' ' cd top/sub && for f in ../x* do - echo "error: pathspec $sq$f$sq did not match any file(s) known to git" + echo "error: pathspec $SQ$f$SQ did not match any file(s) known to git" done >expect.err && - echo "Did you forget to ${sq}git add${sq}?" >>expect.err && + echo "Did you forget to ${SQ}git add${SQ}?" >>expect.err && ls ../y* >expect.out && test_must_fail git ls-files -o --error-unmatch ../[xy]* >actual.out 2>actual.err && test_cmp expect.out actual.out && diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh index ff641b348a..2170758e38 100755 --- a/t/t3030-merge-recursive.sh +++ b/t/t3030-merge-recursive.sh @@ -452,6 +452,34 @@ test_expect_success 'merge-recursive d/f conflict result' ' ' +test_expect_success SYMLINKS 'dir in working tree with symlink ancestor does not produce d/f conflict' ' + git init sym && + ( + cd sym && + ln -s . foo && + mkdir bar && + >bar/file && + git add foo bar/file && + git commit -m "foo symlink" && + + git checkout -b branch1 && + git commit --allow-empty -m "empty commit" && + + git checkout master && + git rm foo && + mkdir foo && + >foo/bar && + git add foo/bar && + git commit -m "replace foo symlink with real foo dir and foo/bar file" && + + git checkout branch1 && + + git cherry-pick master && + test_path_is_dir foo && + test_path_is_file foo/bar + ) +' + test_expect_success 'reset and 3-way merge' ' git reset --hard "$c2" && @@ -667,15 +695,22 @@ test_expect_success 'merging with triple rename across D/F conflict' ' test_expect_success 'merge-recursive remembers the names of all base trees' ' git reset --hard HEAD && + # make the index match $c1 so that merge-recursive below does not + # fail early + git diff --binary HEAD $c1 -- | git apply --cached && + # more trees than static slots used by oid_to_hex() for commit in $c0 $c2 $c4 $c5 $c6 $c7 do git rev-parse "$commit^{tree}" done >trees && - # ignore the return code -- it only fails because the input is weird + # ignore the return code; it only fails because the input is weird... test_must_fail git -c merge.verbosity=5 merge-recursive $(cat trees) -- $c1 $c3 >out && + # ...but make sure it fails in the expected way + test_i18ngrep CONFLICT.*rename/rename out && + # merge-recursive prints in reverse order, but we do not care sort <trees >expect && sed -n "s/^virtual //p" out | sort >actual && diff --git a/t/t3060-ls-files-with-tree.sh b/t/t3060-ls-files-with-tree.sh index 44f378ce41..52ed665fcd 100755 --- a/t/t3060-ls-files-with-tree.sh +++ b/t/t3060-ls-files-with-tree.sh @@ -47,7 +47,7 @@ test_expect_success setup ' git add . ' -test_expect_success 'git -ls-files --with-tree should succeed from subdir' ' +test_expect_success 'git ls-files --with-tree should succeed from subdir' ' # We have to run from a sub-directory to trigger prune_path # Then we finally get to run our --with-tree test ( @@ -57,7 +57,7 @@ test_expect_success 'git -ls-files --with-tree should succeed from subdir' ' ' test_expect_success \ - 'git -ls-files --with-tree should add entries from named tree.' \ + 'git ls-files --with-tree should add entries from named tree.' \ 'test_cmp expected output' test_done diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index e9d7084d19..411a70b0ce 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -206,18 +206,22 @@ test_expect_success 'git branch -M baz bam should succeed when baz is checked ou git worktree add -f bazdir2 baz && git branch -M baz bam && test $(git -C bazdir rev-parse --abbrev-ref HEAD) = bam && - test $(git -C bazdir2 rev-parse --abbrev-ref HEAD) = bam + test $(git -C bazdir2 rev-parse --abbrev-ref HEAD) = bam && + rm -r bazdir bazdir2 && + git worktree prune ' test_expect_success 'git branch -M baz bam should succeed within a worktree in which baz is checked out' ' git checkout -b baz && - git worktree add -f bazdir3 baz && + git worktree add -f bazdir baz && ( - cd bazdir3 && + cd bazdir && git branch -M baz bam && test $(git rev-parse --abbrev-ref HEAD) = bam ) && - test $(git rev-parse --abbrev-ref HEAD) = bam + test $(git rev-parse --abbrev-ref HEAD) = bam && + rm -r bazdir && + git worktree prune ' test_expect_success 'git branch -M master should work when master is checked out' ' @@ -804,7 +808,9 @@ test_expect_success 'test deleting branch without config' ' test_expect_success 'deleting currently checked out branch fails' ' git worktree add -b my7 my7 && test_must_fail git -C my7 branch -d my7 && - test_must_fail git branch -d my7 + test_must_fail git branch -d my7 && + rm -r my7 && + git worktree prune ' test_expect_success 'test --track without .fetch entries' ' diff --git a/t/t3201-branch-contains.sh b/t/t3201-branch-contains.sh index 0ea4fc4694..40251c9f8f 100755 --- a/t/t3201-branch-contains.sh +++ b/t/t3201-branch-contains.sh @@ -192,10 +192,10 @@ test_expect_success 'branch --merged with --verbose' ' EOF test_cmp expect actual && git branch --verbose --merged topic >actual && - cat >expect <<-\EOF && - master c77a0a9 second on master - * topic 2c939f4 [ahead 1] foo - zzz c77a0a9 second on master + cat >expect <<-EOF && + master $(git rev-parse --short master) second on master + * topic $(git rev-parse --short topic ) [ahead 1] foo + zzz $(git rev-parse --short zzz ) second on master EOF test_i18ncmp expect actual ' diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh index be55148930..71818b90f0 100755 --- a/t/t3203-branch-output.sh +++ b/t/t3203-branch-output.sh @@ -136,10 +136,13 @@ test_expect_success 'git branch `--show-current` works properly with worktrees' branch-two EOF git checkout branch-one && - git worktree add worktree branch-two && + test_when_finished " + git worktree remove worktree_dir + " && + git worktree add worktree_dir branch-two && { git branch --show-current && - git -C worktree branch --show-current + git -C worktree_dir branch --show-current } >actual && test_cmp expect actual ' @@ -284,6 +287,24 @@ test_expect_success 'git branch --format option' ' test_i18ncmp expect actual ' +test_expect_success 'worktree colors correct' ' + cat >expect <<-EOF && + * <GREEN>(HEAD detached from fromtag)<RESET> + ambiguous<RESET> + branch-one<RESET> + + <CYAN>branch-two<RESET> + master<RESET> + ref-to-branch<RESET> -> branch-one + ref-to-remote<RESET> -> origin/branch-one + EOF + git worktree add worktree_dir branch-two && + git branch --color >actual.raw && + rm -r worktree_dir && + git worktree prune && + test_decode_color <actual.raw >actual && + test_i18ncmp expect actual +' + test_expect_success "set up color tests" ' echo "<RED>master<RESET>" >expect.color && echo "master" >expect.bare && @@ -308,4 +329,23 @@ test_expect_success '--color overrides auto-color' ' test_cmp expect.color actual ' +test_expect_success 'verbose output lists worktree path' ' + one=$(git rev-parse --short HEAD) && + two=$(git rev-parse --short master) && + cat >expect <<-EOF && + * (HEAD detached from fromtag) $one one + ambiguous $one one + branch-one $two two + + branch-two $one ($(pwd)/worktree_dir) one + master $two two + ref-to-branch $two two + ref-to-remote $two two + EOF + git worktree add worktree_dir branch-two && + git branch -vv >actual && + rm -r worktree_dir && + git worktree prune && + test_i18ncmp expect actual +' + test_done diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh index 048feaf6dd..ec2b456dbb 100755 --- a/t/t3206-range-diff.sh +++ b/t/t3206-range-diff.sh @@ -8,98 +8,205 @@ test_description='range-diff tests' # harm than good. We need some real history. test_expect_success 'setup' ' - git fast-import < "$TEST_DIRECTORY"/t3206/history.export + git fast-import <"$TEST_DIRECTORY"/t3206/history.export && + test_oid_cache <<-\EOF + # topic + t1 sha1:4de457d + t2 sha1:fccce22 + t3 sha1:147e64e + t4 sha1:a63e992 + t1 sha256:b89f8b9 + t2 sha256:5f12aad + t3 sha256:ea8b273 + t4 sha256:14b7336 + + # unmodified + u1 sha1:35b9b25 + u2 sha1:de345ab + u3 sha1:9af6654 + u4 sha1:2901f77 + u1 sha256:e3731be + u2 sha256:14fadf8 + u3 sha256:736c4bc + u4 sha256:673e77d + + # reordered + r1 sha1:aca177a + r2 sha1:14ad629 + r3 sha1:ee58208 + r4 sha1:307b27a + r1 sha256:f59d3aa + r2 sha256:fb261a8 + r3 sha256:cb2649b + r4 sha256:958577e + + # removed (deleted) + d1 sha1:7657159 + d2 sha1:43d84d3 + d3 sha1:a740396 + d1 sha256:e312513 + d2 sha256:eb19258 + d3 sha256:1ccb3c1 + + # added + a1 sha1:2716022 + a2 sha1:b62accd + a3 sha1:df46cfa + a4 sha1:3e64548 + a5 sha1:12b4063 + a1 sha256:d724f4d + a2 sha256:1de7762 + a3 sha256:e159431 + a4 sha256:b3e483c + a5 sha256:90866a7 + + # rebased + b1 sha1:cc9c443 + b2 sha1:c5d9641 + b3 sha1:28cc2b6 + b4 sha1:5628ab7 + b5 sha1:a31b12e + b1 sha256:a1a8717 + b2 sha256:20a5862 + b3 sha256:587172a + b4 sha256:2721c5d + b5 sha256:7b57864 + + # changed + c1 sha1:a4b3333 + c2 sha1:f51d370 + c3 sha1:0559556 + c4 sha1:d966c5c + c1 sha256:f8c2b9d + c2 sha256:3fb6318 + c3 sha256:168ab68 + c4 sha256:3526539 + + # changed-message + m1 sha1:f686024 + m2 sha1:4ab067d + m3 sha1:b9cb956 + m4 sha1:8add5f1 + m1 sha256:31e6281 + m2 sha256:a06bf1b + m3 sha256:82dc654 + m4 sha256:48470c5 + + # renamed + n1 sha1:f258d75 + n2 sha1:017b62d + n3 sha1:3ce7af6 + n4 sha1:1e6226b + n1 sha256:ad52114 + n2 sha256:3b54c8f + n3 sha256:3b0a644 + n4 sha256:e461653 + + # added and removed + s1 sha1:096b1ba + s2 sha1:d92e698 + s3 sha1:9a1db4d + s4 sha1:fea3b5c + s1 sha256:a7f9134 + s2 sha256:b4c2580 + s3 sha256:1d62aa2 + s4 sha256:48160e8 + + # Empty delimiter (included so lines match neatly) + __ sha1:------- + __ sha256:------- + EOF ' test_expect_success 'simple A..B A..C (unmodified)' ' git range-diff --no-color master..topic master..unmodified \ >actual && - cat >expected <<-EOF && - 1: 4de457d = 1: 35b9b25 s/5/A/ - 2: fccce22 = 2: de345ab s/4/A/ - 3: 147e64e = 3: 9af6654 s/11/B/ - 4: a63e992 = 4: 2901f77 s/12/B/ + cat >expect <<-EOF && + 1: $(test_oid t1) = 1: $(test_oid u1) s/5/A/ + 2: $(test_oid t2) = 2: $(test_oid u2) s/4/A/ + 3: $(test_oid t3) = 3: $(test_oid u3) s/11/B/ + 4: $(test_oid t4) = 4: $(test_oid u4) s/12/B/ EOF - test_cmp expected actual + test_cmp expect actual ' test_expect_success 'simple B...C (unmodified)' ' git range-diff --no-color topic...unmodified >actual && - # same "expected" as above - test_cmp expected actual + # same "expect" as above + test_cmp expect actual ' test_expect_success 'simple A B C (unmodified)' ' git range-diff --no-color master topic unmodified >actual && - # same "expected" as above - test_cmp expected actual + # same "expect" as above + test_cmp expect actual ' test_expect_success 'trivial reordering' ' git range-diff --no-color master topic reordered >actual && - cat >expected <<-EOF && - 1: 4de457d = 1: aca177a s/5/A/ - 3: 147e64e = 2: 14ad629 s/11/B/ - 4: a63e992 = 3: ee58208 s/12/B/ - 2: fccce22 = 4: 307b27a s/4/A/ + cat >expect <<-EOF && + 1: $(test_oid t1) = 1: $(test_oid r1) s/5/A/ + 3: $(test_oid t3) = 2: $(test_oid r2) s/11/B/ + 4: $(test_oid t4) = 3: $(test_oid r3) s/12/B/ + 2: $(test_oid t2) = 4: $(test_oid r4) s/4/A/ EOF - test_cmp expected actual + test_cmp expect actual ' test_expect_success 'removed a commit' ' git range-diff --no-color master topic removed >actual && - cat >expected <<-EOF && - 1: 4de457d = 1: 7657159 s/5/A/ - 2: fccce22 < -: ------- s/4/A/ - 3: 147e64e = 2: 43d84d3 s/11/B/ - 4: a63e992 = 3: a740396 s/12/B/ + cat >expect <<-EOF && + 1: $(test_oid t1) = 1: $(test_oid d1) s/5/A/ + 2: $(test_oid t2) < -: $(test_oid __) s/4/A/ + 3: $(test_oid t3) = 2: $(test_oid d2) s/11/B/ + 4: $(test_oid t4) = 3: $(test_oid d3) s/12/B/ EOF - test_cmp expected actual + test_cmp expect actual ' test_expect_success 'added a commit' ' git range-diff --no-color master topic added >actual && - cat >expected <<-EOF && - 1: 4de457d = 1: 2716022 s/5/A/ - 2: fccce22 = 2: b62accd s/4/A/ - -: ------- > 3: df46cfa s/6/A/ - 3: 147e64e = 4: 3e64548 s/11/B/ - 4: a63e992 = 5: 12b4063 s/12/B/ + cat >expect <<-EOF && + 1: $(test_oid t1) = 1: $(test_oid a1) s/5/A/ + 2: $(test_oid t2) = 2: $(test_oid a2) s/4/A/ + -: $(test_oid __) > 3: $(test_oid a3) s/6/A/ + 3: $(test_oid t3) = 4: $(test_oid a4) s/11/B/ + 4: $(test_oid t4) = 5: $(test_oid a5) s/12/B/ EOF - test_cmp expected actual + test_cmp expect actual ' test_expect_success 'new base, A B C' ' git range-diff --no-color master topic rebased >actual && - cat >expected <<-EOF && - 1: 4de457d = 1: cc9c443 s/5/A/ - 2: fccce22 = 2: c5d9641 s/4/A/ - 3: 147e64e = 3: 28cc2b6 s/11/B/ - 4: a63e992 = 4: 5628ab7 s/12/B/ + cat >expect <<-EOF && + 1: $(test_oid t1) = 1: $(test_oid b1) s/5/A/ + 2: $(test_oid t2) = 2: $(test_oid b2) s/4/A/ + 3: $(test_oid t3) = 3: $(test_oid b3) s/11/B/ + 4: $(test_oid t4) = 4: $(test_oid b4) s/12/B/ EOF - test_cmp expected actual + test_cmp expect actual ' test_expect_success 'new base, B...C' ' # this syntax includes the commits from master! git range-diff --no-color topic...rebased >actual && - cat >expected <<-EOF && - -: ------- > 1: a31b12e unrelated - 1: 4de457d = 2: cc9c443 s/5/A/ - 2: fccce22 = 3: c5d9641 s/4/A/ - 3: 147e64e = 4: 28cc2b6 s/11/B/ - 4: a63e992 = 5: 5628ab7 s/12/B/ + cat >expect <<-EOF && + -: $(test_oid __) > 1: $(test_oid b5) unrelated + 1: $(test_oid t1) = 2: $(test_oid b1) s/5/A/ + 2: $(test_oid t2) = 3: $(test_oid b2) s/4/A/ + 3: $(test_oid t3) = 4: $(test_oid b3) s/11/B/ + 4: $(test_oid t4) = 5: $(test_oid b4) s/12/B/ EOF - test_cmp expected actual + test_cmp expect actual ' test_expect_success 'changed commit' ' git range-diff --no-color 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 @@ + cat >expect <<-EOF && + 1: $(test_oid t1) = 1: $(test_oid c1) s/5/A/ + 2: $(test_oid t2) = 2: $(test_oid c2) s/4/A/ + 3: $(test_oid t3) ! 3: $(test_oid c3) s/11/B/ + @@ file: A 9 10 -11 @@ -108,9 +215,9 @@ test_expect_success 'changed commit' ' 12 13 14 - 4: a63e992 ! 4: d966c5c s/12/B/ - @@ -8,7 +8,7 @@ - @@ + 4: $(test_oid t4) ! 4: $(test_oid c4) s/12/B/ + @@ file + @@ file: A 9 10 - B @@ -119,46 +226,46 @@ test_expect_success 'changed commit' ' +B 13 EOF - test_cmp expected actual + test_cmp expect 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/ + cat >expect <<-EOF && + 1: $(test_oid t1) = 1: $(test_oid c1) s/5/A/ + 2: $(test_oid t2) = 2: $(test_oid c2) s/4/A/ + 3: $(test_oid t3) ! 3: $(test_oid c3) s/11/B/ + 4: $(test_oid t4) ! 4: $(test_oid c4) s/12/B/ EOF - test_cmp expected actual + test_cmp expect 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/ + cat >expect <<-EOF && + 1: $(test_oid t1) = 1: $(test_oid c1) s/5/A/ a => b | 0 1 file changed, 0 insertions(+), 0 deletions(-) - 2: fccce22 = 2: f51d370 s/4/A/ + 2: $(test_oid t2) = 2: $(test_oid c2) s/4/A/ a => b | 0 1 file changed, 0 insertions(+), 0 deletions(-) - 3: 147e64e ! 3: 0559556 s/11/B/ + 3: $(test_oid t3) ! 3: $(test_oid c3) s/11/B/ a => b | 0 1 file changed, 0 insertions(+), 0 deletions(-) - 4: a63e992 ! 4: d966c5c s/12/B/ + 4: $(test_oid t4) ! 4: $(test_oid c4) s/12/B/ a => b | 0 1 file changed, 0 insertions(+), 0 deletions(-) EOF - test_cmp expected actual + test_cmp expect 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 @@ + cat >expect <<-EOF && + 1: $(test_oid t1) = 1: $(test_oid c1) s/5/A/ + 2: $(test_oid t2) = 2: $(test_oid c2) s/4/A/ + 3: $(test_oid t3) ! 3: $(test_oid c3) s/11/B/ + @@ file: A 9 10 -11 @@ -167,9 +274,9 @@ test_expect_success 'changed commit with sm config' ' 12 13 14 - 4: a63e992 ! 4: d966c5c s/12/B/ - @@ -8,7 +8,7 @@ - @@ + 4: $(test_oid t4) ! 4: $(test_oid c4) s/12/B/ + @@ file + @@ file: A 9 10 - B @@ -178,7 +285,133 @@ test_expect_success 'changed commit with sm config' ' +B 13 EOF - test_cmp expected actual + test_cmp expect actual +' + +test_expect_success 'renamed file' ' + git range-diff --no-color --submodule=log topic...renamed-file >actual && + sed s/Z/\ /g >expect <<-EOF && + 1: $(test_oid t1) = 1: $(test_oid n1) s/5/A/ + 2: $(test_oid t2) ! 2: $(test_oid n2) s/4/A/ + @@ Metadata + ZAuthor: Thomas Rast <trast@inf.ethz.ch> + Z + Z ## Commit message ## + - s/4/A/ + + s/4/A/ + rename file + Z + - ## file ## + + ## file => renamed-file ## + Z@@ + Z 1 + Z 2 + 3: $(test_oid t3) ! 3: $(test_oid n3) s/11/B/ + @@ Metadata + Z ## Commit message ## + Z s/11/B/ + Z + - ## file ## + -@@ file: A + + ## renamed-file ## + +@@ renamed-file: A + Z 8 + Z 9 + Z 10 + 4: $(test_oid t4) ! 4: $(test_oid n4) s/12/B/ + @@ Metadata + Z ## Commit message ## + Z s/12/B/ + Z + - ## file ## + -@@ file: A + + ## renamed-file ## + +@@ renamed-file: A + Z 9 + Z 10 + Z B + EOF + test_cmp expect actual +' + +test_expect_success 'file with mode only change' ' + git range-diff --no-color --submodule=log topic...mode-only-change >actual && + sed s/Z/\ /g >expect <<-EOF && + 1: fccce22 ! 1: 4d39cb3 s/4/A/ + @@ Metadata + ZAuthor: Thomas Rast <trast@inf.ethz.ch> + Z + Z ## Commit message ## + - s/4/A/ + + s/4/A/ + add other-file + Z + Z ## file ## + Z@@ + @@ file + Z A + Z 6 + Z 7 + + + + ## other-file (new) ## + 2: 147e64e ! 2: 26c107f s/11/B/ + @@ Metadata + ZAuthor: Thomas Rast <trast@inf.ethz.ch> + Z + Z ## Commit message ## + - s/11/B/ + + s/11/B/ + mode change other-file + Z + Z ## file ## + Z@@ file: A + @@ file: A + Z 12 + Z 13 + Z 14 + + + + ## other-file (mode change 100644 => 100755) ## + 3: a63e992 = 3: 4c1e0f5 s/12/B/ + EOF + test_cmp expect actual +' + +test_expect_success 'file added and later removed' ' + git range-diff --no-color --submodule=log topic...added-removed >actual && + sed s/Z/\ /g >expect <<-EOF && + 1: $(test_oid t1) = 1: $(test_oid s1) s/5/A/ + 2: $(test_oid t2) ! 2: $(test_oid s2) s/4/A/ + @@ Metadata + ZAuthor: Thomas Rast <trast@inf.ethz.ch> + Z + Z ## Commit message ## + - s/4/A/ + + s/4/A/ + new-file + Z + Z ## file ## + Z@@ + @@ file + Z A + Z 6 + Z 7 + + + + ## new-file (new) ## + 3: $(test_oid t3) ! 3: $(test_oid s3) s/11/B/ + @@ Metadata + ZAuthor: Thomas Rast <trast@inf.ethz.ch> + Z + Z ## Commit message ## + - s/11/B/ + + s/11/B/ + remove file + Z + Z ## file ## + Z@@ file: A + @@ file: A + Z 12 + Z 13 + Z 14 + + + + ## new-file (deleted) ## + 4: $(test_oid t4) = 4: $(test_oid s4) s/12/B/ + EOF + test_cmp expect actual ' test_expect_success 'no commits on one side' ' @@ -188,39 +421,39 @@ test_expect_success 'no commits on one side' ' test_expect_success 'changed message' ' git range-diff --no-color topic...changed-message >actual && - sed s/Z/\ /g >expected <<-EOF && - 1: 4de457d = 1: f686024 s/5/A/ - 2: fccce22 ! 2: 4ab067d s/4/A/ - @@ -2,6 +2,8 @@ - Z + sed s/Z/\ /g >expect <<-EOF && + 1: $(test_oid t1) = 1: $(test_oid m1) s/5/A/ + 2: $(test_oid t2) ! 2: $(test_oid m2) s/4/A/ + @@ Metadata + Z ## Commit message ## Z s/4/A/ Z + Also a silly comment here! + - Z diff --git a/file b/file - Z --- a/file - Z +++ b/file - 3: 147e64e = 3: b9cb956 s/11/B/ - 4: a63e992 = 4: 8add5f1 s/12/B/ + Z ## file ## + Z@@ + Z 1 + 3: $(test_oid t3) = 3: $(test_oid m3) s/11/B/ + 4: $(test_oid t4) = 4: $(test_oid m4) s/12/B/ EOF - test_cmp expected actual + test_cmp expect actual ' test_expect_success 'dual-coloring' ' - sed -e "s|^:||" >expect <<-\EOF && - :<YELLOW>1: a4b3333 = 1: f686024 s/5/A/<RESET> - :<RED>2: f51d370 <RESET><YELLOW>!<RESET><GREEN> 2: 4ab067d<RESET><YELLOW> s/4/A/<RESET> - : <REVERSE><CYAN>@@ -2,6 +2,8 @@<RESET> - : <RESET> + sed -e "s|^:||" >expect <<-EOF && + :<YELLOW>1: $(test_oid c1) = 1: $(test_oid m1) s/5/A/<RESET> + :<RED>2: $(test_oid c2) <RESET><YELLOW>!<RESET><GREEN> 2: $(test_oid m2)<RESET><YELLOW> s/4/A/<RESET> + : <REVERSE><CYAN>@@<RESET> <RESET>Metadata<RESET> + : ## Commit message ##<RESET> : s/4/A/<RESET> : <RESET> : <REVERSE><GREEN>+<RESET><BOLD> Also a silly comment here!<RESET> : <REVERSE><GREEN>+<RESET> - : diff --git a/file b/file<RESET> - : --- a/file<RESET> - : +++ b/file<RESET> - :<RED>3: 0559556 <RESET><YELLOW>!<RESET><GREEN> 3: b9cb956<RESET><YELLOW> s/11/B/<RESET> - : <REVERSE><CYAN>@@ -10,7 +10,7 @@<RESET> + : ## file ##<RESET> + : <CYAN> @@<RESET> + : 1<RESET> + :<RED>3: $(test_oid c3) <RESET><YELLOW>!<RESET><GREEN> 3: $(test_oid m3)<RESET><YELLOW> s/11/B/<RESET> + : <REVERSE><CYAN>@@<RESET> <RESET>file: A<RESET> : 9<RESET> : 10<RESET> : <RED> -11<RESET> @@ -229,9 +462,9 @@ test_expect_success 'dual-coloring' ' : 12<RESET> : 13<RESET> : 14<RESET> - :<RED>4: d966c5c <RESET><YELLOW>!<RESET><GREEN> 4: 8add5f1<RESET><YELLOW> s/12/B/<RESET> - : <REVERSE><CYAN>@@ -8,7 +8,7 @@<RESET> - : <CYAN> @@<RESET> + :<RED>4: $(test_oid c4) <RESET><YELLOW>!<RESET><GREEN> 4: $(test_oid m4)<RESET><YELLOW> s/12/B/<RESET> + : <REVERSE><CYAN>@@<RESET> <RESET>file<RESET> + : <CYAN> @@ file: A<RESET> : 9<RESET> : 10<RESET> : <REVERSE><RED>-<RESET><FAINT> BB<RESET> @@ -268,4 +501,206 @@ test_expect_success 'format-patch --range-diff as commentary' ' grep "> 1: .* new message" 0001-* ' +test_expect_success 'range-diff overrides diff.noprefix internally' ' + git -c diff.noprefix=true range-diff HEAD^... +' + +test_expect_success 'range-diff compares notes by default' ' + git notes add -m "topic note" topic && + git notes add -m "unmodified note" unmodified && + test_when_finished git notes remove topic unmodified && + git range-diff --no-color master..topic master..unmodified \ + >actual && + sed s/Z/\ /g >expect <<-EOF && + 1: $(test_oid t1) = 1: $(test_oid u1) s/5/A/ + 2: $(test_oid t2) = 2: $(test_oid u2) s/4/A/ + 3: $(test_oid t3) = 3: $(test_oid u3) s/11/B/ + 4: $(test_oid t4) ! 4: $(test_oid u4) s/12/B/ + @@ Commit message + Z + Z + Z ## Notes ## + - topic note + + unmodified note + Z + Z ## file ## + Z@@ file: A + EOF + test_cmp expect actual +' + +test_expect_success 'range-diff with --no-notes' ' + git notes add -m "topic note" topic && + git notes add -m "unmodified note" unmodified && + test_when_finished git notes remove topic unmodified && + git range-diff --no-color --no-notes master..topic master..unmodified \ + >actual && + cat >expect <<-EOF && + 1: $(test_oid t1) = 1: $(test_oid u1) s/5/A/ + 2: $(test_oid t2) = 2: $(test_oid u2) s/4/A/ + 3: $(test_oid t3) = 3: $(test_oid u3) s/11/B/ + 4: $(test_oid t4) = 4: $(test_oid u4) s/12/B/ + EOF + test_cmp expect actual +' + +test_expect_success 'range-diff with multiple --notes' ' + git notes --ref=note1 add -m "topic note1" topic && + git notes --ref=note1 add -m "unmodified note1" unmodified && + test_when_finished git notes --ref=note1 remove topic unmodified && + git notes --ref=note2 add -m "topic note2" topic && + git notes --ref=note2 add -m "unmodified note2" unmodified && + test_when_finished git notes --ref=note2 remove topic unmodified && + git range-diff --no-color --notes=note1 --notes=note2 master..topic master..unmodified \ + >actual && + sed s/Z/\ /g >expect <<-EOF && + 1: $(test_oid t1) = 1: $(test_oid u1) s/5/A/ + 2: $(test_oid t2) = 2: $(test_oid u2) s/4/A/ + 3: $(test_oid t3) = 3: $(test_oid u3) s/11/B/ + 4: $(test_oid t4) ! 4: $(test_oid u4) s/12/B/ + @@ Commit message + Z + Z + Z ## Notes (note1) ## + - topic note1 + + unmodified note1 + Z + Z + Z ## Notes (note2) ## + - topic note2 + + unmodified note2 + Z + Z ## file ## + Z@@ file: A + EOF + test_cmp expect actual +' + +test_expect_success 'format-patch --range-diff does not compare notes by default' ' + git notes add -m "topic note" topic && + git notes add -m "unmodified note" unmodified && + test_when_finished git notes remove topic unmodified && + git format-patch --cover-letter --range-diff=$prev \ + master..unmodified >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-* && + ! grep "Notes" 0000-* && + ! grep "note" 0000-* +' + +test_expect_success 'format-patch --range-diff with --no-notes' ' + git notes add -m "topic note" topic && + git notes add -m "unmodified note" unmodified && + test_when_finished git notes remove topic unmodified && + git format-patch --no-notes --cover-letter --range-diff=$prev \ + master..unmodified >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-* && + ! grep "Notes" 0000-* && + ! grep "note" 0000-* +' + +test_expect_success 'format-patch --range-diff with --notes' ' + git notes add -m "topic note" topic && + git notes add -m "unmodified note" unmodified && + test_when_finished git notes remove topic unmodified && + git format-patch --notes --cover-letter --range-diff=$prev \ + master..unmodified >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-* && + sed s/Z/\ /g >expect <<-EOF && + @@ Commit message + Z + Z + Z ## Notes ## + - topic note + + unmodified note + Z + Z ## file ## + Z@@ file: A + EOF + sed "/@@ Commit message/,/@@ file: A/!d" 0000-* >actual && + test_cmp expect actual +' + +test_expect_success 'format-patch --range-diff with --notes' ' + git notes add -m "topic note" topic && + git notes add -m "unmodified note" unmodified && + test_when_finished git notes remove topic unmodified && + test_config format.notes true && + git format-patch --cover-letter --range-diff=$prev \ + master..unmodified >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-* && + sed s/Z/\ /g >expect <<-EOF && + @@ Commit message + Z + Z + Z ## Notes ## + - topic note + + unmodified note + Z + Z ## file ## + Z@@ file: A + EOF + sed "/@@ Commit message/,/@@ file: A/!d" 0000-* >actual && + test_cmp expect actual +' + +test_expect_success 'format-patch --range-diff with multiple notes' ' + git notes --ref=note1 add -m "topic note1" topic && + git notes --ref=note1 add -m "unmodified note1" unmodified && + test_when_finished git notes --ref=note1 remove topic unmodified && + git notes --ref=note2 add -m "topic note2" topic && + git notes --ref=note2 add -m "unmodified note2" unmodified && + test_when_finished git notes --ref=note2 remove topic unmodified && + git format-patch --notes=note1 --notes=note2 --cover-letter --range-diff=$prev \ + master..unmodified >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-* && + sed s/Z/\ /g >expect <<-EOF && + @@ Commit message + Z + Z + Z ## Notes (note1) ## + - topic note1 + + unmodified note1 + Z + Z + Z ## Notes (note2) ## + - topic note2 + + unmodified note2 + Z + Z ## file ## + Z@@ file: A + EOF + sed "/@@ Commit message/,/@@ file: A/!d" 0000-* >actual && + test_cmp expect actual +' + test_done diff --git a/t/t3206/history.export b/t/t3206/history.export index b8ffff0940..4c808e5b3b 100644 --- a/t/t3206/history.export +++ b/t/t3206/history.export @@ -22,8 +22,8 @@ data 51 19 20 -reset refs/heads/removed -commit refs/heads/removed +reset refs/heads/renamed-file +commit refs/heads/renamed-file mark :2 author Thomas Rast <trast@inf.ethz.ch> 1374424921 +0200 committer Thomas Rast <trast@inf.ethz.ch> 1374484724 +0200 @@ -55,7 +55,7 @@ A 19 20 -commit refs/heads/topic +commit refs/heads/mode-only-change mark :4 author Thomas Rast <trast@inf.ethz.ch> 1374485014 +0200 committer Thomas Rast <trast@inf.ethz.ch> 1374485014 +0200 @@ -599,6 +599,111 @@ s/12/B/ from :46 M 100644 :28 file -reset refs/heads/removed -from :47 +commit refs/heads/added-removed +mark :48 +author Thomas Rast <trast@inf.ethz.ch> 1374485014 +0200 +committer Thomas Gummerer <t.gummerer@gmail.com> 1556574151 +0100 +data 7 +s/5/A/ +from :2 +M 100644 :3 file + +blob +mark :49 +data 0 + +commit refs/heads/added-removed +mark :50 +author Thomas Rast <trast@inf.ethz.ch> 1374485024 +0200 +committer Thomas Gummerer <t.gummerer@gmail.com> 1556574177 +0100 +data 18 +s/4/A/ + new-file +from :48 +M 100644 :5 file +M 100644 :49 new-file + +commit refs/heads/added-removed +mark :51 +author Thomas Rast <trast@inf.ethz.ch> 1374485036 +0200 +committer Thomas Gummerer <t.gummerer@gmail.com> 1556574177 +0100 +data 22 +s/11/B/ + remove file +from :50 +M 100644 :7 file +D new-file + +commit refs/heads/added-removed +mark :52 +author Thomas Rast <trast@inf.ethz.ch> 1374485044 +0200 +committer Thomas Gummerer <t.gummerer@gmail.com> 1556574177 +0100 +data 8 +s/12/B/ +from :51 +M 100644 :9 file + +commit refs/heads/renamed-file +mark :53 +author Thomas Rast <trast@inf.ethz.ch> 1374485014 +0200 +committer Thomas Gummerer <t.gummerer@gmail.com> 1556574309 +0100 +data 7 +s/5/A/ +from :2 +M 100644 :3 file + +commit refs/heads/renamed-file +mark :54 +author Thomas Rast <trast@inf.ethz.ch> 1374485024 +0200 +committer Thomas Gummerer <t.gummerer@gmail.com> 1556574312 +0100 +data 21 +s/4/A/ + rename file +from :53 +D file +M 100644 :5 renamed-file + +commit refs/heads/renamed-file +mark :55 +author Thomas Rast <trast@inf.ethz.ch> 1374485036 +0200 +committer Thomas Gummerer <t.gummerer@gmail.com> 1556574319 +0100 +data 8 +s/11/B/ +from :54 +M 100644 :7 renamed-file + +commit refs/heads/renamed-file +mark :56 +author Thomas Rast <trast@inf.ethz.ch> 1374485044 +0200 +committer Thomas Gummerer <t.gummerer@gmail.com> 1556574319 +0100 +data 8 +s/12/B/ +from :55 +M 100644 :9 renamed-file + +commit refs/heads/mode-only-change +mark :57 +author Thomas Rast <trast@inf.ethz.ch> 1374485024 +0200 +committer Thomas Gummerer <t.gummerer@gmail.com> 1570473767 +0100 +data 24 +s/4/A/ + add other-file +from :4 +M 100644 :5 file +M 100644 :49 other-file + +commit refs/heads/mode-only-change +mark :58 +author Thomas Rast <trast@inf.ethz.ch> 1374485036 +0200 +committer Thomas Gummerer <t.gummerer@gmail.com> 1570473768 +0100 +data 33 +s/11/B/ + mode change other-file +from :57 +M 100644 :7 file +M 100755 :49 other-file + +commit refs/heads/mode-only-change +mark :59 +author Thomas Rast <trast@inf.ethz.ch> 1374485044 +0200 +committer Thomas Gummerer <t.gummerer@gmail.com> 1570473768 +0100 +data 8 +s/12/B/ +from :58 +M 100644 :9 file diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh index 9ea5fa4fd2..f41b2afb99 100755 --- a/t/t3210-pack-refs.sh +++ b/t/t3210-pack-refs.sh @@ -240,7 +240,7 @@ test_expect_success 'retry acquiring packed-refs.lock' ' test_expect_success SYMLINKS 'pack symlinked packed-refs' ' # First make sure that symlinking works when reading: - git update-ref refs/heads/loosy refs/heads/master && + git update-ref refs/heads/lossy refs/heads/master && git for-each-ref >all-refs-before && mv .git/packed-refs .git/my-deviant-packed-refs && ln -s my-deviant-packed-refs .git/packed-refs && diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh index 704bbc6541..d66a5f6faa 100755 --- a/t/t3301-notes.sh +++ b/t/t3301-notes.sh @@ -66,8 +66,9 @@ test_expect_success 'show notes entry with %N' ' ' test_expect_success 'create reflog entry' ' + ref=$(git rev-parse --short refs/notes/commits) && cat <<-EOF >expect && - a1d8fa6 refs/notes/commits@{0}: notes: Notes added by '\''git notes add'\'' + $ref refs/notes/commits@{0}: notes: Notes added by '\''git notes add'\'' EOF git reflog show refs/notes/commits >actual && test_cmp expect actual @@ -134,8 +135,9 @@ test_expect_success 'can overwrite existing note with "git notes add -f"' ' ' test_expect_success 'show notes' ' + commit=$(git rev-parse HEAD) && cat >expect <<-EOF && - commit 7a4ca6ee52a974a66cbaa78e33214535dff1d691 + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:14:13 2005 -0700 @@ -152,8 +154,9 @@ test_expect_success 'show notes' ' test_expect_success 'show multi-line notes' ' test_commit 3rd && MSG="b3${LF}c3c3c3c3${LF}d3d3d3" git notes add && + commit=$(git rev-parse HEAD) && cat >expect-multiline <<-EOF && - commit d07d62e5208f22eb5695e7eb47667dc8b9860290 + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:15:13 2005 -0700 @@ -174,8 +177,9 @@ test_expect_success 'show -F notes' ' test_commit 4th && echo "xyzzy" >note5 && git notes add -F note5 && + commit=$(git rev-parse HEAD) && cat >expect-F <<-EOF && - commit 0f7aa3ec6325aeb88b910453bb3eb37c49d75c11 + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:16:13 2005 -0700 @@ -198,10 +202,13 @@ test_expect_success 'Re-adding -F notes without -f fails' ' ' test_expect_success 'git log --pretty=raw does not show notes' ' + commit=$(git rev-parse HEAD) && + tree=$(git rev-parse HEAD^{tree}) && + parent=$(git rev-parse HEAD^) && cat >expect <<-EOF && - commit 0f7aa3ec6325aeb88b910453bb3eb37c49d75c11 - tree 05ac65288c4c4b3b709a020ae94b2ece2f2201ae - parent d07d62e5208f22eb5695e7eb47667dc8b9860290 + commit $commit + tree $tree + parent $parent author A U Thor <author@example.com> 1112912173 -0700 committer C O Mitter <committer@example.com> 1112912173 -0700 @@ -291,8 +298,9 @@ test_expect_success 'git log --no-notes resets ref list' ' test_expect_success 'show -m notes' ' test_commit 5th && git notes add -m spam -m "foo${LF}bar${LF}baz" && + commit=$(git rev-parse HEAD) && cat >expect-m <<-EOF && - commit 7f9ad8836c775acb134c0a055fc55fb4cd1ba361 + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:17:13 2005 -0700 @@ -313,8 +321,9 @@ test_expect_success 'show -m notes' ' test_expect_success 'remove note with add -f -F /dev/null' ' git notes add -f -F /dev/null && + commit=$(git rev-parse HEAD) && cat >expect-rm-F <<-EOF && - commit 7f9ad8836c775acb134c0a055fc55fb4cd1ba361 + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:17:13 2005 -0700 @@ -356,14 +365,16 @@ test_expect_success 'create note with combination of -m and -F' ' test_expect_success 'remove note with "git notes remove"' ' git notes remove HEAD^ && git notes remove && + commit=$(git rev-parse HEAD) && + parent=$(git rev-parse HEAD^) && cat >expect-rm-remove <<-EOF && - commit 7f9ad8836c775acb134c0a055fc55fb4cd1ba361 + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:17:13 2005 -0700 ${indent}5th - commit 0f7aa3ec6325aeb88b910453bb3eb37c49d75c11 + commit $parent Author: A U Thor <author@example.com> Date: Thu Apr 7 15:16:13 2005 -0700 @@ -459,9 +470,11 @@ test_expect_success 'removing with --stdin --ignore-missing' ' ' test_expect_success 'list notes with "git notes list"' ' - cat >expect <<-EOF && - c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 7a4ca6ee52a974a66cbaa78e33214535dff1d691 - c18dc024e14f08d18d14eea0d747ff692d66d6a3 d07d62e5208f22eb5695e7eb47667dc8b9860290 + commit_2=$(git rev-parse 2nd) && + commit_3=$(git rev-parse 3rd) && + sort -t" " -k2 >expect <<-EOF && + $(git rev-parse refs/notes/commits:$commit_2) $commit_2 + $(git rev-parse refs/notes/commits:$commit_3) $commit_3 EOF git notes list >actual && test_cmp expect actual @@ -474,7 +487,7 @@ test_expect_success 'list notes with "git notes"' ' test_expect_success 'list specific note with "git notes list <object>"' ' cat >expect <<-EOF && - c18dc024e14f08d18d14eea0d747ff692d66d6a3 + $(git rev-parse refs/notes/commits:$commit_3) EOF git notes list HEAD^^ >actual && test_cmp expect actual @@ -498,10 +511,11 @@ test_expect_success 'append to existing note with "git notes append"' ' ' test_expect_success '"git notes list" does not expand to "git notes list HEAD"' ' - cat >expect_list <<-EOF && - c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 7a4ca6ee52a974a66cbaa78e33214535dff1d691 - 4b6ad22357cc8a1296720574b8d2fbc22fab0671 7f9ad8836c775acb134c0a055fc55fb4cd1ba361 - c18dc024e14f08d18d14eea0d747ff692d66d6a3 d07d62e5208f22eb5695e7eb47667dc8b9860290 + commit_5=$(git rev-parse 5th) && + sort -t" " -k2 >expect_list <<-EOF && + $(git rev-parse refs/notes/commits:$commit_2) $commit_2 + $(git rev-parse refs/notes/commits:$commit_3) $commit_3 + $(git rev-parse refs/notes/commits:$commit_5) $commit_5 EOF git notes list >actual && test_cmp expect_list actual @@ -531,8 +545,9 @@ test_expect_success 'appending empty string to non-existing note does not create test_expect_success 'create other note on a different notes ref (setup)' ' test_commit 6th && GIT_NOTES_REF="refs/notes/other" git notes add -m "other note" && + commit=$(git rev-parse HEAD) && cat >expect-not-other <<-EOF && - commit 2c125331118caba0ff8238b7f4958ac6e93fe39c + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:18:13 2005 -0700 @@ -569,8 +584,10 @@ test_expect_success 'Do not show note when core.notesRef is overridden' ' ' test_expect_success 'Show all notes when notes.displayRef=refs/notes/*' ' + commit=$(git rev-parse HEAD) && + parent=$(git rev-parse HEAD^) && cat >expect-both <<-EOF && - commit 2c125331118caba0ff8238b7f4958ac6e93fe39c + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:18:13 2005 -0700 @@ -582,7 +599,7 @@ test_expect_success 'Show all notes when notes.displayRef=refs/notes/*' ' Notes (other): ${indent}other note - commit 7f9ad8836c775acb134c0a055fc55fb4cd1ba361 + commit $parent Author: A U Thor <author@example.com> Date: Thu Apr 7 15:17:13 2005 -0700 @@ -616,8 +633,9 @@ test_expect_success 'notes.displayRef can be given more than once' ' ' test_expect_success 'notes.displayRef respects order' ' + commit=$(git rev-parse HEAD) && cat >expect-both-reversed <<-EOF && - commit 2c125331118caba0ff8238b7f4958ac6e93fe39c + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:18:13 2005 -0700 @@ -642,14 +660,16 @@ test_expect_success 'GIT_NOTES_DISPLAY_REF works' ' ' test_expect_success 'GIT_NOTES_DISPLAY_REF overrides config' ' + commit=$(git rev-parse HEAD) && + parent=$(git rev-parse HEAD^) && cat >expect-none <<-EOF && - commit 2c125331118caba0ff8238b7f4958ac6e93fe39c + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:18:13 2005 -0700 ${indent}6th - commit 7f9ad8836c775acb134c0a055fc55fb4cd1ba361 + commit $parent Author: A U Thor <author@example.com> Date: Thu Apr 7 15:17:13 2005 -0700 @@ -666,8 +686,9 @@ test_expect_success '--show-notes=* adds to GIT_NOTES_DISPLAY_REF' ' ' test_expect_success '--no-standard-notes' ' + commit=$(git rev-parse HEAD) && cat >expect-commits <<-EOF && - commit 2c125331118caba0ff8238b7f4958ac6e93fe39c + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:18:13 2005 -0700 @@ -712,8 +733,10 @@ test_expect_success 'Allow notes on non-commits (trees, blobs, tags)' ' ' test_expect_success 'create note from other note with "git notes add -C"' ' + test_commit 7th && + commit=$(git rev-parse HEAD) && cat >expect <<-EOF && - commit fb01e0ca8c33b6cc0c6451dde747f97df567cb5c + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:19:13 2005 -0700 @@ -722,7 +745,6 @@ test_expect_success 'create note from other note with "git notes add -C"' ' Notes: ${indent}order test EOF - test_commit 7th && git notes add -C $(git notes list HEAD^) && git log -1 >actual && test_cmp expect actual && @@ -744,8 +766,9 @@ test_expect_success 'create note from non-blob with "git notes add -C" fails' ' ' test_expect_success 'create note from blob with "git notes add -C" reuses blob id' ' + commit=$(git rev-parse HEAD) && cat >expect <<-EOF && - commit 9a4c31c7f722b5d517e92c64e932dd751e1413bf + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:20:13 2005 -0700 @@ -762,8 +785,10 @@ test_expect_success 'create note from blob with "git notes add -C" reuses blob i ' test_expect_success 'create note from other note with "git notes add -c"' ' + test_commit 9th && + commit=$(git rev-parse HEAD) && cat >expect <<-EOF && - commit 2e0db4bc649e174d667a1cde19e725cf897a5bd2 + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:21:13 2005 -0700 @@ -772,7 +797,6 @@ test_expect_success 'create note from other note with "git notes add -c"' ' Notes: ${indent}yet another note EOF - test_commit 9th && MSG="yet another note" git notes add -c $(git notes list HEAD^^) && git log -1 >actual && test_cmp expect actual @@ -785,8 +809,9 @@ test_expect_success 'create note from non-existing note with "git notes add -c" ' test_expect_success 'append to note from other note with "git notes append -C"' ' + commit=$(git rev-parse HEAD^) && cat >expect <<-EOF && - commit 2e0db4bc649e174d667a1cde19e725cf897a5bd2 + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:21:13 2005 -0700 @@ -803,8 +828,9 @@ test_expect_success 'append to note from other note with "git notes append -C"' ' test_expect_success 'create note from other note with "git notes append -c"' ' + commit=$(git rev-parse HEAD) && cat >expect <<-EOF && - commit 7c3b87ab368f81e11b1ea87b2ab99a71ccd25406 + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:22:13 2005 -0700 @@ -819,8 +845,9 @@ test_expect_success 'create note from other note with "git notes append -c"' ' ' test_expect_success 'append to note from other note with "git notes append -c"' ' + commit=$(git rev-parse HEAD) && cat >expect <<-EOF && - commit 7c3b87ab368f81e11b1ea87b2ab99a71ccd25406 + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:22:13 2005 -0700 @@ -837,8 +864,28 @@ test_expect_success 'append to note from other note with "git notes append -c"' ' test_expect_success 'copy note with "git notes copy"' ' + commit=$(git rev-parse 4th) && + cat >expect <<-EOF && + commit $commit + Author: A U Thor <author@example.com> + Date: Thu Apr 7 15:16:13 2005 -0700 + + ${indent}4th + + Notes: + ${indent}This is a blob object + EOF + git notes copy 8th 4th && + git log 3rd..4th >actual && + test_cmp expect actual && + test "$(git note list 4th)" = "$(git note list 8th)" +' + +test_expect_success 'copy note with "git notes copy" with default' ' + test_commit 11th && + commit=$(git rev-parse HEAD) && cat >expect <<-EOF && - commit a446fff8777efdc6eb8f4b7c8a5ff699484df0d5 + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:23:13 2005 -0700 @@ -849,8 +896,7 @@ test_expect_success 'copy note with "git notes copy"' ' ${indent} ${indent}yet another note EOF - test_commit 11th && - git notes copy HEAD^ HEAD && + git notes copy HEAD^ && git log -1 >actual && test_cmp expect actual && test "$(git notes list HEAD)" = "$(git notes list HEAD^)" @@ -864,8 +910,27 @@ test_expect_success 'prevent overwrite with "git notes copy"' ' ' test_expect_success 'allow overwrite with "git notes copy -f"' ' + commit=$(git rev-parse HEAD) && + cat >expect <<-EOF && + commit $commit + Author: A U Thor <author@example.com> + Date: Thu Apr 7 15:23:13 2005 -0700 + + ${indent}11th + + Notes: + ${indent}This is a blob object + EOF + git notes copy -f HEAD~3 HEAD && + git log -1 >actual && + test_cmp expect actual && + test "$(git notes list HEAD)" = "$(git notes list HEAD~3)" +' + +test_expect_success 'allow overwrite with "git notes copy -f" with default' ' + commit=$(git rev-parse HEAD) && cat >expect <<-EOF && - commit a446fff8777efdc6eb8f4b7c8a5ff699484df0d5 + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:23:13 2005 -0700 @@ -876,7 +941,7 @@ test_expect_success 'allow overwrite with "git notes copy -f"' ' ${indent} ${indent}yet another note EOF - git notes copy -f HEAD~2 HEAD && + git notes copy -f HEAD~2 && git log -1 >actual && test_cmp expect actual && test "$(git notes list HEAD)" = "$(git notes list HEAD~2)" @@ -889,8 +954,10 @@ test_expect_success 'cannot copy note from object without notes' ' ' test_expect_success 'git notes copy --stdin' ' + commit=$(git rev-parse HEAD) && + parent=$(git rev-parse HEAD^) && cat >expect <<-EOF && - commit e871aa61182b1d95d0a6fb75445d891722863b6b + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:25:13 2005 -0700 @@ -901,7 +968,7 @@ test_expect_success 'git notes copy --stdin' ' ${indent} ${indent}yet another note - commit 65e263ded02ae4e8839bc151095113737579dc12 + commit $parent Author: A U Thor <author@example.com> Date: Thu Apr 7 15:24:13 2005 -0700 @@ -922,21 +989,23 @@ test_expect_success 'git notes copy --stdin' ' ' test_expect_success 'git notes copy --for-rewrite (unconfigured)' ' + test_commit 14th && + test_commit 15th && + commit=$(git rev-parse HEAD) && + parent=$(git rev-parse HEAD^) && cat >expect <<-EOF && - commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89 + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:27:13 2005 -0700 ${indent}15th - commit 07c85d77059393ed0154b8c96906547a59dfcddd + commit $parent Author: A U Thor <author@example.com> Date: Thu Apr 7 15:26:13 2005 -0700 ${indent}14th EOF - test_commit 14th && - test_commit 15th && (echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^) && echo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) | git notes copy --for-rewrite=foo && @@ -945,8 +1014,10 @@ test_expect_success 'git notes copy --for-rewrite (unconfigured)' ' ' test_expect_success 'git notes copy --for-rewrite (enabled)' ' + commit=$(git rev-parse HEAD) && + parent=$(git rev-parse HEAD^) && cat >expect <<-EOF && - commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89 + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:27:13 2005 -0700 @@ -957,7 +1028,7 @@ test_expect_success 'git notes copy --for-rewrite (enabled)' ' ${indent} ${indent}yet another note - commit 07c85d77059393ed0154b8c96906547a59dfcddd + commit $parent Author: A U Thor <author@example.com> Date: Thu Apr 7 15:26:13 2005 -0700 @@ -986,8 +1057,9 @@ test_expect_success 'git notes copy --for-rewrite (disabled)' ' ' test_expect_success 'git notes copy --for-rewrite (overwrite)' ' + commit=$(git rev-parse HEAD) && cat >expect <<-EOF && - commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89 + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:27:13 2005 -0700 @@ -1015,8 +1087,9 @@ test_expect_success 'git notes copy --for-rewrite (ignore)' ' ' test_expect_success 'git notes copy --for-rewrite (append)' ' + commit=$(git rev-parse HEAD) && cat >expect <<-EOF && - commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89 + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:27:13 2005 -0700 @@ -1037,8 +1110,9 @@ test_expect_success 'git notes copy --for-rewrite (append)' ' ' test_expect_success 'git notes copy --for-rewrite (append two to one)' ' + commit=$(git rev-parse HEAD) && cat >expect <<-EOF && - commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89 + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:27:13 2005 -0700 @@ -1075,8 +1149,9 @@ test_expect_success 'git notes copy --for-rewrite (append empty)' ' ' test_expect_success 'GIT_NOTES_REWRITE_MODE works' ' + commit=$(git rev-parse HEAD) && cat >expect <<-EOF && - commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89 + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:27:13 2005 -0700 @@ -1095,8 +1170,9 @@ test_expect_success 'GIT_NOTES_REWRITE_MODE works' ' ' test_expect_success 'GIT_NOTES_REWRITE_REF works' ' + commit=$(git rev-parse HEAD) && cat >expect <<-EOF && - commit 4acf42e847e7fffbbf89ee365c20ac7caf40de89 + commit $commit Author: A U Thor <author@example.com> Date: Thu Apr 7 15:27:13 2005 -0700 @@ -1127,8 +1203,10 @@ test_expect_success 'GIT_NOTES_REWRITE_REF overrides config' ' ' test_expect_success 'git notes copy diagnoses too many or too few parameters' ' - test_must_fail git notes copy && - test_must_fail git notes copy one two three + test_must_fail git notes copy 2>error && + test_i18ngrep "too few parameters" error && + test_must_fail git notes copy one two three 2>error && + test_i18ngrep "too many parameters" error ' test_expect_success 'git notes get-ref expands refs/heads/master to refs/notes/refs/heads/master' ' diff --git a/t/t3305-notes-fanout.sh b/t/t3305-notes-fanout.sh index 54460beec4..831f83d211 100755 --- a/t/t3305-notes-fanout.sh +++ b/t/t3305-notes-fanout.sh @@ -35,15 +35,10 @@ test_expect_success 'many notes created with git-notes triggers fanout' ' git ls-tree -r --name-only refs/notes/commits | while read path do - case "$path" in - ??/??????????????????????????????????????) - : true - ;; - *) + echo $path | grep "^../[0-9a-f]*$" || { echo "Invalid path \"$path\"" && - return 1 - ;; - esac + return 1; + } done ' @@ -77,15 +72,10 @@ test_expect_success 'deleting most notes triggers fanout consolidation' ' git ls-tree -r --name-only refs/notes/commits | while read path do - case "$path" in - ????????????????????????????????????????) - : true - ;; - *) + echo $path | grep -v "^../.*" || { echo "Invalid path \"$path\"" && - return 1 - ;; - esac + return 1; + } done ' diff --git a/t/t3306-notes-prune.sh b/t/t3306-notes-prune.sh index 61748088eb..8f4102ff9e 100755 --- a/t/t3306-notes-prune.sh +++ b/t/t3306-notes-prune.sh @@ -11,23 +11,26 @@ test_expect_success 'setup: create a few commits with notes' ' test_tick && git commit -m 1st && git notes add -m "Note #1" && + first=$(git rev-parse HEAD) && : > file2 && git add file2 && test_tick && git commit -m 2nd && git notes add -m "Note #2" && + second=$(git rev-parse HEAD) && : > file3 && git add file3 && test_tick && git commit -m 3rd && - COMMIT_FILE=.git/objects/5e/e1c35e83ea47cd3cc4f8cbee0568915fbbbd29 && + third=$(git rev-parse HEAD) && + COMMIT_FILE=$(echo $third | sed "s!^..!.git/objects/&/!") && test -f $COMMIT_FILE && test-tool chmtime =+0 $COMMIT_FILE && git notes add -m "Note #3" ' cat > expect <<END_OF_LOG -commit 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 +commit $third Author: A U Thor <author@example.com> Date: Thu Apr 7 15:15:13 2005 -0700 @@ -36,7 +39,7 @@ Date: Thu Apr 7 15:15:13 2005 -0700 Notes: Note #3 -commit 08341ad9e94faa089d60fd3f523affb25c6da189 +commit $second Author: A U Thor <author@example.com> Date: Thu Apr 7 15:14:13 2005 -0700 @@ -45,7 +48,7 @@ Date: Thu Apr 7 15:14:13 2005 -0700 Notes: Note #2 -commit ab5f302035f2e7aaf04265f08b42034c23256e1f +commit $first Author: A U Thor <author@example.com> Date: Thu Apr 7 15:13:13 2005 -0700 @@ -70,16 +73,16 @@ test_expect_success 'remove some commits' ' test_expect_success 'verify that commits are gone' ' - test_must_fail git cat-file -p 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 && - git cat-file -p 08341ad9e94faa089d60fd3f523affb25c6da189 && - git cat-file -p ab5f302035f2e7aaf04265f08b42034c23256e1f + test_must_fail git cat-file -p $third && + git cat-file -p $second && + git cat-file -p $first ' test_expect_success 'verify that notes are still present' ' - git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 && - git notes show 08341ad9e94faa089d60fd3f523affb25c6da189 && - git notes show ab5f302035f2e7aaf04265f08b42034c23256e1f + git notes show $third && + git notes show $second && + git notes show $first ' test_expect_success 'prune -n does not remove notes' ' @@ -90,13 +93,10 @@ test_expect_success 'prune -n does not remove notes' ' test_cmp expect actual ' -cat > expect <<EOF -5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 -EOF test_expect_success 'prune -n lists prunable notes' ' - + echo $third >expect && git notes prune -n > actual && test_cmp expect actual ' @@ -109,9 +109,9 @@ test_expect_success 'prune notes' ' test_expect_success 'verify that notes are gone' ' - test_must_fail git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 && - git notes show 08341ad9e94faa089d60fd3f523affb25c6da189 && - git notes show ab5f302035f2e7aaf04265f08b42034c23256e1f + test_must_fail git notes show $third && + git notes show $second && + git notes show $first ' test_expect_success 'remove some commits' ' @@ -121,21 +121,18 @@ test_expect_success 'remove some commits' ' git gc --prune=now ' -cat > expect <<EOF -08341ad9e94faa089d60fd3f523affb25c6da189 -EOF - test_expect_success 'prune -v notes' ' + echo $second >expect && git notes prune -v > actual && test_cmp expect actual ' test_expect_success 'verify that notes are gone' ' - test_must_fail git notes show 5ee1c35e83ea47cd3cc4f8cbee0568915fbbbd29 && - test_must_fail git notes show 08341ad9e94faa089d60fd3f523affb25c6da189 && - git notes show ab5f302035f2e7aaf04265f08b42034c23256e1f + test_must_fail git notes show $third && + test_must_fail git notes show $second && + git notes show $first ' test_done diff --git a/t/t3311-notes-merge-fanout.sh b/t/t3311-notes-merge-fanout.sh index 93516ef67c..37151a3adc 100755 --- a/t/t3311-notes-merge-fanout.sh +++ b/t/t3311-notes-merge-fanout.sh @@ -114,12 +114,12 @@ cp expect_log_x expect_log_y test_expect_success 'Add a few hundred commits w/notes to trigger fanout (x -> y)' ' git update-ref refs/notes/y refs/notes/x && git config core.notesRef refs/notes/y && - i=5 && - while test $i -lt $num + test_commit_bulk --start=6 --id=commit $((num - 5)) && + i=0 && + while test $i -lt $((num - 5)) do - i=$(($i + 1)) && - test_commit "commit$i" >/dev/null && - git notes add -m "notes for commit$i" || return 1 + git notes add -m "notes for commit$i" HEAD~$i || return 1 + i=$((i + 1)) done && test "$(git rev-parse refs/notes/y)" != "$(git rev-parse refs/notes/x)" && # Expected number of commits and notes diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh index 42f147858d..f267f6cd54 100755 --- a/t/t3400-rebase.sh +++ b/t/t3400-rebase.sh @@ -64,7 +64,7 @@ test_expect_success 'rebase sets ORIG_HEAD to pre-rebase state' ' pre="$(git rev-parse --verify HEAD)" && git rebase master && test_cmp_rev "$pre" ORIG_HEAD && - ! test_cmp_rev "$pre" HEAD + test_cmp_rev ! "$pre" HEAD ' test_expect_success 'rebase, with <onto> and <upstream> specified as :/quuxery' ' @@ -285,7 +285,7 @@ EOF test_cmp From_.msg out ' -test_expect_success 'rebase--am.sh and --show-current-patch' ' +test_expect_success 'rebase --am and --show-current-patch' ' test_create_repo conflict-apply && ( cd conflict-apply && @@ -295,12 +295,48 @@ test_expect_success 'rebase--am.sh and --show-current-patch' ' echo two >>init.t && git commit -a -m two && git tag two && - test_must_fail git rebase --onto init HEAD^ && + test_must_fail git rebase -f --onto init HEAD^ && GIT_TRACE=1 git rebase --show-current-patch >/dev/null 2>stderr && grep "show.*$(git rev-parse two)" stderr ) ' +test_expect_success 'rebase --am and .gitattributes' ' + test_create_repo attributes && + ( + cd attributes && + test_commit init && + git config filter.test.clean "sed -e '\''s/smudged/clean/g'\''" && + git config filter.test.smudge "sed -e '\''s/clean/smudged/g'\''" && + + test_commit second && + git checkout -b test HEAD^ && + + echo "*.txt filter=test" >.gitattributes && + git add .gitattributes && + test_commit third && + + echo "This text is smudged." >a.txt && + git add a.txt && + test_commit fourth && + + git checkout -b removal HEAD^ && + git rm .gitattributes && + git add -u && + test_commit fifth && + git cherry-pick test && + + git checkout test && + git rebase master && + grep "smudged" a.txt && + + git checkout removal && + git reset --hard && + git rebase master && + grep "clean" a.txt + ) +' + test_expect_success 'rebase--merge.sh and --show-current-patch' ' test_create_repo conflict-merge && ( diff --git a/t/t3403-rebase-skip.sh b/t/t3403-rebase-skip.sh index 1f5122b632..ee8a8dba52 100755 --- a/t/t3403-rebase-skip.sh +++ b/t/t3403-rebase-skip.sh @@ -7,6 +7,8 @@ test_description='git rebase --merge --skip tests' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-rebase.sh + # we assume the default git am -3 --skip strategy is tested independently # and always works :) @@ -20,6 +22,13 @@ test_expect_success setup ' git commit -a -m "hello world" && echo goodbye >> hello && git commit -a -m "goodbye" && + git tag goodbye && + + git checkout --detach && + git checkout HEAD^ . && + test_tick && + git commit -m reverted-goodbye && + git tag reverted-goodbye && git checkout -f skip-reference && echo moo > hello && @@ -76,4 +85,27 @@ test_expect_success 'moved back to branch correctly' ' test_debug 'gitk --all & sleep 1' +test_expect_success 'fixup that empties commit fails' ' + test_when_finished "git rebase --abort" && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="1 fixup 2" git rebase -i \ + goodbye^ reverted-goodbye + ) +' + +test_expect_success 'squash that empties commit fails' ' + test_when_finished "git rebase --abort" && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="1 squash 2" git rebase -i \ + goodbye^ reverted-goodbye + ) +' + +# Must be the last test in this file +test_expect_success '$EDITOR and friends are unchanged' ' + test_editor_unchanged +' + test_done diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 461dd539ff..bf0dc756d2 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -29,9 +29,6 @@ Initial setup: . "$TEST_DIRECTORY"/lib-rebase.sh -# WARNING: Modifications to the initial repository can change the SHA ID used -# in the expect2 file for the 'stop on conflicting pick' test. - test_expect_success 'setup' ' test_commit A file1 && test_commit B file1 && @@ -79,8 +76,11 @@ test_expect_success 'rebase -i with empty HEAD' ' cat >expect <<-\EOF && error: nothing to do EOF - set_fake_editor && - test_must_fail env FAKE_LINES="1 exec_true" git rebase -i HEAD^ >actual 2>&1 && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="1 exec_true" \ + git rebase -i HEAD^ >actual 2>&1 + ) && test_i18ncmp expect actual ' @@ -139,8 +139,11 @@ test_expect_success 'rebase -i sets work tree properly' ' test_expect_success 'rebase -i with the exec command checks tree cleanness' ' git checkout master && - set_fake_editor && - test_must_fail env FAKE_LINES="exec_echo_foo_>file1 1" git rebase -i HEAD^ && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="exec_echo_foo_>file1 1" \ + git rebase -i HEAD^ + ) && test_cmp_rev master^ HEAD && git reset --hard && git rebase --continue @@ -155,8 +158,6 @@ test_expect_success 'rebase -x with empty command fails' ' test_i18ncmp expected actual ' -LF=' -' test_expect_success 'rebase -x with newline in command fails' ' test_when_finished "git rebase --abort ||:" && test_must_fail env git rebase -x "a${LF}b" @ 2>actual && @@ -168,9 +169,11 @@ test_expect_success 'rebase -x with newline in command fails' ' test_expect_success 'rebase -i with exec of inexistent command' ' git checkout master && test_when_finished "git rebase --abort" && - set_fake_editor && - test_must_fail env FAKE_LINES="exec_this-command-does-not-exist 1" \ - git rebase -i HEAD^ >actual 2>&1 && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="exec_this-command-does-not-exist 1" \ + git rebase -i HEAD^ >actual 2>&1 + ) && ! grep "Maybe git-rebase is broken" actual ' @@ -181,7 +184,6 @@ test_expect_success 'implicit interactive rebase does not invoke sequence editor test_expect_success 'no changes are a nop' ' git checkout branch2 && - set_fake_editor && git rebase -i F && test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch2" && test $(git rev-parse I) = $(git rev-parse HEAD) @@ -191,7 +193,6 @@ test_expect_success 'test the [branch] option' ' git checkout -b dead-end && git rm file6 && git commit -m "stop here" && - set_fake_editor && git rebase -i F branch2 && test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch2" && test $(git rev-parse I) = $(git rev-parse branch2) && @@ -200,7 +201,6 @@ test_expect_success 'test the [branch] option' ' test_expect_success 'test --onto <branch>' ' git checkout -b test-onto branch2 && - set_fake_editor && git rebase -i --onto branch1 F && test "$(git symbolic-ref -q HEAD)" = "refs/heads/test-onto" && test $(git rev-parse HEAD^) = $(git rev-parse branch1) && @@ -210,7 +210,6 @@ test_expect_success 'test --onto <branch>' ' test_expect_success 'rebase on top of a non-conflicting commit' ' git checkout branch1 && git tag original-branch1 && - set_fake_editor && git rebase -i branch2 && test file6 = $(git diff --name-only original-branch1) && test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch1" && @@ -230,31 +229,35 @@ test_expect_success 'reflog for the branch shows correct finish message' ' ' test_expect_success 'exchange two commits' ' - set_fake_editor && - FAKE_LINES="2 1" git rebase -i HEAD~2 && + ( + set_fake_editor && + FAKE_LINES="2 1" git rebase -i HEAD~2 + ) && test H = $(git cat-file commit HEAD^ | sed -ne \$p) && - test G = $(git cat-file commit HEAD | sed -ne \$p) + test G = $(git cat-file commit HEAD | sed -ne \$p) && + blob1=$(git rev-parse --short HEAD^:file1) && + blob2=$(git rev-parse --short HEAD:file1) && + commit=$(git rev-parse --short HEAD) ' test_expect_success 'stop on conflicting pick' ' - cat >expect <<-\EOF && + cat >expect <<-EOF && diff --git a/file1 b/file1 - index f70f10e..fd79235 100644 + index $blob1..$blob2 100644 --- a/file1 +++ b/file1 @@ -1 +1 @@ -A +G EOF - cat >expect2 <<-\EOF && + cat >expect2 <<-EOF && <<<<<<< HEAD D ======= G - >>>>>>> 5d18e54... G + >>>>>>> $commit... G EOF git tag new-branch1 && - set_fake_editor && test_must_fail git rebase -i master && test "$(git rev-parse HEAD~3)" = "$(git rev-parse master)" && test_cmp expect .git/rebase-merge/patch && @@ -283,7 +286,6 @@ test_expect_success 'abort' ' test_expect_success 'abort with error when new base cannot be checked out' ' git rm --cached file1 && git commit -m "remove file in base" && - set_fake_editor && test_must_fail git rebase -i master > output 2>&1 && test_i18ngrep "The following untracked working tree files would be overwritten by checkout:" \ output && @@ -298,7 +300,6 @@ test_expect_success 'retain authorship' ' test_tick && GIT_AUTHOR_NAME="Twerp Snog" git commit -m "different author" && git tag twerp && - set_fake_editor && git rebase -i --onto master HEAD^ && git show HEAD | grep "^Author: Twerp Snog" ' @@ -316,7 +317,6 @@ test_expect_success 'retain authorship w/ conflicts' ' test_commit b conflict b conflict-b && GIT_AUTHOR_NAME=$oGIT_AUTHOR_NAME && - set_fake_editor && test_must_fail git rebase -i conflict-a && echo resolved >conflict && git add conflict && @@ -332,9 +332,11 @@ test_expect_success 'squash' ' test_tick && GIT_AUTHOR_NAME="Nitfol" git commit -m "nitfol" file7 && echo "******************************" && - set_fake_editor && - FAKE_LINES="1 squash 2" EXPECT_HEADER_COUNT=2 \ - git rebase -i --onto master HEAD~2 && + ( + set_fake_editor && + FAKE_LINES="1 squash 2" EXPECT_HEADER_COUNT=2 \ + git rebase -i --onto master HEAD~2 + ) && test B = $(cat file7) && test $(git rev-parse HEAD^) = $(git rev-parse master) ' @@ -345,7 +347,6 @@ test_expect_success 'retain authorship when squashing' ' test_expect_success REBASE_P '-p handles "no changes" gracefully' ' HEAD=$(git rev-parse HEAD) && - set_fake_editor && git rebase -i -p HEAD^ && git update-index --refresh && git diff-files --quiet && @@ -355,8 +356,10 @@ test_expect_success REBASE_P '-p handles "no changes" gracefully' ' 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 && + ( + set_fake_editor && + FAKE_LINES="2 1" git rebase -i -p HEAD~2 + ) && test H = $(git cat-file commit HEAD^ | sed -ne \$p) && test G = $(git cat-file commit HEAD | sed -ne \$p) ' @@ -390,7 +393,6 @@ test_expect_success REBASE_P 'preserve merges with -p' ' git commit -m M file1 && git checkout -b to-be-rebased && test_tick && - set_fake_editor && git rebase -i -p --onto branch1 master && git update-index --refresh && git diff-files --quiet && @@ -405,8 +407,10 @@ test_expect_success REBASE_P 'preserve merges 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 && + ( + set_fake_editor && + FAKE_LINES="1 2 edit 3 4" git rebase -i -p HEAD~3 + ) && echo 2 > unrelated-file && test_tick && git commit -m L2-modified --amend unrelated-file && @@ -420,11 +424,13 @@ test_expect_success REBASE_P '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^ && - echo resolved > file1 && - git add file1 && - FAKE_COMMIT_MESSAGE="chouette!" git rebase --continue && + ( + set_fake_editor && + test_must_fail git rebase -i --onto new-branch1 HEAD^ && + echo resolved > file1 && + git add file1 && + FAKE_COMMIT_MESSAGE="chouette!" git rebase --continue + ) && test $(git rev-parse HEAD^) = $(git rev-parse new-branch1) && git show HEAD | grep chouette ' @@ -432,7 +438,6 @@ test_expect_success '--continue tries to commit' ' test_expect_success 'verbose flag is heeded, even after --continue' ' git reset --hard master@{1} && test_tick && - set_fake_editor && test_must_fail git rebase -v -i --onto new-branch1 HEAD^ && echo resolved > file1 && git add file1 && @@ -442,10 +447,13 @@ test_expect_success 'verbose flag is heeded, even after --continue' ' test_expect_success C_LOCALE_OUTPUT 'multi-squash only fires up editor once' ' base=$(git rev-parse HEAD~4) && - set_fake_editor && - FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="1 squash 2 squash 3 squash 4" \ - EXPECT_HEADER_COUNT=4 \ - git rebase -i $base && + ( + set_fake_editor && + FAKE_COMMIT_AMEND="ONCE" \ + FAKE_LINES="1 squash 2 squash 3 squash 4" \ + EXPECT_HEADER_COUNT=4 \ + git rebase -i $base + ) && test $base = $(git rev-parse HEAD^) && test 1 = $(git show | grep ONCE | wc -l) ' @@ -453,9 +461,12 @@ test_expect_success C_LOCALE_OUTPUT 'multi-squash only fires up editor once' ' test_expect_success C_LOCALE_OUTPUT 'multi-fixup does not fire up editor' ' git checkout -b multi-fixup E && base=$(git rev-parse HEAD~4) && - set_fake_editor && - FAKE_COMMIT_AMEND="NEVER" FAKE_LINES="1 fixup 2 fixup 3 fixup 4" \ - git rebase -i $base && + ( + set_fake_editor && + FAKE_COMMIT_AMEND="NEVER" \ + FAKE_LINES="1 fixup 2 fixup 3 fixup 4" \ + git rebase -i $base + ) && test $base = $(git rev-parse HEAD^) && test 0 = $(git show | grep NEVER | wc -l) && git checkout @{-1} && @@ -465,12 +476,15 @@ test_expect_success C_LOCALE_OUTPUT 'multi-fixup does not fire up editor' ' test_expect_success 'commit message used after conflict' ' git checkout -b conflict-fixup conflict-branch && base=$(git rev-parse HEAD~4) && - set_fake_editor && - test_must_fail env FAKE_LINES="1 fixup 3 fixup 4" git rebase -i $base && - echo three > conflict && - git add conflict && - FAKE_COMMIT_AMEND="ONCE" EXPECT_HEADER_COUNT=2 \ - git rebase --continue && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="1 fixup 3 fixup 4" \ + git rebase -i $base && + echo three > conflict && + git add conflict && + FAKE_COMMIT_AMEND="ONCE" EXPECT_HEADER_COUNT=2 \ + git rebase --continue + ) && test $base = $(git rev-parse HEAD^) && test 1 = $(git show | grep ONCE | wc -l) && git checkout @{-1} && @@ -480,12 +494,15 @@ test_expect_success 'commit message used after conflict' ' test_expect_success 'commit message retained after conflict' ' git checkout -b conflict-squash conflict-branch && base=$(git rev-parse HEAD~4) && - set_fake_editor && - test_must_fail env FAKE_LINES="1 fixup 3 squash 4" git rebase -i $base && - echo three > conflict && - git add conflict && - FAKE_COMMIT_AMEND="TWICE" EXPECT_HEADER_COUNT=2 \ - git rebase --continue && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="1 fixup 3 squash 4" \ + git rebase -i $base && + echo three > conflict && + git add conflict && + FAKE_COMMIT_AMEND="TWICE" EXPECT_HEADER_COUNT=2 \ + git rebase --continue + ) && test $base = $(git rev-parse HEAD^) && test 2 = $(git show | grep TWICE | wc -l) && git checkout @{-1} && @@ -502,10 +519,13 @@ test_expect_success C_LOCALE_OUTPUT 'squash and fixup generate correct log messa EOF git checkout -b squash-fixup E && base=$(git rev-parse HEAD~4) && - set_fake_editor && - FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="1 fixup 2 squash 3 fixup 4" \ - EXPECT_HEADER_COUNT=4 \ - git rebase -i $base && + ( + set_fake_editor && + FAKE_COMMIT_AMEND="ONCE" \ + FAKE_LINES="1 fixup 2 squash 3 fixup 4" \ + EXPECT_HEADER_COUNT=4 \ + git rebase -i $base + ) && git cat-file commit HEAD | sed -e 1,/^\$/d > actual-squash-fixup && test_cmp expect-squash-fixup actual-squash-fixup && git cat-file commit HEAD@{2} | @@ -519,10 +539,13 @@ test_expect_success C_LOCALE_OUTPUT 'squash and fixup generate correct log messa test_expect_success C_LOCALE_OUTPUT 'squash ignores comments' ' git checkout -b skip-comments E && base=$(git rev-parse HEAD~4) && - set_fake_editor && - FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="# 1 # squash 2 # squash 3 # squash 4 #" \ - EXPECT_HEADER_COUNT=4 \ - git rebase -i $base && + ( + set_fake_editor && + FAKE_COMMIT_AMEND="ONCE" \ + FAKE_LINES="# 1 # squash 2 # squash 3 # squash 4 #" \ + EXPECT_HEADER_COUNT=4 \ + git rebase -i $base + ) && test $base = $(git rev-parse HEAD^) && test 1 = $(git show | grep ONCE | wc -l) && git checkout @{-1} && @@ -532,10 +555,13 @@ test_expect_success C_LOCALE_OUTPUT 'squash ignores comments' ' test_expect_success C_LOCALE_OUTPUT 'squash ignores blank lines' ' git checkout -b skip-blank-lines E && base=$(git rev-parse HEAD~4) && - set_fake_editor && - FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="> 1 > squash 2 > squash 3 > squash 4 >" \ - EXPECT_HEADER_COUNT=4 \ - git rebase -i $base && + ( + set_fake_editor && + FAKE_COMMIT_AMEND="ONCE" \ + FAKE_LINES="> 1 > squash 2 > squash 3 > squash 4 >" \ + EXPECT_HEADER_COUNT=4 \ + git rebase -i $base + ) && test $base = $(git rev-parse HEAD^) && test 1 = $(git show | grep ONCE | wc -l) && git checkout @{-1} && @@ -545,17 +571,21 @@ test_expect_success C_LOCALE_OUTPUT 'squash ignores blank lines' ' 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 s 3 2" EXPECT_HEADER_COUNT=2 \ - git rebase -i HEAD~3 && + ( + set_fake_editor && + FAKE_LINES="1 s 3 2" EXPECT_HEADER_COUNT=2 git rebase -i HEAD~3 + ) && test $one = $(git rev-parse HEAD~2) ' test_expect_success 'interrupted squash works as expected' ' git checkout -b interrupted-squash conflict-branch && one=$(git rev-parse HEAD~3) && - set_fake_editor && - test_must_fail env FAKE_LINES="1 squash 3 2" git rebase -i HEAD~3 && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="1 squash 3 2" \ + git rebase -i HEAD~3 + ) && test_write_lines one two four > conflict && git add conflict && test_must_fail git rebase --continue && @@ -568,8 +598,11 @@ test_expect_success 'interrupted squash works as expected' ' test_expect_success 'interrupted squash works as expected (case 2)' ' git checkout -b interrupted-squash2 conflict-branch && one=$(git rev-parse HEAD~3) && - set_fake_editor && - test_must_fail env FAKE_LINES="3 squash 1 2" git rebase -i HEAD~3 && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="3 squash 1 2" \ + git rebase -i HEAD~3 + ) && test_write_lines one four > conflict && git add conflict && test_must_fail git rebase --continue && @@ -589,11 +622,13 @@ test_expect_success '--continue tries to commit, even for "edit"' ' git commit -m "unrelated change" && parent=$(git rev-parse HEAD^) && test_tick && - set_fake_editor && - FAKE_LINES="edit 1" git rebase -i HEAD^ && - echo edited > file7 && - git add file7 && - FAKE_COMMIT_MESSAGE="chouette!" git rebase --continue && + ( + set_fake_editor && + FAKE_LINES="edit 1" git rebase -i HEAD^ && + echo edited > file7 && + git add file7 && + FAKE_COMMIT_MESSAGE="chouette!" git rebase --continue + ) && test edited = $(git show HEAD:file7) && git show HEAD | grep chouette && test $parent = $(git rev-parse HEAD^) @@ -602,34 +637,41 @@ test_expect_success '--continue tries to commit, even for "edit"' ' test_expect_success 'aborted --continue does not squash commits after "edit"' ' old=$(git rev-parse HEAD) && test_tick && - set_fake_editor && - FAKE_LINES="edit 1" git rebase -i HEAD^ && - echo "edited again" > file7 && - git add file7 && - test_must_fail env FAKE_COMMIT_MESSAGE=" " git rebase --continue && + ( + set_fake_editor && + FAKE_LINES="edit 1" git rebase -i HEAD^ && + echo "edited again" > file7 && + git add file7 && + test_must_fail env FAKE_COMMIT_MESSAGE=" " git rebase --continue + ) && test $old = $(git rev-parse HEAD) && git rebase --abort ' test_expect_success 'auto-amend only edited commits after "edit"' ' test_tick && - set_fake_editor && - FAKE_LINES="edit 1" git rebase -i HEAD^ && - echo "edited again" > file7 && - git add file7 && - FAKE_COMMIT_MESSAGE="edited file7 again" git commit && - echo "and again" > file7 && - git add file7 && - test_tick && - test_must_fail env FAKE_COMMIT_MESSAGE="and again" git rebase --continue && + ( + set_fake_editor && + FAKE_LINES="edit 1" git rebase -i HEAD^ && + echo "edited again" > file7 && + git add file7 && + FAKE_COMMIT_MESSAGE="edited file7 again" git commit && + echo "and again" > file7 && + git add file7 && + test_tick && + test_must_fail env FAKE_COMMIT_MESSAGE="and again" \ + git rebase --continue + ) && git rebase --abort ' test_expect_success 'clean error after failed "exec"' ' test_tick && test_when_finished "git rebase --abort || :" && - set_fake_editor && - test_must_fail env FAKE_LINES="1 exec_false" git rebase -i HEAD^ && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="1 exec_false" git rebase -i HEAD^ + ) && echo "edited again" > file7 && git add file7 && test_must_fail git rebase --continue 2>error && @@ -640,8 +682,10 @@ test_expect_success 'rebase a detached HEAD' ' grandparent=$(git rev-parse HEAD~2) && git checkout $(git rev-parse HEAD) && test_tick && - set_fake_editor && - FAKE_LINES="2 1" git rebase -i HEAD~2 && + ( + set_fake_editor && + FAKE_LINES="2 1" git rebase -i HEAD~2 + ) && test $grandparent = $(git rev-parse HEAD~2) ' @@ -656,9 +700,10 @@ test_expect_success 'rebase a commit violating pre-commit' ' test_must_fail git commit -m doesnt-verify file1 && git commit -m doesnt-verify --no-verify file1 && test_tick && - set_fake_editor && - FAKE_LINES=2 git rebase -i HEAD~2 - + ( + set_fake_editor && + FAKE_LINES=2 git rebase -i HEAD~2 + ) ' test_expect_success 'rebase with a file named HEAD in worktree' ' @@ -678,8 +723,10 @@ test_expect_success 'rebase with a file named HEAD in worktree' ' git commit -m "Add body" ) && - set_fake_editor && - FAKE_LINES="1 squash 2" git rebase -i @{-1} && + ( + set_fake_editor && + FAKE_LINES="1 squash 2" git rebase -i @{-1} + ) && test "$(git show -s --pretty=format:%an)" = "Squashed Away" ' @@ -690,7 +737,6 @@ test_expect_success 'do "noop" when there is nothing to cherry-pick' ' GIT_EDITOR=: git commit --amend \ --author="Somebody else <somebody@else.com>" && test $(git rev-parse branch3) != $(git rev-parse branch4) && - set_fake_editor && git rebase -i branch3 && test $(git rev-parse branch3) = $(git rev-parse branch4) @@ -715,13 +761,14 @@ test_expect_success 'submodule rebase setup' ' git commit -a -m "submodule second" ) && test_tick && - set_fake_editor && git commit -a -m "Three changes submodule" ' test_expect_success 'submodule rebase -i' ' - set_fake_editor && - FAKE_LINES="1 squash 2 3" git rebase -i A + ( + set_fake_editor && + FAKE_LINES="1 squash 2 3" git rebase -i A + ) ' test_expect_success 'submodule conflict setup' ' @@ -738,7 +785,6 @@ test_expect_success 'submodule conflict setup' ' ' test_expect_success 'rebase -i continue with only submodule staged' ' - set_fake_editor && test_must_fail git rebase -i submodule-base && git add sub && git rebase --continue && @@ -748,7 +794,6 @@ test_expect_success 'rebase -i continue with only submodule staged' ' test_expect_success 'rebase -i continue with unstaged submodule' ' git checkout submodule-topic && git reset --hard && - set_fake_editor && test_must_fail git rebase -i submodule-base && git reset && git rebase --continue && @@ -761,7 +806,6 @@ test_expect_success 'avoid unnecessary reset' ' test-tool chmtime =123456789 file3 && git update-index --refresh && HEAD=$(git rev-parse HEAD) && - set_fake_editor && git rebase -i HEAD~4 && test $HEAD = $(git rev-parse HEAD) && MTIME=$(test-tool chmtime --get file3) && @@ -770,16 +814,22 @@ test_expect_success 'avoid unnecessary reset' ' test_expect_success 'reword' ' git checkout -b reword-branch master && - set_fake_editor && - FAKE_LINES="1 2 3 reword 4" FAKE_COMMIT_MESSAGE="E changed" git rebase -i A && - git show HEAD | grep "E changed" && - test $(git rev-parse master) != $(git rev-parse HEAD) && - test $(git rev-parse master^) = $(git rev-parse HEAD^) && - FAKE_LINES="1 2 reword 3 4" FAKE_COMMIT_MESSAGE="D changed" git rebase -i A && - 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 r 2 pick 3 p 4" FAKE_COMMIT_MESSAGE="C changed" git rebase -i A && + ( + set_fake_editor && + FAKE_LINES="1 2 3 reword 4" FAKE_COMMIT_MESSAGE="E changed" \ + git rebase -i A && + git show HEAD | grep "E changed" && + test $(git rev-parse master) != $(git rev-parse HEAD) && + test $(git rev-parse master^) = $(git rev-parse HEAD^) && + FAKE_LINES="1 2 reword 3 4" FAKE_COMMIT_MESSAGE="D changed" \ + git rebase -i A && + 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 r 2 pick 3 p 4" FAKE_COMMIT_MESSAGE="C changed" \ + git rebase -i A + ) && git show HEAD~2 | grep "C changed" ' @@ -790,7 +840,6 @@ test_expect_success 'rebase -i can copy notes' ' test_commit n2 && test_commit n3 && git notes add -m"a note" n3 && - set_fake_editor && git rebase -i --onto n1 n2 && test "a note" = "$(git notes show HEAD)" ' @@ -803,8 +852,11 @@ test_expect_success 'rebase -i can copy notes over a fixup' ' EOF git reset --hard n3 && git notes add -m"an earlier note" n2 && - set_fake_editor && - GIT_NOTES_REWRITE_MODE=concatenate FAKE_LINES="1 f 2" git rebase -i n1 && + ( + set_fake_editor && + GIT_NOTES_REWRITE_MODE=concatenate FAKE_LINES="1 f 2" \ + git rebase -i n1 + ) && git notes show > output && test_cmp expect output ' @@ -813,8 +865,10 @@ test_expect_success 'rebase while detaching HEAD' ' git symbolic-ref HEAD && grandparent=$(git rev-parse HEAD~2) && test_tick && - set_fake_editor && - FAKE_LINES="2 1" git rebase -i HEAD~2 HEAD^0 && + ( + set_fake_editor && + FAKE_LINES="2 1" git rebase -i HEAD~2 HEAD^0 + ) && test $grandparent = $(git rev-parse HEAD~2) && test_must_fail git symbolic-ref HEAD ' @@ -823,7 +877,6 @@ test_tick # Ensure that the rebased commits get a different timestamp. test_expect_success 'always cherry-pick with --no-ff' ' git checkout no-ff-branch && git tag original-no-ff-branch && - set_fake_editor && git rebase -i --no-ff A && for p in 0 1 2 do @@ -855,8 +908,10 @@ test_expect_success 'set up commits with funny messages' ' test_expect_success 'rebase-i history with funny messages' ' git rev-list A..funny >expect && test_tick && - set_fake_editor && - FAKE_LINES="1 2 3 4" git rebase -i A && + ( + set_fake_editor && + FAKE_LINES="1 2 3 4" git rebase -i A + ) && git rev-list A.. >actual && test_cmp expect actual ' @@ -870,9 +925,9 @@ test_expect_success 'prepare for rebase -i --exec' ' ' test_expect_success 'running "git rebase -i --exec git show HEAD"' ' - set_fake_editor && - git rebase -i --exec "git show HEAD" HEAD~2 >actual && ( + set_fake_editor && + git rebase -i --exec "git show HEAD" HEAD~2 >actual && FAKE_LINES="1 exec_git_show_HEAD 2 exec_git_show_HEAD" && export FAKE_LINES && git rebase -i HEAD~2 >expect @@ -883,9 +938,9 @@ test_expect_success 'running "git rebase -i --exec git show HEAD"' ' test_expect_success 'running "git rebase --exec git show HEAD -i"' ' git reset --hard execute && - set_fake_editor && - git rebase --exec "git show HEAD" -i HEAD~2 >actual && ( + set_fake_editor && + git rebase --exec "git show HEAD" -i HEAD~2 >actual && FAKE_LINES="1 exec_git_show_HEAD 2 exec_git_show_HEAD" && export FAKE_LINES && git rebase -i HEAD~2 >expect @@ -896,9 +951,9 @@ test_expect_success 'running "git rebase --exec git show HEAD -i"' ' test_expect_success 'running "git rebase -ix git show HEAD"' ' git reset --hard execute && - set_fake_editor && - git rebase -ix "git show HEAD" HEAD~2 >actual && ( + set_fake_editor && + git rebase -ix "git show HEAD" HEAD~2 >actual && FAKE_LINES="1 exec_git_show_HEAD 2 exec_git_show_HEAD" && export FAKE_LINES && git rebase -i HEAD~2 >expect @@ -910,9 +965,9 @@ test_expect_success 'running "git rebase -ix git show HEAD"' ' test_expect_success 'rebase -ix with several <CMD>' ' git reset --hard execute && - set_fake_editor && - git rebase -ix "git show HEAD; pwd" HEAD~2 >actual && ( + set_fake_editor && + git rebase -ix "git show HEAD; pwd" HEAD~2 >actual && FAKE_LINES="1 exec_git_show_HEAD;_pwd 2 exec_git_show_HEAD;_pwd" && export FAKE_LINES && git rebase -i HEAD~2 >expect @@ -923,9 +978,9 @@ test_expect_success 'rebase -ix with several <CMD>' ' test_expect_success 'rebase -ix with several instances of --exec' ' git reset --hard execute && - set_fake_editor && - git rebase -i --exec "git show HEAD" --exec "pwd" HEAD~2 >actual && ( + set_fake_editor && + git rebase -i --exec "git show HEAD" --exec "pwd" HEAD~2 >actual && FAKE_LINES="1 exec_git_show_HEAD exec_pwd 2 exec_git_show_HEAD exec_pwd" && export FAKE_LINES && @@ -944,13 +999,11 @@ test_expect_success C_LOCALE_OUTPUT 'rebase -ix with --autosquash' ' echo bis >bis.txt && git add bis.txt && git commit -m "fixup! two_exec" && - set_fake_editor && - ( - git checkout -b autosquash_actual && - git rebase -i --exec "git show HEAD" --autosquash HEAD~4 >actual - ) && + git checkout -b autosquash_actual && + git rebase -i --exec "git show HEAD" --autosquash HEAD~4 >actual && git checkout autosquash && ( + set_fake_editor && git checkout -b autosquash_expected && FAKE_LINES="1 fixup 3 fixup 4 exec_git_show_HEAD 2 exec_git_show_HEAD" && export FAKE_LINES && @@ -971,7 +1024,6 @@ test_expect_success 'rebase --exec works without -i ' ' test_expect_success 'rebase -i --exec without <CMD>' ' git reset --hard execute && - set_fake_editor && test_must_fail git rebase -i --exec 2>actual && test_i18ngrep "requires a value" actual && git checkout master @@ -979,8 +1031,10 @@ test_expect_success 'rebase -i --exec without <CMD>' ' test_expect_success 'rebase -i --root re-order and drop commits' ' git checkout E && - set_fake_editor && - FAKE_LINES="3 1 2 5" git rebase -i --root && + ( + set_fake_editor && + FAKE_LINES="3 1 2 5" git rebase -i --root + ) && test E = $(git cat-file commit HEAD | sed -ne \$p) && test B = $(git cat-file commit HEAD^ | sed -ne \$p) && test A = $(git cat-file commit HEAD^^ | sed -ne \$p) && @@ -993,39 +1047,59 @@ test_expect_success 'rebase -i --root retain root commit author and message' ' echo B >file7 && git add file7 && GIT_AUTHOR_NAME="Twerp Snog" git commit -m "different author" && - set_fake_editor && - FAKE_LINES="2" git rebase -i --root && + ( + set_fake_editor && + FAKE_LINES="2" git rebase -i --root + ) && git cat-file commit HEAD | grep -q "^author Twerp Snog" && git cat-file commit HEAD | grep -q "^different author$" ' test_expect_success 'rebase -i --root temporary sentinel commit' ' git checkout B && - set_fake_editor && - test_must_fail env FAKE_LINES="2" git rebase -i --root && - git cat-file commit HEAD | grep "^tree 4b825dc642cb" && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="2" git rebase -i --root + ) && + git cat-file commit HEAD | grep "^tree $EMPTY_TREE" && git rebase --abort ' test_expect_success 'rebase -i --root fixup root commit' ' git checkout B && - set_fake_editor && - FAKE_LINES="1 fixup 2" git rebase -i --root && + ( + set_fake_editor && + FAKE_LINES="1 fixup 2" git rebase -i --root + ) && test A = $(git cat-file commit HEAD | sed -ne \$p) && test B = $(git show HEAD:file1) && test 0 = $(git cat-file commit HEAD | grep -c ^parent\ ) ' -test_expect_success 'rebase -i --root reword root commit' ' +test_expect_success 'rebase -i --root reword original root commit' ' test_when_finished "test_might_fail git rebase --abort" && - git checkout -b reword-root-branch master && - set_fake_editor && - FAKE_LINES="reword 1 2" FAKE_COMMIT_MESSAGE="A changed" \ - git rebase -i --root && + git checkout -b reword-original-root-branch master && + ( + set_fake_editor && + FAKE_LINES="reword 1 2" FAKE_COMMIT_MESSAGE="A changed" \ + git rebase -i --root + ) && git show HEAD^ | grep "A changed" && test -z "$(git show -s --format=%p HEAD^)" ' +test_expect_success 'rebase -i --root reword new root commit' ' + test_when_finished "test_might_fail git rebase --abort" && + git checkout -b reword-now-root-branch master && + ( + set_fake_editor && + FAKE_LINES="reword 3 1" FAKE_COMMIT_MESSAGE="C changed" \ + git rebase -i --root + ) && + git show HEAD^ | grep "C changed" && + test -z "$(git show -s --format=%p HEAD^)" +' + test_expect_success 'rebase -i --root when root has untracked file conflict' ' test_when_finished "reset_rebase" && git checkout -b failing-root-pick A && @@ -1033,8 +1107,10 @@ test_expect_success 'rebase -i --root when root has untracked file conflict' ' git rm file1 && git commit -m "remove file 1 add file 2" && echo z >file1 && - set_fake_editor && - test_must_fail env FAKE_LINES="1 2" git rebase -i --root && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="1 2" git rebase -i --root + ) && rm file1 && git rebase --continue && test "$(git log -1 --format=%B)" = "remove file 1 add file 2" && @@ -1044,32 +1120,38 @@ test_expect_success 'rebase -i --root when root has untracked file conflict' ' test_expect_success 'rebase -i --root reword root when root has untracked file conflict' ' test_when_finished "reset_rebase" && echo z>file1 && - set_fake_editor && - test_must_fail env FAKE_LINES="reword 1 2" \ - FAKE_COMMIT_MESSAGE="Modified A" git rebase -i --root && - rm file1 && - FAKE_COMMIT_MESSAGE="Reworded A" git rebase --continue && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="reword 1 2" \ + FAKE_COMMIT_MESSAGE="Modified A" git rebase -i --root && + rm file1 && + FAKE_COMMIT_MESSAGE="Reworded A" git rebase --continue + ) && test "$(git log -1 --format=%B HEAD^)" = "Reworded A" && test "$(git rev-list --count HEAD)" = 2 ' test_expect_success C_LOCALE_OUTPUT 'rebase --edit-todo does not work on non-interactive rebase' ' - git checkout reword-root-branch && + git checkout reword-original-root-branch && git reset --hard && git checkout conflict-branch && - set_fake_editor && - test_must_fail git rebase --onto HEAD~2 HEAD~ && - test_must_fail git rebase --edit-todo && + ( + set_fake_editor && + test_must_fail git rebase -f --onto HEAD~2 HEAD~ && + test_must_fail git rebase --edit-todo + ) && git rebase --abort ' test_expect_success 'rebase --edit-todo can be used to modify todo' ' git reset --hard && git checkout no-conflict-branch^0 && - set_fake_editor && - FAKE_LINES="edit 1 2 3" git rebase -i HEAD~3 && - FAKE_LINES="2 1" git rebase --edit-todo && - git rebase --continue && + ( + set_fake_editor && + FAKE_LINES="edit 1 2 3" git rebase -i HEAD~3 && + FAKE_LINES="2 1" git rebase --edit-todo && + git rebase --continue + ) && test M = $(git cat-file commit HEAD^ | sed -ne \$p) && test L = $(git cat-file commit HEAD | sed -ne \$p) ' @@ -1077,7 +1159,6 @@ test_expect_success 'rebase --edit-todo can be used to modify todo' ' test_expect_success 'rebase -i produces readable reflog' ' git reset --hard && git branch -f branch-reflog-test H && - set_fake_editor && git rebase -i --onto I F branch-reflog-test && cat >expect <<-\EOF && rebase -i (finish): returning to refs/heads/branch-reflog-test @@ -1098,8 +1179,10 @@ test_expect_success 'rebase -i respects core.commentchar' ' sed -e "2,\$s/^/\\\\/" "$1" >"$1.tmp" && mv "$1.tmp" "$1" EOF - test_set_editor "$(pwd)/remove-all-but-first.sh" && - git rebase -i B && + ( + test_set_editor "$(pwd)/remove-all-but-first.sh" && + git rebase -i B + ) && test B = $(git cat-file commit HEAD^ | sed -ne \$p) ' @@ -1108,9 +1191,11 @@ test_expect_success 'rebase -i respects core.commentchar=auto' ' write_script copy-edit-script.sh <<-\EOF && cp "$1" edit-script EOF - test_set_editor "$(pwd)/copy-edit-script.sh" && test_when_finished "git rebase --abort || :" && - git rebase -i HEAD^ && + ( + test_set_editor "$(pwd)/copy-edit-script.sh" && + git rebase -i HEAD^ + ) && test -z "$(grep -ve "^#" -e "^\$" -e "^pick" edit-script)" ' @@ -1145,8 +1230,11 @@ test_expect_success 'interrupted rebase -i with --strategy and -X' ' echo five >conflict && echo Z >file1 && git commit -a -m "one file conflict" && - set_fake_editor && - FAKE_LINES="edit 1 2" git rebase -i --strategy=recursive -Xours conflict-branch && + ( + set_fake_editor && + FAKE_LINES="edit 1 2" git rebase -i --strategy=recursive \ + -Xours conflict-branch + ) && git rebase --continue && test $(git show conflict-branch:conflict) = $(cat conflict) && test $(cat file1) = Z @@ -1161,7 +1249,7 @@ test_expect_success 'rebase -i error on commits with \ in message' ' test_expect_code 1 grep " emp" error ' -test_expect_success 'short SHA-1 setup' ' +test_expect_success SHA1 'short SHA-1 setup' ' test_when_finished "git checkout master" && git checkout --orphan collide && git rm -rf . && @@ -1173,7 +1261,7 @@ test_expect_success 'short SHA-1 setup' ' ) ' -test_expect_success 'short SHA-1 collide' ' +test_expect_success SHA1 'short SHA-1 collide' ' test_when_finished "reset_rebase && git checkout master" && git checkout collide && ( @@ -1187,8 +1275,10 @@ test_expect_success 'short SHA-1 collide' ' test_expect_success 'respect core.abbrev' ' git config core.abbrev 12 && - set_cat_todo_editor && - test_must_fail git rebase -i HEAD~4 >todo-list && + ( + set_cat_todo_editor && + test_must_fail git rebase -i HEAD~4 >todo-list + ) && test 4 = $(grep -c "pick [0-9a-f]\{12,\}" todo-list) ' @@ -1196,16 +1286,20 @@ test_expect_success 'todo count' ' write_script dump-raw.sh <<-\EOF && cat "$1" EOF - test_set_editor "$(pwd)/dump-raw.sh" && - git rebase -i HEAD~4 >actual && + ( + test_set_editor "$(pwd)/dump-raw.sh" && + git rebase -i HEAD~4 >actual + ) && test_i18ngrep "^# Rebase ..* onto ..* ([0-9]" actual ' test_expect_success 'rebase -i commits that overwrite untracked files (pick)' ' git checkout --force branch2 && git clean -f && - set_fake_editor && - FAKE_LINES="edit 1 2" git rebase -i A && + ( + set_fake_editor && + FAKE_LINES="edit 1 2" git rebase -i A + ) && test_cmp_rev HEAD F && test_path_is_missing file6 && >file6 && @@ -1220,8 +1314,10 @@ test_expect_success 'rebase -i commits that overwrite untracked files (squash)' git checkout --force branch2 && git clean -f && git tag original-branch2 && - set_fake_editor && - FAKE_LINES="edit 1 squash 2" git rebase -i A && + ( + set_fake_editor && + FAKE_LINES="edit 1 squash 2" git rebase -i A + ) && test_cmp_rev HEAD F && test_path_is_missing file6 && >file6 && @@ -1236,8 +1332,10 @@ test_expect_success 'rebase -i commits that overwrite untracked files (squash)' test_expect_success 'rebase -i commits that overwrite untracked files (no ff)' ' git checkout --force branch2 && git clean -f && - set_fake_editor && - FAKE_LINES="edit 1 2" git rebase -i --no-ff A && + ( + set_fake_editor && + FAKE_LINES="edit 1 2" git rebase -i --no-ff A + ) && test $(git cat-file commit HEAD | sed -ne \$p) = F && test_path_is_missing file6 && >file6 && @@ -1260,8 +1358,10 @@ test_expect_success 'rebase --continue removes CHERRY_PICK_HEAD' ' git tag seq-onto && git reset --hard HEAD~2 && git cherry-pick seq-onto && - set_fake_editor && - test_must_fail env FAKE_LINES= git rebase -i seq-onto && + ( + set_fake_editor && + test_must_fail env FAKE_LINES= git rebase -i seq-onto + ) && test -d .git/rebase-merge && git rebase --continue && git diff --exit-code seq-onto && @@ -1280,8 +1380,10 @@ rebase_setup_and_clean () { test_expect_success 'drop' ' rebase_setup_and_clean drop-test && - set_fake_editor && - FAKE_LINES="1 drop 2 3 d 4 5" git rebase -i --root && + ( + set_fake_editor && + 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) @@ -1290,9 +1392,10 @@ test_expect_success 'drop' ' test_expect_success 'rebase -i respects rebase.missingCommitsCheck = ignore' ' test_config rebase.missingCommitsCheck ignore && rebase_setup_and_clean missing-commit && - set_fake_editor && - FAKE_LINES="1 2 3 4" \ - git rebase -i --root 2>actual && + ( + set_fake_editor && + FAKE_LINES="1 2 3 4" git rebase -i --root 2>actual + ) && test D = $(git cat-file commit HEAD | sed -ne \$p) && test_i18ngrep \ "Successfully rebased and updated refs/heads/missing-commit" \ @@ -1308,9 +1411,10 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = warn' ' EOF test_config rebase.missingCommitsCheck warn && rebase_setup_and_clean missing-commit && - set_fake_editor && - FAKE_LINES="1 2 3 4" \ - git rebase -i --root 2>actual.2 && + ( + set_fake_editor && + FAKE_LINES="1 2 3 4" git rebase -i --root 2>actual.2 + ) && head -n4 actual.2 >actual && test_i18ncmp expect actual && test D = $(git cat-file commit HEAD | sed -ne \$p) @@ -1332,14 +1436,15 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = error' ' EOF test_config rebase.missingCommitsCheck error && rebase_setup_and_clean missing-commit && - set_fake_editor && - test_must_fail env FAKE_LINES="1 2 4" \ - git rebase -i --root 2>actual && - test_i18ncmp expect actual && - cp .git/rebase-merge/git-rebase-todo.backup \ - .git/rebase-merge/git-rebase-todo && - FAKE_LINES="1 2 drop 3 4 drop 5" \ - git rebase --edit-todo && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="1 2 4" \ + git rebase -i --root 2>actual && + test_i18ncmp expect actual && + cp .git/rebase-merge/git-rebase-todo.backup \ + .git/rebase-merge/git-rebase-todo && + FAKE_LINES="1 2 drop 3 4 drop 5" git rebase --edit-todo + ) && git rebase --continue && test D = $(git cat-file commit HEAD | sed -ne \$p) && test B = $(git cat-file commit HEAD^ | sed -ne \$p) @@ -1360,21 +1465,27 @@ test_expect_success 'respects rebase.abbreviateCommands with fixup, squash and e x git show HEAD EOF git checkout abbrevcmd && - set_cat_todo_editor && test_config rebase.abbreviateCommands true && - test_must_fail git rebase -i --exec "git show HEAD" \ - --autosquash master >actual && + ( + set_cat_todo_editor && + test_must_fail git rebase -i --exec "git show HEAD" \ + --autosquash master >actual + ) && test_cmp expected actual ' test_expect_success 'static check of bad command' ' rebase_setup_and_clean bad-cmd && - set_fake_editor && - test_must_fail env FAKE_LINES="1 2 3 bad 4 5" \ + ( + set_fake_editor && + test_must_fail env FAKE_LINES="1 2 3 bad 4 5" \ git rebase -i --root 2>actual && - test_i18ngrep "badcmd $(git rev-list --oneline -1 master~1)" actual && - test_i18ngrep "You can fix this with .git rebase --edit-todo.." actual && - FAKE_LINES="1 2 3 drop 4 5" git rebase --edit-todo && + test_i18ngrep "badcmd $(git rev-list --oneline -1 master~1)" \ + actual && + test_i18ngrep "You can fix this with .git rebase --edit-todo.." \ + actual && + FAKE_LINES="1 2 3 drop 4 5" git rebase --edit-todo + ) && git rebase --continue && test E = $(git cat-file commit HEAD | sed -ne \$p) && test C = $(git cat-file commit HEAD^ | sed -ne \$p) @@ -1390,19 +1501,24 @@ test_expect_success 'tabs and spaces are accepted in the todolist' ' ) >"$1.new" mv "$1.new" "$1" EOF - test_set_editor "$(pwd)/add-indent.sh" && - git rebase -i HEAD^^^ && + ( + test_set_editor "$(pwd)/add-indent.sh" && + git rebase -i HEAD^^^ + ) && test E = $(git cat-file commit HEAD | sed -ne \$p) ' test_expect_success 'static check of bad SHA-1' ' rebase_setup_and_clean bad-sha && - set_fake_editor && - test_must_fail env FAKE_LINES="1 2 edit fakesha 3 4 5 #" \ - git rebase -i --root 2>actual && - test_i18ngrep "edit XXXXXXX False commit" actual && - test_i18ngrep "You can fix this with .git rebase --edit-todo.." actual && - FAKE_LINES="1 2 4 5 6" git rebase --edit-todo && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="1 2 edit fakesha 3 4 5 #" \ + git rebase -i --root 2>actual && + test_i18ngrep "edit XXXXXXX False commit" actual && + test_i18ngrep "You can fix this with .git rebase --edit-todo.." \ + actual && + FAKE_LINES="1 2 4 5 6" git rebase --edit-todo + ) && git rebase --continue && test E = $(git cat-file commit HEAD | sed -ne \$p) ' @@ -1419,42 +1535,73 @@ test_expect_success 'editor saves as CR/LF' ' ) ' -SQ="'" test_expect_success 'rebase -i --gpg-sign=<key-id>' ' test_when_finished "test_might_fail git rebase --abort" && - set_fake_editor && - FAKE_LINES="edit 1" git rebase -i --gpg-sign="\"S I Gner\"" HEAD^ \ - >out 2>err && + ( + set_fake_editor && + FAKE_LINES="edit 1" git rebase -i --gpg-sign="\"S I Gner\"" \ + HEAD^ >out 2>err + ) && test_i18ngrep "$SQ-S\"S I Gner\"$SQ" err ' test_expect_success 'rebase -i --gpg-sign=<key-id> overrides commit.gpgSign' ' test_when_finished "test_might_fail git rebase --abort" && test_config commit.gpgsign true && - set_fake_editor && - FAKE_LINES="edit 1" git rebase -i --gpg-sign="\"S I Gner\"" HEAD^ \ - >out 2>err && + ( + set_fake_editor && + FAKE_LINES="edit 1" git rebase -i --gpg-sign="\"S I Gner\"" \ + HEAD^ >out 2>err + ) && test_i18ngrep "$SQ-S\"S I Gner\"$SQ" err ' test_expect_success 'valid author header after --root swap' ' rebase_setup_and_clean author-header no-conflict-branch && - set_fake_editor && git commit --amend --author="Au ${SQ}thor <author@example.com>" --no-edit && git cat-file commit HEAD | grep ^author >expected && - FAKE_LINES="5 1" git rebase -i --root && + ( + set_fake_editor && + FAKE_LINES="5 1" git rebase -i --root + ) && git cat-file commit HEAD^ | grep ^author >actual && test_cmp expected actual ' test_expect_success 'valid author header when author contains single quote' ' rebase_setup_and_clean author-header no-conflict-branch && - set_fake_editor && git commit --amend --author="Au ${SQ}thor <author@example.com>" --no-edit && git cat-file commit HEAD | grep ^author >expected && - FAKE_LINES="2" git rebase -i HEAD~2 && + ( + set_fake_editor && + FAKE_LINES="2" git rebase -i HEAD~2 + ) && git cat-file commit HEAD | grep ^author >actual && test_cmp expected actual ' +test_expect_success 'post-commit hook is called' ' + test_when_finished "rm -f .git/hooks/post-commit" && + >actual && + mkdir -p .git/hooks && + write_script .git/hooks/post-commit <<-\EOS && + git rev-parse HEAD >>actual + EOS + ( + set_fake_editor && + FAKE_LINES="edit 4 1 reword 2 fixup 3" git rebase -i A E && + echo x>file3 && + git add file3 && + FAKE_COMMIT_MESSAGE=edited git rebase --continue + ) && + git rev-parse HEAD@{5} HEAD@{4} HEAD@{3} HEAD@{2} HEAD@{1} HEAD \ + >expect && + test_cmp expect actual +' + +# This must be the last test in this file +test_expect_success '$EDITOR and friends are unchanged' ' + test_editor_unchanged +' + test_done diff --git a/t/t3416-rebase-onto-threedots.sh b/t/t3416-rebase-onto-threedots.sh index ddf2f64853..9c2548423b 100755 --- a/t/t3416-rebase-onto-threedots.sh +++ b/t/t3416-rebase-onto-threedots.sh @@ -99,7 +99,64 @@ test_expect_success 'rebase -i --onto master...side' ' git checkout side && git reset --hard K && + set_fake_editor && test_must_fail git rebase -i --onto master...side J ' +test_expect_success 'rebase --keep-base --onto incompatible' ' + test_must_fail git rebase --keep-base --onto master... +' + +test_expect_success 'rebase --keep-base --root incompatible' ' + test_must_fail git rebase --keep-base --root +' + +test_expect_success 'rebase --keep-base master from topic' ' + git reset --hard && + git checkout topic && + git reset --hard G && + + git rebase --keep-base master && + git rev-parse C >base.expect && + git merge-base master HEAD >base.actual && + test_cmp base.expect base.actual && + + git rev-parse HEAD~2 >actual && + git rev-parse C^0 >expect && + test_cmp expect actual +' + +test_expect_success 'rebase --keep-base master from side' ' + git reset --hard && + git checkout side && + git reset --hard K && + + test_must_fail git rebase --keep-base master +' + +test_expect_success 'rebase -i --keep-base master from topic' ' + git reset --hard && + git checkout topic && + git reset --hard G && + + set_fake_editor && + EXPECT_COUNT=2 git rebase -i --keep-base master && + git rev-parse C >base.expect && + git merge-base master HEAD >base.actual && + test_cmp base.expect base.actual && + + git rev-parse HEAD~2 >actual && + git rev-parse C^0 >expect && + test_cmp expect actual +' + +test_expect_success 'rebase -i --keep-base master from side' ' + git reset --hard && + git checkout side && + git reset --hard K && + + set_fake_editor && + test_must_fail git rebase -i --keep-base master +' + test_done diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh index 4eff14dae5..7a2da972fd 100755 --- a/t/t3418-rebase-continue.sh +++ b/t/t3418-rebase-continue.sh @@ -120,6 +120,20 @@ test_expect_success REBASE_P 'rebase passes merge strategy options correctly' ' git rebase --continue ' +test_expect_success 'rebase -r passes merge strategy options correctly' ' + rm -fr .git/rebase-* && + git reset --hard commit-new-file-F3-on-topic-branch && + test_commit merge-theirs && + git reset --hard HEAD^ && + test_commit some-other-commit && + test_tick && + git merge --no-ff merge-theirs && + FAKE_LINES="1 3 edit 4 5 7 8 9" git rebase -i -f -r -m \ + -s recursive --strategy-option=theirs HEAD~2 && + test_commit force-change-ours && + git rebase --continue +' + test_expect_success '--skip after failed fixup cleans commit message' ' test_when_finished "test_might_fail git rebase --abort" && git checkout -b with-conflicting-fixup && diff --git a/t/t3420-rebase-autostash.sh b/t/t3420-rebase-autostash.sh index 9186e90127..5f7e73cf83 100755 --- a/t/t3420-rebase-autostash.sh +++ b/t/t3420-rebase-autostash.sh @@ -30,13 +30,13 @@ test_expect_success setup ' echo conflicting-change >file2 && git add . && test_tick && - git commit -m "related commit" + git commit -m "related commit" && + remove_progress_re="$(printf "s/.*\\r//")" ' create_expected_success_am () { cat >expected <<-EOF $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual) - HEAD is now at $(git rev-parse --short feature-branch) third commit First, rewinding head to replay your work on top of it... Applying: second commit Applying: third commit @@ -47,16 +47,14 @@ create_expected_success_am () { create_expected_success_interactive () { q_to_cr >expected <<-EOF $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual) - HEAD is now at $(git rev-parse --short feature-branch) third commit - Rebasing (1/2)QRebasing (2/2)QApplied autostash. - Q QSuccessfully rebased and updated refs/heads/rebased-feature-branch. + Applied autostash. + Successfully rebased and updated refs/heads/rebased-feature-branch. EOF } create_expected_failure_am () { cat >expected <<-EOF $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual) - HEAD is now at $(git rev-parse --short feature-branch) third commit First, rewinding head to replay your work on top of it... Applying: second commit Applying: third commit @@ -67,13 +65,12 @@ create_expected_failure_am () { } create_expected_failure_interactive () { - q_to_cr >expected <<-EOF + cat >expected <<-EOF $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual) - HEAD is now at $(git rev-parse --short feature-branch) third commit - Rebasing (1/2)QRebasing (2/2)QApplying autostash resulted in conflicts. + Applying autostash resulted in conflicts. Your changes are safe in the stash. You can run "git stash pop" or "git stash drop" at any time. - Q QSuccessfully rebased and updated refs/heads/rebased-feature-branch. + Successfully rebased and updated refs/heads/rebased-feature-branch. EOF } @@ -109,7 +106,8 @@ testrebase () { suffix=interactive fi && create_expected_success_$suffix && - test_i18ncmp expected actual + sed "$remove_progress_re" <actual >actual2 && + test_i18ncmp expected actual2 ' test_expect_success "rebase$type: dirty index, non-conflicting rebase" ' @@ -209,7 +207,8 @@ testrebase () { suffix=interactive fi && create_expected_failure_$suffix && - test_i18ncmp expected actual + sed "$remove_progress_re" <actual >actual2 && + test_i18ncmp expected actual2 ' } @@ -303,4 +302,12 @@ test_expect_success 'branch is left alone when possible' ' test unchanged-branch = "$(git rev-parse --abbrev-ref HEAD)" ' +test_expect_success 'never change active branch' ' + git checkout -b not-the-feature-branch unrelated-onto-branch && + test_when_finished "git reset --hard && git checkout master" && + echo changed >file0 && + git rebase --autostash not-the-feature-branch feature-branch && + test_cmp_rev not-the-feature-branch unrelated-onto-branch +' + test_done diff --git a/t/t3421-rebase-topology-linear.sh b/t/t3421-rebase-topology-linear.sh index 7274dca40b..325072b0a3 100755 --- a/t/t3421-rebase-topology-linear.sh +++ b/t/t3421-rebase-topology-linear.sh @@ -31,6 +31,16 @@ test_run_rebase success -m test_run_rebase success -i test_have_prereq !REBASE_P || test_run_rebase success -p +test_expect_success 'setup branches and remote tracking' ' + git tag -l >tags && + for tag in $(cat tags) + do + git branch branch-$tag $tag || return 1 + done && + git remote add origin "file://$PWD" && + git fetch origin +' + test_run_rebase () { result=$1 shift @@ -51,12 +61,13 @@ test_run_rebase () { test_expect_$result "rebase $* -f rewrites even if upstream is an ancestor" " reset_rebase && git rebase $* -f b e && - ! test_cmp_rev e HEAD && + test_cmp_rev ! e HEAD && test_cmp_rev b HEAD~2 && test_linear_range 'd e' b.. " } test_run_rebase success '' +test_run_rebase success --fork-point test_run_rebase success -m test_run_rebase success -i test_have_prereq !REBASE_P || test_run_rebase failure -p @@ -64,6 +75,23 @@ test_have_prereq !REBASE_P || test_run_rebase failure -p test_run_rebase () { result=$1 shift + test_expect_$result "rebase $* -f rewrites even if remote upstream is an ancestor" " + reset_rebase && + git rebase $* -f branch-b branch-e && + test_cmp_rev ! branch-e origin/branch-e && + test_cmp_rev branch-b HEAD~2 && + test_linear_range 'd e' branch-b.. + " +} +test_run_rebase success '' +test_run_rebase success --fork-point +test_run_rebase success -m +test_run_rebase success -i +test_have_prereq !REBASE_P || test_run_rebase success -p + +test_run_rebase () { + result=$1 + shift test_expect_$result "rebase $* fast-forwards from ancestor of upstream" " reset_rebase && git rebase $* e b && @@ -71,6 +99,7 @@ test_run_rebase () { " } test_run_rebase success '' +test_run_rebase success --fork-point test_run_rebase success -m test_run_rebase success -i test_have_prereq !REBASE_P || test_run_rebase success -p @@ -339,7 +368,7 @@ test_run_rebase () { test_expect_$result "rebase $* -f --root on linear history causes re-write" " reset_rebase && git rebase $* -f --root c && - ! test_cmp_rev a HEAD~2 && + test_cmp_rev ! a HEAD~2 && test_linear_range 'a b c' HEAD " } diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh index a5868ea152..c8234062c6 100755 --- a/t/t3422-rebase-incompatible-options.sh +++ b/t/t3422-rebase-incompatible-options.sh @@ -61,8 +61,6 @@ test_rebase_am_only () { } test_rebase_am_only --whitespace=fix -test_rebase_am_only --ignore-whitespace -test_rebase_am_only --committer-date-is-author-date test_rebase_am_only -C4 test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' ' @@ -76,14 +74,4 @@ test_expect_success REBASE_P \ test_must_fail git rebase --preserve-merges --rebase-merges A ' -test_expect_success '--rebase-merges incompatible with --strategy' ' - git checkout B^0 && - test_must_fail git rebase --rebase-merges -s resolve A -' - -test_expect_success '--rebase-merges incompatible with --strategy-option' ' - git checkout B^0 && - test_must_fail git rebase --rebase-merges -Xignore-space-change A -' - test_done diff --git a/t/t3427-rebase-subtree.sh b/t/t3427-rebase-subtree.sh index d8640522a0..bec48e6a1f 100755 --- a/t/t3427-rebase-subtree.sh +++ b/t/t3427-rebase-subtree.sh @@ -11,113 +11,99 @@ commit_message() { git log --pretty=format:%s -1 "$1" } +# There are a few bugs in the rebase with regards to the subtree strategy, and +# this test script tries to document them. First, the following commit history +# is generated (the onelines are shown, time flows from left to right): +# +# master1 - master2 - master3 +# \ +# README ---------------------- Add subproject master - master4 - files_subtree/master5 +# +# Where the merge moves the files master[123].t into the subdirectory +# files_subtree/ and master4 as well as files_subtree/master5 add files to that +# directory directly. +# +# Then, in subsequent test cases, `git filter-branch` is used to distill just +# the commits that touch files_subtree/. To give it a final pre-rebase touch, +# an empty commit is added on top. The pre-rebase commit history looks like +# this: +# +# Add subproject master - master4 - files_subtree/master5 - Empty commit +# +# where the root commit adds three files: master1.t, master2.t and master3.t. +# +# This commit history is then rebased onto `master3` with the +# `-Xsubtree=files_subtree` option in three different ways: +# +# 1. using `--preserve-merges` +# 2. using `--preserve-merges` and --keep-empty +# 3. without specifying a rebase backend + test_expect_success 'setup' ' test_commit README && - mkdir files && - ( - cd files && - git init && - test_commit master1 && - test_commit master2 && - test_commit master3 - ) && - git fetch files master && - git branch files-master FETCH_HEAD && - git read-tree --prefix=files_subtree files-master && - git checkout -- files_subtree && - tree=$(git write-tree) && - head=$(git rev-parse HEAD) && - rev=$(git rev-parse --verify files-master^0) && - commit=$(git commit-tree -p $head -p $rev -m "Add subproject master" $tree) && - git update-ref HEAD $commit && - ( - cd files_subtree && - test_commit master4 - ) && - test_commit files_subtree/master5 -' -# FAILURE: Does not preserve master4. -test_expect_failure REBASE_P \ - 'Rebase -Xsubtree --preserve-merges --onto commit 4' ' - reset_rebase && - git checkout -b rebase-preserve-merges-4 master && - git filter-branch --prune-empty -f --subdirectory-filter files_subtree && - git commit -m "Empty commit" --allow-empty && - git rebase -Xsubtree=files_subtree --preserve-merges --onto files-master master && - verbose test "$(commit_message HEAD~)" = "files_subtree/master4" + git init files && + test_commit -C files master1 && + test_commit -C files master2 && + test_commit -C files master3 && + + : perform subtree merge into files_subtree/ && + git fetch files refs/heads/master:refs/heads/files-master && + git merge -s ours --no-commit --allow-unrelated-histories \ + files-master && + git read-tree --prefix=files_subtree -u files-master && + git commit -m "Add subproject master" && + + : add two extra commits to rebase && + test_commit -C files_subtree master4 && + test_commit files_subtree/master5 && + + git checkout -b to-rebase && + git fast-export --no-data HEAD -- files_subtree/ | + sed -e "s%\([0-9a-f]\{40\} \)files_subtree/%\1%" | + git fast-import --force --quiet && + git reset --hard && + git commit -m "Empty commit" --allow-empty ' -# FAILURE: Does not preserve master5. -test_expect_failure REBASE_P \ - 'Rebase -Xsubtree --preserve-merges --onto commit 5' ' +# FAILURE: Does not preserve master4. +test_expect_failure REBASE_P 'Rebase -Xsubtree --preserve-merges --onto commit' ' reset_rebase && - git checkout -b rebase-preserve-merges-5 master && - git filter-branch --prune-empty -f --subdirectory-filter files_subtree && - git commit -m "Empty commit" --allow-empty && + git checkout -b rebase-preserve-merges to-rebase && git rebase -Xsubtree=files_subtree --preserve-merges --onto files-master master && + verbose test "$(commit_message HEAD~)" = "master4" && verbose test "$(commit_message HEAD)" = "files_subtree/master5" ' # FAILURE: Does not preserve master4. -test_expect_failure REBASE_P \ - 'Rebase -Xsubtree --keep-empty --preserve-merges --onto commit 4' ' - reset_rebase && - git checkout -b rebase-keep-empty-4 master && - git filter-branch --prune-empty -f --subdirectory-filter files_subtree && - git commit -m "Empty commit" --allow-empty && - git rebase -Xsubtree=files_subtree --keep-empty --preserve-merges --onto files-master master && - verbose test "$(commit_message HEAD~2)" = "files_subtree/master4" -' - -# FAILURE: Does not preserve master5. -test_expect_failure REBASE_P \ - 'Rebase -Xsubtree --keep-empty --preserve-merges --onto commit 5' ' - reset_rebase && - git checkout -b rebase-keep-empty-5 master && - git filter-branch --prune-empty -f --subdirectory-filter files_subtree && - git commit -m "Empty commit" --allow-empty && - git rebase -Xsubtree=files_subtree --keep-empty --preserve-merges --onto files-master master && - verbose test "$(commit_message HEAD~)" = "files_subtree/master5" -' - -# FAILURE: Does not preserve Empty. -test_expect_failure REBASE_P \ - 'Rebase -Xsubtree --keep-empty --preserve-merges --onto empty commit' ' +test_expect_failure REBASE_P 'Rebase -Xsubtree --keep-empty --preserve-merges --onto commit' ' reset_rebase && - git checkout -b rebase-keep-empty-empty master && - git filter-branch --prune-empty -f --subdirectory-filter files_subtree && - git commit -m "Empty commit" --allow-empty && + git checkout -b rebase-keep-empty to-rebase && git rebase -Xsubtree=files_subtree --keep-empty --preserve-merges --onto files-master master && + verbose test "$(commit_message HEAD~2)" = "master4" && + verbose test "$(commit_message HEAD~)" = "files_subtree/master5" && verbose test "$(commit_message HEAD)" = "Empty commit" ' -# FAILURE: fatal: Could not parse object -test_expect_failure 'Rebase -Xsubtree --onto commit 4' ' +test_expect_success 'Rebase -Xsubtree --keep-empty --onto commit' ' reset_rebase && - git checkout -b rebase-onto-4 master && - git filter-branch --prune-empty -f --subdirectory-filter files_subtree && - git commit -m "Empty commit" --allow-empty && - git rebase -Xsubtree=files_subtree --onto files-master master && - verbose test "$(commit_message HEAD~2)" = "files_subtree/master4" + git checkout -b rebase-onto to-rebase && + test_must_fail git rebase -Xsubtree=files_subtree --keep-empty --onto files-master master && + : first pick results in no changes && + git rebase --continue && + verbose test "$(commit_message HEAD~2)" = "master4" && + verbose test "$(commit_message HEAD~)" = "files_subtree/master5" && + verbose test "$(commit_message HEAD)" = "Empty commit" ' -# FAILURE: fatal: Could not parse object -test_expect_failure 'Rebase -Xsubtree --onto commit 5' ' - reset_rebase && - git checkout -b rebase-onto-5 master && - git filter-branch --prune-empty -f --subdirectory-filter files_subtree && - git commit -m "Empty commit" --allow-empty && - git rebase -Xsubtree=files_subtree --onto files-master master && - verbose test "$(commit_message HEAD~)" = "files_subtree/master5" -' -# FAILURE: fatal: Could not parse object -test_expect_failure 'Rebase -Xsubtree --onto empty commit' ' +test_expect_success 'Rebase -Xsubtree --keep-empty --rebase-merges --onto commit' ' reset_rebase && - git checkout -b rebase-onto-empty master && - git filter-branch --prune-empty -f --subdirectory-filter files_subtree && - git commit -m "Empty commit" --allow-empty && - git rebase -Xsubtree=files_subtree --onto files-master master && + git checkout -b rebase-merges-onto to-rebase && + test_must_fail git rebase -Xsubtree=files_subtree --keep-empty --rebase-merges --onto files-master --root && + : first pick results in no changes && + git rebase --continue && + verbose test "$(commit_message HEAD~2)" = "master4" && + verbose test "$(commit_message HEAD~)" = "files_subtree/master5" && verbose test "$(commit_message HEAD)" = "Empty commit" ' diff --git a/t/t3429-rebase-edit-todo.sh b/t/t3429-rebase-edit-todo.sh index 76f6d306ea..7024d49ae7 100755 --- a/t/t3429-rebase-edit-todo.sh +++ b/t/t3429-rebase-edit-todo.sh @@ -3,15 +3,21 @@ test_description='rebase should reread the todo file if an exec modifies it' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-rebase.sh + +test_expect_success 'setup' ' + test_commit first file && + test_commit second file && + test_commit third file +' test_expect_success 'rebase exec modifies rebase-todo' ' - test_commit initial && todo=.git/rebase-merge/git-rebase-todo && git rebase HEAD -x "echo exec touch F >>$todo" && test -e F ' -test_expect_success SHA1 'loose object cache vs re-reading todo list' ' +test_expect_success 'loose object cache vs re-reading todo list' ' GIT_REBASE_TODO=.git/rebase-merge/git-rebase-todo && export GIT_REBASE_TODO && write_script append-todo.sh <<-\EOS && @@ -33,4 +39,47 @@ test_expect_success SHA1 'loose object cache vs re-reading todo list' ' git rebase HEAD -x "./append-todo.sh 5 6" ' +test_expect_success 'todo is re-read after reword and squash' ' + write_script reword-editor.sh <<-\EOS && + GIT_SEQUENCE_EDITOR="echo \"exec echo $(cat file) >>actual\" >>" \ + git rebase --edit-todo + EOS + + test_write_lines first third >expected && + set_fake_editor && + GIT_SEQUENCE_EDITOR="$EDITOR" FAKE_LINES="reword 1 squash 2 fixup 3" \ + GIT_EDITOR=./reword-editor.sh git rebase -i --root third && + test_cmp expected actual +' + +test_expect_success 're-reading todo doesnt interfere with revert --edit' ' + git reset --hard third && + + git revert --edit third second && + + cat >expect <<-\EOF && + Revert "second" + Revert "third" + third + second + first + EOF + git log --format="%s" >actual && + test_cmp expect actual +' + +test_expect_success 're-reading todo doesnt interfere with cherry-pick --edit' ' + git reset --hard first && + + git cherry-pick --edit second third && + + cat >expect <<-\EOF && + third + second + first + EOF + git log --format="%s" >actual && + test_cmp expect actual +' + test_done diff --git a/t/t3430-rebase-merges.sh b/t/t3430-rebase-merges.sh index f0814d5280..e72ca348ea 100755 --- a/t/t3430-rebase-merges.sh +++ b/t/t3430-rebase-merges.sh @@ -37,20 +37,27 @@ test_expect_success 'setup' ' test_commit A && git checkout -b first && test_commit B && + b=$(git rev-parse --short HEAD) && git checkout master && test_commit C && + c=$(git rev-parse --short HEAD) && test_commit D && + d=$(git rev-parse --short HEAD) && git merge --no-commit B && test_tick && git commit -m E && git tag -m E E && + e=$(git rev-parse --short HEAD) && git checkout -b second C && test_commit F && + f=$(git rev-parse --short HEAD) && test_commit G && + g=$(git rev-parse --short HEAD) && git checkout master && git merge --no-commit G && test_tick && git commit -m H && + h=$(git rev-parse --short HEAD) && git tag -m H H && git checkout A && test_commit conflicting-G G.t @@ -93,24 +100,24 @@ test_expect_success 'create completely different structure' ' ' test_expect_success 'generate correct todo list' ' - cat >expect <<-\EOF && + cat >expect <<-EOF && label onto reset onto - pick d9df450 B + pick $b B label E reset onto - pick 5dee784 C + pick $c C label branch-point - pick ca2c861 F - pick 088b00a G + pick $f F + pick $g G label H reset branch-point # C - pick 12bd07b D - merge -C 2051b56 E # E - merge -C 233d48a H # H + pick $d D + merge -C $e E # E + merge -C $h H # H EOF @@ -151,7 +158,6 @@ test_expect_success 'failed `merge -C` writes patch (may be rescheduled, too)' ' test_path_is_file .git/rebase-merge/patch ' -SQ="'" test_expect_success 'failed `merge <branch>` does not crash' ' test_when_finished "test_might_fail git rebase --abort" && git checkout conflicting-G && @@ -164,6 +170,19 @@ test_expect_success 'failed `merge <branch>` does not crash' ' grep "^Merge branch ${SQ}G${SQ}$" .git/rebase-merge/message ' +test_expect_success 'fast-forward merge -c still rewords' ' + git checkout -b fast-forward-merge-c H && + ( + set_fake_editor && + FAKE_COMMIT_MESSAGE=edited \ + GIT_SEQUENCE_EDITOR="echo merge -c H G >" \ + git rebase -ir @^ + ) && + echo edited >expected && + git log --pretty=format:%B -1 >actual && + test_cmp expected actual +' + test_expect_success 'with a branch tip that was cherry-picked already' ' git checkout -b already-upstream master && base="$(git rev-parse --verify HEAD)" && @@ -327,7 +346,7 @@ test_expect_success 'A root commit can be a cousin, treat it that way' ' git merge --allow-unrelated-histories khnum && test_tick && git rebase -f -r HEAD^ && - ! test_cmp_rev HEAD^2 khnum && + test_cmp_rev ! HEAD^2 khnum && test_cmp_graph HEAD^.. <<-\EOF && * Merge branch '\''khnum'\'' into asherah |\ @@ -389,7 +408,7 @@ test_expect_success 'octopus merges' ' | | * three | * | two | |/ - * | one + * / one |/ o before-octopus EOF @@ -428,4 +447,52 @@ test_expect_success '--continue after resolving conflicts after a merge' ' test_path_is_missing .git/MERGE_HEAD ' +test_expect_success '--rebase-merges with strategies' ' + git checkout -b with-a-strategy F && + test_tick && + git merge -m "Merge conflicting-G" conflicting-G && + + : first, test with a merge strategy option && + git rebase -ir -Xtheirs G && + echo conflicting-G >expect && + test_cmp expect G.t && + + : now, try with a merge strategy other than recursive && + git reset --hard @{1} && + write_script git-merge-override <<-\EOF && + echo overridden$1 >>G.t + git add G.t + EOF + PATH="$PWD:$PATH" git rebase -ir -s override -Xxopt G && + test_write_lines G overridden--xopt >expect && + test_cmp expect G.t +' + +test_expect_success '--rebase-merges with commit that can generate bad characters for filename' ' + git checkout -b colon-in-label E && + git merge -m "colon: this should work" G && + git rebase --rebase-merges --force-rebase E +' + +test_expect_success '--rebase-merges with message matched with onto label' ' + git checkout -b onto-label E && + git merge -m onto G && + git rebase --rebase-merges --force-rebase E && + test_cmp_graph <<-\EOF + * onto + |\ + | * G + | * F + * | E + |\ \ + | * | B + * | | D + | |/ + |/| + * | C + |/ + * A + EOF +' + test_done diff --git a/t/t3431-rebase-fork-point.sh b/t/t3431-rebase-fork-point.sh new file mode 100755 index 0000000000..78851b9a2a --- /dev/null +++ b/t/t3431-rebase-fork-point.sh @@ -0,0 +1,57 @@ +#!/bin/sh +# +# Copyright (c) 2019 Denton Liu +# + +test_description='git rebase --fork-point test' + +. ./test-lib.sh + +# A---B---D---E (master) +# \ +# C*---F---G (side) +# +# C was formerly part of master but master was rewound to remove C +# +test_expect_success setup ' + test_commit A && + test_commit B && + test_commit C && + git branch -t side && + git reset --hard HEAD^ && + test_commit D && + test_commit E && + git checkout side && + test_commit F && + test_commit G +' + +test_rebase () { + expected="$1" && + shift && + test_expect_success "git rebase $*" " + git checkout master && + git reset --hard E && + git checkout side && + git reset --hard G && + git rebase $* && + test_write_lines $expected >expect && + git log --pretty=%s >actual && + test_cmp expect actual + " +} + +test_rebase 'G F E D B A' +test_rebase 'G F D B A' --onto D +test_rebase 'G F B A' --keep-base +test_rebase 'G F C E D B A' --no-fork-point +test_rebase 'G F C D B A' --no-fork-point --onto D +test_rebase 'G F C B A' --no-fork-point --keep-base +test_rebase 'G F E D B A' --fork-point refs/heads/master +test_rebase 'G F D B A' --fork-point --onto D refs/heads/master +test_rebase 'G F B A' --fork-point --keep-base refs/heads/master +test_rebase 'G F C E D B A' refs/heads/master +test_rebase 'G F C D B A' --onto D refs/heads/master +test_rebase 'G F C B A' --keep-base refs/heads/master + +test_done diff --git a/t/t3432-rebase-fast-forward.sh b/t/t3432-rebase-fast-forward.sh new file mode 100755 index 0000000000..92f95b57da --- /dev/null +++ b/t/t3432-rebase-fast-forward.sh @@ -0,0 +1,125 @@ +#!/bin/sh +# +# Copyright (c) 2019 Denton Liu +# + +test_description='ensure rebase fast-forwards commits when possible' + +. ./test-lib.sh + +test_expect_success setup ' + test_commit A && + test_commit B && + test_commit C && + test_commit D && + git checkout -t -b side +' + +test_rebase_same_head () { + status_n="$1" && + shift && + what_n="$1" && + shift && + cmp_n="$1" && + shift && + status_f="$1" && + shift && + what_f="$1" && + shift && + cmp_f="$1" && + shift && + test_rebase_same_head_ $status_n $what_n $cmp_n "" "$*" && + test_rebase_same_head_ $status_f $what_f $cmp_f " --no-ff" "$*" +} + +test_rebase_same_head_ () { + status="$1" && + shift && + what="$1" && + shift && + cmp="$1" && + shift && + flag="$1" + shift && + test_expect_$status "git rebase$flag $* with $changes is $what with $cmp HEAD" " + oldhead=\$(git rev-parse HEAD) && + test_when_finished 'git reset --hard \$oldhead' && + git rebase$flag $* >stdout && + if test $what = work + then + # Must check this case first, for 'is up to + # date, rebase forced[...]rewinding head' cases + test_i18ngrep 'rewinding head' stdout + elif test $what = noop + then + test_i18ngrep 'is up to date' stdout && + test_i18ngrep ! 'rebase forced' stdout + elif test $what = noop-force + then + test_i18ngrep 'is up to date, rebase forced' stdout + fi && + newhead=\$(git rev-parse HEAD) && + if test $cmp = same + then + test_cmp_rev \$oldhead \$newhead + elif test $cmp = diff + then + test_cmp_rev ! \$oldhead \$newhead + fi + " +} + +changes='no changes' +test_rebase_same_head success noop same success work same +test_rebase_same_head success noop same success noop-force same master +test_rebase_same_head success noop same success noop-force diff --onto B B +test_rebase_same_head success noop same success noop-force diff --onto B... B +test_rebase_same_head success noop same success noop-force same --onto master... master +test_rebase_same_head success noop same success noop-force same --keep-base master +test_rebase_same_head success noop same success noop-force same --keep-base +test_rebase_same_head success noop same success noop-force same --no-fork-point +test_rebase_same_head success noop same success noop-force same --keep-base --no-fork-point +test_rebase_same_head success noop same success work same --fork-point master +test_rebase_same_head success noop same success work diff --fork-point --onto B B +test_rebase_same_head success noop same success work diff --fork-point --onto B... B +test_rebase_same_head success noop same success work same --fork-point --onto master... master +test_rebase_same_head success noop same success work same --keep-base --keep-base master + +test_expect_success 'add work same to side' ' + test_commit E +' + +changes='our changes' +test_rebase_same_head success noop same success work same +test_rebase_same_head success noop same success noop-force same master +test_rebase_same_head success noop same success noop-force diff --onto B B +test_rebase_same_head success noop same success noop-force diff --onto B... B +test_rebase_same_head success noop same success noop-force same --onto master... master +test_rebase_same_head success noop same success noop-force same --keep-base master +test_rebase_same_head success noop same success noop-force same --keep-base +test_rebase_same_head success noop same success noop-force same --no-fork-point +test_rebase_same_head success noop same success noop-force same --keep-base --no-fork-point +test_rebase_same_head success noop same success work same --fork-point master +test_rebase_same_head success noop same success work diff --fork-point --onto B B +test_rebase_same_head success noop same success work diff --fork-point --onto B... B +test_rebase_same_head success noop same success work same --fork-point --onto master... master +test_rebase_same_head success noop same success work same --fork-point --keep-base master + +test_expect_success 'add work same to upstream' ' + git checkout master && + test_commit F && + git checkout side +' + +changes='our and their changes' +test_rebase_same_head success noop same success noop-force diff --onto B B +test_rebase_same_head success noop same success noop-force diff --onto B... B +test_rebase_same_head success noop same success work diff --onto master... master +test_rebase_same_head success noop same success work diff --keep-base master +test_rebase_same_head success noop same success work diff --keep-base +test_rebase_same_head failure work same success work diff --fork-point --onto B B +test_rebase_same_head failure work same success work diff --fork-point --onto B... B +test_rebase_same_head success noop same success work diff --fork-point --onto master... master +test_rebase_same_head success noop same success work diff --fork-point --keep-base master + +test_done diff --git a/t/t3433-rebase-options-compatibility.sh b/t/t3433-rebase-options-compatibility.sh new file mode 100755 index 0000000000..5166f158dd --- /dev/null +++ b/t/t3433-rebase-options-compatibility.sh @@ -0,0 +1,131 @@ +#!/bin/sh +# +# Copyright (c) 2019 Rohit Ashiwal +# + +test_description='tests to ensure compatibility between am and interactive backends' + +. ./test-lib.sh + +GIT_AUTHOR_DATE="1999-04-02T08:03:20+05:30" +export GIT_AUTHOR_DATE + +# This is a special case in which both am and interactive backends +# provide the same output. It was done intentionally because +# both the backends fall short of optimal behaviour. +test_expect_success 'setup' ' + git checkout -b topic && + q_to_tab >file <<-\EOF && + line 1 + Qline 2 + line 3 + EOF + git add file && + git commit -m "add file" && + cat >file <<-\EOF && + line 1 + new line 2 + line 3 + EOF + git commit -am "update file" && + git tag side && + test_commit commit1 foo foo1 && + test_commit commit2 foo foo2 && + test_commit commit3 foo foo3 && + + git checkout --orphan master && + git rm --cached foo && + rm foo && + sed -e "s/^|//" >file <<-\EOF && + |line 1 + | line 2 + |line 3 + EOF + git add file && + git commit -m "add file" && + git tag main +' + +test_expect_success '--ignore-whitespace works with am backend' ' + cat >expect <<-\EOF && + line 1 + new line 2 + line 3 + EOF + test_must_fail git rebase main side && + git rebase --abort && + git rebase --ignore-whitespace main side && + test_cmp expect file +' + +test_expect_success '--ignore-whitespace works with interactive backend' ' + cat >expect <<-\EOF && + line 1 + new line 2 + line 3 + EOF + test_must_fail git rebase --merge main side && + git rebase --abort && + git rebase --merge --ignore-whitespace main side && + test_cmp expect file +' + +test_expect_success '--committer-date-is-author-date works with am backend' ' + git commit --amend && + git rebase --committer-date-is-author-date HEAD^ && + git show HEAD --pretty="format:%ai" >authortime && + git show HEAD --pretty="format:%ci" >committertime && + test_cmp authortime committertime +' + +test_expect_success '--committer-date-is-author-date works with interactive backend' ' + git commit --amend && + git rebase -i --committer-date-is-author-date HEAD^ && + git show HEAD --pretty="format:%ai" >authortime && + git show HEAD --pretty="format:%ci" >committertime && + test_cmp authortime committertime +' + +test_expect_success '--committer-date-is-author-date works with rebase -r' ' + git checkout side && + git merge --no-ff commit3 && + git rebase -r --root --committer-date-is-author-date && + git rev-list HEAD >rev_list && + while read HASH + do + git show $HASH --pretty="format:%ai" >authortime + git show $HASH --pretty="format:%ci" >committertime + test_cmp authortime committertime + done <rev_list +' + +# Checking for +0000 in author time is enough since default +# timezone is UTC, but the timezone used while committing +# sets to +0530. +test_expect_success '--ignore-date works with am backend' ' + git commit --amend --date="$GIT_AUTHOR_DATE" && + git rebase --ignore-date HEAD^ && + git show HEAD --pretty="format:%ai" >authortime && + grep "+0000" authortime +' + +test_expect_success '--ignore-date works with interactive backend' ' + git commit --amend --date="$GIT_AUTHOR_DATE" && + git rebase --ignore-date -i HEAD^ && + git show HEAD --pretty="format:%ai" >authortime && + grep "+0000" authortime +' + +test_expect_success '--ignore-date works with rebase -r' ' + git checkout side && + git merge --no-ff commit3 && + git rebase -r --root --ignore-date && + git rev-list HEAD >rev_list && + while read HASH + do + git show $HASH --pretty="format:%ai" >authortime + grep "+0000" authortime + done <rev_list +' + +test_done diff --git a/t/t3434-rebase-i18n.sh b/t/t3434-rebase-i18n.sh new file mode 100755 index 0000000000..4b5b128cd6 --- /dev/null +++ b/t/t3434-rebase-i18n.sh @@ -0,0 +1,84 @@ +#!/bin/sh +# +# Copyright (c) 2019 Doan Tran Cong Danh +# + +test_description='rebase with changing encoding + +Initial setup: + +1 - 2 master + \ + 3 - 4 first + \ + 5 - 6 second +' + +. ./test-lib.sh + +compare_msg () { + iconv -f "$2" -t "$3" "$TEST_DIRECTORY/t3434/$1" >expect && + git cat-file commit HEAD >raw && + sed "1,/^$/d" raw >actual && + test_cmp expect actual +} + +test_expect_success setup ' + test_commit one && + git branch first && + test_commit two && + git switch first && + test_commit three && + git branch second && + test_commit four && + git switch second && + test_commit five && + test_commit six +' + +test_expect_success 'rebase --rebase-merges update encoding eucJP to UTF-8' ' + git switch -c merge-eucJP-UTF-8 first && + git config i18n.commitencoding eucJP && + git merge -F "$TEST_DIRECTORY/t3434/eucJP.txt" second && + git config i18n.commitencoding UTF-8 && + git rebase --rebase-merges master && + compare_msg eucJP.txt eucJP UTF-8 +' + +test_expect_failure 'rebase --rebase-merges update encoding eucJP to ISO-2022-JP' ' + git switch -c merge-eucJP-ISO-2022-JP first && + git config i18n.commitencoding eucJP && + git merge -F "$TEST_DIRECTORY/t3434/eucJP.txt" second && + git config i18n.commitencoding ISO-2022-JP && + git rebase --rebase-merges master && + compare_msg eucJP.txt eucJP ISO-2022-JP +' + +test_rebase_continue_update_encode () { + old=$1 + new=$2 + msgfile=$3 + test_expect_success "rebase --continue update from $old to $new" ' + (git rebase --abort || : abort current git-rebase failure) && + git switch -c conflict-$old-$new one && + echo for-conflict >two.t && + git add two.t && + git config i18n.commitencoding $old && + git commit -F "$TEST_DIRECTORY/t3434/$msgfile" && + git config i18n.commitencoding $new && + test_must_fail git rebase -m master && + test -f .git/rebase-merge/message && + git stripspace <.git/rebase-merge/message >two.t && + git add two.t && + git rebase --continue && + compare_msg $msgfile $old $new && + : git-commit assume invalid utf-8 is latin1 && + test_cmp expect two.t + ' +} + +test_rebase_continue_update_encode ISO-8859-1 UTF-8 ISO8859-1.txt +test_rebase_continue_update_encode eucJP UTF-8 eucJP.txt +test_rebase_continue_update_encode eucJP ISO-2022-JP eucJP.txt + +test_done diff --git a/t/t3434/ISO8859-1.txt b/t/t3434/ISO8859-1.txt new file mode 100644 index 0000000000..7cbef0ee6f --- /dev/null +++ b/t/t3434/ISO8859-1.txt @@ -0,0 +1,3 @@ + + +bdfg diff --git a/t/t3434/eucJP.txt b/t/t3434/eucJP.txt new file mode 100644 index 0000000000..546f2aac01 --- /dev/null +++ b/t/t3434/eucJP.txt @@ -0,0 +1,4 @@ +ϤҤۤ + +ƤΤΤǡ +ͤۤפݤޤӤء diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh index d1c68af8c5..1c51a9131d 100755 --- a/t/t3501-revert-cherry-pick.sh +++ b/t/t3501-revert-cherry-pick.sh @@ -106,7 +106,7 @@ test_expect_success 'cherry-pick on unborn branch' ' rm -rf * && git cherry-pick initial && git diff --quiet initial && - ! test_cmp_rev initial HEAD + test_cmp_rev ! initial HEAD ' test_expect_success 'cherry-pick "-" to pick from previous branch' ' diff --git a/t/t3506-cherry-pick-ff.sh b/t/t3506-cherry-pick-ff.sh index 127dd0082f..9d5adbc130 100755 --- a/t/t3506-cherry-pick-ff.sh +++ b/t/t3506-cherry-pick-ff.sh @@ -16,7 +16,11 @@ test_expect_success setup ' git add file1 && test_tick && git commit -m "second" && - git tag second + git tag second && + test_oid_cache <<-EOF + cp_ff sha1:1df192cd8bc58a2b275d842cede4d221ad9000d1 + cp_ff sha256:e70d6b7fc064bddb516b8d512c9057094b96ce6ff08e12080acc4fe7f1d60a1d + EOF ' test_expect_success 'cherry-pick using --ff fast forwards' ' @@ -102,7 +106,7 @@ test_expect_success 'cherry pick a root commit with --ff' ' git add file2 && git commit --amend -m "file2" && git cherry-pick --ff first && - test "$(git rev-parse --verify HEAD)" = "1df192cd8bc58a2b275d842cede4d221ad9000d1" + test "$(git rev-parse --verify HEAD)" = "$(test_oid cp_ff)" ' test_expect_success 'cherry-pick --ff on unborn branch' ' diff --git a/t/t3508-cherry-pick-many-commits.sh b/t/t3508-cherry-pick-many-commits.sh index b457333e18..23070a7b73 100755 --- a/t/t3508-cherry-pick-many-commits.sh +++ b/t/t3508-cherry-pick-many-commits.sh @@ -5,7 +5,7 @@ test_description='test cherry-picking many commits' . ./test-lib.sh check_head_differs_from() { - ! test_cmp_rev HEAD "$1" + test_cmp_rev ! HEAD "$1" } check_head_equals() { diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh index 941d5026da..793bcc7fe3 100755 --- a/t/t3510-cherry-pick-sequence.sh +++ b/t/t3510-cherry-pick-sequence.sh @@ -93,6 +93,128 @@ test_expect_success 'cherry-pick cleans up sequencer state upon success' ' test_path_is_missing .git/sequencer ' +test_expect_success 'cherry-pick --skip requires cherry-pick in progress' ' + pristine_detach initial && + test_must_fail git cherry-pick --skip +' + +test_expect_success 'revert --skip requires revert in progress' ' + pristine_detach initial && + test_must_fail git revert --skip +' + +test_expect_success 'cherry-pick --skip to skip commit' ' + pristine_detach initial && + test_must_fail git cherry-pick anotherpick && + test_must_fail git revert --skip && + git cherry-pick --skip && + test_cmp_rev initial HEAD && + test_path_is_missing .git/CHERRY_PICK_HEAD +' + +test_expect_success 'revert --skip to skip commit' ' + pristine_detach anotherpick && + test_must_fail git revert anotherpick~1 && + test_must_fail git cherry-pick --skip && + git revert --skip && + test_cmp_rev anotherpick HEAD +' + +test_expect_success 'skip "empty" commit' ' + pristine_detach picked && + test_commit dummy foo d && + test_must_fail git cherry-pick anotherpick && + git cherry-pick --skip && + test_cmp_rev dummy HEAD +' + +test_expect_success 'skip a commit and check if rest of sequence is correct' ' + pristine_detach initial && + echo e >expect && + cat >expect.log <<-EOF && + OBJID + :100644 100644 OBJID OBJID M foo + OBJID + :100644 100644 OBJID OBJID M foo + OBJID + :100644 100644 OBJID OBJID M unrelated + OBJID + :000000 100644 OBJID OBJID A foo + :000000 100644 OBJID OBJID A unrelated + EOF + test_must_fail git cherry-pick base..yetanotherpick && + test_must_fail git cherry-pick --skip && + echo d >foo && + git add foo && + git cherry-pick --continue && + { + git rev-list HEAD | + git diff-tree --root --stdin | + sed "s/$OID_REGEX/OBJID/g" + } >actual.log && + test_cmp expect foo && + test_cmp expect.log actual.log +' + +test_expect_success 'check advice when we move HEAD by committing' ' + pristine_detach initial && + cat >expect <<-EOF && + error: there is nothing to skip + hint: have you committed already? + hint: try "git cherry-pick --continue" + fatal: cherry-pick failed + EOF + test_must_fail git cherry-pick base..yetanotherpick && + echo c >foo && + git commit -a && + test_path_is_missing .git/CHERRY_PICK_HEAD && + test_must_fail git cherry-pick --skip 2>advice && + test_i18ncmp expect advice +' + +test_expect_success 'selectively advise --skip while launching another sequence' ' + pristine_detach initial && + cat >expect <<-EOF && + error: cherry-pick is already in progress + hint: try "git cherry-pick (--continue | --skip | --abort | --quit)" + fatal: cherry-pick failed + EOF + test_must_fail git cherry-pick picked..yetanotherpick && + test_must_fail git cherry-pick picked..yetanotherpick 2>advice && + test_i18ncmp expect advice && + cat >expect <<-EOF && + error: cherry-pick is already in progress + hint: try "git cherry-pick (--continue | --abort | --quit)" + fatal: cherry-pick failed + EOF + git reset --merge && + test_must_fail git cherry-pick picked..yetanotherpick 2>advice && + test_i18ncmp expect advice +' + +test_expect_success 'allow skipping commit but not abort for a new history' ' + pristine_detach initial && + cat >expect <<-EOF && + error: cannot abort from a branch yet to be born + fatal: cherry-pick failed + EOF + git checkout --orphan new_disconnected && + git reset --hard && + test_must_fail git cherry-pick anotherpick && + test_must_fail git cherry-pick --abort 2>advice && + git cherry-pick --skip && + test_i18ncmp expect advice +' + +test_expect_success 'allow skipping stopped cherry-pick because of untracked file modifications' ' + pristine_detach initial && + git rm --cached unrelated && + git commit -m "untrack unrelated" && + test_must_fail git cherry-pick initial base && + test_path_is_missing .git/CHERRY_PICK_HEAD && + git cherry-pick --skip +' + test_expect_success '--quit does not complain when no cherry-pick is in progress' ' pristine_detach initial && git cherry-pick --quit diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh index 66282a720e..8c8cca5bfb 100755 --- a/t/t3600-rm.sh +++ b/t/t3600-rm.sh @@ -240,12 +240,14 @@ test_expect_success 'refresh index before checking if it is up-to-date' ' ' test_expect_success 'choking "git rm" should not let it die with cruft' ' + test_oid_init && git reset -q --hard && test_when_finished "rm -f .git/index.lock && git reset -q --hard" && i=0 && + hash=$(test_oid deadbeef) && while test $i -lt 12000 do - echo "100644 1234567890123456789012345678901234567890 0 some-file-$i" + echo "100644 $hash 0 some-file-$i" i=$(( $i + 1 )) done | git update-index --index-info && git rm -n "some-file-*" | : && diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index 69991a3168..d4f9386621 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -314,7 +314,7 @@ test_expect_success C_LOCALE_OUTPUT 'add first line works' ' git commit -am "clear local changes" && git apply patch && printf "%s\n" s y y | git add -p file 2>error | - sed -n -e "s/^Stage this hunk[^@]*\(@@ .*\)/\1/" \ + sed -n -e "s/^([1-2]\/[1-2]) Stage this hunk[^@]*\(@@ .*\)/\1/" \ -e "/^[-+@ \\\\]"/p >output && test_must_be_empty error && git diff --cached >diff && @@ -647,4 +647,29 @@ test_expect_success 'checkout -p works with pathological context lines' ' test_write_lines a b a b a a b a b a >expect && test_cmp expect a ' + +test_expect_success 'show help from add--helper' ' + git reset --hard && + cat >expect <<-EOF && + + <BOLD>*** Commands ***<RESET> + 1: <BOLD;BLUE>s<RESET>tatus 2: <BOLD;BLUE>u<RESET>pdate 3: <BOLD;BLUE>r<RESET>evert 4: <BOLD;BLUE>a<RESET>dd untracked + 5: <BOLD;BLUE>p<RESET>atch 6: <BOLD;BLUE>d<RESET>iff 7: <BOLD;BLUE>q<RESET>uit 8: <BOLD;BLUE>h<RESET>elp + <BOLD;BLUE>What now<RESET>> <BOLD;RED>status - show paths with changes<RESET> + <BOLD;RED>update - add working tree state to the staged set of changes<RESET> + <BOLD;RED>revert - revert staged set of changes back to the HEAD version<RESET> + <BOLD;RED>patch - pick hunks and update selectively<RESET> + <BOLD;RED>diff - view diff between HEAD and index<RESET> + <BOLD;RED>add untracked - add contents of untracked files to the staged set of changes<RESET> + <BOLD>*** Commands ***<RESET> + 1: <BOLD;BLUE>s<RESET>tatus 2: <BOLD;BLUE>u<RESET>pdate 3: <BOLD;BLUE>r<RESET>evert 4: <BOLD;BLUE>a<RESET>dd untracked + 5: <BOLD;BLUE>p<RESET>atch 6: <BOLD;BLUE>d<RESET>iff 7: <BOLD;BLUE>q<RESET>uit 8: <BOLD;BLUE>h<RESET>elp + <BOLD;BLUE>What now<RESET>>$SP + Bye. + EOF + test_write_lines h | GIT_PAGER_IN_USE=true TERM=vt100 git add -i >actual.colored && + test_decode_color <actual.colored >actual && + test_i18ncmp expect actual +' + test_done diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh index 8eb47942e2..64dcc5ec28 100755 --- a/t/t3800-mktag.sh +++ b/t/t3800-mktag.sh @@ -23,6 +23,7 @@ check_verify_failure () { # first create a commit, so we have a valid object/type # for the tag. test_expect_success 'setup' ' + test_oid_init && echo Hello >A && git update-index --add A && git commit -m "Initial commit" && @@ -69,28 +70,28 @@ check_verify_failure '"object" line SHA1 check' '^error: char7: .*SHA1 hash$' # 4. type line label check cat >tag.sig <<EOF -object 779e9b33986b1c2670fff52c5067603117b3e895 +object $head xxxx tag tag mytag tagger . <> 0 +0000 EOF -check_verify_failure '"type" line label check' '^error: char47: .*"\\ntype "$' +check_verify_failure '"type" line label check' '^error: char.*: .*"\\ntype "$' ############################################################ # 5. type line eol check -echo "object 779e9b33986b1c2670fff52c5067603117b3e895" >tag.sig +echo "object $head" >tag.sig printf "type tagsssssssssssssssssssssssssssssss" >>tag.sig -check_verify_failure '"type" line eol check' '^error: char48: .*"\\n"$' +check_verify_failure '"type" line eol check' '^error: char.*: .*"\\n"$' ############################################################ # 6. tag line label check #1 cat >tag.sig <<EOF -object 779e9b33986b1c2670fff52c5067603117b3e895 +object $head type tag xxx mytag tagger . <> 0 +0000 @@ -98,37 +99,37 @@ tagger . <> 0 +0000 EOF check_verify_failure '"tag" line label check #1' \ - '^error: char57: no "tag " found$' + '^error: char.*: no "tag " found$' ############################################################ # 7. tag line label check #2 cat >tag.sig <<EOF -object 779e9b33986b1c2670fff52c5067603117b3e895 +object $head type taggggggggggggggggggggggggggggggg tag EOF check_verify_failure '"tag" line label check #2' \ - '^error: char87: no "tag " found$' + '^error: char.*: no "tag " found$' ############################################################ # 8. type line type-name length check cat >tag.sig <<EOF -object 779e9b33986b1c2670fff52c5067603117b3e895 +object $head type taggggggggggggggggggggggggggggggg tag mytag EOF check_verify_failure '"type" line type-name length check' \ - '^error: char53: type too long$' + '^error: char.*: type too long$' ############################################################ # 9. verify object (SHA1/type) check cat >tag.sig <<EOF -object 779e9b33986b1c2670fff52c5067603117b3e895 +object $(test_oid deadbeef) type tagggg tag mytag tagger . <> 0 +0000 @@ -150,7 +151,7 @@ tagger . <> 0 +0000 EOF check_verify_failure 'verify tag-name check' \ - '^error: char67: could not verify tag name$' + '^error: char.*: could not verify tag name$' ############################################################ # 11. tagger line label check #1 @@ -164,7 +165,7 @@ This is filler EOF check_verify_failure '"tagger" line label check #1' \ - '^error: char70: could not find "tagger "$' + '^error: char.*: could not find "tagger "$' ############################################################ # 12. tagger line label check #2 @@ -179,7 +180,7 @@ This is filler EOF check_verify_failure '"tagger" line label check #2' \ - '^error: char70: could not find "tagger "$' + '^error: char.*: could not find "tagger "$' ############################################################ # 13. disallow missing tag author name @@ -194,7 +195,7 @@ This is filler EOF check_verify_failure 'disallow missing tag author name' \ - '^error: char77: missing tagger name$' + '^error: char.*: missing tagger name$' ############################################################ # 14. disallow missing tag author name @@ -209,7 +210,7 @@ tagger T A Gger < EOF check_verify_failure 'disallow malformed tagger' \ - '^error: char77: malformed tagger field$' + '^error: char.*: malformed tagger field$' ############################################################ # 15. allow empty tag email @@ -238,7 +239,7 @@ tagger T A Gger <tag ger@example.com> 0 +0000 EOF check_verify_failure 'disallow spaces in tag email' \ - '^error: char77: malformed tagger field$' + '^error: char.*: malformed tagger field$' ############################################################ # 17. disallow missing tag timestamp @@ -252,7 +253,7 @@ tagger T A Gger <tagger@example.com>__ EOF check_verify_failure 'disallow missing tag timestamp' \ - '^error: char107: missing tag timestamp$' + '^error: char.*: missing tag timestamp$' ############################################################ # 18. detect invalid tag timestamp1 @@ -266,7 +267,7 @@ tagger T A Gger <tagger@example.com> Tue Mar 25 15:47:44 2008 EOF check_verify_failure 'detect invalid tag timestamp1' \ - '^error: char107: missing tag timestamp$' + '^error: char.*: missing tag timestamp$' ############################################################ # 19. detect invalid tag timestamp2 @@ -280,7 +281,7 @@ tagger T A Gger <tagger@example.com> 2008-03-31T12:20:15-0500 EOF check_verify_failure 'detect invalid tag timestamp2' \ - '^error: char111: malformed tag timestamp$' + '^error: char.*: malformed tag timestamp$' ############################################################ # 20. detect invalid tag timezone1 @@ -294,7 +295,7 @@ tagger T A Gger <tagger@example.com> 1206478233 GMT EOF check_verify_failure 'detect invalid tag timezone1' \ - '^error: char118: malformed tag timezone$' + '^error: char.*: malformed tag timezone$' ############################################################ # 21. detect invalid tag timezone2 @@ -308,7 +309,7 @@ tagger T A Gger <tagger@example.com> 1206478233 + 30 EOF check_verify_failure 'detect invalid tag timezone2' \ - '^error: char118: malformed tag timezone$' + '^error: char.*: malformed tag timezone$' ############################################################ # 22. detect invalid tag timezone3 @@ -322,7 +323,7 @@ tagger T A Gger <tagger@example.com> 1206478233 -1430 EOF check_verify_failure 'detect invalid tag timezone3' \ - '^error: char118: malformed tag timezone$' + '^error: char.*: malformed tag timezone$' ############################################################ # 23. detect invalid header entry @@ -337,7 +338,7 @@ this line should not be here EOF check_verify_failure 'detect invalid header entry' \ - '^error: char124: trailing garbage in tag header$' + '^error: char.*: trailing garbage in tag header$' ############################################################ # 24. create valid tag diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh index b92ff95977..d277a9f4b7 100755 --- a/t/t3900-i18n-commit.sh +++ b/t/t3900-i18n-commit.sh @@ -204,4 +204,41 @@ test_commit_autosquash_flags eucJP fixup test_commit_autosquash_flags ISO-2022-JP squash +test_commit_autosquash_multi_encoding () { + flag=$1 + old=$2 + new=$3 + msg=$4 + test_expect_success "commit --$flag into $old from $new" ' + git checkout -b $flag-$old-$new C0 && + git config i18n.commitencoding $old && + echo $old >>F && + git commit -a -F "$TEST_DIRECTORY"/t3900/$msg && + test_tick && + echo intermediate stuff >>G && + git add G && + git commit -a -m "intermediate commit" && + test_tick && + git config i18n.commitencoding $new && + echo $new-$flag >>F && + git commit -a --$flag HEAD^ && + git rebase --autosquash -i HEAD^^^ && + git rev-list HEAD >actual && + test_line_count = 3 actual && + iconv -f $old -t UTF-8 "$TEST_DIRECTORY"/t3900/$msg >expect && + if test $flag = squash; then + subject="$(head -1 expect)" && + printf "\nsquash! %s\n" "$subject" >>expect + fi && + git cat-file commit HEAD^ >raw && + (sed "1,/^$/d" raw | iconv -f $new -t utf-8) >actual && + test_cmp expect actual + ' +} + +test_commit_autosquash_multi_encoding fixup UTF-8 ISO-8859-1 1-UTF-8.txt +test_commit_autosquash_multi_encoding squash ISO-8859-1 UTF-8 ISO8859-1.txt +test_commit_autosquash_multi_encoding squash eucJP ISO-2022-JP eucJP.txt +test_commit_autosquash_multi_encoding fixup ISO-2022-JP UTF-8 ISO-2022-JP.txt + test_done diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh index b22e671608..ea56e85e70 100755 --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@ -7,6 +7,18 @@ test_description='Test git stash' . ./test-lib.sh +diff_cmp () { + for i in "$1" "$2" + do + sed -e 's/^index 0000000\.\.[0-9a-f]*/index 0000000..1234567/' \ + -e 's/^index [0-9a-f]*\.\.[0-9a-f]*/index 1234567..89abcde/' \ + -e 's/^index [0-9a-f]*,[0-9a-f]*\.\.[0-9a-f]*/index 1234567,7654321..89abcde/' \ + "$i" >"$i.compare" || return 1 + done && + test_cmp "$1.compare" "$2.compare" && + rm -f "$1.compare" "$2.compare" +} + test_expect_success 'stash some dirty working directory' ' echo 1 >file && git add file && @@ -36,7 +48,7 @@ EOF test_expect_success 'parents of stash' ' test $(git rev-parse stash^) = $(git rev-parse HEAD) && git diff stash^2..stash >output && - test_cmp expect output + diff_cmp expect output ' test_expect_success 'applying bogus stash does nothing' ' @@ -210,13 +222,13 @@ test_expect_success 'stash branch' ' test refs/heads/stashbranch = $(git symbolic-ref HEAD) && test $(git rev-parse HEAD) = $(git rev-parse master^) && git diff --cached >output && - test_cmp expect output && + diff_cmp expect output && git diff >output && - test_cmp expect1 output && + diff_cmp expect1 output && git add file && git commit -m alternate\ second && git diff master..stashbranch >output && - test_cmp output expect2 && + diff_cmp output expect2 && test 0 = $(git stash list | wc -l) ' @@ -232,8 +244,11 @@ test_expect_success 'save -q is quiet' ' test_must_be_empty output.out ' -test_expect_success 'pop -q is quiet' ' +test_expect_success 'pop -q works and is quiet' ' git stash pop -q >output.out 2>&1 && + echo bar >expect && + git show :file >actual && + test_cmp expect actual && test_must_be_empty output.out ' @@ -242,6 +257,8 @@ test_expect_success 'pop -q --index works and is quiet' ' git add file && git stash save --quiet && git stash pop -q --index >output.out 2>&1 && + git diff-files file2 >file2.diff && + test_must_be_empty file2.diff && test foo = "$(git show :file)" && test_must_be_empty output.out ' @@ -577,7 +594,7 @@ test_expect_success 'stash show -p - stashes on stack, stash-like argument' ' +bar EOF git stash show -p ${STASH_ID} >actual && - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'stash show - no stashes on stack, stash-like argument' ' @@ -609,7 +626,7 @@ test_expect_success 'stash show -p - no stashes on stack, stash-like argument' ' +foo EOF git stash show -p ${STASH_ID} >actual && - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'stash show --patience shows diff' ' @@ -627,7 +644,7 @@ test_expect_success 'stash show --patience shows diff' ' +foo EOF git stash show --patience ${STASH_ID} >actual && - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'drop: fail early if specified stash is not a stash ref' ' @@ -791,7 +808,7 @@ test_expect_success 'stash where working directory contains "HEAD" file' ' git diff-index --cached --quiet HEAD && test "$(git rev-parse stash^)" = "$(git rev-parse HEAD)" && git diff stash^..stash >output && - test_cmp expect output + diff_cmp expect output ' test_expect_success 'store called with invalid commit' ' @@ -847,7 +864,7 @@ test_expect_success 'stash list implies --first-parent -m' ' +working EOF git stash list --format=%gd -p >actual && - test_cmp expect actual + diff_cmp expect actual ' test_expect_success 'stash list --cc shows combined diff' ' @@ -864,7 +881,7 @@ test_expect_success 'stash list --cc shows combined diff' ' ++working EOF git stash list --format=%gd -p --cc >actual && - test_cmp expect actual + diff_cmp expect actual ' test_expect_success 'stash is not confused by partial renames' ' @@ -1234,4 +1251,38 @@ test_expect_success 'stash works when user.name and user.email are not set' ' ) ' +test_expect_success 'stash --keep-index with file deleted in index does not resurrect it on disk' ' + test_commit to-remove to-remove && + git rm to-remove && + git stash --keep-index && + test_path_is_missing to-remove +' + +test_expect_success 'stash apply should succeed with unmodified file' ' + echo base >file && + git add file && + git commit -m base && + + # now stash a modification + echo modified >file && + git stash && + + # make the file stat dirty + cp file other && + mv other file && + + git stash apply +' + +test_expect_success 'stash handles skip-worktree entries nicely' ' + test_commit A && + echo changed >A.t && + git add A.t && + git update-index --skip-worktree A.t && + rm A.t && + git stash && + + git rev-parse --verify refs/stash:A.t +' + test_done diff --git a/t/t3905-stash-include-untracked.sh b/t/t3905-stash-include-untracked.sh index 29ca76f2fb..f075c7f1f3 100755 --- a/t/t3905-stash-include-untracked.sh +++ b/t/t3905-stash-include-untracked.sh @@ -277,8 +277,8 @@ test_expect_success 'stash -u -- <ignored> leaves ignored file alone' ' test_path_is_file ignored.d/bar ' -test_expect_success 'stash -u -- <non-existant> shows no changes when there are none' ' - git stash push -u -- non-existant >actual && +test_expect_success 'stash -u -- <non-existent> shows no changes when there are none' ' + git stash push -u -- non-existent >actual && echo "No local changes to save" >expect && test_i18ncmp expect actual ' diff --git a/t/t3906-stash-submodule.sh b/t/t3906-stash-submodule.sh index d7219d6f8f..b93d1d74da 100755 --- a/t/t3906-stash-submodule.sh +++ b/t/t3906-stash-submodule.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='stash apply can handle submodules' +test_description='stash can handle submodules' . ./test-lib.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh @@ -21,4 +21,44 @@ KNOWN_FAILURE_CHERRY_PICK_SEES_EMPTY_COMMIT=1 KNOWN_FAILURE_NOFF_MERGE_DOESNT_CREATE_EMPTY_SUBMODULE_DIR=1 test_submodule_switch "git_stash" +setup_basic () { + test_when_finished "rm -rf main sub" && + git init sub && + ( + cd sub && + test_commit sub_file + ) && + git init main && + ( + cd main && + git submodule add ../sub && + test_commit main_file + ) +} + +test_expect_success 'stash push with submodule.recurse=true preserves dirty submodule worktree' ' + setup_basic && + ( + cd main && + git config submodule.recurse true && + echo "x" >main_file.t && + echo "y" >sub/sub_file.t && + git stash push && + test_must_fail git -C sub diff --quiet + ) +' + +test_expect_success 'stash push and pop with submodule.recurse=true preserves dirty submodule worktree' ' + setup_basic && + ( + cd main && + git config submodule.recurse true && + echo "x" >main_file.t && + echo "y" >sub/sub_file.t && + git stash push && + git stash pop && + test_must_fail git -C sub diff --quiet + ) +' + test_done diff --git a/t/t3908-stash-in-worktree.sh b/t/t3908-stash-in-worktree.sh new file mode 100755 index 0000000000..2b2b366ef9 --- /dev/null +++ b/t/t3908-stash-in-worktree.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# +# Copyright (c) 2019 Johannes E Schindelin +# + +test_description='Test git stash in a worktree' + +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit initial && + git worktree add wt && + test_commit -C wt in-worktree +' + +test_expect_success 'apply in subdirectory' ' + mkdir wt/subdir && + ( + cd wt/subdir && + echo modified >../initial.t && + git stash && + git stash apply >out + ) && + grep "\.\.\/initial\.t" wt/subdir/out +' + +test_done diff --git a/t/t4000-diff-format.sh b/t/t4000-diff-format.sh index 8de36b7d12..e5116a76a1 100755 --- a/t/t4000-diff-format.sh +++ b/t/t4000-diff-format.sh @@ -78,7 +78,7 @@ test_expect_success 'git diff-files --no-patch --patch shows the patch' ' test_expect_success 'git diff-files --no-patch --patch-with-raw shows the patch and raw data' ' git diff-files --no-patch --patch-with-raw >actual && - grep -q "^:100644 100755 .* 0000000000000000000000000000000000000000 M path0\$" actual && + grep -q "^:100644 100755 .* $ZERO_OID M path0\$" actual && tail -n +4 actual >actual-patch && compare_diff_patch expected actual-patch ' diff --git a/t/t4002-diff-basic.sh b/t/t4002-diff-basic.sh index 3a6c21e825..cbcdd10464 100755 --- a/t/t4002-diff-basic.sh +++ b/t/t4002-diff-basic.sh @@ -7,123 +7,272 @@ test_description='Test diff raw-output. ' . ./test-lib.sh + . "$TEST_DIRECTORY"/lib-read-tree-m-3way.sh -cat >.test-plain-OA <<\EOF -:000000 100644 0000000000000000000000000000000000000000 ccba72ad3888a3520b39efcf780b9ee64167535d A AA -:000000 100644 0000000000000000000000000000000000000000 7e426fb079479fd67f6d81f984e4ec649a44bc25 A AN -:100644 000000 bcc68ef997017466d5c9094bcf7692295f588c9a 0000000000000000000000000000000000000000 D DD -:000000 040000 0000000000000000000000000000000000000000 6d50f65d3bdab91c63444294d38f08aeff328e42 A DF -:100644 000000 141c1f1642328e4bc46a7d801a71da392e66791e 0000000000000000000000000000000000000000 D DM -:100644 000000 35abde1506ddf806572ff4d407bd06885d0f8ee9 0000000000000000000000000000000000000000 D DN -:000000 100644 0000000000000000000000000000000000000000 1d41122ebdd7a640f29d3c9cc4f9d70094374762 A LL -:100644 100644 03f24c8c4700babccfd28b654e7e8eac402ad6cd 103d9f89b50b9aad03054b579be5e7aa665f2d57 M MD -:100644 100644 b258508afb7ceb449981bd9d63d2d3e971bf8d34 b431b272d829ff3aa4d1a5085f4394ab4d3305b6 M MM -:100644 100644 bd084b0c27c7b6cc34f11d6d0509a29be3caf970 a716d58de4a570e0038f5c307bd8db34daea021f M MN -:100644 100644 40c959f984c8b89a2b02520d17f00d717f024397 2ac547ae9614a00d1b28275de608131f7a0e259f M SS -:100644 100644 4ac13458899ab908ef3b1128fa378daefc88d356 4c86f9a85fbc5e6804ee2e17a797538fbe785bca M TT -:040000 040000 7d670fdcdb9929f6c7dac196ff78689cd1c566a1 5e5f22072bb39f6e12cf663a57cb634c76eefb49 M Z +test_oid_init + +test_oid_cache <<\EOF +aa_1 sha1:ccba72ad3888a3520b39efcf780b9ee64167535d +aa_1 sha256:9febfbf18197819b2735c45291f138525d2476d59470f98239647544586ba403 + +aa_2 sha1:6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 +aa_2 sha256:6eaa3437de83f145a4aaa6ba355303075ade547b128ec6a2cd00a81ff7ce7a56 + +an_1 sha1:7e426fb079479fd67f6d81f984e4ec649a44bc25 +an_1 sha256:8f92a0bec99e399a38e3bd0e1bf19fbf121e0160efb29b857df79d439f1c4536 + +dd_1 sha1:bcc68ef997017466d5c9094bcf7692295f588c9a +dd_1 sha256:07e17428b00639b85485d2b01083d219e2f3e3ba8579e9ca44e9cc8dd554d952 + +df_1 sha1:6d50f65d3bdab91c63444294d38f08aeff328e42 +df_1 sha256:e367cecc27e9bf5451b1c65828cb21938d36a5f8e39c1b03ad6509cc36bb8e9d + +df_2 sha1:71420ab81e254145d26d6fc0cddee64c1acd4787 +df_2 sha256:0f0a86d10347ff6921d03a3c954679f3f1d14fa3d5cd82f57b32c09755f3a47d + +dfd1 sha1:68a6d8b91da11045cf4aa3a5ab9f2a781c701249 +dfd1 sha256:f3bd3265b02b6978ce86490d8ad026c573639c974b3de1d9faf30d8d5a77d3d5 + +dm_1 sha1:141c1f1642328e4bc46a7d801a71da392e66791e +dm_1 sha256:c89f8656e7b94e21ee5fbaf0e2149bbf783c51edbe2ce110349cac13059ee7ed + +dm_2 sha1:3c4d8de5fbad08572bab8e10eef8dbb264cf0231 +dm_2 sha256:83a572e37e0c94086294dae2cecc43d9131afd6f6c906e495c78972230b54988 + +dn_1 sha1:35abde1506ddf806572ff4d407bd06885d0f8ee9 +dn_1 sha256:775d5852582070e620be63327bfa515fab8f71c7ac3e4f0c3cd6267b4377ba28 + +ll_2 sha1:1d41122ebdd7a640f29d3c9cc4f9d70094374762 +ll_2 sha256:7917b4948a883cfed0a77d3d5a625dc8577d6ddcc3c6c3bbc56c4d4226a2246d + +md_1 sha1:03f24c8c4700babccfd28b654e7e8eac402ad6cd +md_1 sha256:fc9f30369b978595ad685ba11ca9a17de0af16d79cd4b629975f4f1590033902 + +md_2 sha1:103d9f89b50b9aad03054b579be5e7aa665f2d57 +md_2 sha256:fc78ec75275628762fe520479a6b2398dec295ce7aabcb1d15e5963c7b4e9317 + +mm_1 sha1:b258508afb7ceb449981bd9d63d2d3e971bf8d34 +mm_1 sha256:a4b7847d228e900e3000285e240c20fd96f9dd41ce1445305f6eada126d4a04a + +mm_2 sha1:b431b272d829ff3aa4d1a5085f4394ab4d3305b6 +mm_2 sha256:3f8b83ea36aacf689bcf1a1290a9a8ed341564d32682ea6f76fea9a979186782 + +mm_3 sha1:19989d4559aae417fedee240ccf2ba315ea4dc2b +mm_3 sha256:71b3bfc5747ac033fff9ea0ab39ee453a3af2969890e75d6ef547b87544e2681 + +mn_1 sha1:bd084b0c27c7b6cc34f11d6d0509a29be3caf970 +mn_1 sha256:47a67450583d7a329eb01a7c4ba644945af72c0ed2c7c95eb5a00d6e46d4d483 + +mn_2 sha1:a716d58de4a570e0038f5c307bd8db34daea021f +mn_2 sha256:f95104c1ebe27acb84bac25a7be98c71f6b8d3054b21f357a5be0c524ad97e08 + +nm_1 sha1:c8f25781e8f1792e3e40b74225e20553041b5226 +nm_1 sha256:09baddc7afaa62e62e152c23c9c3ab94bf15a3894031e227e9be7fe68e1f4e49 + +nm_2 sha1:cdb9a8c3da571502ac30225e9c17beccb8387983 +nm_2 sha256:58b5227956ac2d2a08d0efa513c0ae37430948b16791ea3869a1308dbf05536d + +na_1 sha1:15885881ea69115351c09b38371f0348a3fb8c67 +na_1 sha256:18e4fdd1670cd7968ee23d35bfd29e5418d56fb190c840094c1c57ceee0aad8f + +nd_1 sha1:a4e179e4291e5536a5e1c82e091052772d2c5a93 +nd_1 sha256:07dac9b01d00956ea0c65bd993d7de4864aeef2ed3cbb1255d9f1d949fcd6df6 + +ss_1 sha1:40c959f984c8b89a2b02520d17f00d717f024397 +ss_1 sha256:50fc1b5df74d9910db2f9270993484235f15b69b75b01bcfb53e059289d14af9 + +ss_2 sha1:2ac547ae9614a00d1b28275de608131f7a0e259f +ss_2 sha256:a90f02e6044f1497d13db587d22ab12f90150a7d1e084afcf96065fab35ae2bc + +tt_1 sha1:4ac13458899ab908ef3b1128fa378daefc88d356 +tt_1 sha256:c53113c7dd5060e86b5b251428bd058f6726f66273c6a24bff1c61a04f498dd3 + +tt_2 sha1:4c86f9a85fbc5e6804ee2e17a797538fbe785bca +tt_2 sha256:0775f2a296129a7cf2862b46bc0e88c14d593f2773a3e3fb1c5193db6f5a7e77 + +tt_3 sha1:c4e4a12231b9fa79a0053cb6077fcb21bb5b135a +tt_3 sha256:47860f93cdd211f96443e0560f21c57ab6c2f4b0ac27ff03651a352e53fe8484 + +z__1 sha1:7d670fdcdb9929f6c7dac196ff78689cd1c566a1 +z__1 sha256:44d0f37aff5e51cfcfdd1134c93a6419bcca7b9964f792ffcd5f9b4fcba1ee63 + +z__2 sha1:5e5f22072bb39f6e12cf663a57cb634c76eefb49 +z__2 sha256:d29de162113190fed104eb5f010820cef4e315f89b9326e8497f7219fb737894 + +z__3 sha1:1ba523955d5160681af65cb776411f574c1e8155 +z__3 sha256:07422d772b07794ab4369a5648e617719f89c2d2212cbeab05d97214b6471636 + +zaa1 sha1:8acb8e9750e3f644bf323fcf3d338849db106c77 +zaa1 sha256:e79b029282c8abec2d9f3f7faceaf2a1405e02d1f368e66450ae66cf5b68d1f4 + +zaa2 sha1:6c0b99286d0bce551ac4a7b3dff8b706edff3715 +zaa2 sha256:c82bd78c3e69ea1796e6b1a7a3ba45bb106c50e819296475b862123d3f5cc5a0 + +zan1 sha1:087494262084cefee7ed484d20c8dc0580791272 +zan1 sha256:4b159eb3804d05599023dd074f771d06d02870f4ab24a7165add8ac3d703b8d3 + +zdd1 sha1:879007efae624d2b1307214b24a956f0a8d686a8 +zdd1 sha256:eecfdd4d8092dd0363fb6d4548b54c6afc8982c3ed9b34e393f1d6a921d8eaa3 + +zdm1 sha1:9b541b2275c06e3a7b13f28badf5294e2ae63df4 +zdm1 sha256:ab136e88e19a843c4bf7713d2090d5a2186ba16a6a80dacc12eeddd256a8e556 + +zdm2 sha1:d77371d15817fcaa57eeec27f770c505ba974ec1 +zdm2 sha256:1c1a5f57363f46a15d95ce8527b3c2c158d88d16853b4acbf81bd20fd2c89a46 + +zdn1 sha1:beb5d38c55283d280685ea21a0e50cfcc0ca064a +zdn1 sha256:0f0eca66183617b0aa5ad74b256540329f841470922ca6760263c996d825eb18 + +zmd1 sha1:d41fda41b7ec4de46b43cb7ea42a45001ae393d5 +zmd1 sha256:1ed32d481852eddf31a0ce12652a0ad14bf5b7a842667b5dbb0b50f35bf1c80a + +zmd2 sha1:a79ac3be9377639e1c7d1edf1ae1b3a5f0ccd8a9 +zmd2 sha256:b238da211b404f8917df2d9c6f7030535e904b2186131007a3c292ec6902f933 + +zmm1 sha1:4ca22bae2527d3d9e1676498a0fba3b355bd1278 +zmm1 sha256:072b1d85b5f34fabc99dfa46008c5418df68302d3e317430006f49b32d244226 + +zmm2 sha1:61422ba9c2c873416061a88cd40a59a35b576474 +zmm2 sha256:81dd5d2b3c5cda16fef552256aed4e2ea0802a8450a08f308a92142112ff6dda + +zmm3 sha1:697aad7715a1e7306ca76290a3dd4208fbaeddfa +zmm3 sha256:8b10fab49e9be3414aa5e9a93d0e46f9569053440138a7c19a5eb5536d8e95bf + +zmn1 sha1:b16d7b25b869f2beb124efa53467d8a1550ad694 +zmn1 sha256:609e4f75d1295e844c826feeba213acb0b6cfc609adfe8ff705b19e3829ae3e9 + +zmn2 sha1:a5c544c21cfcb07eb80a4d89a5b7d1570002edfd +zmn2 sha256:d6d03edf2dc1a3b267a8205de5f41a2ff4b03def8c7ae02052b543fb09d589fc + +zna1 sha1:d12979c22fff69c59ca9409e7a8fe3ee25eaee80 +zna1 sha256:b37b80e789e8ea32aa323f004628f02013f632124b0282c7fe00a127d3c64c3c + +znd1 sha1:a18393c636b98e9bd7296b8b437ea4992b72440c +znd1 sha256:af92a22eee8c38410a0c9d2b5135a10aeb052cbc7cf675541ed9a67bfcaf7cf9 + +znm1 sha1:3fdbe17fd013303a2e981e1ca1c6cd6e72789087 +znm1 sha256:f75aeaa0c11e76918e381c105f0752932c6150e941fec565d24fa31098a13dc1 + +znm2 sha1:7e09d6a3a14bd630913e8c75693cea32157b606d +znm2 sha256:938d73cfbaa1c902a84fb5b3afd9736aa0590367fb9bd59c6c4d072ce70fcd6d +EOF + +cat >.test-plain-OA <<EOF +:000000 100644 $(test_oid zero) $(test_oid aa_1) A AA +:000000 100644 $(test_oid zero) $(test_oid an_1) A AN +:100644 000000 $(test_oid dd_1) $(test_oid zero) D DD +:000000 040000 $(test_oid zero) $(test_oid df_1) A DF +:100644 000000 $(test_oid dm_1) $(test_oid zero) D DM +:100644 000000 $(test_oid dn_1) $(test_oid zero) D DN +:000000 100644 $(test_oid zero) $(test_oid ll_2) A LL +:100644 100644 $(test_oid md_1) $(test_oid md_2) M MD +:100644 100644 $(test_oid mm_1) $(test_oid mm_2) M MM +:100644 100644 $(test_oid mn_1) $(test_oid mn_2) M MN +:100644 100644 $(test_oid ss_1) $(test_oid ss_2) M SS +:100644 100644 $(test_oid tt_1) $(test_oid tt_2) M TT +:040000 040000 $(test_oid z__1) $(test_oid z__2) M Z EOF -cat >.test-recursive-OA <<\EOF -:000000 100644 0000000000000000000000000000000000000000 ccba72ad3888a3520b39efcf780b9ee64167535d A AA -:000000 100644 0000000000000000000000000000000000000000 7e426fb079479fd67f6d81f984e4ec649a44bc25 A AN -:100644 000000 bcc68ef997017466d5c9094bcf7692295f588c9a 0000000000000000000000000000000000000000 D DD -:000000 100644 0000000000000000000000000000000000000000 68a6d8b91da11045cf4aa3a5ab9f2a781c701249 A DF/DF -:100644 000000 141c1f1642328e4bc46a7d801a71da392e66791e 0000000000000000000000000000000000000000 D DM -:100644 000000 35abde1506ddf806572ff4d407bd06885d0f8ee9 0000000000000000000000000000000000000000 D DN -:000000 100644 0000000000000000000000000000000000000000 1d41122ebdd7a640f29d3c9cc4f9d70094374762 A LL -:100644 100644 03f24c8c4700babccfd28b654e7e8eac402ad6cd 103d9f89b50b9aad03054b579be5e7aa665f2d57 M MD -:100644 100644 b258508afb7ceb449981bd9d63d2d3e971bf8d34 b431b272d829ff3aa4d1a5085f4394ab4d3305b6 M MM -:100644 100644 bd084b0c27c7b6cc34f11d6d0509a29be3caf970 a716d58de4a570e0038f5c307bd8db34daea021f M MN -:100644 100644 40c959f984c8b89a2b02520d17f00d717f024397 2ac547ae9614a00d1b28275de608131f7a0e259f M SS -:100644 100644 4ac13458899ab908ef3b1128fa378daefc88d356 4c86f9a85fbc5e6804ee2e17a797538fbe785bca M TT -:000000 100644 0000000000000000000000000000000000000000 8acb8e9750e3f644bf323fcf3d338849db106c77 A Z/AA -:000000 100644 0000000000000000000000000000000000000000 087494262084cefee7ed484d20c8dc0580791272 A Z/AN -:100644 000000 879007efae624d2b1307214b24a956f0a8d686a8 0000000000000000000000000000000000000000 D Z/DD -:100644 000000 9b541b2275c06e3a7b13f28badf5294e2ae63df4 0000000000000000000000000000000000000000 D Z/DM -:100644 000000 beb5d38c55283d280685ea21a0e50cfcc0ca064a 0000000000000000000000000000000000000000 D Z/DN -:100644 100644 d41fda41b7ec4de46b43cb7ea42a45001ae393d5 a79ac3be9377639e1c7d1edf1ae1b3a5f0ccd8a9 M Z/MD -:100644 100644 4ca22bae2527d3d9e1676498a0fba3b355bd1278 61422ba9c2c873416061a88cd40a59a35b576474 M Z/MM -:100644 100644 b16d7b25b869f2beb124efa53467d8a1550ad694 a5c544c21cfcb07eb80a4d89a5b7d1570002edfd M Z/MN +cat >.test-recursive-OA <<EOF +:000000 100644 $(test_oid zero) $(test_oid aa_1) A AA +:000000 100644 $(test_oid zero) $(test_oid an_1) A AN +:100644 000000 $(test_oid dd_1) $(test_oid zero) D DD +:000000 100644 $(test_oid zero) $(test_oid dfd1) A DF/DF +:100644 000000 $(test_oid dm_1) $(test_oid zero) D DM +:100644 000000 $(test_oid dn_1) $(test_oid zero) D DN +:000000 100644 $(test_oid zero) $(test_oid ll_2) A LL +:100644 100644 $(test_oid md_1) $(test_oid md_2) M MD +:100644 100644 $(test_oid mm_1) $(test_oid mm_2) M MM +:100644 100644 $(test_oid mn_1) $(test_oid mn_2) M MN +:100644 100644 $(test_oid ss_1) $(test_oid ss_2) M SS +:100644 100644 $(test_oid tt_1) $(test_oid tt_2) M TT +:000000 100644 $(test_oid zero) $(test_oid zaa1) A Z/AA +:000000 100644 $(test_oid zero) $(test_oid zan1) A Z/AN +:100644 000000 $(test_oid zdd1) $(test_oid zero) D Z/DD +:100644 000000 $(test_oid zdm1) $(test_oid zero) D Z/DM +:100644 000000 $(test_oid zdn1) $(test_oid zero) D Z/DN +:100644 100644 $(test_oid zmd1) $(test_oid zmd2) M Z/MD +:100644 100644 $(test_oid zmm1) $(test_oid zmm2) M Z/MM +:100644 100644 $(test_oid zmn1) $(test_oid zmn2) M Z/MN EOF -cat >.test-plain-OB <<\EOF -:000000 100644 0000000000000000000000000000000000000000 6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 A AA -:100644 000000 bcc68ef997017466d5c9094bcf7692295f588c9a 0000000000000000000000000000000000000000 D DD -:000000 100644 0000000000000000000000000000000000000000 71420ab81e254145d26d6fc0cddee64c1acd4787 A DF -:100644 100644 141c1f1642328e4bc46a7d801a71da392e66791e 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 M DM -:000000 100644 0000000000000000000000000000000000000000 1d41122ebdd7a640f29d3c9cc4f9d70094374762 A LL -:100644 000000 03f24c8c4700babccfd28b654e7e8eac402ad6cd 0000000000000000000000000000000000000000 D MD -:100644 100644 b258508afb7ceb449981bd9d63d2d3e971bf8d34 19989d4559aae417fedee240ccf2ba315ea4dc2b M MM -:000000 100644 0000000000000000000000000000000000000000 15885881ea69115351c09b38371f0348a3fb8c67 A NA -:100644 000000 a4e179e4291e5536a5e1c82e091052772d2c5a93 0000000000000000000000000000000000000000 D ND -:100644 100644 c8f25781e8f1792e3e40b74225e20553041b5226 cdb9a8c3da571502ac30225e9c17beccb8387983 M NM -:100644 100644 40c959f984c8b89a2b02520d17f00d717f024397 2ac547ae9614a00d1b28275de608131f7a0e259f M SS -:100644 100644 4ac13458899ab908ef3b1128fa378daefc88d356 c4e4a12231b9fa79a0053cb6077fcb21bb5b135a M TT -:040000 040000 7d670fdcdb9929f6c7dac196ff78689cd1c566a1 1ba523955d5160681af65cb776411f574c1e8155 M Z +cat >.test-plain-OB <<EOF +:000000 100644 $(test_oid zero) $(test_oid aa_2) A AA +:100644 000000 $(test_oid dd_1) $(test_oid zero) D DD +:000000 100644 $(test_oid zero) $(test_oid df_2) A DF +:100644 100644 $(test_oid dm_1) $(test_oid dm_2) M DM +:000000 100644 $(test_oid zero) $(test_oid ll_2) A LL +:100644 000000 $(test_oid md_1) $(test_oid zero) D MD +:100644 100644 $(test_oid mm_1) $(test_oid mm_3) M MM +:000000 100644 $(test_oid zero) $(test_oid na_1) A NA +:100644 000000 $(test_oid nd_1) $(test_oid zero) D ND +:100644 100644 $(test_oid nm_1) $(test_oid nm_2) M NM +:100644 100644 $(test_oid ss_1) $(test_oid ss_2) M SS +:100644 100644 $(test_oid tt_1) $(test_oid tt_3) M TT +:040000 040000 $(test_oid z__1) $(test_oid z__3) M Z EOF -cat >.test-recursive-OB <<\EOF -:000000 100644 0000000000000000000000000000000000000000 6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 A AA -:100644 000000 bcc68ef997017466d5c9094bcf7692295f588c9a 0000000000000000000000000000000000000000 D DD -:000000 100644 0000000000000000000000000000000000000000 71420ab81e254145d26d6fc0cddee64c1acd4787 A DF -:100644 100644 141c1f1642328e4bc46a7d801a71da392e66791e 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 M DM -:000000 100644 0000000000000000000000000000000000000000 1d41122ebdd7a640f29d3c9cc4f9d70094374762 A LL -:100644 000000 03f24c8c4700babccfd28b654e7e8eac402ad6cd 0000000000000000000000000000000000000000 D MD -:100644 100644 b258508afb7ceb449981bd9d63d2d3e971bf8d34 19989d4559aae417fedee240ccf2ba315ea4dc2b M MM -:000000 100644 0000000000000000000000000000000000000000 15885881ea69115351c09b38371f0348a3fb8c67 A NA -:100644 000000 a4e179e4291e5536a5e1c82e091052772d2c5a93 0000000000000000000000000000000000000000 D ND -:100644 100644 c8f25781e8f1792e3e40b74225e20553041b5226 cdb9a8c3da571502ac30225e9c17beccb8387983 M NM -:100644 100644 40c959f984c8b89a2b02520d17f00d717f024397 2ac547ae9614a00d1b28275de608131f7a0e259f M SS -:100644 100644 4ac13458899ab908ef3b1128fa378daefc88d356 c4e4a12231b9fa79a0053cb6077fcb21bb5b135a M TT -:000000 100644 0000000000000000000000000000000000000000 6c0b99286d0bce551ac4a7b3dff8b706edff3715 A Z/AA -:100644 000000 879007efae624d2b1307214b24a956f0a8d686a8 0000000000000000000000000000000000000000 D Z/DD -:100644 100644 9b541b2275c06e3a7b13f28badf5294e2ae63df4 d77371d15817fcaa57eeec27f770c505ba974ec1 M Z/DM -:100644 000000 d41fda41b7ec4de46b43cb7ea42a45001ae393d5 0000000000000000000000000000000000000000 D Z/MD -:100644 100644 4ca22bae2527d3d9e1676498a0fba3b355bd1278 697aad7715a1e7306ca76290a3dd4208fbaeddfa M Z/MM -:000000 100644 0000000000000000000000000000000000000000 d12979c22fff69c59ca9409e7a8fe3ee25eaee80 A Z/NA -:100644 000000 a18393c636b98e9bd7296b8b437ea4992b72440c 0000000000000000000000000000000000000000 D Z/ND -:100644 100644 3fdbe17fd013303a2e981e1ca1c6cd6e72789087 7e09d6a3a14bd630913e8c75693cea32157b606d M Z/NM +cat >.test-recursive-OB <<EOF +:000000 100644 $(test_oid zero) $(test_oid aa_2) A AA +:100644 000000 $(test_oid dd_1) $(test_oid zero) D DD +:000000 100644 $(test_oid zero) $(test_oid df_2) A DF +:100644 100644 $(test_oid dm_1) $(test_oid dm_2) M DM +:000000 100644 $(test_oid zero) $(test_oid ll_2) A LL +:100644 000000 $(test_oid md_1) $(test_oid zero) D MD +:100644 100644 $(test_oid mm_1) $(test_oid mm_3) M MM +:000000 100644 $(test_oid zero) $(test_oid na_1) A NA +:100644 000000 $(test_oid nd_1) $(test_oid zero) D ND +:100644 100644 $(test_oid nm_1) $(test_oid nm_2) M NM +:100644 100644 $(test_oid ss_1) $(test_oid ss_2) M SS +:100644 100644 $(test_oid tt_1) $(test_oid tt_3) M TT +:000000 100644 $(test_oid zero) $(test_oid zaa2) A Z/AA +:100644 000000 $(test_oid zdd1) $(test_oid zero) D Z/DD +:100644 100644 $(test_oid zdm1) $(test_oid zdm2) M Z/DM +:100644 000000 $(test_oid zmd1) $(test_oid zero) D Z/MD +:100644 100644 $(test_oid zmm1) $(test_oid zmm3) M Z/MM +:000000 100644 $(test_oid zero) $(test_oid zna1) A Z/NA +:100644 000000 $(test_oid znd1) $(test_oid zero) D Z/ND +:100644 100644 $(test_oid znm1) $(test_oid znm2) M Z/NM EOF -cat >.test-plain-AB <<\EOF -:100644 100644 ccba72ad3888a3520b39efcf780b9ee64167535d 6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 M AA -:100644 000000 7e426fb079479fd67f6d81f984e4ec649a44bc25 0000000000000000000000000000000000000000 D AN -:000000 100644 0000000000000000000000000000000000000000 71420ab81e254145d26d6fc0cddee64c1acd4787 A DF -:040000 000000 6d50f65d3bdab91c63444294d38f08aeff328e42 0000000000000000000000000000000000000000 D DF -:000000 100644 0000000000000000000000000000000000000000 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 A DM -:000000 100644 0000000000000000000000000000000000000000 35abde1506ddf806572ff4d407bd06885d0f8ee9 A DN -:100644 000000 103d9f89b50b9aad03054b579be5e7aa665f2d57 0000000000000000000000000000000000000000 D MD -:100644 100644 b431b272d829ff3aa4d1a5085f4394ab4d3305b6 19989d4559aae417fedee240ccf2ba315ea4dc2b M MM -:100644 100644 a716d58de4a570e0038f5c307bd8db34daea021f bd084b0c27c7b6cc34f11d6d0509a29be3caf970 M MN -:000000 100644 0000000000000000000000000000000000000000 15885881ea69115351c09b38371f0348a3fb8c67 A NA -:100644 000000 a4e179e4291e5536a5e1c82e091052772d2c5a93 0000000000000000000000000000000000000000 D ND -:100644 100644 c8f25781e8f1792e3e40b74225e20553041b5226 cdb9a8c3da571502ac30225e9c17beccb8387983 M NM -:100644 100644 4c86f9a85fbc5e6804ee2e17a797538fbe785bca c4e4a12231b9fa79a0053cb6077fcb21bb5b135a M TT -:040000 040000 5e5f22072bb39f6e12cf663a57cb634c76eefb49 1ba523955d5160681af65cb776411f574c1e8155 M Z +cat >.test-plain-AB <<EOF +:100644 100644 $(test_oid aa_1) $(test_oid aa_2) M AA +:100644 000000 $(test_oid an_1) $(test_oid zero) D AN +:000000 100644 $(test_oid zero) $(test_oid df_2) A DF +:040000 000000 $(test_oid df_1) $(test_oid zero) D DF +:000000 100644 $(test_oid zero) $(test_oid dm_2) A DM +:000000 100644 $(test_oid zero) $(test_oid dn_1) A DN +:100644 000000 $(test_oid md_2) $(test_oid zero) D MD +:100644 100644 $(test_oid mm_2) $(test_oid mm_3) M MM +:100644 100644 $(test_oid mn_2) $(test_oid mn_1) M MN +:000000 100644 $(test_oid zero) $(test_oid na_1) A NA +:100644 000000 $(test_oid nd_1) $(test_oid zero) D ND +:100644 100644 $(test_oid nm_1) $(test_oid nm_2) M NM +:100644 100644 $(test_oid tt_2) $(test_oid tt_3) M TT +:040000 040000 $(test_oid z__2) $(test_oid z__3) M Z EOF -cat >.test-recursive-AB <<\EOF -:100644 100644 ccba72ad3888a3520b39efcf780b9ee64167535d 6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 M AA -:100644 000000 7e426fb079479fd67f6d81f984e4ec649a44bc25 0000000000000000000000000000000000000000 D AN -:000000 100644 0000000000000000000000000000000000000000 71420ab81e254145d26d6fc0cddee64c1acd4787 A DF -:100644 000000 68a6d8b91da11045cf4aa3a5ab9f2a781c701249 0000000000000000000000000000000000000000 D DF/DF -:000000 100644 0000000000000000000000000000000000000000 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 A DM -:000000 100644 0000000000000000000000000000000000000000 35abde1506ddf806572ff4d407bd06885d0f8ee9 A DN -:100644 000000 103d9f89b50b9aad03054b579be5e7aa665f2d57 0000000000000000000000000000000000000000 D MD -:100644 100644 b431b272d829ff3aa4d1a5085f4394ab4d3305b6 19989d4559aae417fedee240ccf2ba315ea4dc2b M MM -:100644 100644 a716d58de4a570e0038f5c307bd8db34daea021f bd084b0c27c7b6cc34f11d6d0509a29be3caf970 M MN -:000000 100644 0000000000000000000000000000000000000000 15885881ea69115351c09b38371f0348a3fb8c67 A NA -:100644 000000 a4e179e4291e5536a5e1c82e091052772d2c5a93 0000000000000000000000000000000000000000 D ND -:100644 100644 c8f25781e8f1792e3e40b74225e20553041b5226 cdb9a8c3da571502ac30225e9c17beccb8387983 M NM -:100644 100644 4c86f9a85fbc5e6804ee2e17a797538fbe785bca c4e4a12231b9fa79a0053cb6077fcb21bb5b135a M TT -:100644 100644 8acb8e9750e3f644bf323fcf3d338849db106c77 6c0b99286d0bce551ac4a7b3dff8b706edff3715 M Z/AA -:100644 000000 087494262084cefee7ed484d20c8dc0580791272 0000000000000000000000000000000000000000 D Z/AN -:000000 100644 0000000000000000000000000000000000000000 d77371d15817fcaa57eeec27f770c505ba974ec1 A Z/DM -:000000 100644 0000000000000000000000000000000000000000 beb5d38c55283d280685ea21a0e50cfcc0ca064a A Z/DN -:100644 000000 a79ac3be9377639e1c7d1edf1ae1b3a5f0ccd8a9 0000000000000000000000000000000000000000 D Z/MD -:100644 100644 61422ba9c2c873416061a88cd40a59a35b576474 697aad7715a1e7306ca76290a3dd4208fbaeddfa M Z/MM -:100644 100644 a5c544c21cfcb07eb80a4d89a5b7d1570002edfd b16d7b25b869f2beb124efa53467d8a1550ad694 M Z/MN -:000000 100644 0000000000000000000000000000000000000000 d12979c22fff69c59ca9409e7a8fe3ee25eaee80 A Z/NA -:100644 000000 a18393c636b98e9bd7296b8b437ea4992b72440c 0000000000000000000000000000000000000000 D Z/ND -:100644 100644 3fdbe17fd013303a2e981e1ca1c6cd6e72789087 7e09d6a3a14bd630913e8c75693cea32157b606d M Z/NM +cat >.test-recursive-AB <<EOF +:100644 100644 $(test_oid aa_1) $(test_oid aa_2) M AA +:100644 000000 $(test_oid an_1) $(test_oid zero) D AN +:000000 100644 $(test_oid zero) $(test_oid df_2) A DF +:100644 000000 $(test_oid dfd1) $(test_oid zero) D DF/DF +:000000 100644 $(test_oid zero) $(test_oid dm_2) A DM +:000000 100644 $(test_oid zero) $(test_oid dn_1) A DN +:100644 000000 $(test_oid md_2) $(test_oid zero) D MD +:100644 100644 $(test_oid mm_2) $(test_oid mm_3) M MM +:100644 100644 $(test_oid mn_2) $(test_oid mn_1) M MN +:000000 100644 $(test_oid zero) $(test_oid na_1) A NA +:100644 000000 $(test_oid nd_1) $(test_oid zero) D ND +:100644 100644 $(test_oid nm_1) $(test_oid nm_2) M NM +:100644 100644 $(test_oid tt_2) $(test_oid tt_3) M TT +:100644 100644 $(test_oid zaa1) $(test_oid zaa2) M Z/AA +:100644 000000 $(test_oid zan1) $(test_oid zero) D Z/AN +:000000 100644 $(test_oid zero) $(test_oid zdm2) A Z/DM +:000000 100644 $(test_oid zero) $(test_oid zdn1) A Z/DN +:100644 000000 $(test_oid zmd2) $(test_oid zero) D Z/MD +:100644 100644 $(test_oid zmm2) $(test_oid zmm3) M Z/MM +:100644 100644 $(test_oid zmn2) $(test_oid zmn1) M Z/MN +:000000 100644 $(test_oid zero) $(test_oid zna1) A Z/NA +:100644 000000 $(test_oid znd1) $(test_oid zero) D Z/ND +:100644 100644 $(test_oid znm1) $(test_oid znm2) M Z/NM EOF cmp_diff_files_output () { diff --git a/t/t4009-diff-rename-4.sh b/t/t4009-diff-rename-4.sh index 3641fd84d6..b63bdf031f 100755 --- a/t/t4009-diff-rename-4.sh +++ b/t/t4009-diff-rename-4.sh @@ -14,6 +14,7 @@ test_expect_success \ 'cat "$TEST_DIRECTORY"/diff-lib/COPYING >COPYING && echo frotz >rezrov && git update-index --add COPYING rezrov && + orig=$(git hash-object COPYING) && tree=$(git write-tree) && echo $tree' @@ -22,6 +23,8 @@ test_expect_success \ 'sed -e 's/HOWEVER/However/' <COPYING >COPYING.1 && sed -e 's/GPL/G.P.L/g' <COPYING >COPYING.2 && rm -f COPYING && + c1=$(git hash-object COPYING.1) && + c2=$(git hash-object COPYING.2) && git update-index --add --remove COPYING COPYING.?' # tree has COPYING and rezrov. work tree has COPYING.1 and COPYING.2, @@ -31,11 +34,11 @@ test_expect_success \ git diff-index -z -C $tree >current -cat >expected <<\EOF -:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 +cat >expected <<EOF +:100644 100644 $orig $c1 C1234 COPYING COPYING.1 -:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 06c67961bbaed34a127f76d261f4c0bf73eda471 R1234 +:100644 100644 $orig $c2 R1234 COPYING COPYING.2 EOF @@ -57,10 +60,10 @@ test_expect_success \ # about rezrov. git diff-index -z -C $tree >current -cat >expected <<\EOF -:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 06c67961bbaed34a127f76d261f4c0bf73eda471 M +cat >expected <<EOF +:100644 100644 $orig $c2 M COPYING -:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 +:100644 100644 $orig $c1 C1234 COPYING COPYING.1 EOF @@ -82,8 +85,8 @@ test_expect_success \ git update-index --add --remove COPYING COPYING.1' git diff-index -z -C --find-copies-harder $tree >current -cat >expected <<\EOF -:100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0603b3238a076dc6c8022aedc6648fa523a17178 C1234 +cat >expected <<EOF +:100644 100644 $orig $c1 C1234 COPYING COPYING.1 EOF diff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh index 281f8fad0c..e5ca359edf 100755 --- a/t/t4010-diff-pathspec.sh +++ b/t/t4010-diff-pathspec.sh @@ -17,11 +17,15 @@ test_expect_success \ 'echo frotz >file0 && mkdir path1 && echo rezrov >path1/file1 && + before0=$(git hash-object file0) && + before1=$(git hash-object path1/file1) && git update-index --add file0 path1/file1 && tree=$(git write-tree) && echo "$tree" && echo nitfol >file0 && echo yomin >path1/file1 && + after0=$(git hash-object file0) && + after1=$(git hash-object path1/file1) && git update-index file0 path1/file1' cat >expected <<\EOF @@ -31,32 +35,32 @@ test_expect_success \ 'git diff-index --cached $tree -- path >current && compare_diff_raw current expected' -cat >expected <<\EOF -:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M path1/file1 +cat >expected <<EOF +:100644 100644 $before1 $after1 M path1/file1 EOF test_expect_success \ 'limit to path1 should show path1/file1' \ 'git diff-index --cached $tree -- path1 >current && compare_diff_raw current expected' -cat >expected <<\EOF -:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M path1/file1 +cat >expected <<EOF +:100644 100644 $before1 $after1 M path1/file1 EOF test_expect_success \ 'limit to path1/ should show path1/file1' \ 'git diff-index --cached $tree -- path1/ >current && compare_diff_raw current expected' -cat >expected <<\EOF -:100644 100644 766498d93a4b06057a8e49d23f4068f1170ff38f 0a41e115ab61be0328a19b29f18cdcb49338d516 M path1/file1 +cat >expected <<EOF +:100644 100644 $before1 $after1 M path1/file1 EOF test_expect_success \ '"*file1" should show path1/file1' \ 'git diff-index --cached $tree -- "*file1" >current && compare_diff_raw current expected' -cat >expected <<\EOF -:100644 100644 8e4020bb5a8d8c873b25de15933e75cc0fc275df dca6b92303befc93086aa025d90a5facd7eb2812 M file0 +cat >expected <<EOF +:100644 100644 $before0 $after0 M file0 EOF test_expect_success \ 'limit to file0 should show file0' \ diff --git a/t/t4011-diff-symlink.sh b/t/t4011-diff-symlink.sh index 5ae19b987d..717034bb50 100755 --- a/t/t4011-diff-symlink.sh +++ b/t/t4011-diff-symlink.sh @@ -9,11 +9,24 @@ test_description='Test diff of symlinks. . ./test-lib.sh . "$TEST_DIRECTORY"/diff-lib.sh +# Print the short OID of a symlink with the given name. +symlink_oid () { + local oid=$(printf "%s" "$1" | git hash-object --stdin) && + git rev-parse --short "$oid" +} + +# Print the short OID of the given file. +short_oid () { + local oid=$(git hash-object "$1") && + git rev-parse --short "$oid" +} + test_expect_success 'diff new symlink and file' ' - cat >expected <<-\EOF && + symlink=$(symlink_oid xyzzy) && + cat >expected <<-EOF && diff --git a/frotz b/frotz new file mode 120000 - index 0000000..7c465af + index 0000000..$symlink --- /dev/null +++ b/frotz @@ -0,0 +1 @@ @@ -21,7 +34,7 @@ test_expect_success 'diff new symlink and file' ' \ No newline at end of file diff --git a/nitfol b/nitfol new file mode 100644 - index 0000000..7c465af + index 0000000..$symlink --- /dev/null +++ b/nitfol @@ -0,0 +1 @@ @@ -46,10 +59,10 @@ test_expect_success 'diff unchanged symlink and file' ' ' test_expect_success 'diff removed symlink and file' ' - cat >expected <<-\EOF && + cat >expected <<-EOF && diff --git a/frotz b/frotz deleted file mode 120000 - index 7c465af..0000000 + index $symlink..0000000 --- a/frotz +++ /dev/null @@ -1 +0,0 @@ @@ -57,7 +70,7 @@ test_expect_success 'diff removed symlink and file' ' \ No newline at end of file diff --git a/nitfol b/nitfol deleted file mode 100644 - index 7c465af..0000000 + index $symlink..0000000 --- a/nitfol +++ /dev/null @@ -1 +0,0 @@ @@ -90,9 +103,10 @@ test_expect_success 'diff identical, but newly created symlink and file' ' ' test_expect_success 'diff different symlink and file' ' - cat >expected <<-\EOF && + new=$(symlink_oid yxyyz) && + cat >expected <<-EOF && diff --git a/frotz b/frotz - index 7c465af..df1db54 120000 + index $symlink..$new 120000 --- a/frotz +++ b/frotz @@ -1 +1 @@ @@ -101,7 +115,7 @@ test_expect_success 'diff different symlink and file' ' +yxyyz \ No newline at end of file diff --git a/nitfol b/nitfol - index 7c465af..df1db54 100644 + index $symlink..$new 100644 --- a/nitfol +++ b/nitfol @@ -1 +1 @@ @@ -137,14 +151,16 @@ test_expect_success SYMLINKS 'setup symlinks with attributes' ' ' test_expect_success SYMLINKS 'symlinks do not respect userdiff config by path' ' - cat >expect <<-\EOF && + file=$(short_oid file.bin) && + link=$(symlink_oid file.bin) && + cat >expect <<-EOF && diff --git a/file.bin b/file.bin new file mode 100644 - index 0000000..d95f3ad + index 0000000..$file Binary files /dev/null and b/file.bin differ diff --git a/link.bin b/link.bin new file mode 120000 - index 0000000..dce41ec + index 0000000..$link --- /dev/null +++ b/link.bin @@ -0,0 +1 @@ diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index a9054d2db1..5ac94b390d 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -7,9 +7,6 @@ test_description='Various diff formatting options' . ./test-lib.sh -LF=' -' - test_expect_success setup ' GIT_AUTHOR_DATE="2006-06-26 00:00:00 +0000" && diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index b6e2fdbc44..69267b16f0 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -9,7 +9,6 @@ test_description='various format-patch tests' . "$TEST_DIRECTORY"/lib-terminal.sh test_expect_success setup ' - for i in 1 2 3 4 5 6 7 8 9 10; do echo "$i"; done >file && cat file >elif && git add file elif && @@ -34,39 +33,54 @@ test_expect_success setup ' git commit -m "Side changes #3 with \\n backslash-n in it." && git checkout master && - git diff-tree -p C2 | git apply --index && + git diff-tree -p C2 >patch && + git apply --index <patch && test_tick && - git commit -m "Master accepts moral equivalent of #2" + git commit -m "Master accepts moral equivalent of #2" && -' + git checkout side && + git checkout -b patchid && + for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file2 && + for i in 1 2 3 A 4 B C 7 8 9 10 D E F 5 6; do echo "$i"; done >file3 && + for i in 8 9 10; do echo "$i"; done >file && + git add file file2 file3 && + test_tick && + git commit -m "patchid 1" && + for i in 4 A B 7 8 9 10; do echo "$i"; done >file2 && + for i in 8 9 10 5 6; do echo "$i"; done >file3 && + git add file2 file3 && + test_tick && + git commit -m "patchid 2" && + for i in 10 5 6; do echo "$i"; done >file && + git add file && + test_tick && + git commit -m "patchid 3" && -test_expect_success "format-patch --ignore-if-in-upstream" ' + git checkout master +' +test_expect_success 'format-patch --ignore-if-in-upstream' ' git format-patch --stdout master..side >patch0 && - cnt=$(grep "^From " patch0 | wc -l) && - test $cnt = 3 - + grep "^From " patch0 >from0 && + test_line_count = 3 from0 ' -test_expect_success "format-patch --ignore-if-in-upstream" ' - +test_expect_success 'format-patch --ignore-if-in-upstream' ' git format-patch --stdout \ --ignore-if-in-upstream master..side >patch1 && - cnt=$(grep "^From " patch1 | wc -l) && - test $cnt = 2 - + grep "^From " patch1 >from1 && + test_line_count = 2 from1 ' -test_expect_success "format-patch --ignore-if-in-upstream handles tags" ' +test_expect_success 'format-patch --ignore-if-in-upstream handles tags' ' git tag -a v1 -m tag side && git tag -a v2 -m tag master && git format-patch --stdout --ignore-if-in-upstream v2..v1 >patch1 && - cnt=$(grep "^From " patch1 | wc -l) && - test $cnt = 2 + grep "^From " patch1 >from1 && + test_line_count = 2 from1 ' test_expect_success "format-patch doesn't consider merge commits" ' - git checkout -b slave master && echo "Another line" >>file && test_tick && @@ -77,148 +91,138 @@ test_expect_success "format-patch doesn't consider merge commits" ' git checkout -b merger master && test_tick && git merge --no-ff slave && - cnt=$(git format-patch -3 --stdout | grep "^From " | wc -l) && - test $cnt = 3 + git format-patch -3 --stdout >patch && + grep "^From " patch >from && + test_line_count = 3 from ' -test_expect_success "format-patch result applies" ' - +test_expect_success 'format-patch result applies' ' git checkout -b rebuild-0 master && git am -3 patch0 && - cnt=$(git rev-list master.. | wc -l) && - test $cnt = 2 + git rev-list master.. >list && + test_line_count = 2 list ' -test_expect_success "format-patch --ignore-if-in-upstream result applies" ' - +test_expect_success 'format-patch --ignore-if-in-upstream result applies' ' git checkout -b rebuild-1 master && git am -3 patch1 && - cnt=$(git rev-list master.. | wc -l) && - test $cnt = 2 + git rev-list master.. >list && + test_line_count = 2 list ' test_expect_success 'commit did not screw up the log message' ' - - git cat-file commit side | grep "^Side .* with .* backslash-n" - + git cat-file commit side >actual && + grep "^Side .* with .* backslash-n" actual ' test_expect_success 'format-patch did not screw up the log message' ' - grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 && grep "^Subject: .*Side changes #3 with .* backslash-n" patch1 - ' test_expect_success 'replay did not screw up the log message' ' - - git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n" - + git cat-file commit rebuild-1 >actual && + grep "^Side .* with .* backslash-n" actual ' test_expect_success 'extra headers' ' - git config format.headers "To: R E Cipient <rcipient@example.com> " && git config --add format.headers "Cc: S E Cipient <scipient@example.com> " && - git format-patch --stdout master..side > patch2 && - sed -e "/^\$/q" patch2 > hdrs2 && + git format-patch --stdout master..side >patch2 && + sed -e "/^\$/q" patch2 >hdrs2 && grep "^To: R E Cipient <rcipient@example.com>\$" hdrs2 && grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs2 - ' test_expect_success 'extra headers without newlines' ' - git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" && git config --add format.headers "Cc: S E Cipient <scipient@example.com>" && git format-patch --stdout master..side >patch3 && - sed -e "/^\$/q" patch3 > hdrs3 && + sed -e "/^\$/q" patch3 >hdrs3 && grep "^To: R E Cipient <rcipient@example.com>\$" hdrs3 && grep "^Cc: S E Cipient <scipient@example.com>\$" hdrs3 - ' test_expect_success 'extra headers with multiple To:s' ' - git config --replace-all format.headers "To: R E Cipient <rcipient@example.com>" && git config --add format.headers "To: S E Cipient <scipient@example.com>" && - git format-patch --stdout master..side > patch4 && - sed -e "/^\$/q" patch4 > hdrs4 && + git format-patch --stdout master..side >patch4 && + sed -e "/^\$/q" patch4 >hdrs4 && grep "^To: R E Cipient <rcipient@example.com>,\$" hdrs4 && grep "^ *S E Cipient <scipient@example.com>\$" hdrs4 ' test_expect_success 'additional command line cc (ascii)' ' - git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" && - git format-patch --cc="S E Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 && - grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch5 && - grep "^ *S E Cipient <scipient@example.com>\$" patch5 + git format-patch --cc="S E Cipient <scipient@example.com>" --stdout master..side >patch5 && + sed -e "/^\$/q" patch5 >hdrs5 && + grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs5 && + grep "^ *S E Cipient <scipient@example.com>\$" hdrs5 ' test_expect_failure 'additional command line cc (rfc822)' ' - git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" && - git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch5 && - grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch5 && - grep "^ *\"S. E. Cipient\" <scipient@example.com>\$" patch5 + git format-patch --cc="S. E. Cipient <scipient@example.com>" --stdout master..side >patch5 && + sed -e "/^\$/q" patch5 >hdrs5 && + grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs5 && + grep "^ *\"S. E. Cipient\" <scipient@example.com>\$" hdrs5 ' test_expect_success 'command line headers' ' - git config --unset-all format.headers && - git format-patch --add-header="Cc: R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch6 && - grep "^Cc: R E Cipient <rcipient@example.com>\$" patch6 + git format-patch --add-header="Cc: R E Cipient <rcipient@example.com>" --stdout master..side >patch6 && + sed -e "/^\$/q" patch6 >hdrs6 && + grep "^Cc: R E Cipient <rcipient@example.com>\$" hdrs6 ' test_expect_success 'configuration headers and command line headers' ' - git config --replace-all format.headers "Cc: R E Cipient <rcipient@example.com>" && - git format-patch --add-header="Cc: S E Cipient <scipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch7 && - grep "^Cc: R E Cipient <rcipient@example.com>,\$" patch7 && - grep "^ *S E Cipient <scipient@example.com>\$" patch7 + git format-patch --add-header="Cc: S E Cipient <scipient@example.com>" --stdout master..side >patch7 && + sed -e "/^\$/q" patch7 >hdrs7 && + grep "^Cc: R E Cipient <rcipient@example.com>,\$" hdrs7 && + grep "^ *S E Cipient <scipient@example.com>\$" hdrs7 ' test_expect_success 'command line To: header (ascii)' ' - git config --unset-all format.headers && - git format-patch --to="R E Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 && - grep "^To: R E Cipient <rcipient@example.com>\$" patch8 + git format-patch --to="R E Cipient <rcipient@example.com>" --stdout master..side >patch8 && + sed -e "/^\$/q" patch8 >hdrs8 && + grep "^To: R E Cipient <rcipient@example.com>\$" hdrs8 ' test_expect_failure 'command line To: header (rfc822)' ' - - git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 && - grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch8 + git format-patch --to="R. E. Cipient <rcipient@example.com>" --stdout master..side >patch8 && + sed -e "/^\$/q" patch8 >hdrs8 && + grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" hdrs8 ' test_expect_failure 'command line To: header (rfc2047)' ' - - git format-patch --to="R Ä Cipient <rcipient@example.com>" --stdout master..side | sed -e "/^\$/q" >patch8 && - grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch8 + git format-patch --to="R Ä Cipient <rcipient@example.com>" --stdout master..side >patch8 && + sed -e "/^\$/q" patch8 >hdrs8 && + grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" hdrs8 ' test_expect_success 'configuration To: header (ascii)' ' - git config format.to "R E Cipient <rcipient@example.com>" && - git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 && - grep "^To: R E Cipient <rcipient@example.com>\$" patch9 + git format-patch --stdout master..side >patch9 && + sed -e "/^\$/q" patch9 >hdrs9 && + grep "^To: R E Cipient <rcipient@example.com>\$" hdrs9 ' test_expect_failure 'configuration To: header (rfc822)' ' - git config format.to "R. E. Cipient <rcipient@example.com>" && - git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 && - grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" patch9 + git format-patch --stdout master..side >patch9 && + sed -e "/^\$/q" patch9 >hdrs9 && + grep "^To: \"R. E. Cipient\" <rcipient@example.com>\$" hdrs9 ' test_expect_failure 'configuration To: header (rfc2047)' ' - git config format.to "R Ä Cipient <rcipient@example.com>" && - git format-patch --stdout master..side | sed -e "/^\$/q" >patch9 && - grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" patch9 + git format-patch --stdout master..side >patch9 && + sed -e "/^\$/q" patch9 >hdrs9 && + grep "^To: =?UTF-8?q?R=20=C3=84=20Cipient?= <rcipient@example.com>\$" hdrs9 ' # check_patch <patch>: Verify that <patch> looks like a half-sane @@ -230,89 +234,79 @@ check_patch () { } test_expect_success 'format.from=false' ' - - git -c format.from=false format-patch --stdout master..side | - sed -e "/^\$/q" >patch && + git -c format.from=false format-patch --stdout master..side >patch && + sed -e "/^\$/q" patch >hdrs && check_patch patch && - ! grep "^From: C O Mitter <committer@example.com>\$" patch + ! grep "^From: C O Mitter <committer@example.com>\$" hdrs ' test_expect_success 'format.from=true' ' - - git -c format.from=true format-patch --stdout master..side | - sed -e "/^\$/q" >patch && - check_patch patch && - grep "^From: C O Mitter <committer@example.com>\$" patch + git -c format.from=true format-patch --stdout master..side >patch && + sed -e "/^\$/q" patch >hdrs && + check_patch hdrs && + grep "^From: C O Mitter <committer@example.com>\$" hdrs ' test_expect_success 'format.from with address' ' - - git -c format.from="F R Om <from@example.com>" format-patch --stdout master..side | - sed -e "/^\$/q" >patch && - check_patch patch && - grep "^From: F R Om <from@example.com>\$" patch + git -c format.from="F R Om <from@example.com>" format-patch --stdout master..side >patch && + sed -e "/^\$/q" patch >hdrs && + check_patch hdrs && + grep "^From: F R Om <from@example.com>\$" hdrs ' test_expect_success '--no-from overrides format.from' ' - - git -c format.from="F R Om <from@example.com>" format-patch --no-from --stdout master..side | - sed -e "/^\$/q" >patch && - check_patch patch && - ! grep "^From: F R Om <from@example.com>\$" patch + git -c format.from="F R Om <from@example.com>" format-patch --no-from --stdout master..side >patch && + sed -e "/^\$/q" patch >hdrs && + check_patch hdrs && + ! grep "^From: F R Om <from@example.com>\$" hdrs ' test_expect_success '--from overrides format.from' ' - - git -c format.from="F R Om <from@example.com>" format-patch --from --stdout master..side | - sed -e "/^\$/q" >patch && - check_patch patch && - ! grep "^From: F R Om <from@example.com>\$" patch + git -c format.from="F R Om <from@example.com>" format-patch --from --stdout master..side >patch && + sed -e "/^\$/q" patch >hdrs && + check_patch hdrs && + ! grep "^From: F R Om <from@example.com>\$" hdrs ' test_expect_success '--no-to overrides config.to' ' - git config --replace-all format.to \ "R E Cipient <rcipient@example.com>" && - git format-patch --no-to --stdout master..side | - sed -e "/^\$/q" >patch10 && - check_patch patch10 && - ! grep "^To: R E Cipient <rcipient@example.com>\$" patch10 + git format-patch --no-to --stdout master..side >patch10 && + sed -e "/^\$/q" patch10 >hdrs10 && + check_patch hdrs10 && + ! grep "^To: R E Cipient <rcipient@example.com>\$" hdrs10 ' test_expect_success '--no-to and --to replaces config.to' ' - git config --replace-all format.to \ "Someone <someone@out.there>" && git format-patch --no-to --to="Someone Else <else@out.there>" \ - --stdout master..side | - sed -e "/^\$/q" >patch11 && - check_patch patch11 && - ! grep "^To: Someone <someone@out.there>\$" patch11 && - grep "^To: Someone Else <else@out.there>\$" patch11 + --stdout master..side >patch11 && + sed -e "/^\$/q" patch11 >hdrs11 && + check_patch hdrs11 && + ! grep "^To: Someone <someone@out.there>\$" hdrs11 && + grep "^To: Someone Else <else@out.there>\$" hdrs11 ' test_expect_success '--no-cc overrides config.cc' ' - git config --replace-all format.cc \ "C E Cipient <rcipient@example.com>" && - git format-patch --no-cc --stdout master..side | - sed -e "/^\$/q" >patch12 && - check_patch patch12 && - ! grep "^Cc: C E Cipient <rcipient@example.com>\$" patch12 + git format-patch --no-cc --stdout master..side >patch12 && + sed -e "/^\$/q" patch12 >hdrs12 && + check_patch hdrs12 && + ! grep "^Cc: C E Cipient <rcipient@example.com>\$" hdrs12 ' test_expect_success '--no-add-header overrides config.headers' ' - git config --replace-all format.headers \ "Header1: B E Cipient <rcipient@example.com>" && - git format-patch --no-add-header --stdout master..side | - sed -e "/^\$/q" >patch13 && - check_patch patch13 && - ! grep "^Header1: B E Cipient <rcipient@example.com>\$" patch13 + git format-patch --no-add-header --stdout master..side >patch13 && + sed -e "/^\$/q" patch13 >hdrs13 && + check_patch hdrs13 && + ! grep "^Header1: B E Cipient <rcipient@example.com>\$" hdrs13 ' test_expect_success 'multiple files' ' - rm -rf patches/ && git checkout side && git format-patch -o patches/ master && @@ -338,7 +332,7 @@ test_expect_success 'reroll count (-v)' ' check_threading () { expect="$1" && shift && - (git format-patch --stdout "$@"; echo $? > status.out) | + git format-patch --stdout "$@" >patch && # Prints everything between the Message-ID and In-Reply-To, # and replaces all Message-ID-lookalikes by a sequence number perl -ne ' @@ -353,12 +347,11 @@ check_threading () { print; } print "---\n" if /^From /i; - ' > actual && - test 0 = "$(cat status.out)" && + ' <patch >actual && test_cmp "$expect" actual } -cat >> expect.no-threading <<EOF +cat >>expect.no-threading <<EOF --- --- --- @@ -369,7 +362,7 @@ test_expect_success 'no threading' ' check_threading expect.no-threading master ' -cat > expect.thread <<EOF +cat >expect.thread <<EOF --- Message-Id: <0> --- @@ -386,7 +379,7 @@ test_expect_success 'thread' ' check_threading expect.thread --thread master ' -cat > expect.in-reply-to <<EOF +cat >expect.in-reply-to <<EOF --- Message-Id: <0> In-Reply-To: <1> @@ -406,7 +399,7 @@ test_expect_success 'thread in-reply-to' ' --thread master ' -cat > expect.cover-letter <<EOF +cat >expect.cover-letter <<EOF --- Message-Id: <0> --- @@ -427,7 +420,7 @@ test_expect_success 'thread cover-letter' ' check_threading expect.cover-letter --cover-letter --thread master ' -cat > expect.cl-irt <<EOF +cat >expect.cl-irt <<EOF --- Message-Id: <0> In-Reply-To: <1> @@ -459,7 +452,7 @@ test_expect_success 'thread explicit shallow' ' --in-reply-to="<test.message>" --thread=shallow master ' -cat > expect.deep <<EOF +cat >expect.deep <<EOF --- Message-Id: <0> --- @@ -477,7 +470,7 @@ test_expect_success 'thread deep' ' check_threading expect.deep --thread=deep master ' -cat > expect.deep-irt <<EOF +cat >expect.deep-irt <<EOF --- Message-Id: <0> In-Reply-To: <1> @@ -500,7 +493,7 @@ test_expect_success 'thread deep in-reply-to' ' --in-reply-to="<test.message>" master ' -cat > expect.deep-cl <<EOF +cat >expect.deep-cl <<EOF --- Message-Id: <0> --- @@ -524,7 +517,7 @@ test_expect_success 'thread deep cover-letter' ' check_threading expect.deep-cl --cover-letter --thread=deep master ' -cat > expect.deep-cl-irt <<EOF +cat >expect.deep-cl-irt <<EOF --- Message-Id: <0> In-Reply-To: <1> @@ -575,7 +568,6 @@ test_expect_success 'thread config + --no-thread' ' ' test_expect_success 'excessive subject' ' - rm -rf patches/ && git checkout side && before=$(git hash-object file) && @@ -603,10 +595,9 @@ test_expect_success 'cover-letter inherits diff options' ' ! grep "file => foo .* 0 *\$" 0000-cover-letter.patch && git format-patch --cover-letter -1 -M && grep "file => foo .* 0 *\$" 0000-cover-letter.patch - ' -cat > expect << EOF +cat >expect <<EOF This is an excessively long subject line for a message due to the habit some projects have of not having a short, one-line subject at the start of the commit message, but rather sticking a whole @@ -617,14 +608,12 @@ cat > expect << EOF EOF test_expect_success 'shortlog of cover-letter wraps overly-long onelines' ' - git format-patch --cover-letter -2 && - sed -e "1,/A U Thor/d" -e "/^\$/q" < 0000-cover-letter.patch > output && + sed -e "1,/A U Thor/d" -e "/^\$/q" 0000-cover-letter.patch >output && test_cmp expect output - ' -cat > expect << EOF +cat >expect <<EOF index $before..$after 100644 --- a/file +++ b/file @@ -637,16 +626,14 @@ index $before..$after 100644 EOF test_expect_success 'format-patch respects -U' ' - git format-patch -U4 -2 && sed -e "1,/^diff/d" -e "/^+5/q" \ <0001-This-is-an-excessively-long-subject-line-for-a-messa.patch \ >output && test_cmp expect output - ' -cat > expect << EOF +cat >expect <<EOF diff --git a/file b/file index $before..$after 100644 @@ -660,11 +647,9 @@ index $before..$after 100644 EOF test_expect_success 'format-patch -p suppresses stat' ' - git format-patch -p -2 && - sed -e "1,/^\$/d" -e "/^+5/q" < 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch > output && + sed -e "1,/^\$/d" -e "/^+5/q" 0001-This-is-an-excessively-long-subject-line-for-a-messa.patch >output && test_cmp expect output - ' test_expect_success 'format-patch from a subdirectory (1)' ' @@ -717,7 +702,7 @@ test_expect_success 'format-patch from a subdirectory (3)' ' ' test_expect_success 'format-patch --in-reply-to' ' - git format-patch -1 --stdout --in-reply-to "baz@foo.bar" > patch8 && + git format-patch -1 --stdout --in-reply-to "baz@foo.bar" >patch8 && grep "^In-Reply-To: <baz@foo.bar>" patch8 && grep "^References: <baz@foo.bar>" patch8 ' @@ -738,21 +723,94 @@ test_expect_success 'format-patch --notes --signoff' ' sed "1,/^---$/d" out | grep "test message" ' -echo "fatal: --name-only does not make sense" > expect.name-only -echo "fatal: --name-status does not make sense" > expect.name-status -echo "fatal: --check does not make sense" > expect.check +test_expect_success 'format-patch notes output control' ' + git notes add -m "notes config message" HEAD && + test_when_finished git notes remove HEAD && + + git format-patch -1 --stdout >out && + ! grep "notes config message" out && + git format-patch -1 --stdout --notes >out && + grep "notes config message" out && + git format-patch -1 --stdout --no-notes >out && + ! grep "notes config message" out && + git format-patch -1 --stdout --notes --no-notes >out && + ! grep "notes config message" out && + git format-patch -1 --stdout --no-notes --notes >out && + grep "notes config message" out && + + test_config format.notes true && + git format-patch -1 --stdout >out && + grep "notes config message" out && + git format-patch -1 --stdout --notes >out && + grep "notes config message" out && + git format-patch -1 --stdout --no-notes >out && + ! grep "notes config message" out && + git format-patch -1 --stdout --notes --no-notes >out && + ! grep "notes config message" out && + git format-patch -1 --stdout --no-notes --notes >out && + grep "notes config message" out +' + +test_expect_success 'format-patch with multiple notes refs' ' + git notes --ref note1 add -m "this is note 1" HEAD && + test_when_finished git notes --ref note1 remove HEAD && + git notes --ref note2 add -m "this is note 2" HEAD && + test_when_finished git notes --ref note2 remove HEAD && + + git format-patch -1 --stdout >out && + ! grep "this is note 1" out && + ! grep "this is note 2" out && + git format-patch -1 --stdout --notes=note1 >out && + grep "this is note 1" out && + ! grep "this is note 2" out && + git format-patch -1 --stdout --notes=note2 >out && + ! grep "this is note 1" out && + grep "this is note 2" out && + git format-patch -1 --stdout --notes=note1 --notes=note2 >out && + grep "this is note 1" out && + grep "this is note 2" out && + + test_config format.notes note1 && + git format-patch -1 --stdout >out && + grep "this is note 1" out && + ! grep "this is note 2" out && + git format-patch -1 --stdout --no-notes >out && + ! grep "this is note 1" out && + ! grep "this is note 2" out && + git format-patch -1 --stdout --notes=note2 >out && + grep "this is note 1" out && + grep "this is note 2" out && + git format-patch -1 --stdout --no-notes --notes=note2 >out && + ! grep "this is note 1" out && + grep "this is note 2" out && + + git config --add format.notes note2 && + git format-patch -1 --stdout >out && + grep "this is note 1" out && + grep "this is note 2" out && + git format-patch -1 --stdout --no-notes >out && + ! grep "this is note 1" out && + ! grep "this is note 2" out +' + +echo "fatal: --name-only does not make sense" >expect.name-only +echo "fatal: --name-status does not make sense" >expect.name-status +echo "fatal: --check does not make sense" >expect.check test_expect_success 'options no longer allowed for format-patch' ' - test_must_fail git format-patch --name-only 2> output && + test_must_fail git format-patch --name-only 2>output && test_i18ncmp expect.name-only output && - test_must_fail git format-patch --name-status 2> output && + test_must_fail git format-patch --name-status 2>output && test_i18ncmp expect.name-status output && - test_must_fail git format-patch --check 2> output && - test_i18ncmp expect.check output' + test_must_fail git format-patch --check 2>output && + test_i18ncmp expect.check output +' test_expect_success 'format-patch --numstat should produce a patch' ' - git format-patch --numstat --stdout master..side > output && - test 5 = $(grep "^diff --git a/" output | wc -l)' + git format-patch --numstat --stdout master..side >output && + grep "^diff --git a/" output >diff && + test_line_count = 5 diff +' test_expect_success 'format-patch -- <path>' ' git format-patch master..side -- file 2>error && @@ -763,20 +821,25 @@ test_expect_success 'format-patch --ignore-if-in-upstream HEAD' ' git format-patch --ignore-if-in-upstream HEAD ' -git_version="$(git --version | sed "s/.* //")" +test_expect_success 'get git version' ' + git_version=$(git --version) && + git_version=${git_version##* } +' signature() { printf "%s\n%s\n\n" "-- " "${1:-$git_version}" } test_expect_success 'format-patch default signature' ' - git format-patch --stdout -1 | tail -n 3 >output && + git format-patch --stdout -1 >patch && + tail -n 3 patch >output && signature >expect && test_cmp expect output ' test_expect_success 'format-patch --signature' ' - git format-patch --stdout --signature="my sig" -1 | tail -n 3 >output && + git format-patch --stdout --signature="my sig" -1 >patch && + tail -n 3 patch >output && signature "my sig" >expect && test_cmp expect output ' @@ -808,8 +871,8 @@ test_expect_success 'format-patch --signature --cover-letter' ' git config --unset-all format.signature && git format-patch --stdout --signature="my sig" --cover-letter \ -1 >output && - grep "my sig" output && - test 2 = $(grep "my sig" output | wc -l) + grep "my sig" output >sig && + test_line_count = 2 sig ' test_expect_success 'format.signature="" suppresses signatures' ' @@ -846,7 +909,7 @@ test_expect_success 'prepare mail-signature input' ' test_expect_success '--signature-file=file works' ' git format-patch --stdout --signature-file=mail-signature -1 >output && check_patch output && - sed -e "1,/^-- \$/d" <output >actual && + sed -e "1,/^-- \$/d" output >actual && { cat mail-signature && echo } >expect && @@ -857,7 +920,7 @@ test_expect_success 'format.signaturefile works' ' test_config format.signaturefile mail-signature && git format-patch --stdout -1 >output && check_patch output && - sed -e "1,/^-- \$/d" <output >actual && + sed -e "1,/^-- \$/d" output >actual && { cat mail-signature && echo } >expect && @@ -879,7 +942,7 @@ test_expect_success '--signature-file overrides format.signaturefile' ' git format-patch --stdout \ --signature-file=other-mail-signature -1 >output && check_patch output && - sed -e "1,/^-- \$/d" <output >actual && + sed -e "1,/^-- \$/d" output >actual && { cat other-mail-signature && echo } >expect && @@ -948,7 +1011,7 @@ test_expect_success 'format-patch wraps extremely long subject (ascii)' ' git add file && git commit -m "$M512" && git format-patch --stdout -1 >patch && - sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject && + sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject && test_cmp expect subject ' @@ -987,7 +1050,7 @@ test_expect_success 'format-patch wraps extremely long subject (rfc2047)' ' git add file && git commit -m "$M512" && git format-patch --stdout -1 >patch && - sed -n "/^Subject/p; /^ /p; /^$/q" <patch >subject && + sed -n "/^Subject/p; /^ /p; /^$/q" patch >subject && test_cmp expect subject ' @@ -996,7 +1059,7 @@ check_author() { git add file && GIT_AUTHOR_NAME=$1 git commit -m author-check && git format-patch --stdout -1 >patch && - sed -n "/^From: /p; /^ /p; /^$/q" <patch >actual && + sed -n "/^From: /p; /^ /p; /^$/q" patch >actual && test_cmp expect actual } @@ -1116,7 +1179,7 @@ test_expect_success '--from=ident replaces author' ' From: A U Thor <author@example.com> EOF - sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head && + sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head && test_cmp expect patch.head ' @@ -1128,7 +1191,7 @@ test_expect_success '--from uses committer ident' ' From: A U Thor <author@example.com> EOF - sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head && + sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head && test_cmp expect patch.head ' @@ -1138,7 +1201,7 @@ test_expect_success '--from omits redundant in-body header' ' From: A U Thor <author@example.com> EOF - sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head && + sed -ne "/^From:/p; /^$/p; /^---$/q" patch >patch.head && test_cmp expect patch.head ' @@ -1153,7 +1216,7 @@ test_expect_success 'in-body headers trigger content encoding' ' From: éxötìc <author@example.com> EOF - sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" <patch >patch.head && + sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" patch >patch.head && test_cmp expect patch.head ' @@ -1167,283 +1230,283 @@ append_signoff() test_expect_success 'signoff: commit with no body' ' append_signoff </dev/null >actual && - cat <<\EOF | sed "s/EOL$//" >expected && -4:Subject: [PATCH] EOL -8: -9:Signed-off-by: C O Mitter <committer@example.com> -EOF - test_cmp expected actual + cat <<-\EOF | sed "s/EOL$//" >expect && + 4:Subject: [PATCH] EOL + 8: + 9:Signed-off-by: C O Mitter <committer@example.com> + EOF + test_cmp expect actual ' test_expect_success 'signoff: commit with only subject' ' echo subject | append_signoff >actual && - cat >expected <<\EOF && -4:Subject: [PATCH] subject -8: -9:Signed-off-by: C O Mitter <committer@example.com> -EOF - test_cmp expected actual + cat >expect <<-\EOF && + 4:Subject: [PATCH] subject + 8: + 9:Signed-off-by: C O Mitter <committer@example.com> + EOF + test_cmp expect actual ' test_expect_success 'signoff: commit with only subject that does not end with NL' ' printf subject | append_signoff >actual && - cat >expected <<\EOF && -4:Subject: [PATCH] subject -8: -9:Signed-off-by: C O Mitter <committer@example.com> -EOF - test_cmp expected actual + cat >expect <<-\EOF && + 4:Subject: [PATCH] subject + 8: + 9:Signed-off-by: C O Mitter <committer@example.com> + EOF + test_cmp expect actual ' test_expect_success 'signoff: no existing signoffs' ' - append_signoff <<\EOF >actual && -subject + append_signoff <<-\EOF >actual && + subject -body -EOF - cat >expected <<\EOF && -4:Subject: [PATCH] subject -8: -10: -11:Signed-off-by: C O Mitter <committer@example.com> -EOF - test_cmp expected actual + body + EOF + cat >expect <<-\EOF && + 4:Subject: [PATCH] subject + 8: + 10: + 11:Signed-off-by: C O Mitter <committer@example.com> + EOF + test_cmp expect actual ' test_expect_success 'signoff: no existing signoffs and no trailing NL' ' printf "subject\n\nbody" | append_signoff >actual && - cat >expected <<\EOF && -4:Subject: [PATCH] subject -8: -10: -11:Signed-off-by: C O Mitter <committer@example.com> -EOF - test_cmp expected actual + cat >expect <<-\EOF && + 4:Subject: [PATCH] subject + 8: + 10: + 11:Signed-off-by: C O Mitter <committer@example.com> + EOF + test_cmp expect actual ' test_expect_success 'signoff: some random signoff' ' - append_signoff <<\EOF >actual && -subject + append_signoff <<-\EOF >actual && + subject -body + body -Signed-off-by: my@house -EOF - cat >expected <<\EOF && -4:Subject: [PATCH] subject -8: -10: -11:Signed-off-by: my@house -12:Signed-off-by: C O Mitter <committer@example.com> -EOF - test_cmp expected actual + Signed-off-by: my@house + EOF + cat >expect <<-\EOF && + 4:Subject: [PATCH] subject + 8: + 10: + 11:Signed-off-by: my@house + 12:Signed-off-by: C O Mitter <committer@example.com> + EOF + test_cmp expect actual ' test_expect_success 'signoff: misc conforming footer elements' ' - append_signoff <<\EOF >actual && -subject + append_signoff <<-\EOF >actual && + subject -body + body -Signed-off-by: my@house -(cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709) -Tested-by: Some One <someone@example.com> -Bug: 1234 -EOF - cat >expected <<\EOF && -4:Subject: [PATCH] subject -8: -10: -11:Signed-off-by: my@house -15:Signed-off-by: C O Mitter <committer@example.com> -EOF - test_cmp expected actual + Signed-off-by: my@house + (cherry picked from commit da39a3ee5e6b4b0d3255bfef95601890afd80709) + Tested-by: Some One <someone@example.com> + Bug: 1234 + EOF + cat >expect <<-\EOF && + 4:Subject: [PATCH] subject + 8: + 10: + 11:Signed-off-by: my@house + 15:Signed-off-by: C O Mitter <committer@example.com> + EOF + test_cmp expect actual ' test_expect_success 'signoff: some random signoff-alike' ' - append_signoff <<\EOF >actual && -subject + append_signoff <<-\EOF >actual && + subject -body -Fooled-by-me: my@house -EOF - cat >expected <<\EOF && -4:Subject: [PATCH] subject -8: -11: -12:Signed-off-by: C O Mitter <committer@example.com> -EOF - test_cmp expected actual + body + Fooled-by-me: my@house + EOF + cat >expect <<-\EOF && + 4:Subject: [PATCH] subject + 8: + 11: + 12:Signed-off-by: C O Mitter <committer@example.com> + EOF + test_cmp expect actual ' test_expect_success 'signoff: not really a signoff' ' - append_signoff <<\EOF >actual && -subject + append_signoff <<-\EOF >actual && + subject -I want to mention about Signed-off-by: here. -EOF - cat >expected <<\EOF && -4:Subject: [PATCH] subject -8: -9:I want to mention about Signed-off-by: here. -10: -11:Signed-off-by: C O Mitter <committer@example.com> -EOF - test_cmp expected actual + I want to mention about Signed-off-by: here. + EOF + cat >expect <<-\EOF && + 4:Subject: [PATCH] subject + 8: + 9:I want to mention about Signed-off-by: here. + 10: + 11:Signed-off-by: C O Mitter <committer@example.com> + EOF + test_cmp expect actual ' test_expect_success 'signoff: not really a signoff (2)' ' - append_signoff <<\EOF >actual && -subject + append_signoff <<-\EOF >actual && + subject -My unfortunate -Signed-off-by: example happens to be wrapped here. -EOF - cat >expected <<\EOF && -4:Subject: [PATCH] subject -8: -10:Signed-off-by: example happens to be wrapped here. -11:Signed-off-by: C O Mitter <committer@example.com> -EOF - test_cmp expected actual + My unfortunate + Signed-off-by: example happens to be wrapped here. + EOF + cat >expect <<-\EOF && + 4:Subject: [PATCH] subject + 8: + 10:Signed-off-by: example happens to be wrapped here. + 11:Signed-off-by: C O Mitter <committer@example.com> + EOF + test_cmp expect actual ' test_expect_success 'signoff: valid S-o-b paragraph in the middle' ' - append_signoff <<\EOF >actual && -subject + append_signoff <<-\EOF >actual && + subject -Signed-off-by: my@house -Signed-off-by: your@house + Signed-off-by: my@house + Signed-off-by: your@house -A lot of houses. -EOF - cat >expected <<\EOF && -4:Subject: [PATCH] subject -8: -9:Signed-off-by: my@house -10:Signed-off-by: your@house -11: -13: -14:Signed-off-by: C O Mitter <committer@example.com> -EOF - test_cmp expected actual + A lot of houses. + EOF + cat >expect <<-\EOF && + 4:Subject: [PATCH] subject + 8: + 9:Signed-off-by: my@house + 10:Signed-off-by: your@house + 11: + 13: + 14:Signed-off-by: C O Mitter <committer@example.com> + EOF + test_cmp expect actual ' test_expect_success 'signoff: the same signoff at the end' ' - append_signoff <<\EOF >actual && -subject + append_signoff <<-\EOF >actual && + subject -body + body -Signed-off-by: C O Mitter <committer@example.com> -EOF - cat >expected <<\EOF && -4:Subject: [PATCH] subject -8: -10: -11:Signed-off-by: C O Mitter <committer@example.com> -EOF - test_cmp expected actual + Signed-off-by: C O Mitter <committer@example.com> + EOF + cat >expect <<-\EOF && + 4:Subject: [PATCH] subject + 8: + 10: + 11:Signed-off-by: C O Mitter <committer@example.com> + EOF + test_cmp expect actual ' test_expect_success 'signoff: the same signoff at the end, no trailing NL' ' printf "subject\n\nSigned-off-by: C O Mitter <committer@example.com>" | append_signoff >actual && - cat >expected <<\EOF && -4:Subject: [PATCH] subject -8: -9:Signed-off-by: C O Mitter <committer@example.com> -EOF - test_cmp expected actual + cat >expect <<-\EOF && + 4:Subject: [PATCH] subject + 8: + 9:Signed-off-by: C O Mitter <committer@example.com> + EOF + test_cmp expect actual ' test_expect_success 'signoff: the same signoff NOT at the end' ' - append_signoff <<\EOF >actual && -subject + append_signoff <<-\EOF >actual && + subject -body + body -Signed-off-by: C O Mitter <committer@example.com> -Signed-off-by: my@house -EOF - cat >expected <<\EOF && -4:Subject: [PATCH] subject -8: -10: -11:Signed-off-by: C O Mitter <committer@example.com> -12:Signed-off-by: my@house -EOF - test_cmp expected actual + Signed-off-by: C O Mitter <committer@example.com> + Signed-off-by: my@house + EOF + cat >expect <<-\EOF && + 4:Subject: [PATCH] subject + 8: + 10: + 11:Signed-off-by: C O Mitter <committer@example.com> + 12:Signed-off-by: my@house + EOF + test_cmp expect actual ' test_expect_success 'signoff: tolerate garbage in conforming footer' ' - append_signoff <<\EOF >actual && -subject + append_signoff <<-\EOF >actual && + subject -body + body -Tested-by: my@house -Some Trash -Signed-off-by: C O Mitter <committer@example.com> -EOF - cat >expected <<\EOF && -4:Subject: [PATCH] subject -8: -10: -13:Signed-off-by: C O Mitter <committer@example.com> -EOF - test_cmp expected actual + Tested-by: my@house + Some Trash + Signed-off-by: C O Mitter <committer@example.com> + EOF + cat >expect <<-\EOF && + 4:Subject: [PATCH] subject + 8: + 10: + 13:Signed-off-by: C O Mitter <committer@example.com> + EOF + test_cmp expect actual ' test_expect_success 'signoff: respect trailer config' ' - append_signoff <<\EOF >actual && -subject + append_signoff <<-\EOF >actual && + subject -Myfooter: x -Some Trash -EOF - cat >expected <<\EOF && -4:Subject: [PATCH] subject -8: -11: -12:Signed-off-by: C O Mitter <committer@example.com> -EOF - test_cmp expected actual && + Myfooter: x + Some Trash + EOF + cat >expect <<-\EOF && + 4:Subject: [PATCH] subject + 8: + 11: + 12:Signed-off-by: C O Mitter <committer@example.com> + EOF + test_cmp expect actual && test_config trailer.Myfooter.ifexists add && - append_signoff <<\EOF >actual && -subject + append_signoff <<-\EOF >actual && + subject -Myfooter: x -Some Trash -EOF - cat >expected <<\EOF && -4:Subject: [PATCH] subject -8: -11:Signed-off-by: C O Mitter <committer@example.com> -EOF - test_cmp expected actual + Myfooter: x + Some Trash + EOF + cat >expect <<-\EOF && + 4:Subject: [PATCH] subject + 8: + 11:Signed-off-by: C O Mitter <committer@example.com> + EOF + test_cmp expect actual ' test_expect_success 'signoff: footer begins with non-signoff without @ sign' ' - append_signoff <<\EOF >actual && -subject + append_signoff <<-\EOF >actual && + subject -body + body -Reviewed-id: Noone -Tested-by: my@house -Change-id: Ideadbeef -Signed-off-by: C O Mitter <committer@example.com> -Bug: 1234 -EOF - cat >expected <<\EOF && -4:Subject: [PATCH] subject -8: -10: -14:Signed-off-by: C O Mitter <committer@example.com> -EOF - test_cmp expected actual + Reviewed-id: Noone + Tested-by: my@house + Change-id: Ideadbeef + Signed-off-by: C O Mitter <committer@example.com> + Bug: 1234 + EOF + cat >expect <<-\EOF && + 4:Subject: [PATCH] subject + 8: + 10: + 14:Signed-off-by: C O Mitter <committer@example.com> + EOF + test_cmp expect actual ' test_expect_success 'format patch ignores color.ui' ' @@ -1454,46 +1517,218 @@ test_expect_success 'format patch ignores color.ui' ' test_cmp expect actual ' +test_expect_success 'cover letter with invalid --cover-from-description and config' ' + test_config branch.rebuild-1.description "config subject + +body" && + test_must_fail git format-patch --cover-letter --cover-from-description garbage master && + test_config format.coverFromDescription garbage && + test_must_fail git format-patch --cover-letter master +' + +test_expect_success 'cover letter with format.coverFromDescription = default' ' + test_config branch.rebuild-1.description "config subject + +body" && + test_config format.coverFromDescription default && + git checkout rebuild-1 && + git format-patch --stdout --cover-letter master >actual && + grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual && + ! grep "^\*\*\* BLURB HERE \*\*\*$" actual && + grep "^config subject$" actual && + grep "^body$" actual +' + +test_expect_success 'cover letter with --cover-from-description default' ' + test_config branch.rebuild-1.description "config subject + +body" && + git checkout rebuild-1 && + git format-patch --stdout --cover-letter --cover-from-description default master >actual && + grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual && + ! grep "^\*\*\* BLURB HERE \*\*\*$" actual && + grep "^config subject$" actual && + grep "^body$" actual +' + +test_expect_success 'cover letter with format.coverFromDescription = none' ' + test_config branch.rebuild-1.description "config subject + +body" && + test_config format.coverFromDescription none && + git checkout rebuild-1 && + git format-patch --stdout --cover-letter master >actual && + grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual && + grep "^\*\*\* BLURB HERE \*\*\*$" actual && + ! grep "^config subject$" actual && + ! grep "^body$" actual +' + +test_expect_success 'cover letter with --cover-from-description none' ' + test_config branch.rebuild-1.description "config subject + +body" && + git checkout rebuild-1 && + git format-patch --stdout --cover-letter --cover-from-description none master >actual && + grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual && + grep "^\*\*\* BLURB HERE \*\*\*$" actual && + ! grep "^config subject$" actual && + ! grep "^body$" actual +' + +test_expect_success 'cover letter with format.coverFromDescription = message' ' + test_config branch.rebuild-1.description "config subject + +body" && + test_config format.coverFromDescription message && + git checkout rebuild-1 && + git format-patch --stdout --cover-letter master >actual && + grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual && + ! grep "^\*\*\* BLURB HERE \*\*\*$" actual && + grep "^config subject$" actual && + grep "^body$" actual +' + +test_expect_success 'cover letter with --cover-from-description message' ' + test_config branch.rebuild-1.description "config subject + +body" && + git checkout rebuild-1 && + git format-patch --stdout --cover-letter --cover-from-description message master >actual && + grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual && + ! grep "^\*\*\* BLURB HERE \*\*\*$" actual && + grep "^config subject$" actual && + grep "^body$" actual +' + +test_expect_success 'cover letter with format.coverFromDescription = subject' ' + test_config branch.rebuild-1.description "config subject + +body" && + test_config format.coverFromDescription subject && + git checkout rebuild-1 && + git format-patch --stdout --cover-letter master >actual && + grep "^Subject: \[PATCH 0/2\] config subject$" actual && + ! grep "^\*\*\* BLURB HERE \*\*\*$" actual && + ! grep "^config subject$" actual && + grep "^body$" actual +' + +test_expect_success 'cover letter with --cover-from-description subject' ' + test_config branch.rebuild-1.description "config subject + +body" && + git checkout rebuild-1 && + git format-patch --stdout --cover-letter --cover-from-description subject master >actual && + grep "^Subject: \[PATCH 0/2\] config subject$" actual && + ! grep "^\*\*\* BLURB HERE \*\*\*$" actual && + ! grep "^config subject$" actual && + grep "^body$" actual +' + +test_expect_success 'cover letter with format.coverFromDescription = auto (short subject line)' ' + test_config branch.rebuild-1.description "config subject + +body" && + test_config format.coverFromDescription auto && + git checkout rebuild-1 && + git format-patch --stdout --cover-letter master >actual && + grep "^Subject: \[PATCH 0/2\] config subject$" actual && + ! grep "^\*\*\* BLURB HERE \*\*\*$" actual && + ! grep "^config subject$" actual && + grep "^body$" actual +' + +test_expect_success 'cover letter with --cover-from-description auto (short subject line)' ' + test_config branch.rebuild-1.description "config subject + +body" && + git checkout rebuild-1 && + git format-patch --stdout --cover-letter --cover-from-description auto master >actual && + grep "^Subject: \[PATCH 0/2\] config subject$" actual && + ! grep "^\*\*\* BLURB HERE \*\*\*$" actual && + ! grep "^config subject$" actual && + grep "^body$" actual +' + +test_expect_success 'cover letter with format.coverFromDescription = auto (long subject line)' ' + test_config branch.rebuild-1.description "this is a really long first line and it is over 100 characters long which is the threshold for long subjects + +body" && + test_config format.coverFromDescription auto && + git checkout rebuild-1 && + git format-patch --stdout --cover-letter master >actual && + grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual && + ! grep "^\*\*\* BLURB HERE \*\*\*$" actual && + grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual && + grep "^body$" actual +' + +test_expect_success 'cover letter with --cover-from-description auto (long subject line)' ' + test_config branch.rebuild-1.description "this is a really long first line and it is over 100 characters long which is the threshold for long subjects + +body" && + git checkout rebuild-1 && + git format-patch --stdout --cover-letter --cover-from-description auto master >actual && + grep "^Subject: \[PATCH 0/2\] \*\*\* SUBJECT HERE \*\*\*$" actual && + ! grep "^\*\*\* BLURB HERE \*\*\*$" actual && + grep "^this is a really long first line and it is over 100 characters long which is the threshold for long subjects$" actual && + grep "^body$" actual +' + +test_expect_success 'cover letter with command-line --cover-from-description overrides config' ' + test_config branch.rebuild-1.description "config subject + +body" && + test_config format.coverFromDescription none && + git checkout rebuild-1 && + git format-patch --stdout --cover-letter --cover-from-description subject master >actual && + grep "^Subject: \[PATCH 0/2\] config subject$" actual && + ! grep "^\*\*\* BLURB HERE \*\*\*$" actual && + ! grep "^config subject$" actual && + grep "^body$" actual +' + test_expect_success 'cover letter using branch description (1)' ' git checkout rebuild-1 && test_config branch.rebuild-1.description hello && git format-patch --stdout --cover-letter master >actual && - grep hello actual >/dev/null + grep hello actual ' test_expect_success 'cover letter using branch description (2)' ' git checkout rebuild-1 && test_config branch.rebuild-1.description hello && git format-patch --stdout --cover-letter rebuild-1~2..rebuild-1 >actual && - grep hello actual >/dev/null + grep hello actual ' test_expect_success 'cover letter using branch description (3)' ' git checkout rebuild-1 && test_config branch.rebuild-1.description hello && git format-patch --stdout --cover-letter ^master rebuild-1 >actual && - grep hello actual >/dev/null + grep hello actual ' test_expect_success 'cover letter using branch description (4)' ' git checkout rebuild-1 && test_config branch.rebuild-1.description hello && git format-patch --stdout --cover-letter master.. >actual && - grep hello actual >/dev/null + grep hello actual ' test_expect_success 'cover letter using branch description (5)' ' git checkout rebuild-1 && test_config branch.rebuild-1.description hello && git format-patch --stdout --cover-letter -2 HEAD >actual && - grep hello actual >/dev/null + grep hello actual ' test_expect_success 'cover letter using branch description (6)' ' git checkout rebuild-1 && test_config branch.rebuild-1.description hello && git format-patch --stdout --cover-letter -2 >actual && - grep hello actual >/dev/null + grep hello actual ' test_expect_success 'cover letter with nothing' ' @@ -1543,11 +1778,39 @@ test_expect_success 'From line has expected format' ' test_cmp from filtered ' +test_expect_success 'format-patch -o with no leading directories' ' + rm -fr patches && + git format-patch -o patches master..side && + count=$(git rev-list --count master..side) && + ls patches >list && + test_line_count = $count list +' + +test_expect_success 'format-patch -o with leading existing directories' ' + rm -rf existing-dir && + mkdir existing-dir && + git format-patch -o existing-dir/patches master..side && + count=$(git rev-list --count master..side) && + ls existing-dir/patches >list && + test_line_count = $count list +' + +test_expect_success 'format-patch -o with leading non-existing directories' ' + rm -rf non-existing-dir && + git format-patch -o non-existing-dir/patches master..side && + count=$(git rev-list --count master..side) && + test_path_is_dir non-existing-dir && + ls non-existing-dir/patches >list && + test_line_count = $count list +' + test_expect_success 'format-patch format.outputDirectory option' ' test_config format.outputDirectory patches && rm -fr patches && git format-patch master..side && - test $(git rev-list master..side | wc -l) -eq $(ls patches | wc -l) + count=$(git rev-list --count master..side) && + ls patches >list && + test_line_count = $count list ' test_expect_success 'format-patch -o overrides format.outputDirectory' ' @@ -1559,16 +1822,44 @@ test_expect_success 'format-patch -o overrides format.outputDirectory' ' ' test_expect_success 'format-patch --base' ' - git checkout side && - git format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual1 && - git format-patch --stdout --base=HEAD~3 HEAD~.. | tail -n 7 >actual2 && - echo >expected && - echo "base-commit: $(git rev-parse HEAD~3)" >>expected && - echo "prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --stable | awk "{print \$1}")" >>expected && - echo "prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk "{print \$1}")" >>expected && - signature >> expected && - test_cmp expected actual1 && - test_cmp expected actual2 + git checkout patchid && + + git format-patch --stdout --base=HEAD~3 -1 >patch && + tail -n 7 patch >actual1 && + + git format-patch --stdout --base=HEAD~3 HEAD~.. >patch && + tail -n 7 patch >actual2 && + + echo >expect && + git rev-parse HEAD~3 >commit-id-base && + echo "base-commit: $(cat commit-id-base)" >>expect && + + git show --patch HEAD~2 >patch && + git patch-id --stable <patch >patch.id.raw && + awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect && + + git show --patch HEAD~1 >patch && + git patch-id --stable <patch >patch.id.raw && + awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>expect && + + signature >>expect && + test_cmp expect actual1 && + test_cmp expect actual2 && + + echo >fail && + echo "base-commit: $(cat commit-id-base)" >>fail && + + git show --patch HEAD~2 >patch && + git patch-id --unstable <patch >patch.id.raw && + awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail && + + git show --patch HEAD~1 >patch && + git patch-id --unstable <patch >patch.id.raw && + awk "{print \"prerequisite-patch-id:\", \$1}" <patch.id.raw >>fail && + + signature >>fail && + ! test_cmp fail actual1 && + ! test_cmp fail actual2 ' test_expect_success 'format-patch --base errors out when base commit is in revision list' ' @@ -1576,8 +1867,9 @@ test_expect_success 'format-patch --base errors out when base commit is in revis test_must_fail git format-patch --base=HEAD~1 -2 && git format-patch --stdout --base=HEAD~2 -2 >patch && grep "^base-commit:" patch >actual && - echo "base-commit: $(git rev-parse HEAD~2)" >expected && - test_cmp expected actual + git rev-parse HEAD~2 >commit-id-base && + echo "base-commit: $(cat commit-id-base)" >expect && + test_cmp expect actual ' test_expect_success 'format-patch --base errors out when base commit is not ancestor of revision list' ' @@ -1603,8 +1895,8 @@ test_expect_success 'format-patch --base errors out when base commit is not ance test_must_fail git format-patch --base=$(cat commit-id-Z) -3 && git format-patch --stdout --base=$(cat commit-id-base) -3 >patch && grep "^base-commit:" patch >actual && - echo "base-commit: $(cat commit-id-base)" >expected && - test_cmp expected actual + echo "base-commit: $(cat commit-id-base)" >expect && + test_cmp expect actual ' test_expect_success 'format-patch --base=auto' ' @@ -1615,8 +1907,9 @@ test_expect_success 'format-patch --base=auto' ' test_commit N2 && git format-patch --stdout --base=auto -2 >patch && grep "^base-commit:" patch >actual && - echo "base-commit: $(git rev-parse upstream)" >expected && - test_cmp expected actual + git rev-parse upstream >commit-id-base && + echo "base-commit: $(cat commit-id-base)" >expect && + test_cmp expect actual ' test_expect_success 'format-patch errors out when history involves criss-cross' ' @@ -1652,8 +1945,9 @@ test_expect_success 'format-patch format.useAutoBaseoption' ' git config format.useAutoBase true && git format-patch --stdout -1 >patch && grep "^base-commit:" patch >actual && - echo "base-commit: $(git rev-parse upstream)" >expected && - test_cmp expected actual + git rev-parse upstream >commit-id-base && + echo "base-commit: $(cat commit-id-base)" >expect && + test_cmp expect actual ' test_expect_success 'format-patch --base overrides format.useAutoBase' ' @@ -1661,8 +1955,9 @@ test_expect_success 'format-patch --base overrides format.useAutoBase' ' git config format.useAutoBase true && git format-patch --stdout --base=HEAD~1 -1 >patch && grep "^base-commit:" patch >actual && - echo "base-commit: $(git rev-parse HEAD~1)" >expected && - test_cmp expected actual + git rev-parse HEAD~1 >commit-id-base && + echo "base-commit: $(cat commit-id-base)" >expect && + test_cmp expect actual ' test_expect_success 'format-patch --base with --attach' ' @@ -1737,7 +2032,7 @@ test_expect_success 'interdiff: cover-letter' ' git format-patch --cover-letter --interdiff=boop~2 -1 boop && test_i18ngrep "^Interdiff:$" 0000-cover-letter.patch && test_i18ngrep ! "^Interdiff:$" 0001-fleep.patch && - sed "1,/^@@ /d; /^-- $/q" <0000-cover-letter.patch >actual && + sed "1,/^@@ /d; /^-- $/q" 0000-cover-letter.patch >actual && test_cmp expect actual ' @@ -1753,7 +2048,7 @@ test_expect_success 'interdiff: solo-patch' ' EOF git format-patch --interdiff=boop~2 -1 boop && test_i18ngrep "^Interdiff:$" 0001-fleep.patch && - sed "1,/^ @@ /d; /^$/q" <0001-fleep.patch >actual && + sed "1,/^ @@ /d; /^$/q" 0001-fleep.patch >actual && test_cmp expect actual ' diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index 6b087df3dc..eadaf57262 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -16,6 +16,7 @@ test_expect_success "Ray Lehtiniemi's example" ' } while (0); EOF git update-index --add x && + before=$(git rev-parse --short $(git hash-object x)) && cat <<-\EOF >x && do @@ -24,10 +25,11 @@ test_expect_success "Ray Lehtiniemi's example" ' } while (0); EOF + after=$(git rev-parse --short $(git hash-object x)) && - cat <<-\EOF >expect && + cat <<-EOF >expect && diff --git a/x b/x - index adf3937..6edc172 100644 + index $before..$after 100644 --- a/x +++ b/x @@ -1,3 +1,5 @@ @@ -61,6 +63,7 @@ test_expect_success 'another test, without options' ' EOF git update-index x && + before=$(git rev-parse --short $(git hash-object x)) && tr "_" " " <<-\EOF >x && _ whitespace at beginning @@ -70,10 +73,11 @@ test_expect_success 'another test, without options' ' unchanged line CR at end EOF + after=$(git rev-parse --short $(git hash-object x)) && - tr "Q_" "\015 " <<-\EOF >expect && + tr "Q_" "\015 " <<-EOF >expect && diff --git a/x b/x - index d99af23..22d9f73 100644 + index $before..$after 100644 --- a/x +++ b/x @@ -1,6 +1,6 @@ @@ -108,9 +112,9 @@ test_expect_success 'another test, without options' ' git diff -w --ignore-cr-at-eol >out && test_must_be_empty out && - tr "Q_" "\015 " <<-\EOF >expect && + tr "Q_" "\015 " <<-EOF >expect && diff --git a/x b/x - index d99af23..22d9f73 100644 + index $before..$after 100644 --- a/x +++ b/x @@ -1,6 +1,6 @@ @@ -132,9 +136,9 @@ test_expect_success 'another test, without options' ' git diff -b --ignore-cr-at-eol >out && test_cmp expect out && - tr "Q_" "\015 " <<-\EOF >expect && + tr "Q_" "\015 " <<-EOF >expect && diff --git a/x b/x - index d99af23..22d9f73 100644 + index $before..$after 100644 --- a/x +++ b/x @@ -1,6 +1,6 @@ @@ -154,9 +158,9 @@ test_expect_success 'another test, without options' ' git diff --ignore-space-at-eol --ignore-cr-at-eol >out && test_cmp expect out && - tr "Q_" "\015 " <<-\EOF >expect && + tr "Q_" "\015 " <<-EOF >expect && diff --git a/x b/x - index_d99af23..22d9f73 100644 + index_$before..$after 100644 --- a/x +++ b/x @@ -1,6 +1,6 @@ @@ -786,23 +790,25 @@ test_expect_success 'whitespace-only changes not reported' ' test_must_be_empty actual ' -cat <<EOF >expect -diff --git a/x b/z -similarity index NUM% -rename from x -rename to z -index 380c32a..a97b785 100644 -EOF test_expect_success 'whitespace-only changes reported across renames' ' git reset --hard && for i in 1 2 3 4 5 6 7 8 9; do echo "$i$i$i$i$i$i"; done >x && git add x && + before=$(git rev-parse --short $(git hash-object x)) && git commit -m "base" && sed -e "5s/^/ /" x >z && git rm x && git add z && + after=$(git rev-parse --short $(git hash-object z)) && git diff -w -M --cached | sed -e "/^similarity index /s/[0-9][0-9]*/NUM/" >actual && + cat <<-EOF >expect && + diff --git a/x b/z + similarity index NUM% + rename from x + rename to z + index $before..$after 100644 + EOF test_cmp expect actual ' @@ -858,13 +864,15 @@ test_expect_success 'diff that introduces a line with only tabs' ' git config core.whitespace blank-at-eol && git reset --hard && echo "test" >x && + before=$(git rev-parse --short $(git hash-object x)) && git commit -m "initial" x && echo "{NTN}" | tr "NT" "\n\t" >>x && + after=$(git rev-parse --short $(git hash-object x)) && git diff --color | test_decode_color >current && - cat >expected <<-\EOF && + cat >expected <<-EOF && <BOLD>diff --git a/x b/x<RESET> - <BOLD>index 9daeafb..2874b91 100644<RESET> + <BOLD>index $before..$after 100644<RESET> <BOLD>--- a/x<RESET> <BOLD>+++ b/x<RESET> <CYAN>@@ -1 +1,4 @@<RESET> @@ -883,19 +891,21 @@ test_expect_success 'diff that introduces and removes ws breakages' ' echo "0. blank-at-eol " && echo "1. blank-at-eol " } >x && + before=$(git rev-parse --short $(git hash-object x)) && git commit -a --allow-empty -m preimage && { echo "0. blank-at-eol " && echo "1. still-blank-at-eol " && echo "2. and a new line " } >x && + after=$(git rev-parse --short $(git hash-object x)) && git diff --color | test_decode_color >current && - cat >expected <<-\EOF && + cat >expected <<-EOF && <BOLD>diff --git a/x b/x<RESET> - <BOLD>index d0233a2..700886e 100644<RESET> + <BOLD>index $before..$after 100644<RESET> <BOLD>--- a/x<RESET> <BOLD>+++ b/x<RESET> <CYAN>@@ -1,2 +1,3 @@<RESET> @@ -915,16 +925,18 @@ test_expect_success 'ws-error-highlight test setup' ' echo "0. blank-at-eol " && echo "1. blank-at-eol " } >x && + before=$(git rev-parse --short $(git hash-object x)) && git commit -a --allow-empty -m preimage && { echo "0. blank-at-eol " && echo "1. still-blank-at-eol " && echo "2. and a new line " } >x && + after=$(git rev-parse --short $(git hash-object x)) && - cat >expect.default-old <<-\EOF && + cat >expect.default-old <<-EOF && <BOLD>diff --git a/x b/x<RESET> - <BOLD>index d0233a2..700886e 100644<RESET> + <BOLD>index $before..$after 100644<RESET> <BOLD>--- a/x<RESET> <BOLD>+++ b/x<RESET> <CYAN>@@ -1,2 +1,3 @@<RESET> @@ -934,9 +946,9 @@ test_expect_success 'ws-error-highlight test setup' ' <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET> EOF - cat >expect.all <<-\EOF && + cat >expect.all <<-EOF && <BOLD>diff --git a/x b/x<RESET> - <BOLD>index d0233a2..700886e 100644<RESET> + <BOLD>index $before..$after 100644<RESET> <BOLD>--- a/x<RESET> <BOLD>+++ b/x<RESET> <CYAN>@@ -1,2 +1,3 @@<RESET> @@ -946,9 +958,9 @@ test_expect_success 'ws-error-highlight test setup' ' <GREEN>+<RESET><GREEN>2. and a new line<RESET><BLUE> <RESET> EOF - cat >expect.none <<-\EOF + cat >expect.none <<-EOF <BOLD>diff --git a/x b/x<RESET> - <BOLD>index d0233a2..700886e 100644<RESET> + <BOLD>index $before..$after 100644<RESET> <BOLD>--- a/x<RESET> <BOLD>+++ b/x<RESET> <CYAN>@@ -1,2 +1,3 @@<RESET> @@ -1022,14 +1034,15 @@ test_expect_success 'detect moved code, complete file' ' EOF git add test.c && git commit -m "add main function" && + file=$(git rev-parse --short HEAD:test.c) && git mv test.c main.c && test_config color.diff.oldMoved "normal red" && test_config color.diff.newMoved "normal green" && git diff HEAD --color-moved=zebra --color --no-renames | test_decode_color >actual && - cat >expected <<-\EOF && + cat >expected <<-EOF && <BOLD>diff --git a/main.c b/main.c<RESET> <BOLD>new file mode 100644<RESET> - <BOLD>index 0000000..a986c57<RESET> + <BOLD>index 0000000..$file<RESET> <BOLD>--- /dev/null<RESET> <BOLD>+++ b/main.c<RESET> <CYAN>@@ -0,0 +1,5 @@<RESET> @@ -1040,7 +1053,7 @@ test_expect_success 'detect moved code, complete file' ' <BGREEN>+<RESET><BGREEN>}<RESET> <BOLD>diff --git a/test.c b/test.c<RESET> <BOLD>deleted file mode 100644<RESET> - <BOLD>index a986c57..0000000<RESET> + <BOLD>index $file..0000000<RESET> <BOLD>--- a/test.c<RESET> <BOLD>+++ /dev/null<RESET> <CYAN>@@ -1,5 +0,0 @@<RESET> @@ -1094,6 +1107,8 @@ test_expect_success 'detect malicious moved code, inside file' ' EOF git add main.c test.c && git commit -m "add main and test file" && + before_main=$(git rev-parse --short HEAD:main.c) && + before_test=$(git rev-parse --short HEAD:test.c) && cat <<-\EOF >main.c && #include<stdio.h> int stuff() @@ -1126,10 +1141,12 @@ test_expect_success 'detect malicious moved code, inside file' ' bar(); } EOF + after_main=$(git rev-parse --short $(git hash-object main.c)) && + after_test=$(git rev-parse --short $(git hash-object test.c)) && git diff HEAD --no-renames --color-moved=zebra --color | test_decode_color >actual && - cat <<-\EOF >expected && + cat <<-EOF >expected && <BOLD>diff --git a/main.c b/main.c<RESET> - <BOLD>index 27a619c..7cf9336 100644<RESET> + <BOLD>index $before_main..$after_main 100644<RESET> <BOLD>--- a/main.c<RESET> <BOLD>+++ b/main.c<RESET> <CYAN>@@ -5,13 +5,6 @@<RESET> <RESET>printf("Hello ");<RESET> @@ -1147,7 +1164,7 @@ test_expect_success 'detect malicious moved code, inside file' ' {<RESET> foo();<RESET> <BOLD>diff --git a/test.c b/test.c<RESET> - <BOLD>index 1dc1d85..2bedec9 100644<RESET> + <BOLD>index $before_test..$after_test 100644<RESET> <BOLD>--- a/test.c<RESET> <BOLD>+++ b/test.c<RESET> <CYAN>@@ -4,6 +4,13 @@<RESET> <RESET>int bar()<RESET> @@ -1176,9 +1193,9 @@ test_expect_success 'plain moved code, inside file' ' test_config color.diff.newMovedAlternative "yellow" && # needs previous test as setup git diff HEAD --no-renames --color-moved=plain --color | test_decode_color >actual && - cat <<-\EOF >expected && + cat <<-EOF >expected && <BOLD>diff --git a/main.c b/main.c<RESET> - <BOLD>index 27a619c..7cf9336 100644<RESET> + <BOLD>index $before_main..$after_main 100644<RESET> <BOLD>--- a/main.c<RESET> <BOLD>+++ b/main.c<RESET> <CYAN>@@ -5,13 +5,6 @@<RESET> <RESET>printf("Hello ");<RESET> @@ -1196,7 +1213,7 @@ test_expect_success 'plain moved code, inside file' ' {<RESET> foo();<RESET> <BOLD>diff --git a/test.c b/test.c<RESET> - <BOLD>index 1dc1d85..2bedec9 100644<RESET> + <BOLD>index $before_test..$after_test 100644<RESET> <BOLD>--- a/test.c<RESET> <BOLD>+++ b/test.c<RESET> <CYAN>@@ -4,6 +4,13 @@<RESET> <RESET>int bar()<RESET> diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh index 22f9f88f0a..c0f4839543 100755 --- a/t/t4018-diff-funcname.sh +++ b/t/t4018-diff-funcname.sh @@ -31,6 +31,8 @@ diffpatterns=" cpp csharp css + dts + elixir fortran fountain golang @@ -43,6 +45,7 @@ diffpatterns=" php python ruby + rust tex custom1 custom2 diff --git a/t/t4018/dts-labels b/t/t4018/dts-labels new file mode 100644 index 0000000000..b21ef8737b --- /dev/null +++ b/t/t4018/dts-labels @@ -0,0 +1,9 @@ +/ { + label_1: node1@ff00 { + label2: RIGHT { + vendor,some-property; + + ChangeMe = <0x45-30>; + }; + }; +}; diff --git a/t/t4018/dts-node-unitless b/t/t4018/dts-node-unitless new file mode 100644 index 0000000000..c5287d9141 --- /dev/null +++ b/t/t4018/dts-node-unitless @@ -0,0 +1,8 @@ +/ { + label_1: node1 { + RIGHT { + prop-array = <1>, <4>; + ChangeMe = <0xffeedd00>; + }; + }; +}; diff --git a/t/t4018/dts-nodes b/t/t4018/dts-nodes new file mode 100644 index 0000000000..5a4334bb16 --- /dev/null +++ b/t/t4018/dts-nodes @@ -0,0 +1,8 @@ +/ { + label_1: node1@ff00 { + RIGHT@deadf00,4000 { + #size-cells = <1>; + ChangeMe = <0xffeedd00>; + }; + }; +}; diff --git a/t/t4018/dts-nodes-boolean-prop b/t/t4018/dts-nodes-boolean-prop new file mode 100644 index 0000000000..afc6b5b404 --- /dev/null +++ b/t/t4018/dts-nodes-boolean-prop @@ -0,0 +1,9 @@ +/ { + label_1: node1@ff00 { + RIGHT@deadf00,4000 { + boolean-prop1; + + ChangeMe; + }; + }; +}; diff --git a/t/t4018/dts-nodes-comment1 b/t/t4018/dts-nodes-comment1 new file mode 100644 index 0000000000..559dfce9b3 --- /dev/null +++ b/t/t4018/dts-nodes-comment1 @@ -0,0 +1,8 @@ +/ { + label_1: node1@ff00 { + RIGHT@deadf00,4000 /* &a comment */ { + #size-cells = <1>; + ChangeMe = <0xffeedd00>; + }; + }; +}; diff --git a/t/t4018/dts-nodes-comment2 b/t/t4018/dts-nodes-comment2 new file mode 100644 index 0000000000..27e9718b31 --- /dev/null +++ b/t/t4018/dts-nodes-comment2 @@ -0,0 +1,8 @@ +/ { + label_1: node1@ff00 { + RIGHT@deadf00,4000 { /* a trailing comment */ + #size-cells = <1>; + ChangeMe = <0xffeedd00>; + }; + }; +}; diff --git a/t/t4018/dts-nodes-multiline-prop b/t/t4018/dts-nodes-multiline-prop new file mode 100644 index 0000000000..072d58b69d --- /dev/null +++ b/t/t4018/dts-nodes-multiline-prop @@ -0,0 +1,13 @@ +/ { + label_1: node1@ff00 { + RIGHT@deadf00,4000 { + multilineprop = <3>, + <4>, + <5>, + <6>, + <7>; + + ChangeMe = <0xffeedd00>; + }; + }; +}; diff --git a/t/t4018/dts-reference b/t/t4018/dts-reference new file mode 100644 index 0000000000..8f0c87d863 --- /dev/null +++ b/t/t4018/dts-reference @@ -0,0 +1,9 @@ +&label_1 { + TEST = <455>; +}; + +&RIGHT { + vendor,some-property; + + ChangeMe = <0x45-30>; +}; diff --git a/t/t4018/dts-root b/t/t4018/dts-root new file mode 100644 index 0000000000..4353b8220c --- /dev/null +++ b/t/t4018/dts-root @@ -0,0 +1,5 @@ +/ { RIGHT /* Technically just supposed to be a slash and brace */ + #size-cells = <1>; + + ChangeMe = <0xffeedd00>; +}; diff --git a/t/t4018/dts-root-comment b/t/t4018/dts-root-comment new file mode 100644 index 0000000000..333a625c70 --- /dev/null +++ b/t/t4018/dts-root-comment @@ -0,0 +1,8 @@ +/ { RIGHT /* Technically just supposed to be a slash and brace */ + #size-cells = <1>; + + /* This comment should be ignored */ + + some-property = <40+2>; + ChangeMe = <0xffeedd00>; +}; diff --git a/t/t4018/elixir-do-not-pick-end b/t/t4018/elixir-do-not-pick-end new file mode 100644 index 0000000000..fae08ba7e8 --- /dev/null +++ b/t/t4018/elixir-do-not-pick-end @@ -0,0 +1,5 @@ +defmodule RIGHT do +end +# +# +# ChangeMe; do not pick up 'end' line diff --git a/t/t4018/elixir-ex-unit-test b/t/t4018/elixir-ex-unit-test new file mode 100644 index 0000000000..0560a2b697 --- /dev/null +++ b/t/t4018/elixir-ex-unit-test @@ -0,0 +1,6 @@ +defmodule Test do + test "RIGHT" do + assert true == true + assert ChangeMe + end +end diff --git a/t/t4018/elixir-function b/t/t4018/elixir-function new file mode 100644 index 0000000000..d452f495a7 --- /dev/null +++ b/t/t4018/elixir-function @@ -0,0 +1,5 @@ +def function(RIGHT, arg) do + # comment + # comment + ChangeMe +end diff --git a/t/t4018/elixir-macro b/t/t4018/elixir-macro new file mode 100644 index 0000000000..4f925e9ad4 --- /dev/null +++ b/t/t4018/elixir-macro @@ -0,0 +1,5 @@ +defmacro foo(RIGHT) do + # Code + # Code + ChangeMe +end diff --git a/t/t4018/elixir-module b/t/t4018/elixir-module new file mode 100644 index 0000000000..91a4e7aa20 --- /dev/null +++ b/t/t4018/elixir-module @@ -0,0 +1,9 @@ +defmodule RIGHT do + @moduledoc """ + Foo bar + """ + + def ChangeMe(a) where is_map(a) do + a + end +end diff --git a/t/t4018/elixir-module-func b/t/t4018/elixir-module-func new file mode 100644 index 0000000000..c9910d0675 --- /dev/null +++ b/t/t4018/elixir-module-func @@ -0,0 +1,8 @@ +defmodule Foo do + def fun(RIGHT) do + # Code + # Code + # Code + ChangeMe + end +end diff --git a/t/t4018/elixir-nested-module b/t/t4018/elixir-nested-module new file mode 100644 index 0000000000..771ebc5c42 --- /dev/null +++ b/t/t4018/elixir-nested-module @@ -0,0 +1,9 @@ +defmodule MyApp.RIGHT do + @moduledoc """ + Foo bar + """ + + def ChangeMe(a) where is_map(a) do + a + end +end diff --git a/t/t4018/elixir-private-function b/t/t4018/elixir-private-function new file mode 100644 index 0000000000..1aabe33b7a --- /dev/null +++ b/t/t4018/elixir-private-function @@ -0,0 +1,5 @@ +defp function(RIGHT, arg) do + # comment + # comment + ChangeMe +end diff --git a/t/t4018/elixir-protocol b/t/t4018/elixir-protocol new file mode 100644 index 0000000000..7d9173691e --- /dev/null +++ b/t/t4018/elixir-protocol @@ -0,0 +1,6 @@ +defprotocol RIGHT do + @doc """ + Calculates the size (and not the length!) of a data structure + """ + def size(data, ChangeMe) +end diff --git a/t/t4018/elixir-protocol-implementation b/t/t4018/elixir-protocol-implementation new file mode 100644 index 0000000000..f9234bbfc4 --- /dev/null +++ b/t/t4018/elixir-protocol-implementation @@ -0,0 +1,5 @@ +defimpl RIGHT do + # Docs + # Docs + def foo(ChangeMe), do: :ok +end diff --git a/t/t4018/matlab-class-definition b/t/t4018/matlab-class-definition new file mode 100644 index 0000000000..84daedfb4e --- /dev/null +++ b/t/t4018/matlab-class-definition @@ -0,0 +1,5 @@ +classdef RIGHT + properties + ChangeMe + end +end diff --git a/t/t4018/matlab-function b/t/t4018/matlab-function new file mode 100644 index 0000000000..897a9b13ff --- /dev/null +++ b/t/t4018/matlab-function @@ -0,0 +1,4 @@ +function y = RIGHT() +x = 5; +y = ChangeMe + x; +end diff --git a/t/t4018/matlab-octave-section-1 b/t/t4018/matlab-octave-section-1 new file mode 100644 index 0000000000..3bb6c4670e --- /dev/null +++ b/t/t4018/matlab-octave-section-1 @@ -0,0 +1,3 @@ +%%% RIGHT section +# this is octave script +ChangeMe = 1; diff --git a/t/t4018/matlab-octave-section-2 b/t/t4018/matlab-octave-section-2 new file mode 100644 index 0000000000..ab2980f7f2 --- /dev/null +++ b/t/t4018/matlab-octave-section-2 @@ -0,0 +1,3 @@ +## RIGHT section +# this is octave script +ChangeMe = 1; diff --git a/t/t4018/matlab-section b/t/t4018/matlab-section new file mode 100644 index 0000000000..5ea59a5de0 --- /dev/null +++ b/t/t4018/matlab-section @@ -0,0 +1,3 @@ +%% RIGHT section +% this is understood by both matlab and octave +ChangeMe = 1; diff --git a/t/t4018/python-async-def b/t/t4018/python-async-def new file mode 100644 index 0000000000..87640e03d2 --- /dev/null +++ b/t/t4018/python-async-def @@ -0,0 +1,4 @@ +async def RIGHT(pi: int = 3.14): + while True: + break + return ChangeMe() diff --git a/t/t4018/python-class b/t/t4018/python-class new file mode 100644 index 0000000000..ba9e741430 --- /dev/null +++ b/t/t4018/python-class @@ -0,0 +1,4 @@ +class RIGHT(int, str): + # comment + # another comment + # ChangeMe diff --git a/t/t4018/python-def b/t/t4018/python-def new file mode 100644 index 0000000000..e50b31b0ad --- /dev/null +++ b/t/t4018/python-def @@ -0,0 +1,4 @@ +def RIGHT(pi: int = 3.14): + while True: + break + return ChangeMe() diff --git a/t/t4018/python-indented-async-def b/t/t4018/python-indented-async-def new file mode 100644 index 0000000000..f5d03258af --- /dev/null +++ b/t/t4018/python-indented-async-def @@ -0,0 +1,7 @@ +class Foo: + async def RIGHT(self, x: int): + return [ + 1, + 2, + ChangeMe, + ] diff --git a/t/t4018/python-indented-class b/t/t4018/python-indented-class new file mode 100644 index 0000000000..19b4f35c4c --- /dev/null +++ b/t/t4018/python-indented-class @@ -0,0 +1,5 @@ +if TYPE_CHECKING: + class RIGHT: + # comment + # another comment + # ChangeMe diff --git a/t/t4018/python-indented-def b/t/t4018/python-indented-def new file mode 100644 index 0000000000..208fbadd2b --- /dev/null +++ b/t/t4018/python-indented-def @@ -0,0 +1,7 @@ +class Foo: + def RIGHT(self, x: int): + return [ + 1, + 2, + ChangeMe, + ] diff --git a/t/t4018/rust-fn b/t/t4018/rust-fn new file mode 100644 index 0000000000..cbe02155f1 --- /dev/null +++ b/t/t4018/rust-fn @@ -0,0 +1,5 @@ +pub(self) fn RIGHT<T>(x: &[T]) where T: Debug { + let _ = x; + // a comment + let a = ChangeMe; +} diff --git a/t/t4018/rust-impl b/t/t4018/rust-impl new file mode 100644 index 0000000000..09df3cd93b --- /dev/null +++ b/t/t4018/rust-impl @@ -0,0 +1,5 @@ +impl<'a, T: AsRef<[u8]>> std::RIGHT for Git<'a> { + + pub fn ChangeMe(&self) -> () { + } +} diff --git a/t/t4018/rust-struct b/t/t4018/rust-struct new file mode 100644 index 0000000000..76aff1c0d8 --- /dev/null +++ b/t/t4018/rust-struct @@ -0,0 +1,5 @@ +#[derive(Debug)] +pub(super) struct RIGHT<'a> { + name: &'a str, + age: ChangeMe, +} diff --git a/t/t4018/rust-trait b/t/t4018/rust-trait new file mode 100644 index 0000000000..ea397f09ed --- /dev/null +++ b/t/t4018/rust-trait @@ -0,0 +1,5 @@ +unsafe trait RIGHT<T> { + fn len(&self) -> u32; + fn ChangeMe(&self, n: u32) -> T; + fn iter<F>(&self, f: F) where F: Fn(T); +} diff --git a/t/t4027-diff-submodule.sh b/t/t4027-diff-submodule.sh index 9aa8e2b39b..e29deaf4a5 100755 --- a/t/t4027-diff-submodule.sh +++ b/t/t4027-diff-submodule.sh @@ -6,6 +6,7 @@ test_description='difference in submodules' . "$TEST_DIRECTORY"/diff-lib.sh test_expect_success setup ' + test_oid_init && test_tick && test_create_repo sub && ( @@ -36,7 +37,8 @@ test_expect_success setup ' ' test_expect_success 'git diff --raw HEAD' ' - git diff --raw --abbrev=40 HEAD >actual && + hexsz=$(test_oid hexsz) && + git diff --raw --abbrev=$hexsz HEAD >actual && test_cmp expect actual ' @@ -245,23 +247,21 @@ test_expect_success 'git diff (empty submodule dir)' ' ' test_expect_success 'conflicted submodule setup' ' - - # 39 efs - c=fffffffffffffffffffffffffffffffffffffff && + c=$(test_oid ff_1) && ( echo "000000 $ZERO_OID 0 sub" && echo "160000 1$c 1 sub" && echo "160000 2$c 2 sub" && echo "160000 3$c 3 sub" ) | git update-index --index-info && - echo >expect.nosub '\''diff --cc sub + echo >expect.nosub "diff --cc sub index 2ffffff,3ffffff..0000000 --- a/sub +++ b/sub @@@ -1,1 -1,1 +1,1 @@@ -- Subproject commit 2fffffffffffffffffffffffffffffffffffffff - -Subproject commit 3fffffffffffffffffffffffffffffffffffffff -++Subproject commit 0000000000000000000000000000000000000000'\'' && +- Subproject commit 2$c + -Subproject commit 3$c +++Subproject commit $ZERO_OID" && hh=$(git rev-parse HEAD) && sed -e "s/$ZERO_OID/$hh/" expect.nosub >expect.withsub diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh index 912df91226..fb145aa173 100755 --- a/t/t4034-diff-words.sh +++ b/t/t4034-diff-words.sh @@ -19,9 +19,11 @@ cat >post.simple <<-\EOF aeff = aeff * ( aaa ) EOF -cat >expect.letter-runs-are-words <<-\EOF +pre=$(git rev-parse --short $(git hash-object pre.simple)) +post=$(git rev-parse --short $(git hash-object post.simple)) +cat >expect.letter-runs-are-words <<-EOF <BOLD>diff --git a/pre b/post<RESET> - <BOLD>index 330b04f..5ed8eff 100644<RESET> + <BOLD>index $pre..$post 100644<RESET> <BOLD>--- a/pre<RESET> <BOLD>+++ b/post<RESET> <CYAN>@@ -1,3 +1,7 @@<RESET> @@ -33,9 +35,9 @@ cat >expect.letter-runs-are-words <<-\EOF <GREEN>aeff = aeff * ( aaa<RESET> ) EOF -cat >expect.non-whitespace-is-word <<-\EOF +cat >expect.non-whitespace-is-word <<-EOF <BOLD>diff --git a/pre b/post<RESET> - <BOLD>index 330b04f..5ed8eff 100644<RESET> + <BOLD>index $pre..$post 100644<RESET> <BOLD>--- a/pre<RESET> <BOLD>+++ b/post<RESET> <CYAN>@@ -1,3 +1,7 @@<RESET> @@ -49,9 +51,12 @@ cat >expect.non-whitespace-is-word <<-\EOF EOF word_diff () { + pre=$(git rev-parse --short $(git hash-object pre)) && + post=$(git rev-parse --short $(git hash-object post)) && test_must_fail git diff --no-index "$@" pre post >output && test_decode_color <output >output.decrypted && - test_cmp expect output.decrypted + sed -e "2s/index [^ ]*/index $pre..$post/" expect >expected + test_cmp expected output.decrypted } test_language_driver () { @@ -77,9 +82,9 @@ test_expect_success 'set up pre and post with runs of whitespace' ' ' test_expect_success 'word diff with runs of whitespace' ' - cat >expect <<-\EOF && + cat >expect <<-EOF && <BOLD>diff --git a/pre b/post<RESET> - <BOLD>index 330b04f..5ed8eff 100644<RESET> + <BOLD>index $pre..$post 100644<RESET> <BOLD>--- a/pre<RESET> <BOLD>+++ b/post<RESET> <CYAN>@@ -1,3 +1,7 @@<RESET> @@ -97,9 +102,9 @@ test_expect_success 'word diff with runs of whitespace' ' ' test_expect_success '--word-diff=porcelain' ' - sed 's/#.*$//' >expect <<-\EOF && + sed 's/#.*$//' >expect <<-EOF && diff --git a/pre b/post - index 330b04f..5ed8eff 100644 + index $pre..$post 100644 --- a/pre +++ b/post @@ -1,3 +1,7 @@ @@ -121,9 +126,9 @@ test_expect_success '--word-diff=porcelain' ' ' test_expect_success '--word-diff=plain' ' - cat >expect <<-\EOF && + cat >expect <<-EOF && diff --git a/pre b/post - index 330b04f..5ed8eff 100644 + index $pre..$post 100644 --- a/pre +++ b/post @@ -1,3 +1,7 @@ @@ -140,9 +145,9 @@ test_expect_success '--word-diff=plain' ' ' test_expect_success '--word-diff=plain --color' ' - cat >expect <<-\EOF && + cat >expect <<-EOF && <BOLD>diff --git a/pre b/post<RESET> - <BOLD>index 330b04f..5ed8eff 100644<RESET> + <BOLD>index $pre..$post 100644<RESET> <BOLD>--- a/pre<RESET> <BOLD>+++ b/post<RESET> <CYAN>@@ -1,3 +1,7 @@<RESET> @@ -158,9 +163,9 @@ test_expect_success '--word-diff=plain --color' ' ' test_expect_success 'word diff without context' ' - cat >expect <<-\EOF && + cat >expect <<-EOF && <BOLD>diff --git a/pre b/post<RESET> - <BOLD>index 330b04f..5ed8eff 100644<RESET> + <BOLD>index $pre..$post 100644<RESET> <BOLD>--- a/pre<RESET> <BOLD>+++ b/post<RESET> <CYAN>@@ -1 +1 @@<RESET> @@ -207,9 +212,9 @@ test_expect_success 'command-line overrides config' ' ' test_expect_success 'command-line overrides config: --word-diff-regex' ' - cat >expect <<-\EOF && + cat >expect <<-EOF && <BOLD>diff --git a/pre b/post<RESET> - <BOLD>index 330b04f..5ed8eff 100644<RESET> + <BOLD>index $pre..$post 100644<RESET> <BOLD>--- a/pre<RESET> <BOLD>+++ b/post<RESET> <CYAN>@@ -1,3 +1,7 @@<RESET> @@ -234,9 +239,9 @@ test_expect_success 'setup: remove diff driver regex' ' ' test_expect_success 'use configured regex' ' - cat >expect <<-\EOF && + cat >expect <<-EOF && <BOLD>diff --git a/pre b/post<RESET> - <BOLD>index 330b04f..5ed8eff 100644<RESET> + <BOLD>index $pre..$post 100644<RESET> <BOLD>--- a/pre<RESET> <BOLD>+++ b/post<RESET> <CYAN>@@ -1,3 +1,7 @@<RESET> @@ -254,9 +259,11 @@ test_expect_success 'use configured regex' ' test_expect_success 'test parsing words for newline' ' echo "aaa (aaa)" >pre && echo "aaa (aaa) aaa" >post && - cat >expect <<-\EOF && + pre=$(git rev-parse --short $(git hash-object pre)) && + post=$(git rev-parse --short $(git hash-object post)) && + cat >expect <<-EOF && <BOLD>diff --git a/pre b/post<RESET> - <BOLD>index c29453b..be22f37 100644<RESET> + <BOLD>index $pre..$post 100644<RESET> <BOLD>--- a/pre<RESET> <BOLD>+++ b/post<RESET> <CYAN>@@ -1 +1 @@<RESET> @@ -268,9 +275,11 @@ test_expect_success 'test parsing words for newline' ' test_expect_success 'test when words are only removed at the end' ' echo "(:" >pre && echo "(" >post && - cat >expect <<-\EOF && + pre=$(git rev-parse --short $(git hash-object pre)) && + post=$(git rev-parse --short $(git hash-object post)) && + cat >expect <<-EOF && <BOLD>diff --git a/pre b/post<RESET> - <BOLD>index 289cb9d..2d06f37 100644<RESET> + <BOLD>index $pre..$post 100644<RESET> <BOLD>--- a/pre<RESET> <BOLD>+++ b/post<RESET> <CYAN>@@ -1 +1 @@<RESET> @@ -282,9 +291,11 @@ test_expect_success 'test when words are only removed at the end' ' test_expect_success '--word-diff=none' ' echo "(:" >pre && echo "(" >post && - cat >expect <<-\EOF && + pre=$(git rev-parse --short $(git hash-object pre)) && + post=$(git rev-parse --short $(git hash-object post)) && + cat >expect <<-EOF && diff --git a/pre b/post - index 289cb9d..2d06f37 100644 + index $pre..$post 100644 --- a/pre +++ b/post @@ -1 +1 @@ @@ -303,6 +314,7 @@ test_language_driver bibtex test_language_driver cpp test_language_driver csharp test_language_driver css +test_language_driver dts test_language_driver fortran test_language_driver html test_language_driver java @@ -316,16 +328,6 @@ test_language_driver ruby test_language_driver tex test_expect_success 'word-diff with diff.sbe' ' - cat >expect <<-\EOF && - diff --git a/pre b/post - index a1a53b5..bc8fe6d 100644 - --- a/pre - +++ b/post - @@ -1,3 +1,3 @@ - a - - [-b-]{+c+} - EOF cat >pre <<-\EOF && a @@ -336,21 +338,35 @@ test_expect_success 'word-diff with diff.sbe' ' c EOF + pre=$(git rev-parse --short $(git hash-object pre)) && + post=$(git rev-parse --short $(git hash-object post)) && + cat >expect <<-EOF && + diff --git a/pre b/post + index $pre..$post 100644 + --- a/pre + +++ b/post + @@ -1,3 +1,3 @@ + a + + [-b-]{+c+} + EOF test_config diff.suppress-blank-empty true && word_diff --word-diff=plain ' test_expect_success 'word-diff with no newline at EOF' ' - cat >expect <<-\EOF && + printf "%s" "a a a a a" >pre && + printf "%s" "a a ab a a" >post && + pre=$(git rev-parse --short $(git hash-object pre)) && + post=$(git rev-parse --short $(git hash-object post)) && + cat >expect <<-EOF && diff --git a/pre b/post - index 7bf316e..3dd0303 100644 + index $pre..$post 100644 --- a/pre +++ b/post @@ -1 +1 @@ a a [-a-]{+ab+} a a EOF - printf "%s" "a a a a a" >pre && - printf "%s" "a a ab a a" >post && word_diff --word-diff=plain ' diff --git a/t/t4034/dts/expect b/t/t4034/dts/expect new file mode 100644 index 0000000000..560fc99184 --- /dev/null +++ b/t/t4034/dts/expect @@ -0,0 +1,37 @@ +<BOLD>diff --git a/pre b/post<RESET> +<BOLD>index b6a9051..7803aee 100644<RESET> +<BOLD>--- a/pre<RESET> +<BOLD>+++ b/post<RESET> +<CYAN>@@ -1,32 +1,32 @@<RESET> +/ {<RESET> + <RED>this_handle<RESET><GREEN>HANDLE_2<RESET>: <RED>node<RESET><GREEN>new-node<RESET>@<RED>f00<RESET><GREEN>eeda<RESET> { + compatible = "<RED>mydev<RESET><GREEN>vendor,compat<RESET>"; + string-prop = <RED>start<RESET><GREEN>end<RESET>: "hello <RED>world!<RESET><GREEN>world?<RESET>" <RED>end<RESET><GREEN>start<RESET>: ; + <RED>#size-cells<RESET><GREEN>#address-cells<RESET> = <<RED>0+0<RESET><GREEN>0+40<RESET>>; + reg = <<RED>0xf00<RESET><GREEN>0xeeda<RESET>>; + prop = <<GREEN>(<RESET>1<GREEN>)<RESET>>; + prop = <<GREEN>(<RESET>-1e10<GREEN>)<RESET>>; + prop = <(!<RED>3<RESET><GREEN>1<RESET>)>; + prop = <(~<RED>3<RESET><GREEN>1<RESET>)>; + prop = <(<RED>3<RESET><GREEN>1<RESET>*<RED>4<RESET><GREEN>2<RESET>)>; + prop = <(<RED>3<RESET><GREEN>1<RESET>&<RED>4<RESET><GREEN>2<RESET>)>; + prop = <(<RED>3<RESET><GREEN>1<RESET>*<RED>4<RESET><GREEN>2<RESET>)>; + prop = <(<RED>3<RESET><GREEN>1<RESET>/<RED>4<RESET><GREEN>2<RESET>)>; + prop = <(<RED>3<RESET><GREEN>1<RESET>%<RED>4<RESET><GREEN>2<RESET>)>; + prop = <(<RED>3+4<RESET><GREEN>1+2<RESET>)>; + prop = <(<RED>3-4<RESET><GREEN>1-2<RESET>)>; + prop = /bits/ <RED>64<RESET><GREEN>32<RESET> <(<RED>3<RESET><GREEN>1<RESET><<<RED>4<RESET><GREEN>2<RESET>)>; + prop = <(<RED>3<RESET><GREEN>1<RESET>>><RED>4<RESET><GREEN>2<RESET>)>; + prop = <(<RED>3<RESET><GREEN>1<RESET>&<RED>4<RESET><GREEN>2<RESET>)>; + prop = <(<RED>3<RESET><GREEN>1<RESET>^<RED>4<RESET><GREEN>2<RESET>)>; + prop = <(<RED>3<RESET><GREEN>1<RESET>|<RED>4<RESET><GREEN>2<RESET>)>; + prop = <(<RED>3<RESET><GREEN>1<RESET>&&<RED>4<RESET><GREEN>2<RESET>)>; + prop = <(<RED>3<RESET><GREEN>1<RESET>||<RED>4<RESET><GREEN>2<RESET>)>; + prop = <(<RED>4?5<RESET><GREEN>1?2<RESET>:3)>; + list = <&<RED>this_handle<RESET><GREEN>HANDLE_2<RESET>>, <0 0 0 <RED>0<RESET><GREEN>1<RESET>>; + };<RESET> + + &<RED>phandle<RESET><GREEN>phandle2<RESET> { + <RED>pre-phandle<RESET><GREEN>prop_handle<RESET> = <&<RED>this_handle<RESET><GREEN>HANDLE_2<RESET>>; + };<RESET> +};<RESET> diff --git a/t/t4034/dts/post b/t/t4034/dts/post new file mode 100644 index 0000000000..7803aee280 --- /dev/null +++ b/t/t4034/dts/post @@ -0,0 +1,32 @@ +/ { + HANDLE_2: new-node@eeda { + compatible = "vendor,compat"; + string-prop = end: "hello world?" start: ; + #address-cells = <0+40>; + reg = <0xeeda>; + prop = <(1)>; + prop = <(-1e10)>; + prop = <(!1)>; + prop = <(~1)>; + prop = <(1*2)>; + prop = <(1&2)>; + prop = <(1*2)>; + prop = <(1/2)>; + prop = <(1%2)>; + prop = <(1+2)>; + prop = <(1-2)>; + prop = /bits/ 32 <(1<<2)>; + prop = <(1>>2)>; + prop = <(1&2)>; + prop = <(1^2)>; + prop = <(1|2)>; + prop = <(1&&2)>; + prop = <(1||2)>; + prop = <(1?2:3)>; + list = <&HANDLE_2>, <0 0 0 1>; + }; + + &phandle2 { + prop_handle = <&HANDLE_2>; + }; +}; diff --git a/t/t4034/dts/pre b/t/t4034/dts/pre new file mode 100644 index 0000000000..b6a905113c --- /dev/null +++ b/t/t4034/dts/pre @@ -0,0 +1,32 @@ +/ { + this_handle: node@f00 { + compatible = "mydev"; + string-prop = start: "hello world!" end: ; + #size-cells = <0+0>; + reg = <0xf00>; + prop = <1>; + prop = <-1e10>; + prop = <(!3)>; + prop = <(~3)>; + prop = <(3*4)>; + prop = <(3&4)>; + prop = <(3*4)>; + prop = <(3/4)>; + prop = <(3%4)>; + prop = <(3+4)>; + prop = <(3-4)>; + prop = /bits/ 64 <(3<<4)>; + prop = <(3>>4)>; + prop = <(3&4)>; + prop = <(3^4)>; + prop = <(3|4)>; + prop = <(3&&4)>; + prop = <(3||4)>; + prop = <(4?5:3)>; + list = <&this_handle>, <0 0 0 0>; + }; + + &phandle { + pre-phandle = <&this_handle>; + }; +}; diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh index d4afe12554..94680836ce 100755 --- a/t/t4038-diff-combined.sh +++ b/t/t4038-diff-combined.sh @@ -354,7 +354,7 @@ test_expect_failure 'combine diff coalesce three parents' ' ' # Test for a bug reported at -# https://public-inbox.org/git/20130515143508.GO25742@login.drsnuggles.stderr.nl/ +# https://lore.kernel.org/git/20130515143508.GO25742@login.drsnuggles.stderr.nl/ # where a delete lines were missing from combined diff output when they # occurred exactly before the context lines of a later change. test_expect_success 'combine diff missing delete bug' ' @@ -440,11 +440,13 @@ test_expect_success 'setup for --combined-all-paths' ' git branch side2c && git checkout side1c && test_seq 1 10 >filename-side1c && + side1cf=$(git hash-object filename-side1c) && git add filename-side1c && git commit -m with && git checkout side2c && test_seq 1 9 >filename-side2c && echo ten >>filename-side2c && + side2cf=$(git hash-object filename-side2c) && git add filename-side2c && git commit -m iam && git checkout -b mergery side1c && @@ -452,13 +454,14 @@ test_expect_success 'setup for --combined-all-paths' ' git rm filename-side1c && echo eleven >>filename-side2c && git mv filename-side2c filename-merged && + mergedf=$(git hash-object filename-merged) && git add filename-merged && git commit ' test_expect_success '--combined-all-paths and --raw' ' - cat <<-\EOF >expect && - ::100644 100644 100644 f00c965d8307308469e537302baa73048488f162 088bd5d92c2a8e0203ca8e7e4c2a5c692f6ae3f7 333b9c62519f285e1854830ade0fe1ef1d40ee1b RR filename-side1c filename-side2c filename-merged + cat <<-EOF >expect && + ::100644 100644 100644 $side1cf $side2cf $mergedf RR filename-side1c filename-side2c filename-merged EOF git diff-tree -c -M --raw --combined-all-paths HEAD >actual.tmp && sed 1d <actual.tmp >actual && @@ -482,11 +485,13 @@ test_expect_success FUNNYNAMES 'setup for --combined-all-paths with funny names' git checkout side1d && test_seq 1 10 >"$(printf "file\twith\ttabs")" && git add file* && + side1df=$(git hash-object *tabs) && git commit -m with && git checkout side2d && test_seq 1 9 >"$(printf "i\tam\ttabbed")" && echo ten >>"$(printf "i\tam\ttabbed")" && git add *tabbed && + side2df=$(git hash-object *tabbed) && git commit -m iam && git checkout -b funny-names-mergery side1d && git merge --no-commit side2d && @@ -494,12 +499,14 @@ test_expect_success FUNNYNAMES 'setup for --combined-all-paths with funny names' echo eleven >>"$(printf "i\tam\ttabbed")" && git mv "$(printf "i\tam\ttabbed")" "$(printf "fickle\tnaming")" && git add fickle* && - git commit + headf=$(git hash-object fickle*) && + git commit && + head=$(git rev-parse HEAD) ' test_expect_success FUNNYNAMES '--combined-all-paths and --raw and funny names' ' - cat <<-\EOF >expect && - ::100644 100644 100644 f00c965d8307308469e537302baa73048488f162 088bd5d92c2a8e0203ca8e7e4c2a5c692f6ae3f7 333b9c62519f285e1854830ade0fe1ef1d40ee1b RR "file\twith\ttabs" "i\tam\ttabbed" "fickle\tnaming" + cat <<-EOF >expect && + ::100644 100644 100644 $side1df $side2df $headf RR "file\twith\ttabs" "i\tam\ttabbed" "fickle\tnaming" EOF git diff-tree -c -M --raw --combined-all-paths HEAD >actual.tmp && sed 1d <actual.tmp >actual && @@ -507,9 +514,9 @@ test_expect_success FUNNYNAMES '--combined-all-paths and --raw and funny names' ' test_expect_success FUNNYNAMES '--combined-all-paths and --raw -and -z and funny names' ' - printf "aaf8087c3cbd4db8e185a2d074cf27c53cfb75d7\0::100644 100644 100644 f00c965d8307308469e537302baa73048488f162 088bd5d92c2a8e0203ca8e7e4c2a5c692f6ae3f7 333b9c62519f285e1854830ade0fe1ef1d40ee1b RR\0file\twith\ttabs\0i\tam\ttabbed\0fickle\tnaming\0" >expect && + printf "$head\0::100644 100644 100644 $side1df $side2df $headf RR\0file\twith\ttabs\0i\tam\ttabbed\0fickle\tnaming\0" >expect && git diff-tree -c -M --raw --combined-all-paths -z HEAD >actual && - test_cmp -a expect actual + test_cmp expect actual ' test_expect_success FUNNYNAMES '--combined-all-paths and --cc and funny names' ' diff --git a/t/t4039-diff-assume-unchanged.sh b/t/t4039-diff-assume-unchanged.sh index 53ac44b0f0..0eb0314a8b 100755 --- a/t/t4039-diff-assume-unchanged.sh +++ b/t/t4039-diff-assume-unchanged.sh @@ -12,6 +12,7 @@ test_expect_success 'setup' ' git commit -m zero && echo one > one && echo two > two && + blob=$(git hash-object one) && git add one two && git commit -m onetwo && git update-index --assume-unchanged one && @@ -20,7 +21,7 @@ test_expect_success 'setup' ' ' test_expect_success 'diff-index does not examine assume-unchanged entries' ' - git diff-index HEAD^ -- one | grep -q 5626abf0f72e58d7a153368ba57db4c673c0e171 + git diff-index HEAD^ -- one | grep -q $blob ' test_expect_success 'diff-files does not examine assume-unchanged entries' ' diff --git a/t/t4041-diff-submodule-option.sh b/t/t4041-diff-submodule-option.sh index 619bf97098..f852136585 100755 --- a/t/t4041-diff-submodule-option.sh +++ b/t/t4041-diff-submodule-option.sh @@ -284,7 +284,7 @@ test_expect_success 'submodule contains untracked content (all ignored)' ' test_must_be_empty actual ' -test_expect_success 'submodule contains untracked and modifed content' ' +test_expect_success 'submodule contains untracked and modified content' ' echo new > sm1/foo6 && git diff-index -p --submodule=log HEAD >actual && cat >expected <<-EOF && @@ -294,7 +294,7 @@ test_expect_success 'submodule contains untracked and modifed content' ' test_cmp expected actual ' -test_expect_success 'submodule contains untracked and modifed content (untracked ignored)' ' +test_expect_success 'submodule contains untracked and modified content (untracked ignored)' ' echo new > sm1/foo6 && git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual && cat >expected <<-EOF && @@ -303,19 +303,19 @@ test_expect_success 'submodule contains untracked and modifed content (untracked test_cmp expected actual ' -test_expect_success 'submodule contains untracked and modifed content (dirty ignored)' ' +test_expect_success 'submodule contains untracked and modified content (dirty ignored)' ' echo new > sm1/foo6 && git diff-index -p --ignore-submodules=dirty --submodule=log HEAD >actual && test_must_be_empty actual ' -test_expect_success 'submodule contains untracked and modifed content (all ignored)' ' +test_expect_success 'submodule contains untracked and modified content (all ignored)' ' echo new > sm1/foo6 && git diff-index -p --ignore-submodules --submodule=log HEAD >actual && test_must_be_empty actual ' -test_expect_success 'submodule contains modifed content' ' +test_expect_success 'submodule contains modified content' ' rm -f sm1/new-file && git diff-index -p --submodule=log HEAD >actual && cat >expected <<-EOF && @@ -369,7 +369,7 @@ test_expect_success 'modified submodule contains untracked content (all ignored) test_must_be_empty actual ' -test_expect_success 'modified submodule contains untracked and modifed content' ' +test_expect_success 'modified submodule contains untracked and modified content' ' echo modification >> sm1/foo6 && git diff-index -p --submodule=log HEAD >actual && cat >expected <<-EOF && @@ -381,7 +381,7 @@ test_expect_success 'modified submodule contains untracked and modifed content' test_cmp expected actual ' -test_expect_success 'modified submodule contains untracked and modifed content (untracked ignored)' ' +test_expect_success 'modified submodule contains untracked and modified content (untracked ignored)' ' echo modification >> sm1/foo6 && git diff-index -p --ignore-submodules=untracked --submodule=log HEAD >actual && cat >expected <<-EOF && @@ -392,7 +392,7 @@ test_expect_success 'modified submodule contains untracked and modifed content ( test_cmp expected actual ' -test_expect_success 'modified submodule contains untracked and modifed content (dirty ignored)' ' +test_expect_success 'modified submodule contains untracked and modified content (dirty ignored)' ' echo modification >> sm1/foo6 && git diff-index -p --ignore-submodules=dirty --submodule=log HEAD >actual && cat >expected <<-EOF && @@ -402,13 +402,13 @@ test_expect_success 'modified submodule contains untracked and modifed content ( test_cmp expected actual ' -test_expect_success 'modified submodule contains untracked and modifed content (all ignored)' ' +test_expect_success 'modified submodule contains untracked and modified content (all ignored)' ' echo modification >> sm1/foo6 && git diff-index -p --ignore-submodules --submodule=log HEAD >actual && test_must_be_empty actual ' -test_expect_success 'modified submodule contains modifed content' ' +test_expect_success 'modified submodule contains modified content' ' rm -f sm1/new-file && git diff-index -p --submodule=log HEAD >actual && cat >expected <<-EOF && diff --git a/t/t4044-diff-index-unique-abbrev.sh b/t/t4044-diff-index-unique-abbrev.sh index 647905e01f..4701796d10 100755 --- a/t/t4044-diff-index-unique-abbrev.sh +++ b/t/t4044-diff-index-unique-abbrev.sh @@ -3,34 +3,48 @@ test_description='test unique sha1 abbreviation on "index from..to" line' . ./test-lib.sh -if ! test_have_prereq SHA1 -then - skip_all='not using SHA-1 for objects' - test_done -fi - -cat >expect_initial <<EOF -100644 blob 51d2738463ea4ca66f8691c91e33ce64b7d41bb1 foo -EOF +test_expect_success 'setup' ' + test_oid_cache <<-EOF && + val1 sha1:4827 + val1 sha256:5664 -cat >expect_update <<EOF -100644 blob 51d2738efb4ad8a1e40bed839ab8e116f0a15e47 foo -EOF + val2 sha1:11742 + val2 sha256:10625 -test_expect_success 'setup' ' - echo 4827 > foo && + hash1 sha1:51d2738463ea4ca66f8691c91e33ce64b7d41bb1 + hash1 sha256:ae31dfff0af93b2c62b0098a039b38569c43b0a7e97b873000ca42d128f27350 + + hasht1 sha1:51d27384 + hasht1 sha256:ae31dfff + + hash2 sha1:51d2738efb4ad8a1e40bed839ab8e116f0a15e47 + hash2 sha256:ae31dffada88a46fd5f53c7ed5aa25a7a8951f1d5e88456c317c8d5484d263e5 + + hasht2 sha1:51d2738e + hasht2 sha256:ae31dffa + EOF + + cat >expect_initial <<-EOF && + 100644 blob $(test_oid hash1) foo + EOF + + cat >expect_update <<-EOF && + 100644 blob $(test_oid hash2) foo + EOF + + echo "$(test_oid val1)" > foo && git add foo && git commit -m "initial" && git cat-file -p HEAD: > actual && test_cmp expect_initial actual && - echo 11742 > foo && + echo "$(test_oid val2)" > foo && git commit -a -m "update" && git cat-file -p HEAD: > actual && test_cmp expect_update actual ' cat >expect <<EOF -index 51d27384..51d2738e 100644 +index $(test_oid hasht1)..$(test_oid hasht2) 100644 EOF test_expect_success 'diff does not produce ambiguous index line' ' diff --git a/t/t4045-diff-relative.sh b/t/t4045-diff-relative.sh index 36f8ed8a81..258808708e 100755 --- a/t/t4045-diff-relative.sh +++ b/t/t4045-diff-relative.sh @@ -70,7 +70,7 @@ check_raw () { expect=$1 shift cat >expected <<-EOF - :000000 100644 0000000000000000000000000000000000000000 $blob A $expect + :000000 100644 $ZERO_OID $blob A $expect EOF test_expect_success "--raw $*" " git -C '$dir' diff --no-abbrev --raw $* HEAD^ >actual && diff --git a/t/t4048-diff-combined-binary.sh b/t/t4048-diff-combined-binary.sh index 87a8949500..7f9ad9fa3d 100755 --- a/t/t4048-diff-combined-binary.sh +++ b/t/t4048-diff-combined-binary.sh @@ -9,24 +9,27 @@ test_expect_success 'setup binary merge conflict' ' git commit -m one && echo twoQ2 | q_to_nul >binary && git commit -a -m two && + two=$(git rev-parse --short HEAD:binary) && git checkout -b branch-binary HEAD^ && echo threeQ3 | q_to_nul >binary && git commit -a -m three && + three=$(git rev-parse --short HEAD:binary) && test_must_fail git merge master && echo resolvedQhooray | q_to_nul >binary && - git commit -a -m resolved + git commit -a -m resolved && + res=$(git rev-parse --short HEAD:binary) ' -cat >expect <<'EOF' +cat >expect <<EOF resolved diff --git a/binary b/binary -index 7ea6ded..9563691 100644 +index $three..$res 100644 Binary files a/binary and b/binary differ resolved diff --git a/binary b/binary -index 6197570..9563691 100644 +index $two..$res 100644 Binary files a/binary and b/binary differ EOF test_expect_success 'diff -m indicates binary-ness' ' @@ -34,11 +37,11 @@ test_expect_success 'diff -m indicates binary-ness' ' test_cmp expect actual ' -cat >expect <<'EOF' +cat >expect <<EOF resolved diff --combined binary -index 7ea6ded,6197570..9563691 +index $three,$two..$res Binary files differ EOF test_expect_success 'diff -c indicates binary-ness' ' @@ -46,11 +49,11 @@ test_expect_success 'diff -c indicates binary-ness' ' test_cmp expect actual ' -cat >expect <<'EOF' +cat >expect <<EOF resolved diff --cc binary -index 7ea6ded,6197570..9563691 +index $three,$two..$res Binary files differ EOF test_expect_success 'diff --cc indicates binary-ness' ' @@ -62,23 +65,26 @@ test_expect_success 'setup non-binary with binary attribute' ' git checkout master && test_commit one text && test_commit two text && + two=$(git rev-parse --short HEAD:text) && git checkout -b branch-text HEAD^ && test_commit three text && + three=$(git rev-parse --short HEAD:text) && test_must_fail git merge master && test_commit resolved text && + res=$(git rev-parse --short HEAD:text) && echo text -diff >.gitattributes ' -cat >expect <<'EOF' +cat >expect <<EOF resolved diff --git a/text b/text -index 2bdf67a..2ab19ae 100644 +index $three..$res 100644 Binary files a/text and b/text differ resolved diff --git a/text b/text -index f719efd..2ab19ae 100644 +index $two..$res 100644 Binary files a/text and b/text differ EOF test_expect_success 'diff -m respects binary attribute' ' @@ -86,11 +92,11 @@ test_expect_success 'diff -m respects binary attribute' ' test_cmp expect actual ' -cat >expect <<'EOF' +cat >expect <<EOF resolved diff --combined text -index 2bdf67a,f719efd..2ab19ae +index $three,$two..$res Binary files differ EOF test_expect_success 'diff -c respects binary attribute' ' @@ -98,11 +104,11 @@ test_expect_success 'diff -c respects binary attribute' ' test_cmp expect actual ' -cat >expect <<'EOF' +cat >expect <<EOF resolved diff --cc text -index 2bdf67a,f719efd..2ab19ae +index $three,$two..$res Binary files differ EOF test_expect_success 'diff --cc respects binary attribute' ' @@ -115,11 +121,11 @@ test_expect_success 'setup textconv attribute' ' git config diff.upcase.textconv "tr a-z A-Z <" ' -cat >expect <<'EOF' +cat >expect <<EOF resolved diff --git a/text b/text -index 2bdf67a..2ab19ae 100644 +index $three..$res 100644 --- a/text +++ b/text @@ -1 +1 @@ @@ -128,7 +134,7 @@ index 2bdf67a..2ab19ae 100644 resolved diff --git a/text b/text -index f719efd..2ab19ae 100644 +index $two..$res 100644 --- a/text +++ b/text @@ -1 +1 @@ @@ -140,11 +146,11 @@ test_expect_success 'diff -m respects textconv attribute' ' test_cmp expect actual ' -cat >expect <<'EOF' +cat >expect <<EOF resolved diff --combined text -index 2bdf67a,f719efd..2ab19ae +index $three,$two..$res --- a/text +++ b/text @@@ -1,1 -1,1 +1,1 @@@ @@ -157,11 +163,11 @@ test_expect_success 'diff -c respects textconv attribute' ' test_cmp expect actual ' -cat >expect <<'EOF' +cat >expect <<EOF resolved diff --cc text -index 2bdf67a,f719efd..2ab19ae +index $three,$two..$res --- a/text +++ b/text @@@ -1,1 -1,1 +1,1 @@@ @@ -174,9 +180,9 @@ test_expect_success 'diff --cc respects textconv attribute' ' test_cmp expect actual ' -cat >expect <<'EOF' +cat >expect <<EOF diff --combined text -index 2bdf67a,f719efd..2ab19ae +index $three,$two..$res --- a/text +++ b/text @@@ -1,1 -1,1 +1,1 @@@ @@ -190,9 +196,9 @@ test_expect_success 'diff-tree plumbing does not respect textconv' ' test_cmp expect actual ' -cat >expect <<'EOF' +cat >expect <<EOF diff --cc text -index 2bdf67a,f719efd..0000000 +index $three,$two..0000000 --- a/text +++ b/text @@@ -1,1 -1,1 +1,5 @@@ diff --git a/t/t4057-diff-combined-paths.sh b/t/t4057-diff-combined-paths.sh index dff36b77ec..4f4b541658 100755 --- a/t/t4057-diff-combined-paths.sh +++ b/t/t4057-diff-combined-paths.sh @@ -33,7 +33,7 @@ test_expect_success 'trivial merge - combine-diff empty' ' ' -test_expect_success 'only one trully conflicting path' ' +test_expect_success 'only one truly conflicting path' ' git checkout side && for i in $(test_seq 2 9) do diff --git a/t/t4067-diff-partial-clone.sh b/t/t4067-diff-partial-clone.sh index 90c8fb2901..4831ad35e6 100755 --- a/t/t4067-diff-partial-clone.sh +++ b/t/t4067-diff-partial-clone.sh @@ -75,6 +75,37 @@ test_expect_success 'diff skips same-OID blobs' ' ! grep "want $(cat hash-b)" trace ' +test_expect_success 'when fetching missing objects, diff skips GITLINKs' ' + test_when_finished "rm -rf sub server client trace" && + + test_create_repo sub && + test_commit -C sub first && + + test_create_repo server && + echo a >server/a && + git -C server add a && + git -C server submodule add "file://$(pwd)/sub" && + git -C server commit -m x && + + test_commit -C server/sub second && + echo another-a >server/a && + git -C server add a sub && + git -C server commit -m x && + + test_config -C server uploadpack.allowfilter 1 && + test_config -C server uploadpack.allowanysha1inwant 1 && + git clone --bare --filter=blob:limit=0 "file://$(pwd)/server" client && + + echo a | git hash-object --stdin >hash-old-a && + echo another-a | git hash-object --stdin >hash-new-a && + + # Ensure that a and another-a are fetched, and check (by successful + # execution of the diff) that no invalid OIDs are sent. + GIT_TRACE_PACKET="$(pwd)/trace" git -C client diff HEAD^ HEAD && + grep "want $(cat hash-old-a)" trace && + grep "want $(cat hash-new-a)" trace +' + test_expect_success 'diff with rename detection batches blobs' ' test_when_finished "rm -rf server client trace" && diff --git a/t/t4100/t-apply-1.patch b/t/t4100/t-apply-1.patch index 90ab54f0f5..43394f8285 100644 --- a/t/t4100/t-apply-1.patch +++ b/t/t4100/t-apply-1.patch @@ -75,8 +75,8 @@ diff --git a/Documentation/git.txt b/Documentation/git.txt +link:git-ssh-pull.html[git-ssh-pull]:: Pulls from a remote repository over ssh connection - Interogators: -@@ -156,8 +156,8 @@ Interogators: + Interrogators: +@@ -156,8 +156,8 @@ Interrogators: link:git-diff-helper.html[git-diff-helper]:: Generates patch format output for git-diff-* diff --git a/t/t4100/t-apply-3.patch b/t/t4100/t-apply-3.patch index 90cdbaa5bb..cac172e779 100644 --- a/t/t4100/t-apply-3.patch +++ b/t/t4100/t-apply-3.patch @@ -211,7 +211,7 @@ dissimilarity index 82% - - /* If this is an exact directory match, we may have - * directory files following this path. Match on them. -- * Otherwise, we're at a pach subcomponent, and we need +- * Otherwise, we're at a patch subcomponent, and we need - * to try to match again. - */ - if (mtype == 0) diff --git a/t/t4100/t-apply-5.patch b/t/t4100/t-apply-5.patch index 5f6ddc1059..57ec79d887 100644 --- a/t/t4100/t-apply-5.patch +++ b/t/t4100/t-apply-5.patch @@ -185,8 +185,8 @@ diff a/Documentation/git.txt b/Documentation/git.txt +link:git-ssh-pull.html[git-ssh-pull]:: Pulls from a remote repository over ssh connection - Interogators: -@@ -156,8 +156,8 @@ Interogators: + Interrogators: +@@ -156,8 +156,8 @@ Interrogators: link:git-diff-helper.html[git-diff-helper]:: Generates patch format output for git-diff-* diff --git a/t/t4100/t-apply-7.patch b/t/t4100/t-apply-7.patch index 07c6589e74..fa24305108 100644 --- a/t/t4100/t-apply-7.patch +++ b/t/t4100/t-apply-7.patch @@ -335,7 +335,7 @@ diff a/ls-tree.c b/ls-tree.c - /* If this is an exact directory match, we may have - * directory files following this path. Match on them. -- * Otherwise, we're at a pach subcomponent, and we need +- * Otherwise, we're at a patch subcomponent, and we need - * to try to match again. + if (e->directory) { + /* If this is a directory, we have the following cases: diff --git a/t/t4108-apply-threeway.sh b/t/t4108-apply-threeway.sh index fa5d4efb89..d7349ced6b 100755 --- a/t/t4108-apply-threeway.sh +++ b/t/t4108-apply-threeway.sh @@ -4,23 +4,17 @@ test_description='git apply --3way' . ./test-lib.sh -create_file () { - for i - do - echo "$i" - done -} - -sanitize_conflicted_diff () { +print_sanitized_conflicted_diff () { + git diff HEAD >diff.raw && sed -e ' /^index /d - s/^\(+[<>][<>][<>][<>]*\) .*/\1/ - ' + s/^\(+[<>|][<>|][<>|][<>|]*\) .*/\1/ + ' diff.raw } test_expect_success setup ' test_tick && - create_file >one 1 2 3 4 5 6 7 && + test_write_lines 1 2 3 4 5 6 7 >one && cat one >two && git add one two && git commit -m initial && @@ -28,13 +22,13 @@ test_expect_success setup ' git branch side && test_tick && - create_file >one 1 two 3 4 5 six 7 && - create_file >two 1 two 3 4 5 6 7 && + test_write_lines 1 two 3 4 5 six 7 >one && + test_write_lines 1 two 3 4 5 6 7 >two && git commit -a -m master && git checkout side && - create_file >one 1 2 3 4 five 6 7 && - create_file >two 1 2 3 4 five 6 7 && + test_write_lines 1 2 3 4 five 6 7 >one && + test_write_lines 1 2 3 4 five 6 7 >two && git commit -a -m side && git checkout master @@ -52,7 +46,7 @@ test_expect_success 'apply without --3way' ' git diff-index --exit-code --cached HEAD ' -test_expect_success 'apply with --3way' ' +test_apply_with_3way () { # Merging side should be similar to applying this patch git diff ...side >P.diff && @@ -61,22 +55,31 @@ test_expect_success 'apply with --3way' ' git checkout master^0 && test_must_fail git merge --no-commit side && git ls-files -s >expect.ls && - git diff HEAD | sanitize_conflicted_diff >expect.diff && + print_sanitized_conflicted_diff >expect.diff && # should fail to apply git reset --hard && git checkout master^0 && test_must_fail git apply --index --3way P.diff && git ls-files -s >actual.ls && - git diff HEAD | sanitize_conflicted_diff >actual.diff && + print_sanitized_conflicted_diff >actual.diff && # The result should resemble the corresponding merge test_cmp expect.ls actual.ls && test_cmp expect.diff actual.diff +} + +test_expect_success 'apply with --3way' ' + test_apply_with_3way +' + +test_expect_success 'apply with --3way with merge.conflictStyle = diff3' ' + test_config merge.conflictStyle diff3 && + test_apply_with_3way ' test_expect_success 'apply with --3way with rerere enabled' ' - git config rerere.enabled true && + test_config rerere.enabled true && # Merging side should be similar to applying this patch git diff ...side >P.diff && @@ -87,7 +90,7 @@ test_expect_success 'apply with --3way with rerere enabled' ' test_must_fail git merge --no-commit side && # Manually resolve and record the resolution - create_file 1 two 3 4 five six 7 >one && + test_write_lines 1 two 3 4 five six 7 >one && git rerere && cat one >expect && @@ -104,14 +107,14 @@ test_expect_success 'apply -3 with add/add conflict setup' ' git reset --hard && git checkout -b adder && - create_file 1 2 3 4 5 6 7 >three && - create_file 1 2 3 4 5 6 7 >four && + test_write_lines 1 2 3 4 5 6 7 >three && + test_write_lines 1 2 3 4 5 6 7 >four && git add three four && git commit -m "add three and four" && git checkout -b another adder^ && - create_file 1 2 3 4 5 6 7 >three && - create_file 1 2 3 four 5 6 7 >four && + test_write_lines 1 2 3 4 5 6 7 >three && + test_write_lines 1 2 3 four 5 6 7 >four && git add three four && git commit -m "add three and four" && @@ -121,7 +124,7 @@ test_expect_success 'apply -3 with add/add conflict setup' ' git checkout adder^0 && test_must_fail git merge --no-commit another && git ls-files -s >expect.ls && - git diff HEAD | sanitize_conflicted_diff >expect.diff + print_sanitized_conflicted_diff >expect.diff ' test_expect_success 'apply -3 with add/add conflict' ' @@ -131,7 +134,7 @@ test_expect_success 'apply -3 with add/add conflict' ' test_must_fail git apply --index --3way P.diff && # ... and leave conflicts in the index and in the working tree git ls-files -s >actual.ls && - git diff HEAD | sanitize_conflicted_diff >actual.diff && + print_sanitized_conflicted_diff >actual.diff && # The result should resemble the corresponding merge test_cmp expect.ls actual.ls && diff --git a/t/t4150-am.sh b/t/t4150-am.sh index 3f7f750cc8..4f1e24ecbe 100755 --- a/t/t4150-am.sh +++ b/t/t4150-am.sh @@ -1061,4 +1061,56 @@ test_expect_success 'am --quit keeps HEAD where it is' ' test_cmp expected actual ' +test_expect_success 'am and .gitattibutes' ' + test_create_repo attributes && + ( + cd attributes && + test_commit init && + git config filter.test.clean "sed -e '\''s/smudged/clean/g'\''" && + git config filter.test.smudge "sed -e '\''s/clean/smudged/g'\''" && + + test_commit second && + git checkout -b test HEAD^ && + + echo "*.txt filter=test conflict-marker-size=10" >.gitattributes && + git add .gitattributes && + test_commit third && + + echo "This text is smudged." >a.txt && + git add a.txt && + test_commit fourth && + + git checkout -b removal HEAD^ && + git rm .gitattributes && + git add -u && + test_commit fifth && + git cherry-pick test && + + git checkout -b conflict third && + echo "This text is different." >a.txt && + git add a.txt && + test_commit sixth && + + git checkout test && + git format-patch --stdout master..HEAD >patches && + git reset --hard master && + git am patches && + grep "smudged" a.txt && + + git checkout removal && + git reset --hard && + git format-patch --stdout master..HEAD >patches && + git reset --hard master && + git am patches && + grep "clean" a.txt && + + git checkout conflict && + git reset --hard && + git format-patch --stdout master..HEAD >patches && + git reset --hard fourth && + test_must_fail git am -3 patches && + grep "<<<<<<<<<<" a.txt + ) +' + test_done diff --git a/t/t4202-log.sh b/t/t4202-log.sh index da8cb06f9b..2c9489484a 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -352,7 +352,7 @@ test_expect_success 'log with grep.patternType configuration and command line' ' test_cmp expect actual ' -test_expect_success 'log with various grep.patternType configurations & command-lines' ' +test_expect_success !FAIL_PREREQS 'log with various grep.patternType configurations & command-lines' ' git init pattern-type && ( cd pattern-type && @@ -667,7 +667,7 @@ cat > expect <<\EOF * | | fifth * | | fourth |/ / -* | third +* / third |/ * second * initial @@ -837,6 +837,21 @@ test_expect_success 'decorate-refs and decorate-refs-exclude' ' test_cmp expect.decorate actual ' +test_expect_success 'decorate-refs-exclude and simplify-by-decoration' ' + cat >expect.decorate <<-\EOF && + Merge-tag-reach (HEAD -> master) + reach (tag: reach, reach) + seventh (tag: seventh) + Merge-branch-tangle + Merge-branch-side-early-part-into-tangle (tangle) + tangle-a (tag: tangle-a) + EOF + git log -n6 --decorate=short --pretty="tformat:%f%d" \ + --decorate-refs-exclude="*octopus*" \ + --simplify-by-decoration >actual && + test_cmp expect.decorate actual +' + test_expect_success 'log.decorate config parsing' ' git log --oneline --decorate=full >expect.full && git log --oneline --decorate=short >expect.short && @@ -1727,4 +1742,11 @@ test_expect_success '--exclude-promisor-objects does not BUG-crash' ' test_must_fail git log --exclude-promisor-objects source-a ' +test_expect_success 'log --end-of-options' ' + git update-ref refs/heads/--source HEAD && + git log --end-of-options --source >actual && + git log >expect && + test_cmp expect actual +' + test_done diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh index 43b1522ea2..586c3a86b1 100755 --- a/t/t4203-mailmap.sh +++ b/t/t4203-mailmap.sh @@ -13,8 +13,8 @@ fuzz_blame () { } test_expect_success setup ' - cat >contacts <<-\EOF && - A U Thor <author@example.com> + cat >contacts <<- EOF && + $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> nick1 <bugs@company.xx> EOF @@ -33,19 +33,19 @@ test_expect_success 'check-mailmap no arguments' ' ' test_expect_success 'check-mailmap arguments' ' - cat >expect <<-\EOF && - A U Thor <author@example.com> + cat >expect <<- EOF && + $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> nick1 <bugs@company.xx> EOF git check-mailmap \ - "A U Thor <author@example.com>" \ + "$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" \ "nick1 <bugs@company.xx>" >actual && test_cmp expect actual ' test_expect_success 'check-mailmap --stdin' ' - cat >expect <<-\EOF && - A U Thor <author@example.com> + cat >expect <<- EOF && + $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> nick1 <bugs@company.xx> EOF git check-mailmap --stdin <contacts >actual && @@ -66,8 +66,8 @@ test_expect_success 'check-mailmap bogus contact' ' test_must_fail git check-mailmap bogus ' -cat >expect <<\EOF -A U Thor (1): +cat >expect << EOF +$GIT_AUTHOR_NAME (1): initial nick1 (1): @@ -90,7 +90,7 @@ nick1 (1): EOF test_expect_success 'default .mailmap' ' - echo "Repo Guy <author@example.com>" > .mailmap && + echo "Repo Guy <$GIT_AUTHOR_EMAIL>" > .mailmap && git shortlog HEAD >actual && test_cmp expect actual ' @@ -122,7 +122,7 @@ Internal Guy (1): EOF test_expect_success 'mailmap.file override' ' - echo "External Guy <author@example.com>" >> internal_mailmap/.mailmap && + echo "External Guy <$GIT_AUTHOR_EMAIL>" >> internal_mailmap/.mailmap && git config mailmap.file internal_mailmap/.mailmap && git shortlog HEAD >actual && test_cmp expect actual @@ -178,8 +178,8 @@ test_expect_success 'name entry after email entry, case-insensitive' ' test_cmp expect actual ' -cat >expect <<\EOF -A U Thor (1): +cat >expect << EOF +$GIT_AUTHOR_NAME (1): initial nick1 (1): @@ -195,18 +195,18 @@ test_expect_success 'No mailmap files, but configured' ' test_expect_success 'setup mailmap blob tests' ' git checkout -b map && test_when_finished "git checkout master" && - cat >just-bugs <<-\EOF && + cat >just-bugs <<- EOF && Blob Guy <bugs@company.xx> EOF - cat >both <<-\EOF && - Blob Guy <author@example.com> + cat >both <<- EOF && + Blob Guy <$GIT_AUTHOR_EMAIL> Blob Guy <bugs@company.xx> EOF - printf "Tricky Guy <author@example.com>" >no-newline && + printf "Tricky Guy <$GIT_AUTHOR_EMAIL>" >no-newline && git add just-bugs both no-newline && git commit -m "my mailmaps" && - echo "Repo Guy <author@example.com>" >.mailmap && - echo "Internal Guy <author@example.com>" >internal.map + echo "Repo Guy <$GIT_AUTHOR_EMAIL>" >.mailmap && + echo "Internal Guy <$GIT_AUTHOR_EMAIL>" >internal.map ' test_expect_success 'mailmap.blob set' ' @@ -266,12 +266,12 @@ test_expect_success 'mailmap.blob defaults to off in non-bare repo' ' git init non-bare && ( cd non-bare && - test_commit one .mailmap "Fake Name <author@example.com>" && + test_commit one .mailmap "Fake Name <$GIT_AUTHOR_EMAIL>" && echo " 1 Fake Name" >expect && git shortlog -ns HEAD >actual && test_cmp expect actual && rm .mailmap && - echo " 1 A U Thor" >expect && + echo " 1 $GIT_AUTHOR_NAME" >expect && git shortlog -ns HEAD >actual && test_cmp expect actual ) @@ -305,26 +305,26 @@ test_expect_success 'cleanup after mailmap.blob tests' ' ' test_expect_success 'single-character name' ' - echo " 1 A <author@example.com>" >expect && + echo " 1 A <$GIT_AUTHOR_EMAIL>" >expect && echo " 1 nick1 <bugs@company.xx>" >>expect && - echo "A <author@example.com>" >.mailmap && + echo "A <$GIT_AUTHOR_EMAIL>" >.mailmap && test_when_finished "rm .mailmap" && git shortlog -es HEAD >actual && test_cmp expect actual ' test_expect_success 'preserve canonical email case' ' - echo " 1 A U Thor <AUTHOR@example.com>" >expect && + echo " 1 $GIT_AUTHOR_NAME <AUTHOR@example.com>" >expect && echo " 1 nick1 <bugs@company.xx>" >>expect && - echo "<AUTHOR@example.com> <author@example.com>" >.mailmap && + echo "<AUTHOR@example.com> <$GIT_AUTHOR_EMAIL>" >.mailmap && test_when_finished "rm .mailmap" && git shortlog -es HEAD >actual && test_cmp expect actual ' # Extended mailmap configurations should give us the following output for shortlog -cat >expect <<\EOF -A U Thor <author@example.com> (1): +cat >expect << EOF +$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> (1): initial CTO <cto@company.xx> (1): @@ -370,7 +370,7 @@ test_expect_success 'Shortlog output (complex mapping)' ' git commit --author "CTO <cto@coompany.xx>" -m seventh && mkdir -p internal_mailmap && - echo "Committed <committer@example.com>" > internal_mailmap/.mailmap && + echo "Committed <$GIT_COMMITTER_EMAIL>" > internal_mailmap/.mailmap && echo "<cto@company.xx> <cto@coompany.xx>" >> internal_mailmap/.mailmap && echo "Some Dude <some@dude.xx> nick1 <bugs@company.xx>" >> internal_mailmap/.mailmap && echo "Other Author <other@author.xx> nick2 <bugs@company.xx>" >> internal_mailmap/.mailmap && @@ -384,27 +384,27 @@ test_expect_success 'Shortlog output (complex mapping)' ' ' # git log with --pretty format which uses the name and email mailmap placemarkers -cat >expect <<\EOF +cat >expect << EOF Author CTO <cto@coompany.xx> maps to CTO <cto@company.xx> -Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com> +Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> Author claus <me@company.xx> maps to Santa Claus <santa.claus@northpole.xx> -Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com> +Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> Author santa <me@company.xx> maps to Santa Claus <santa.claus@northpole.xx> -Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com> +Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> Author nick2 <nick2@company.xx> maps to Other Author <other@author.xx> -Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com> +Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> Author nick2 <bugs@company.xx> maps to Other Author <other@author.xx> -Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com> +Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> Author nick1 <bugs@company.xx> maps to Some Dude <some@dude.xx> -Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com> +Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> -Author A U Thor <author@example.com> maps to A U Thor <author@example.com> -Committer C O Mitter <committer@example.com> maps to Committed <committer@example.com> +Author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> maps to $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> +Committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> maps to Committed <$GIT_COMMITTER_EMAIL> EOF test_expect_success 'Log output (complex mapping)' ' @@ -412,14 +412,42 @@ test_expect_success 'Log output (complex mapping)' ' test_cmp expect actual ' -cat >expect <<\EOF +cat >expect << EOF +Author email cto@coompany.xx has local-part cto +Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME + +Author email me@company.xx has local-part me +Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME + +Author email me@company.xx has local-part me +Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME + +Author email nick2@company.xx has local-part nick2 +Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME + +Author email bugs@company.xx has local-part bugs +Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME + +Author email bugs@company.xx has local-part bugs +Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME + +Author email author@example.com has local-part author +Committer email $GIT_COMMITTER_EMAIL has local-part $TEST_COMMITTER_LOCALNAME +EOF + +test_expect_success 'Log output (local-part email address)' ' + git log --pretty=format:"Author email %ae has local-part %al%nCommitter email %ce has local-part %cl%n" >actual && + test_cmp expect actual +' + +cat >expect << EOF Author: CTO <cto@company.xx> Author: Santa Claus <santa.claus@northpole.xx> Author: Santa Claus <santa.claus@northpole.xx> Author: Other Author <other@author.xx> Author: Other Author <other@author.xx> Author: Some Dude <some@dude.xx> -Author: A U Thor <author@example.com> +Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> EOF test_expect_success 'Log output with --use-mailmap' ' @@ -427,14 +455,14 @@ test_expect_success 'Log output with --use-mailmap' ' test_cmp expect actual ' -cat >expect <<\EOF +cat >expect << EOF Author: CTO <cto@company.xx> Author: Santa Claus <santa.claus@northpole.xx> Author: Santa Claus <santa.claus@northpole.xx> Author: Other Author <other@author.xx> Author: Other Author <other@author.xx> Author: Some Dude <some@dude.xx> -Author: A U Thor <author@example.com> +Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> EOF test_expect_success 'Log output with log.mailmap' ' @@ -442,6 +470,34 @@ test_expect_success 'Log output with log.mailmap' ' test_cmp expect actual ' +test_expect_success 'log.mailmap=false disables mailmap' ' + cat >expect <<- EOF && + Author: CTO <cto@coompany.xx> + Author: claus <me@company.xx> + Author: santa <me@company.xx> + Author: nick2 <nick2@company.xx> + Author: nick2 <bugs@company.xx> + Author: nick1 <bugs@company.xx> + Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> + EOF + git -c log.mailmap=False log | grep Author > actual && + test_cmp expect actual +' + +test_expect_success '--no-use-mailmap disables mailmap' ' + cat >expect <<- EOF && + Author: CTO <cto@coompany.xx> + Author: claus <me@company.xx> + Author: santa <me@company.xx> + Author: nick2 <nick2@company.xx> + Author: nick2 <bugs@company.xx> + Author: nick1 <bugs@company.xx> + Author: $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> + EOF + git log --no-use-mailmap | grep Author > actual && + test_cmp expect actual +' + cat >expect <<\EOF Author: Santa Claus <santa.claus@northpole.xx> Author: Santa Claus <santa.claus@northpole.xx> @@ -461,14 +517,19 @@ test_expect_success 'Grep author with log.mailmap' ' test_cmp expect actual ' +test_expect_success 'log.mailmap is true by default these days' ' + git log --author Santa | grep Author >actual && + test_cmp expect actual +' + test_expect_success 'Only grep replaced author with --use-mailmap' ' git log --use-mailmap --author "<cto@coompany.xx>" >actual && test_must_be_empty actual ' # git blame -cat >expect <<\EOF -^OBJI (A U Thor DATE 1) one +cat >expect <<EOF +^OBJI ($GIT_AUTHOR_NAME DATE 1) one OBJID (Some Dude DATE 2) two OBJID (Other Author DATE 3) three OBJID (Other Author DATE 4) four diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh index f42a69faa2..204c149d5a 100755 --- a/t/t4205-log-pretty-formats.sh +++ b/t/t4205-log-pretty-formats.sh @@ -134,6 +134,36 @@ test_expect_failure C_LOCALE_OUTPUT 'NUL termination with --stat' ' test_cmp expected actual ' +for p in short medium full fuller email raw +do + test_expect_success "NUL termination with --reflog --pretty=$p" ' + revs="$(git rev-list --reflog)" && + for r in $revs + do + git show -s "$r" --pretty="$p" && + printf "\0" || return 1 + done >expect && + { + git log -z --reflog --pretty="$p" && + printf "\0" + } >actual && + test_cmp expect actual + ' +done + +test_expect_success 'NUL termination with --reflog --pretty=oneline' ' + revs="$(git rev-list --reflog)" && + for r in $revs + do + git show -s --pretty=oneline "$r" >raw && + cat raw | lf_to_nul || exit 1 + done >expect && + # the trailing NUL is already produced so we do not need to + # output another one + git log -z --pretty=oneline --reflog >actual && + test_cmp expect actual +' + test_expect_success 'setup more commits' ' test_commit "message one" one one message-one && test_commit "message two" two two message-two && @@ -503,6 +533,12 @@ test_expect_success 'ISO and ISO-strict date formats display the same values' ' test_cmp expected actual ' +test_expect_success 'short date' ' + git log --format=%ad%n%cd --date=short >expected && + git log --format=%as%n%cs >actual && + test_cmp expected actual +' + # get new digests (with no abbreviations) test_expect_success 'set up log decoration tests' ' head1=$(git rev-parse --verify HEAD~0) && @@ -640,7 +676,7 @@ test_expect_success 'pretty format %(trailers:key=foo) multiple keys' ' test_cmp expect actual ' -test_expect_success '%(trailers:key=nonexistant) becomes empty' ' +test_expect_success '%(trailers:key=nonexistent) becomes empty' ' git log --no-walk --pretty="x%(trailers:key=Nacked-by)x" >actual && echo "xx" >expect && test_cmp expect actual @@ -788,4 +824,47 @@ test_expect_success '%S in git log --format works with other placeholders (part test_cmp expect actual ' +test_expect_success 'log --pretty=reference' ' + git log --pretty="tformat:%h (%s, %as)" >expect && + git log --pretty=reference >actual && + test_cmp expect actual +' + +test_expect_success 'log --pretty=reference with log.date is overridden by short date' ' + git log --pretty="tformat:%h (%s, %as)" >expect && + test_config log.date rfc && + git log --pretty=reference >actual && + test_cmp expect actual +' + +test_expect_success 'log --pretty=reference with explicit date overrides short date' ' + git log --date=rfc --pretty="tformat:%h (%s, %ad)" >expect && + git log --date=rfc --pretty=reference >actual && + test_cmp expect actual +' + +test_expect_success 'log --pretty=reference is never unabbreviated' ' + git log --pretty="tformat:%h (%s, %as)" >expect && + git log --no-abbrev-commit --pretty=reference >actual && + test_cmp expect actual +' + +test_expect_success 'log --pretty=reference is never decorated' ' + git log --pretty="tformat:%h (%s, %as)" >expect && + git log --decorate=short --pretty=reference >actual && + test_cmp expect actual +' + +test_expect_success 'log --pretty=reference does not output reflog info' ' + git log --walk-reflogs --pretty="tformat:%h (%s, %as)" >expect && + git log --walk-reflogs --pretty=reference >actual && + test_cmp expect actual +' + +test_expect_success 'log --pretty=reference is colored appropriately' ' + git log --color=always --pretty="tformat:%C(auto)%h (%s, %as)" >expect && + git log --color=always --pretty=reference >actual && + test_cmp expect actual +' + test_done diff --git a/t/t4210-log-i18n.sh b/t/t4210-log-i18n.sh index 7c519436ef..6e61f57f09 100755 --- a/t/t4210-log-i18n.sh +++ b/t/t4210-log-i18n.sh @@ -1,12 +1,15 @@ #!/bin/sh test_description='test log with i18n features' -. ./test-lib.sh +. ./lib-gettext.sh # two forms of é utf8_e=$(printf '\303\251') latin1_e=$(printf '\351') +# invalid UTF-8 +invalid_e=$(printf '\303\50)') # ")" at end to close opening "(" + test_expect_success 'create commits in different encodings' ' test_tick && cat >msg <<-EOF && @@ -48,9 +51,43 @@ test_expect_success !MINGW 'log --grep does not find non-reencoded values (utf8) test_must_be_empty actual ' -test_expect_success 'log --grep does not find non-reencoded values (latin1)' ' +test_expect_success !MINGW 'log --grep does not find non-reencoded values (latin1)' ' git log --encoding=ISO-8859-1 --format=%s --grep=$utf8_e >actual && test_must_be_empty actual ' +for engine in fixed basic extended perl +do + prereq= + if test $engine = "perl" + then + prereq="PCRE" + else + prereq="" + fi + force_regex= + if test $engine != "fixed" + then + force_regex=.* + fi + test_expect_success !MINGW,GETTEXT_LOCALE,$prereq "-c grep.patternType=$engine log --grep does not find non-reencoded values (latin1 + locale)" " + cat >expect <<-\EOF && + latin1 + utf8 + EOF + LC_ALL=\"$is_IS_locale\" git -c grep.patternType=$engine log --encoding=ISO-8859-1 --format=%s --grep=\"$force_regex$latin1_e\" >actual && + test_cmp expect actual + " + + test_expect_success !MINGW,GETTEXT_LOCALE,$prereq "-c grep.patternType=$engine log --grep does not find non-reencoded values (latin1 + locale)" " + LC_ALL=\"$is_IS_locale\" git -c grep.patternType=$engine log --encoding=ISO-8859-1 --format=%s --grep=\"$force_regex$utf8_e\" >actual && + test_must_be_empty actual + " + + test_expect_success !MINGW,GETTEXT_LOCALE,$prereq "-c grep.patternType=$engine log --grep does not die on invalid UTF-8 value (latin1 + locale + invalid needle)" " + LC_ALL=\"$is_IS_locale\" git -c grep.patternType=$engine log --encoding=ISO-8859-1 --format=%s --grep=\"$force_regex$invalid_e\" >actual && + test_must_be_empty actual + " +done + test_done diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh index 1db7bd0f59..8319163744 100755 --- a/t/t4211-line-log.sh +++ b/t/t4211-line-log.sh @@ -132,4 +132,86 @@ test_expect_success '--raw is forbidden' ' test_must_fail git log -L1,24:b.c --raw ' +test_expect_success 'setup for checking fancy rename following' ' + git checkout --orphan moves-start && + git reset --hard && + + printf "%s\n" 12 13 14 15 b c d e >file-1 && + printf "%s\n" 22 23 24 25 B C D E >file-2 && + git add file-1 file-2 && + test_tick && + git commit -m "Add file-1 and file-2" && + oid_add_f1_f2=$(git rev-parse --short HEAD) && + + git checkout -b moves-main && + printf "%s\n" 11 12 13 14 15 b c d e >file-1 && + git commit -a -m "Modify file-1 on main" && + oid_mod_f1_main=$(git rev-parse --short HEAD) && + + printf "%s\n" 21 22 23 24 25 B C D E >file-2 && + git commit -a -m "Modify file-2 on main #1" && + oid_mod_f2_main_1=$(git rev-parse --short HEAD) && + + git mv file-1 renamed-1 && + git commit -m "Rename file-1 to renamed-1 on main" && + + printf "%s\n" 11 12 13 14 15 b c d e f >renamed-1 && + git commit -a -m "Modify renamed-1 on main" && + oid_mod_r1_main=$(git rev-parse --short HEAD) && + + printf "%s\n" 21 22 23 24 25 B C D E F >file-2 && + git commit -a -m "Modify file-2 on main #2" && + oid_mod_f2_main_2=$(git rev-parse --short HEAD) && + + git checkout -b moves-side moves-start && + printf "%s\n" 12 13 14 15 16 b c d e >file-1 && + git commit -a -m "Modify file-1 on side #1" && + oid_mod_f1_side_1=$(git rev-parse --short HEAD) && + + printf "%s\n" 22 23 24 25 26 B C D E >file-2 && + git commit -a -m "Modify file-2 on side" && + oid_mod_f2_side=$(git rev-parse --short HEAD) && + + git mv file-2 renamed-2 && + git commit -m "Rename file-2 to renamed-2 on side" && + + printf "%s\n" 12 13 14 15 16 a b c d e >file-1 && + git commit -a -m "Modify file-1 on side #2" && + oid_mod_f1_side_2=$(git rev-parse --short HEAD) && + + printf "%s\n" 22 23 24 25 26 A B C D E >renamed-2 && + git commit -a -m "Modify renamed-2 on side" && + oid_mod_r2_side=$(git rev-parse --short HEAD) && + + git checkout moves-main && + git merge moves-side && + oid_merge=$(git rev-parse --short HEAD) +' + +test_expect_success 'fancy rename following #1' ' + cat >expect <<-EOF && + $oid_merge Merge branch '\''moves-side'\'' into moves-main + $oid_mod_f1_side_2 Modify file-1 on side #2 + $oid_mod_f1_side_1 Modify file-1 on side #1 + $oid_mod_r1_main Modify renamed-1 on main + $oid_mod_f1_main Modify file-1 on main + $oid_add_f1_f2 Add file-1 and file-2 + EOF + git log -L1:renamed-1 --oneline --no-patch >actual && + test_cmp expect actual +' + +test_expect_success 'fancy rename following #2' ' + cat >expect <<-EOF && + $oid_merge Merge branch '\''moves-side'\'' into moves-main + $oid_mod_r2_side Modify renamed-2 on side + $oid_mod_f2_side Modify file-2 on side + $oid_mod_f2_main_2 Modify file-2 on main #2 + $oid_mod_f2_main_1 Modify file-2 on main #1 + $oid_add_f1_f2 Add file-1 and file-2 + EOF + git log -L1:renamed-2 --oneline --no-patch >actual && + test_cmp expect actual +' + test_done diff --git a/t/t4213-log-tabexpand.sh b/t/t4213-log-tabexpand.sh index 7f90f58c03..53a4af3244 100755 --- a/t/t4213-log-tabexpand.sh +++ b/t/t4213-log-tabexpand.sh @@ -36,7 +36,7 @@ count_expand () esac # Prefix the output with the command line arguments, and - # replace SP with a dot both in the expecte and actual output + # replace SP with a dot both in the expected and actual output # so that test_cmp would show the difference together with the # breakage in a way easier to consume by the debugging user. { diff --git a/t/t4214-log-graph-octopus.sh b/t/t4214-log-graph-octopus.sh index dab96c89aa..40d27db674 100755 --- a/t/t4214-log-graph-octopus.sh +++ b/t/t4214-log-graph-octopus.sh @@ -5,61 +5,63 @@ test_description='git log --graph of skewed left octopus merge.' . ./test-lib.sh test_expect_success 'set up merge history' ' + test_commit initial && + for i in 1 2 3 4 ; do + git checkout master -b $i || return $? + # Make tag name different from branch name, to avoid + # ambiguity error when calling checkout. + test_commit $i $i $i tag$i || return $? + done && + git checkout 1 -b merge && + test_merge octopus-merge 1 2 3 4 && + test_commit after-merge && + git checkout 1 -b L && + test_commit left && + git checkout 4 -b crossover && + test_commit after-4 && + git checkout initial -b more-L && + test_commit after-initial +' + +test_expect_success 'log --graph with tricky octopus merge, no color' ' cat >expect.uncolored <<-\EOF && * left - | *---. octopus-merge - | |\ \ \ - |/ / / / + | *-. octopus-merge + |/|\ \ | | | * 4 | | * | 3 | | |/ - | * | 2 + | * / 2 | |/ - * | 1 + * / 1 |/ * initial EOF + git log --color=never --graph --date-order --pretty=tformat:%s left octopus-merge >actual.raw && + sed "s/ *\$//" actual.raw >actual && + test_cmp expect.uncolored actual +' + +test_expect_success 'log --graph with tricky octopus merge with colors' ' + test_config log.graphColors red,green,yellow,blue,magenta,cyan && cat >expect.colors <<-\EOF && * left - <RED>|<RESET> *<BLUE>-<RESET><BLUE>-<RESET><MAGENTA>-<RESET><MAGENTA>.<RESET> octopus-merge - <RED>|<RESET> <RED>|<RESET><YELLOW>\<RESET> <BLUE>\<RESET> <MAGENTA>\<RESET> - <RED>|<RESET><RED>/<RESET> <YELLOW>/<RESET> <BLUE>/<RESET> <MAGENTA>/<RESET> + <RED>|<RESET> *<MAGENTA>-<RESET><MAGENTA>.<RESET> octopus-merge + <RED>|<RESET><RED>/<RESET><YELLOW>|<RESET><BLUE>\<RESET> <MAGENTA>\<RESET> <RED>|<RESET> <YELLOW>|<RESET> <BLUE>|<RESET> * 4 <RED>|<RESET> <YELLOW>|<RESET> * <MAGENTA>|<RESET> 3 <RED>|<RESET> <YELLOW>|<RESET> <MAGENTA>|<RESET><MAGENTA>/<RESET> - <RED>|<RESET> * <MAGENTA>|<RESET> 2 + <RED>|<RESET> * <MAGENTA>/<RESET> 2 <RED>|<RESET> <MAGENTA>|<RESET><MAGENTA>/<RESET> - * <MAGENTA>|<RESET> 1 + * <MAGENTA>/<RESET> 1 <MAGENTA>|<RESET><MAGENTA>/<RESET> * initial EOF - test_commit initial && - for i in 1 2 3 4 ; do - git checkout master -b $i || return $? - # Make tag name different from branch name, to avoid - # ambiguity error when calling checkout. - test_commit $i $i $i tag$i || return $? - done && - git checkout 1 -b merge && - test_tick && - git merge -m octopus-merge 1 2 3 4 && - git checkout 1 -b L && - test_commit left -' - -test_expect_success 'log --graph with tricky octopus merge with colors' ' - test_config log.graphColors red,green,yellow,blue,magenta,cyan && - git log --color=always --graph --date-order --pretty=tformat:%s --all >actual.colors.raw && + git log --color=always --graph --date-order --pretty=tformat:%s left octopus-merge >actual.colors.raw && test_decode_color <actual.colors.raw | sed "s/ *\$//" >actual.colors && test_cmp expect.colors actual.colors ' -test_expect_success 'log --graph with tricky octopus merge, no color' ' - git log --color=never --graph --date-order --pretty=tformat:%s --all >actual.raw && - sed "s/ *\$//" actual.raw >actual && - test_cmp expect.uncolored actual -' - # Repeat the previous two tests with "normal" octopus merge (i.e., # without the first parent skewing to the "left" branch column). @@ -70,13 +72,13 @@ test_expect_success 'log --graph with normal octopus merge, no color' ' | | | * 4 | | * | 3 | | |/ - | * | 2 + | * / 2 | |/ - * | 1 + * / 1 |/ * initial EOF - git log --color=never --graph --date-order --pretty=tformat:%s merge >actual.raw && + git log --color=never --graph --date-order --pretty=tformat:%s octopus-merge >actual.raw && sed "s/ *\$//" actual.raw >actual && test_cmp expect.uncolored actual ' @@ -88,15 +90,288 @@ test_expect_success 'log --graph with normal octopus merge with colors' ' <RED>|<RESET> <GREEN>|<RESET> <YELLOW>|<RESET> * 4 <RED>|<RESET> <GREEN>|<RESET> * <BLUE>|<RESET> 3 <RED>|<RESET> <GREEN>|<RESET> <BLUE>|<RESET><BLUE>/<RESET> - <RED>|<RESET> * <BLUE>|<RESET> 2 + <RED>|<RESET> * <BLUE>/<RESET> 2 <RED>|<RESET> <BLUE>|<RESET><BLUE>/<RESET> - * <BLUE>|<RESET> 1 + * <BLUE>/<RESET> 1 <BLUE>|<RESET><BLUE>/<RESET> * initial EOF test_config log.graphColors red,green,yellow,blue,magenta,cyan && - git log --color=always --graph --date-order --pretty=tformat:%s merge >actual.colors.raw && + git log --color=always --graph --date-order --pretty=tformat:%s octopus-merge >actual.colors.raw && + test_decode_color <actual.colors.raw | sed "s/ *\$//" >actual.colors && + test_cmp expect.colors actual.colors +' + +test_expect_success 'log --graph with normal octopus merge and child, no color' ' + cat >expect.uncolored <<-\EOF && + * after-merge + *---. octopus-merge + |\ \ \ + | | | * 4 + | | * | 3 + | | |/ + | * / 2 + | |/ + * / 1 + |/ + * initial + EOF + git log --color=never --graph --date-order --pretty=tformat:%s after-merge >actual.raw && + sed "s/ *\$//" actual.raw >actual && + test_cmp expect.uncolored actual +' + +test_expect_success 'log --graph with normal octopus and child merge with colors' ' + cat >expect.colors <<-\EOF && + * after-merge + *<BLUE>-<RESET><BLUE>-<RESET><MAGENTA>-<RESET><MAGENTA>.<RESET> octopus-merge + <GREEN>|<RESET><YELLOW>\<RESET> <BLUE>\<RESET> <MAGENTA>\<RESET> + <GREEN>|<RESET> <YELLOW>|<RESET> <BLUE>|<RESET> * 4 + <GREEN>|<RESET> <YELLOW>|<RESET> * <MAGENTA>|<RESET> 3 + <GREEN>|<RESET> <YELLOW>|<RESET> <MAGENTA>|<RESET><MAGENTA>/<RESET> + <GREEN>|<RESET> * <MAGENTA>/<RESET> 2 + <GREEN>|<RESET> <MAGENTA>|<RESET><MAGENTA>/<RESET> + * <MAGENTA>/<RESET> 1 + <MAGENTA>|<RESET><MAGENTA>/<RESET> + * initial + EOF + test_config log.graphColors red,green,yellow,blue,magenta,cyan && + git log --color=always --graph --date-order --pretty=tformat:%s after-merge >actual.colors.raw && test_decode_color <actual.colors.raw | sed "s/ *\$//" >actual.colors && test_cmp expect.colors actual.colors ' + +test_expect_success 'log --graph with tricky octopus merge and its child, no color' ' + cat >expect.uncolored <<-\EOF && + * left + | * after-merge + | *-. octopus-merge + |/|\ \ + | | | * 4 + | | * | 3 + | | |/ + | * / 2 + | |/ + * / 1 + |/ + * initial + EOF + git log --color=never --graph --date-order --pretty=tformat:%s left after-merge >actual.raw && + sed "s/ *\$//" actual.raw >actual && + test_cmp expect.uncolored actual +' + +test_expect_success 'log --graph with tricky octopus merge and its child with colors' ' + test_config log.graphColors red,green,yellow,blue,magenta,cyan && + cat >expect.colors <<-\EOF && + * left + <RED>|<RESET> * after-merge + <RED>|<RESET> *<CYAN>-<RESET><CYAN>.<RESET> octopus-merge + <RED>|<RESET><RED>/<RESET><BLUE>|<RESET><MAGENTA>\<RESET> <CYAN>\<RESET> + <RED>|<RESET> <BLUE>|<RESET> <MAGENTA>|<RESET> * 4 + <RED>|<RESET> <BLUE>|<RESET> * <CYAN>|<RESET> 3 + <RED>|<RESET> <BLUE>|<RESET> <CYAN>|<RESET><CYAN>/<RESET> + <RED>|<RESET> * <CYAN>/<RESET> 2 + <RED>|<RESET> <CYAN>|<RESET><CYAN>/<RESET> + * <CYAN>/<RESET> 1 + <CYAN>|<RESET><CYAN>/<RESET> + * initial + EOF + git log --color=always --graph --date-order --pretty=tformat:%s left after-merge >actual.colors.raw && + test_decode_color <actual.colors.raw | sed "s/ *\$//" >actual.colors && + test_cmp expect.colors actual.colors +' + +test_expect_success 'log --graph with crossover in octopus merge, no color' ' + cat >expect.uncolored <<-\EOF && + * after-4 + | *---. octopus-merge + | |\ \ \ + | |_|_|/ + |/| | | + * | | | 4 + | | | * 3 + | |_|/ + |/| | + | | * 2 + | |/ + |/| + | * 1 + |/ + * initial + EOF + git log --color=never --graph --date-order --pretty=tformat:%s after-4 octopus-merge >actual.raw && + sed "s/ *\$//" actual.raw >actual && + test_cmp expect.uncolored actual +' + +test_expect_success 'log --graph with crossover in octopus merge with colors' ' + test_config log.graphColors red,green,yellow,blue,magenta,cyan && + cat >expect.colors <<-\EOF && + * after-4 + <RED>|<RESET> *<BLUE>-<RESET><BLUE>-<RESET><RED>-<RESET><RED>.<RESET> octopus-merge + <RED>|<RESET> <GREEN>|<RESET><YELLOW>\<RESET> <BLUE>\<RESET> <RED>\<RESET> + <RED>|<RESET> <GREEN>|<RESET><RED>_<RESET><YELLOW>|<RESET><RED>_<RESET><BLUE>|<RESET><RED>/<RESET> + <RED>|<RESET><RED>/<RESET><GREEN>|<RESET> <YELLOW>|<RESET> <BLUE>|<RESET> + * <GREEN>|<RESET> <YELLOW>|<RESET> <BLUE>|<RESET> 4 + <MAGENTA>|<RESET> <GREEN>|<RESET> <YELLOW>|<RESET> * 3 + <MAGENTA>|<RESET> <GREEN>|<RESET><MAGENTA>_<RESET><YELLOW>|<RESET><MAGENTA>/<RESET> + <MAGENTA>|<RESET><MAGENTA>/<RESET><GREEN>|<RESET> <YELLOW>|<RESET> + <MAGENTA>|<RESET> <GREEN>|<RESET> * 2 + <MAGENTA>|<RESET> <GREEN>|<RESET><MAGENTA>/<RESET> + <MAGENTA>|<RESET><MAGENTA>/<RESET><GREEN>|<RESET> + <MAGENTA>|<RESET> * 1 + <MAGENTA>|<RESET><MAGENTA>/<RESET> + * initial + EOF + git log --color=always --graph --date-order --pretty=tformat:%s after-4 octopus-merge >actual.colors.raw && + test_decode_color <actual.colors.raw | sed "s/ *\$//" >actual.colors && + test_cmp expect.colors actual.colors +' + +test_expect_success 'log --graph with crossover in octopus merge and its child, no color' ' + cat >expect.uncolored <<-\EOF && + * after-4 + | * after-merge + | *---. octopus-merge + | |\ \ \ + | |_|_|/ + |/| | | + * | | | 4 + | | | * 3 + | |_|/ + |/| | + | | * 2 + | |/ + |/| + | * 1 + |/ + * initial + EOF + git log --color=never --graph --date-order --pretty=tformat:%s after-4 after-merge >actual.raw && + sed "s/ *\$//" actual.raw >actual && + test_cmp expect.uncolored actual +' + +test_expect_success 'log --graph with crossover in octopus merge and its child with colors' ' + test_config log.graphColors red,green,yellow,blue,magenta,cyan && + cat >expect.colors <<-\EOF && + * after-4 + <RED>|<RESET> * after-merge + <RED>|<RESET> *<MAGENTA>-<RESET><MAGENTA>-<RESET><RED>-<RESET><RED>.<RESET> octopus-merge + <RED>|<RESET> <YELLOW>|<RESET><BLUE>\<RESET> <MAGENTA>\<RESET> <RED>\<RESET> + <RED>|<RESET> <YELLOW>|<RESET><RED>_<RESET><BLUE>|<RESET><RED>_<RESET><MAGENTA>|<RESET><RED>/<RESET> + <RED>|<RESET><RED>/<RESET><YELLOW>|<RESET> <BLUE>|<RESET> <MAGENTA>|<RESET> + * <YELLOW>|<RESET> <BLUE>|<RESET> <MAGENTA>|<RESET> 4 + <CYAN>|<RESET> <YELLOW>|<RESET> <BLUE>|<RESET> * 3 + <CYAN>|<RESET> <YELLOW>|<RESET><CYAN>_<RESET><BLUE>|<RESET><CYAN>/<RESET> + <CYAN>|<RESET><CYAN>/<RESET><YELLOW>|<RESET> <BLUE>|<RESET> + <CYAN>|<RESET> <YELLOW>|<RESET> * 2 + <CYAN>|<RESET> <YELLOW>|<RESET><CYAN>/<RESET> + <CYAN>|<RESET><CYAN>/<RESET><YELLOW>|<RESET> + <CYAN>|<RESET> * 1 + <CYAN>|<RESET><CYAN>/<RESET> + * initial + EOF + git log --color=always --graph --date-order --pretty=tformat:%s after-4 after-merge >actual.colors.raw && + test_decode_color <actual.colors.raw | sed "s/ *\$//" >actual.colors && + test_cmp expect.colors actual.colors +' + +test_expect_success 'log --graph with unrelated commit and octopus tip, no color' ' + cat >expect.uncolored <<-\EOF && + * after-initial + | *---. octopus-merge + | |\ \ \ + | | | | * 4 + | |_|_|/ + |/| | | + | | | * 3 + | |_|/ + |/| | + | | * 2 + | |/ + |/| + | * 1 + |/ + * initial + EOF + git log --color=never --graph --date-order --pretty=tformat:%s after-initial octopus-merge >actual.raw && + sed "s/ *\$//" actual.raw >actual && + test_cmp expect.uncolored actual +' + +test_expect_success 'log --graph with unrelated commit and octopus tip with colors' ' + test_config log.graphColors red,green,yellow,blue,magenta,cyan && + cat >expect.colors <<-\EOF && + * after-initial + <RED>|<RESET> *<BLUE>-<RESET><BLUE>-<RESET><MAGENTA>-<RESET><MAGENTA>.<RESET> octopus-merge + <RED>|<RESET> <GREEN>|<RESET><YELLOW>\<RESET> <BLUE>\<RESET> <MAGENTA>\<RESET> + <RED>|<RESET> <GREEN>|<RESET> <YELLOW>|<RESET> <BLUE>|<RESET> * 4 + <RED>|<RESET> <GREEN>|<RESET><RED>_<RESET><YELLOW>|<RESET><RED>_<RESET><BLUE>|<RESET><RED>/<RESET> + <RED>|<RESET><RED>/<RESET><GREEN>|<RESET> <YELLOW>|<RESET> <BLUE>|<RESET> + <RED>|<RESET> <GREEN>|<RESET> <YELLOW>|<RESET> * 3 + <RED>|<RESET> <GREEN>|<RESET><RED>_<RESET><YELLOW>|<RESET><RED>/<RESET> + <RED>|<RESET><RED>/<RESET><GREEN>|<RESET> <YELLOW>|<RESET> + <RED>|<RESET> <GREEN>|<RESET> * 2 + <RED>|<RESET> <GREEN>|<RESET><RED>/<RESET> + <RED>|<RESET><RED>/<RESET><GREEN>|<RESET> + <RED>|<RESET> * 1 + <RED>|<RESET><RED>/<RESET> + * initial + EOF + git log --color=always --graph --date-order --pretty=tformat:%s after-initial octopus-merge >actual.colors.raw && + test_decode_color <actual.colors.raw | sed "s/ *\$//" >actual.colors && + test_cmp expect.colors actual.colors +' + +test_expect_success 'log --graph with unrelated commit and octopus child, no color' ' + cat >expect.uncolored <<-\EOF && + * after-initial + | * after-merge + | *---. octopus-merge + | |\ \ \ + | | | | * 4 + | |_|_|/ + |/| | | + | | | * 3 + | |_|/ + |/| | + | | * 2 + | |/ + |/| + | * 1 + |/ + * initial + EOF + git log --color=never --graph --date-order --pretty=tformat:%s after-initial after-merge >actual.raw && + sed "s/ *\$//" actual.raw >actual && + test_cmp expect.uncolored actual +' + +test_expect_success 'log --graph with unrelated commit and octopus child with colors' ' + test_config log.graphColors red,green,yellow,blue,magenta,cyan && + cat >expect.colors <<-\EOF && + * after-initial + <RED>|<RESET> * after-merge + <RED>|<RESET> *<MAGENTA>-<RESET><MAGENTA>-<RESET><CYAN>-<RESET><CYAN>.<RESET> octopus-merge + <RED>|<RESET> <YELLOW>|<RESET><BLUE>\<RESET> <MAGENTA>\<RESET> <CYAN>\<RESET> + <RED>|<RESET> <YELLOW>|<RESET> <BLUE>|<RESET> <MAGENTA>|<RESET> * 4 + <RED>|<RESET> <YELLOW>|<RESET><RED>_<RESET><BLUE>|<RESET><RED>_<RESET><MAGENTA>|<RESET><RED>/<RESET> + <RED>|<RESET><RED>/<RESET><YELLOW>|<RESET> <BLUE>|<RESET> <MAGENTA>|<RESET> + <RED>|<RESET> <YELLOW>|<RESET> <BLUE>|<RESET> * 3 + <RED>|<RESET> <YELLOW>|<RESET><RED>_<RESET><BLUE>|<RESET><RED>/<RESET> + <RED>|<RESET><RED>/<RESET><YELLOW>|<RESET> <BLUE>|<RESET> + <RED>|<RESET> <YELLOW>|<RESET> * 2 + <RED>|<RESET> <YELLOW>|<RESET><RED>/<RESET> + <RED>|<RESET><RED>/<RESET><YELLOW>|<RESET> + <RED>|<RESET> * 1 + <RED>|<RESET><RED>/<RESET> + * initial + EOF + git log --color=always --graph --date-order --pretty=tformat:%s after-initial after-merge >actual.colors.raw && + test_decode_color <actual.colors.raw | sed "s/ *\$//" >actual.colors && + test_cmp expect.colors actual.colors +' + test_done diff --git a/t/t4215-log-skewed-merges.sh b/t/t4215-log-skewed-merges.sh new file mode 100755 index 0000000000..18709a723e --- /dev/null +++ b/t/t4215-log-skewed-merges.sh @@ -0,0 +1,243 @@ +#!/bin/sh + +test_description='git log --graph of skewed merges' + +. ./test-lib.sh + +check_graph () { + cat >expect && + git log --graph --pretty=tformat:%s "$@" >actual.raw && + sed "s/ *$//" actual.raw >actual && + test_cmp expect actual +} + +test_expect_success 'log --graph with merge fusing with its left and right neighbors' ' + git checkout --orphan _p && + test_commit A && + test_commit B && + git checkout -b _q @^ && test_commit C && + git checkout -b _r @^ && test_commit D && + git checkout _p && git merge --no-ff _q _r -m E && + git checkout _r && test_commit F && + git checkout _p && git merge --no-ff _r -m G && + git checkout @^^ && git merge --no-ff _p -m H && + + check_graph <<-\EOF + * H + |\ + | * G + | |\ + | | * F + | * | E + |/|\| + | | * D + | * | C + | |/ + * / B + |/ + * A + EOF +' + +test_expect_success 'log --graph with left-skewed merge' ' + git checkout --orphan 0_p && test_commit 0_A && + git checkout -b 0_q 0_p && test_commit 0_B && + git checkout -b 0_r 0_p && + test_commit 0_C && + test_commit 0_D && + git checkout -b 0_s 0_p && test_commit 0_E && + git checkout -b 0_t 0_p && git merge --no-ff 0_r^ 0_s -m 0_F && + git checkout 0_p && git merge --no-ff 0_s -m 0_G && + git checkout @^ && git merge --no-ff 0_q 0_r 0_t 0_p -m 0_H && + + check_graph <<-\EOF + *-----. 0_H + |\ \ \ \ + | | | | * 0_G + | |_|_|/| + |/| | | | + | | | * | 0_F + | |_|/|\| + |/| | | | + | | | | * 0_E + | |_|_|/ + |/| | | + | | * | 0_D + | | |/ + | | * 0_C + | |/ + |/| + | * 0_B + |/ + * 0_A + EOF +' + +test_expect_success 'log --graph with nested left-skewed merge' ' + git checkout --orphan 1_p && + test_commit 1_A && + test_commit 1_B && + test_commit 1_C && + git checkout -b 1_q @^ && test_commit 1_D && + git checkout 1_p && git merge --no-ff 1_q -m 1_E && + git checkout -b 1_r @~3 && test_commit 1_F && + git checkout 1_p && git merge --no-ff 1_r -m 1_G && + git checkout @^^ && git merge --no-ff 1_p -m 1_H && + + check_graph <<-\EOF + * 1_H + |\ + | * 1_G + | |\ + | | * 1_F + | * | 1_E + |/| | + | * | 1_D + * | | 1_C + |/ / + * / 1_B + |/ + * 1_A + EOF +' + +test_expect_success 'log --graph with nested left-skewed merge following normal merge' ' + git checkout --orphan 2_p && + test_commit 2_A && + test_commit 2_B && + test_commit 2_C && + git checkout -b 2_q @^^ && + test_commit 2_D && + test_commit 2_E && + git checkout -b 2_r @^ && test_commit 2_F && + git checkout 2_q && + git merge --no-ff 2_r -m 2_G && + git merge --no-ff 2_p^ -m 2_H && + git checkout -b 2_s @^^ && git merge --no-ff 2_q -m 2_J && + git checkout 2_p && git merge --no-ff 2_s -m 2_K && + + check_graph <<-\EOF + * 2_K + |\ + | * 2_J + | |\ + | | * 2_H + | | |\ + | | * | 2_G + | |/| | + | | * | 2_F + | * | | 2_E + | |/ / + | * | 2_D + * | | 2_C + | |/ + |/| + * | 2_B + |/ + * 2_A + EOF +' + +test_expect_success 'log --graph with nested right-skewed merge following left-skewed merge' ' + git checkout --orphan 3_p && + test_commit 3_A && + git checkout -b 3_q && + test_commit 3_B && + test_commit 3_C && + git checkout -b 3_r @^ && + test_commit 3_D && + git checkout 3_q && git merge --no-ff 3_r -m 3_E && + git checkout 3_p && git merge --no-ff 3_q -m 3_F && + git checkout 3_r && test_commit 3_G && + git checkout 3_p && git merge --no-ff 3_r -m 3_H && + git checkout @^^ && git merge --no-ff 3_p -m 3_J && + + check_graph <<-\EOF + * 3_J + |\ + | * 3_H + | |\ + | | * 3_G + | * | 3_F + |/| | + | * | 3_E + | |\| + | | * 3_D + | * | 3_C + | |/ + | * 3_B + |/ + * 3_A + EOF +' + +test_expect_success 'log --graph with right-skewed merge following a left-skewed one' ' + git checkout --orphan 4_p && + test_commit 4_A && + test_commit 4_B && + test_commit 4_C && + git checkout -b 4_q @^^ && test_commit 4_D && + git checkout -b 4_r 4_p^ && git merge --no-ff 4_q -m 4_E && + git checkout -b 4_s 4_p^^ && + git merge --no-ff 4_r -m 4_F && + git merge --no-ff 4_p -m 4_G && + git checkout @^^ && git merge --no-ff 4_s -m 4_H && + + check_graph --date-order <<-\EOF + * 4_H + |\ + | * 4_G + | |\ + | * | 4_F + |/| | + | * | 4_E + | |\ \ + | | * | 4_D + | |/ / + |/| | + | | * 4_C + | |/ + | * 4_B + |/ + * 4_A + EOF +' + +test_expect_success 'log --graph with octopus merge with column joining its penultimate parent' ' + git checkout --orphan 5_p && + test_commit 5_A && + git branch 5_q && + git branch 5_r && + test_commit 5_B && + git checkout 5_q && test_commit 5_C && + git checkout 5_r && test_commit 5_D && + git checkout 5_p && + git merge --no-ff 5_q 5_r -m 5_E && + git checkout 5_q && test_commit 5_F && + git checkout -b 5_s 5_p^ && + git merge --no-ff 5_p 5_q -m 5_G && + git checkout 5_r && + git merge --no-ff 5_s -m 5_H && + + check_graph <<-\EOF + * 5_H + |\ + | *-. 5_G + | |\ \ + | | | * 5_F + | | * | 5_E + | |/|\ \ + | |_|/ / + |/| | / + | | |/ + * | | 5_D + | | * 5_C + | |/ + |/| + | * 5_B + |/ + * 5_A + EOF +' + +test_done diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh index 602bfd9574..37655a237c 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -94,6 +94,13 @@ check_tar() { ' } +test_expect_success 'setup' ' + test_oid_cache <<-EOF + obj sha1:19f9c8273ec45a8938e6999cb59b3ff66739902a + obj sha256:3c666f798798601571f5cec0adb57ce4aba8546875e7693177e0535f34d2c49b + EOF +' + test_expect_success \ 'populate workdir' \ 'mkdir a && @@ -369,11 +376,10 @@ test_lazy_prereq TAR_HUGE ' ' test_expect_success LONG_IS_64BIT 'set up repository with huge blob' ' - obj_d=19 && - obj_f=f9c8273ec45a8938e6999cb59b3ff66739902a && - obj=${obj_d}${obj_f} && - mkdir -p .git/objects/$obj_d && - cp "$TEST_DIRECTORY"/t5000/$obj .git/objects/$obj_d/$obj_f && + obj=$(test_oid obj) && + path=$(test_oid_to_path $obj) && + mkdir -p .git/objects/$(dirname $path) && + cp "$TEST_DIRECTORY"/t5000/huge-object .git/objects/$path && rm -f .git/index && git update-index --add --cacheinfo 100644,$obj,huge && git commit -m huge diff --git a/t/t5000/19f9c8273ec45a8938e6999cb59b3ff66739902a b/t/t5000/huge-object Binary files differindex 5cbe9ec312..5cbe9ec312 100644 --- a/t/t5000/19f9c8273ec45a8938e6999cb59b3ff66739902a +++ b/t/t5000/huge-object diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh index 271eb5a1fd..3e7b23cb32 100755 --- a/t/t5004-archive-corner-cases.sh +++ b/t/t5004-archive-corner-cases.sh @@ -204,4 +204,23 @@ test_expect_success EXPENSIVE,LONG_IS_64BIT,UNZIP,UNZIP_ZIP64_SUPPORT,ZIPINFO \ grep $size big.lst ' +build_tree() { + perl -e ' + my $hash = $ARGV[0]; + foreach my $order (2..6) { + $first = 10 ** $order; + foreach my $i (-13..-9) { + my $name = "a" x ($first + $i); + print "100644 blob $hash\t$name\n" + } + } + ' "$1" +} + +test_expect_success 'tar archive with long paths' ' + blob=$(echo foo | git hash-object -w --stdin) && + tree=$(build_tree $blob | git mktree) && + git archive -o long_paths.tar $tree +' + test_done diff --git a/t/t5200-update-server-info.sh b/t/t5200-update-server-info.sh new file mode 100755 index 0000000000..21a58eecb9 --- /dev/null +++ b/t/t5200-update-server-info.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +test_description='Test git update-server-info' + +. ./test-lib.sh + +test_expect_success 'setup' 'test_commit file' + +test_expect_success 'create info/refs' ' + git update-server-info && + test_path_is_file .git/info/refs +' + +test_expect_success 'modify and store mtime' ' + test-tool chmtime =0 .git/info/refs && + test-tool chmtime --get .git/info/refs >a +' + +test_expect_success 'info/refs is not needlessly overwritten' ' + git update-server-info && + test-tool chmtime --get .git/info/refs >b && + test_cmp a b +' + +test_expect_success 'info/refs can be forced to update' ' + git update-server-info -f && + test-tool chmtime --get .git/info/refs >b && + ! test_cmp a b +' + +test_expect_success 'info/refs updates when changes are made' ' + test-tool chmtime =0 .git/info/refs && + test-tool chmtime --get .git/info/refs >b && + test_cmp a b && + git update-ref refs/heads/foo HEAD && + git update-server-info && + test-tool chmtime --get .git/info/refs >b && + ! test_cmp a b +' + +test_done diff --git a/t/t5307-pack-missing-commit.sh b/t/t5307-pack-missing-commit.sh index dacb440b27..f4338abb78 100755 --- a/t/t5307-pack-missing-commit.sh +++ b/t/t5307-pack-missing-commit.sh @@ -24,11 +24,11 @@ test_expect_success 'check corruption' ' ' test_expect_success 'rev-list notices corruption (1)' ' - test_must_fail env GIT_TEST_COMMIT_GRAPH=0 git rev-list HEAD + test_must_fail env GIT_TEST_COMMIT_GRAPH=0 git -c core.commitGraph=false rev-list HEAD ' test_expect_success 'rev-list notices corruption (2)' ' - test_must_fail env GIT_TEST_COMMIT_GRAPH=0 git rev-list --objects HEAD + test_must_fail env GIT_TEST_COMMIT_GRAPH=0 git -c core.commitGraph=false rev-list --objects HEAD ' test_expect_success 'pack-objects notices corruption' ' diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh index a26c8ba9a2..6640329ebf 100755 --- a/t/t5310-pack-bitmaps.sh +++ b/t/t5310-pack-bitmaps.sh @@ -21,15 +21,9 @@ has_any () { } test_expect_success 'setup repo with moderate-sized history' ' - for i in $(test_seq 1 10) - do - test_commit $i - done && + test_commit_bulk --id=file 100 && git checkout -b other HEAD~5 && - for i in $(test_seq 1 10) - do - test_commit side-$i - done && + test_commit_bulk --id=side 10 && git checkout master && bitmaptip=$(git rev-parse master) && blob=$(echo tagged-blob | git hash-object -w --stdin) && @@ -106,10 +100,7 @@ test_expect_success 'clone from bitmapped repository' ' ' test_expect_success 'setup further non-bitmapped commits' ' - for i in $(test_seq 1 10) - do - test_commit further-$i - done + test_commit_bulk --id=further 10 ' rev_list_tests 'partial bitmap' diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh index 5267c4be20..3f03de6018 100755 --- a/t/t5318-commit-graph.sh +++ b/t/t5318-commit-graph.sh @@ -20,14 +20,13 @@ test_expect_success 'verify graph with no graph file' ' test_expect_success 'write graph with no packs' ' cd "$TRASH_DIRECTORY/full" && git commit-graph write --object-dir . && - test_path_is_file info/commit-graph + test_path_is_missing info/commit-graph ' -test_expect_success 'close with correct error on bad input' ' +test_expect_success 'exit with correct error on bad input to --stdin-packs' ' cd "$TRASH_DIRECTORY/full" && echo doesnotexist >in && - { git commit-graph write --stdin-packs <in 2>stderr; ret=$?; } && - test "$ret" = 1 && + test_expect_code 1 git commit-graph write --stdin-packs <in 2>stderr && test_i18ngrep "error adding pack" stderr ' @@ -41,6 +40,15 @@ test_expect_success 'create commits and repack' ' git repack ' +test_expect_success 'exit with correct error on bad input to --stdin-commits' ' + cd "$TRASH_DIRECTORY/full" && + echo HEAD | test_expect_code 1 git commit-graph write --stdin-commits 2>stderr && + test_i18ngrep "invalid commit object id" stderr && + # valid tree OID, but not a commit OID + git rev-parse HEAD^{tree} | test_expect_code 1 git commit-graph write --stdin-commits 2>stderr && + test_i18ngrep "invalid commit object id" stderr +' + graph_git_two_modes() { git -c core.commitGraph=true $1 >output git -c core.commitGraph=false $1 >expect @@ -77,7 +85,7 @@ graph_read_expect() { num_commits: $1 chunks: oid_fanout oid_lookup commit_metadata$OPTIONAL EOF - git commit-graph read >output && + test-tool read-graph >output && test_cmp expect output } @@ -116,6 +124,42 @@ test_expect_success 'Add more commits' ' git repack ' +test_expect_success 'commit-graph write progress off for redirected stderr' ' + cd "$TRASH_DIRECTORY/full" && + git commit-graph write 2>err && + test_line_count = 0 err +' + +test_expect_success 'commit-graph write force progress on for stderr' ' + cd "$TRASH_DIRECTORY/full" && + GIT_PROGRESS_DELAY=0 git commit-graph write --progress 2>err && + test_file_not_empty err +' + +test_expect_success 'commit-graph write with the --no-progress option' ' + cd "$TRASH_DIRECTORY/full" && + git commit-graph write --no-progress 2>err && + test_line_count = 0 err +' + +test_expect_success 'commit-graph verify progress off for redirected stderr' ' + cd "$TRASH_DIRECTORY/full" && + git commit-graph verify 2>err && + test_line_count = 0 err +' + +test_expect_success 'commit-graph verify force progress on for stderr' ' + cd "$TRASH_DIRECTORY/full" && + GIT_PROGRESS_DELAY=0 git commit-graph verify --progress 2>err && + test_file_not_empty err +' + +test_expect_success 'commit-graph verify with the --no-progress option' ' + cd "$TRASH_DIRECTORY/full" && + git commit-graph verify --no-progress 2>err && + test_line_count = 0 err +' + # Current graph structure: # # __M3___ @@ -577,4 +621,47 @@ test_expect_success 'get_commit_tree_in_graph works for non-the_repository' ' test_cmp expect actual ' +test_expect_success 'corrupt commit-graph write (broken parent)' ' + rm -rf repo && + git init repo && + ( + cd repo && + empty="$(git mktree </dev/null)" && + cat >broken <<-EOF && + tree $empty + parent 0000000000000000000000000000000000000000 + author whatever <whatever@example.com> 1234 -0000 + committer whatever <whatever@example.com> 1234 -0000 + + broken commit + EOF + broken="$(git hash-object -w -t commit --literally broken)" && + git commit-tree -p "$broken" -m "good commit" "$empty" >good && + test_must_fail git commit-graph write --stdin-commits \ + <good 2>test_err && + test_i18ngrep "unable to parse commit" test_err + ) +' + +test_expect_success 'corrupt commit-graph write (missing tree)' ' + rm -rf repo && + git init repo && + ( + cd repo && + tree="$(git mktree </dev/null)" && + cat >broken <<-EOF && + parent 0000000000000000000000000000000000000000 + author whatever <whatever@example.com> 1234 -0000 + committer whatever <whatever@example.com> 1234 -0000 + + broken commit + EOF + broken="$(git hash-object -w -t commit --literally broken)" && + git commit-tree -p "$broken" -m "good" "$tree" >good && + test_must_fail git commit-graph write --stdin-commits \ + <good 2>test_err && + test_i18ngrep "unable to parse commit" test_err + ) +' + test_done diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh index 1ebf19ec3c..cd2f87be6a 100755 --- a/t/t5319-multi-pack-index.sh +++ b/t/t5319-multi-pack-index.sh @@ -147,6 +147,21 @@ test_expect_success 'write midx with two packs' ' compare_results_with_midx "two packs" +test_expect_success 'write progress off for redirected stderr' ' + git multi-pack-index --object-dir=$objdir write 2>err && + test_line_count = 0 err +' + +test_expect_success 'write force progress on for stderr' ' + git multi-pack-index --object-dir=$objdir --progress write 2>err && + test_file_not_empty err +' + +test_expect_success 'write with the --no-progress option' ' + git multi-pack-index --object-dir=$objdir --no-progress write 2>err && + test_line_count = 0 err +' + test_expect_success 'add more packs' ' for j in $(test_seq 11 20) do @@ -169,6 +184,21 @@ test_expect_success 'verify multi-pack-index success' ' git multi-pack-index verify --object-dir=$objdir ' +test_expect_success 'verify progress off for redirected stderr' ' + git multi-pack-index verify --object-dir=$objdir 2>err && + test_line_count = 0 err +' + +test_expect_success 'verify force progress on for stderr' ' + git multi-pack-index verify --object-dir=$objdir --progress 2>err && + test_file_not_empty err +' + +test_expect_success 'verify with the --no-progress option' ' + git multi-pack-index verify --object-dir=$objdir --no-progress 2>err && + test_line_count = 0 err +' + # usage: corrupt_midx_and_verify <pos> <data> <objdir> <string> corrupt_midx_and_verify() { POS=$1 && @@ -284,6 +314,21 @@ test_expect_success 'git-fsck incorrect offset' ' "git -c core.multipackindex=true fsck" ' +test_expect_success 'repack progress off for redirected stderr' ' + git multi-pack-index --object-dir=$objdir repack 2>err && + test_line_count = 0 err +' + +test_expect_success 'repack force progress on for stderr' ' + git multi-pack-index --object-dir=$objdir --progress repack 2>err && + test_file_not_empty err +' + +test_expect_success 'repack with the --no-progress option' ' + git multi-pack-index --object-dir=$objdir --no-progress repack 2>err && + test_line_count = 0 err +' + test_expect_success 'repack removes multi-pack-index' ' test_path_is_file $objdir/pack/multi-pack-index && GIT_TEST_MULTI_PACK_INDEX=0 git repack -adf && @@ -363,4 +408,212 @@ test_expect_success 'verify incorrect 64-bit offset' ' "incorrect object offset" ' +test_expect_success 'setup expire tests' ' + mkdir dup && + ( + cd dup && + git init && + test-tool genrandom "data" 4096 >large_file.txt && + git update-index --add large_file.txt && + for i in $(test_seq 1 20) + do + test_commit $i + done && + git branch A HEAD && + git branch B HEAD~8 && + git branch C HEAD~13 && + git branch D HEAD~16 && + git branch E HEAD~18 && + git pack-objects --revs .git/objects/pack/pack-A <<-EOF && + refs/heads/A + ^refs/heads/B + EOF + git pack-objects --revs .git/objects/pack/pack-B <<-EOF && + refs/heads/B + ^refs/heads/C + EOF + git pack-objects --revs .git/objects/pack/pack-C <<-EOF && + refs/heads/C + ^refs/heads/D + EOF + git pack-objects --revs .git/objects/pack/pack-D <<-EOF && + refs/heads/D + ^refs/heads/E + EOF + git pack-objects --revs .git/objects/pack/pack-E <<-EOF && + refs/heads/E + EOF + git multi-pack-index write && + cp -r .git/objects/pack .git/objects/pack-backup + ) +' + +test_expect_success 'expire does not remove any packs' ' + ( + cd dup && + ls .git/objects/pack >expect && + git multi-pack-index expire && + ls .git/objects/pack >actual && + test_cmp expect actual + ) +' + +test_expect_success 'expire progress off for redirected stderr' ' + ( + cd dup && + git multi-pack-index expire 2>err && + test_line_count = 0 err + ) +' + +test_expect_success 'expire force progress on for stderr' ' + ( + cd dup && + git multi-pack-index --progress expire 2>err && + test_file_not_empty err + ) +' + +test_expect_success 'expire with the --no-progress option' ' + ( + cd dup && + git multi-pack-index --no-progress expire 2>err && + test_line_count = 0 err + ) +' + +test_expect_success 'expire removes unreferenced packs' ' + ( + cd dup && + git pack-objects --revs .git/objects/pack/pack-combined <<-EOF && + refs/heads/A + ^refs/heads/C + EOF + git multi-pack-index write && + ls .git/objects/pack | grep -v -e pack-[AB] >expect && + git multi-pack-index expire && + ls .git/objects/pack >actual && + test_cmp expect actual && + ls .git/objects/pack/ | grep idx >expect-idx && + test-tool read-midx .git/objects | grep idx >actual-midx && + test_cmp expect-idx actual-midx && + git multi-pack-index verify && + git fsck + ) +' + +test_expect_success 'repack with minimum size does not alter existing packs' ' + ( + cd dup && + rm -rf .git/objects/pack && + mv .git/objects/pack-backup .git/objects/pack && + touch -m -t 201901010000 .git/objects/pack/pack-D* && + touch -m -t 201901010001 .git/objects/pack/pack-C* && + touch -m -t 201901010002 .git/objects/pack/pack-B* && + touch -m -t 201901010003 .git/objects/pack/pack-A* && + ls .git/objects/pack >expect && + MINSIZE=$(test-tool path-utils file-size .git/objects/pack/*pack | sort -n | head -n 1) && + git multi-pack-index repack --batch-size=$MINSIZE && + ls .git/objects/pack >actual && + test_cmp expect actual + ) +' + +test_expect_success 'repack creates a new pack' ' + ( + cd dup && + ls .git/objects/pack/*idx >idx-list && + test_line_count = 5 idx-list && + THIRD_SMALLEST_SIZE=$(test-tool path-utils file-size .git/objects/pack/*pack | sort -n | head -n 3 | tail -n 1) && + BATCH_SIZE=$(($THIRD_SMALLEST_SIZE + 1)) && + git multi-pack-index repack --batch-size=$BATCH_SIZE && + ls .git/objects/pack/*idx >idx-list && + test_line_count = 6 idx-list && + test-tool read-midx .git/objects | grep idx >midx-list && + test_line_count = 6 midx-list + ) +' + +test_expect_success 'expire removes repacked packs' ' + ( + cd dup && + ls -al .git/objects/pack/*pack && + ls -S .git/objects/pack/*pack | head -n 4 >expect && + git multi-pack-index expire && + ls -S .git/objects/pack/*pack >actual && + test_cmp expect actual && + test-tool read-midx .git/objects | grep idx >midx-list && + test_line_count = 4 midx-list + ) +' + +test_expect_success 'expire works when adding new packs' ' + ( + cd dup && + git pack-objects --revs .git/objects/pack/pack-combined <<-EOF && + refs/heads/A + ^refs/heads/B + EOF + git pack-objects --revs .git/objects/pack/pack-combined <<-EOF && + refs/heads/B + ^refs/heads/C + EOF + git pack-objects --revs .git/objects/pack/pack-combined <<-EOF && + refs/heads/C + ^refs/heads/D + EOF + git multi-pack-index write && + git pack-objects --revs .git/objects/pack/a-pack <<-EOF && + refs/heads/D + ^refs/heads/E + EOF + git multi-pack-index write && + git pack-objects --revs .git/objects/pack/z-pack <<-EOF && + refs/heads/E + EOF + git multi-pack-index expire && + ls .git/objects/pack/ | grep idx >expect && + test-tool read-midx .git/objects | grep idx >actual && + test_cmp expect actual && + git multi-pack-index verify + ) +' + +test_expect_success 'expire respects .keep files' ' + ( + cd dup && + git pack-objects --revs .git/objects/pack/pack-all <<-EOF && + refs/heads/A + EOF + git multi-pack-index write && + PACKA=$(ls .git/objects/pack/a-pack*\.pack | sed s/\.pack\$//) && + touch $PACKA.keep && + git multi-pack-index expire && + ls -S .git/objects/pack/a-pack* | grep $PACKA >a-pack-files && + test_line_count = 3 a-pack-files && + test-tool read-midx .git/objects | grep idx >midx-list && + test_line_count = 2 midx-list + ) +' + +test_expect_success 'repack --batch-size=0 repacks everything' ' + ( + cd dup && + rm .git/objects/pack/*.keep && + ls .git/objects/pack/*idx >idx-list && + test_line_count = 2 idx-list && + git multi-pack-index repack --batch-size=0 && + ls .git/objects/pack/*idx >idx-list && + test_line_count = 3 idx-list && + test-tool read-midx .git/objects | grep idx >midx-list && + test_line_count = 3 midx-list && + git multi-pack-index expire && + ls -al .git/objects/pack/*idx >idx-list && + test_line_count = 1 idx-list && + git multi-pack-index repack --batch-size=0 && + ls -al .git/objects/pack/*idx >new-idx-list && + test_cmp idx-list new-idx-list + ) +' + test_done diff --git a/t/t5324-split-commit-graph.sh b/t/t5324-split-commit-graph.sh new file mode 100755 index 0000000000..c24823431f --- /dev/null +++ b/t/t5324-split-commit-graph.sh @@ -0,0 +1,347 @@ +#!/bin/sh + +test_description='split commit graph' +. ./test-lib.sh + +GIT_TEST_COMMIT_GRAPH=0 + +test_expect_success 'setup repo' ' + git init && + git config core.commitGraph true && + git config gc.writeCommitGraph false && + infodir=".git/objects/info" && + graphdir="$infodir/commit-graphs" && + test_oid_init +' + +graph_read_expect() { + NUM_BASE=0 + if test ! -z $2 + then + NUM_BASE=$2 + fi + cat >expect <<- EOF + header: 43475048 1 1 3 $NUM_BASE + num_commits: $1 + chunks: oid_fanout oid_lookup commit_metadata + EOF + test-tool read-graph >output && + test_cmp expect output +} + +test_expect_success 'create commits and write commit-graph' ' + for i in $(test_seq 3) + do + test_commit $i && + git branch commits/$i || return 1 + done && + git commit-graph write --reachable && + test_path_is_file $infodir/commit-graph && + graph_read_expect 3 +' + +graph_git_two_modes() { + git -c core.commitGraph=true $1 >output + git -c core.commitGraph=false $1 >expect + test_cmp expect output +} + +graph_git_behavior() { + MSG=$1 + BRANCH=$2 + COMPARE=$3 + test_expect_success "check normal git operations: $MSG" ' + graph_git_two_modes "log --oneline $BRANCH" && + graph_git_two_modes "log --topo-order $BRANCH" && + graph_git_two_modes "log --graph $COMPARE..$BRANCH" && + graph_git_two_modes "branch -vv" && + graph_git_two_modes "merge-base -a $BRANCH $COMPARE" + ' +} + +graph_git_behavior 'graph exists' commits/3 commits/1 + +verify_chain_files_exist() { + for hash in $(cat $1/commit-graph-chain) + do + test_path_is_file $1/graph-$hash.graph || return 1 + done +} + +test_expect_success 'add more commits, and write a new base graph' ' + git reset --hard commits/1 && + for i in $(test_seq 4 5) + do + test_commit $i && + git branch commits/$i || return 1 + done && + git reset --hard commits/2 && + for i in $(test_seq 6 10) + do + test_commit $i && + git branch commits/$i || return 1 + done && + git reset --hard commits/2 && + git merge commits/4 && + git branch merge/1 && + git reset --hard commits/4 && + git merge commits/6 && + git branch merge/2 && + git commit-graph write --reachable && + graph_read_expect 12 +' + +test_expect_success 'fork and fail to base a chain on a commit-graph file' ' + test_when_finished rm -rf fork && + git clone . fork && + ( + cd fork && + rm .git/objects/info/commit-graph && + echo "$(pwd)/../.git/objects" >.git/objects/info/alternates && + test_commit new-commit && + git commit-graph write --reachable --split && + test_path_is_file $graphdir/commit-graph-chain && + test_line_count = 1 $graphdir/commit-graph-chain && + verify_chain_files_exist $graphdir + ) +' + +test_expect_success 'add three more commits, write a tip graph' ' + git reset --hard commits/3 && + git merge merge/1 && + git merge commits/5 && + git merge merge/2 && + git branch merge/3 && + git commit-graph write --reachable --split && + test_path_is_missing $infodir/commit-graph && + test_path_is_file $graphdir/commit-graph-chain && + ls $graphdir/graph-*.graph >graph-files && + test_line_count = 2 graph-files && + verify_chain_files_exist $graphdir +' + +graph_git_behavior 'split commit-graph: merge 3 vs 2' merge/3 merge/2 + +test_expect_success 'add one commit, write a tip graph' ' + test_commit 11 && + git branch commits/11 && + git commit-graph write --reachable --split && + test_path_is_missing $infodir/commit-graph && + test_path_is_file $graphdir/commit-graph-chain && + ls $graphdir/graph-*.graph >graph-files && + test_line_count = 3 graph-files && + verify_chain_files_exist $graphdir +' + +graph_git_behavior 'three-layer commit-graph: commit 11 vs 6' commits/11 commits/6 + +test_expect_success 'add one commit, write a merged graph' ' + test_commit 12 && + git branch commits/12 && + git commit-graph write --reachable --split && + test_path_is_file $graphdir/commit-graph-chain && + test_line_count = 2 $graphdir/commit-graph-chain && + ls $graphdir/graph-*.graph >graph-files && + test_line_count = 2 graph-files && + verify_chain_files_exist $graphdir +' + +graph_git_behavior 'merged commit-graph: commit 12 vs 6' commits/12 commits/6 + +test_expect_success 'create fork and chain across alternate' ' + git clone . fork && + ( + cd fork && + git config core.commitGraph true && + rm -rf $graphdir && + echo "$(pwd)/../.git/objects" >.git/objects/info/alternates && + test_commit 13 && + git branch commits/13 && + git commit-graph write --reachable --split && + test_path_is_file $graphdir/commit-graph-chain && + test_line_count = 3 $graphdir/commit-graph-chain && + ls $graphdir/graph-*.graph >graph-files && + test_line_count = 1 graph-files && + git -c core.commitGraph=true rev-list HEAD >expect && + git -c core.commitGraph=false rev-list HEAD >actual && + test_cmp expect actual && + test_commit 14 && + git commit-graph write --reachable --split --object-dir=.git/objects/ && + test_line_count = 3 $graphdir/commit-graph-chain && + ls $graphdir/graph-*.graph >graph-files && + test_line_count = 1 graph-files + ) +' + +graph_git_behavior 'alternate: commit 13 vs 6' commits/13 commits/6 + +test_expect_success 'test merge stragety constants' ' + git clone . merge-2 && + ( + cd merge-2 && + git config core.commitGraph true && + test_line_count = 2 $graphdir/commit-graph-chain && + test_commit 14 && + git commit-graph write --reachable --split --size-multiple=2 && + test_line_count = 3 $graphdir/commit-graph-chain + + ) && + git clone . merge-10 && + ( + cd merge-10 && + git config core.commitGraph true && + test_line_count = 2 $graphdir/commit-graph-chain && + test_commit 14 && + git commit-graph write --reachable --split --size-multiple=10 && + test_line_count = 1 $graphdir/commit-graph-chain && + ls $graphdir/graph-*.graph >graph-files && + test_line_count = 1 graph-files + ) && + git clone . merge-10-expire && + ( + cd merge-10-expire && + git config core.commitGraph true && + test_line_count = 2 $graphdir/commit-graph-chain && + test_commit 15 && + git commit-graph write --reachable --split --size-multiple=10 --expire-time=1980-01-01 && + test_line_count = 1 $graphdir/commit-graph-chain && + ls $graphdir/graph-*.graph >graph-files && + test_line_count = 3 graph-files + ) && + git clone --no-hardlinks . max-commits && + ( + cd max-commits && + git config core.commitGraph true && + test_line_count = 2 $graphdir/commit-graph-chain && + test_commit 16 && + test_commit 17 && + git commit-graph write --reachable --split --max-commits=1 && + test_line_count = 1 $graphdir/commit-graph-chain && + ls $graphdir/graph-*.graph >graph-files && + test_line_count = 1 graph-files + ) +' + +test_expect_success 'remove commit-graph-chain file after flattening' ' + git clone . flatten && + ( + cd flatten && + test_line_count = 2 $graphdir/commit-graph-chain && + git commit-graph write --reachable && + test_path_is_missing $graphdir/commit-graph-chain && + ls $graphdir >graph-files && + test_line_count = 0 graph-files + ) +' + +corrupt_file() { + file=$1 + pos=$2 + data="${3:-\0}" + chmod a+w "$file" && + printf "$data" | dd of="$file" bs=1 seek="$pos" conv=notrunc +} + +test_expect_success 'verify hashes along chain, even in shallow' ' + git clone --no-hardlinks . verify && + ( + cd verify && + git commit-graph verify && + base_file=$graphdir/graph-$(head -n 1 $graphdir/commit-graph-chain).graph && + corrupt_file "$base_file" 1760 "\01" && + test_must_fail git commit-graph verify --shallow 2>test_err && + grep -v "^+" test_err >err && + test_i18ngrep "incorrect checksum" err + ) +' + +test_expect_success 'verify --shallow does not check base contents' ' + git clone --no-hardlinks . verify-shallow && + ( + cd verify-shallow && + git commit-graph verify && + base_file=$graphdir/graph-$(head -n 1 $graphdir/commit-graph-chain).graph && + corrupt_file "$base_file" 1000 "\01" && + git commit-graph verify --shallow && + test_must_fail git commit-graph verify 2>test_err && + grep -v "^+" test_err >err && + test_i18ngrep "incorrect checksum" err + ) +' + +test_expect_success 'warn on base graph chunk incorrect' ' + git clone --no-hardlinks . base-chunk && + ( + cd base-chunk && + git commit-graph verify && + base_file=$graphdir/graph-$(tail -n 1 $graphdir/commit-graph-chain).graph && + corrupt_file "$base_file" 1376 "\01" && + git commit-graph verify --shallow 2>test_err && + grep -v "^+" test_err >err && + test_i18ngrep "commit-graph chain does not match" err + ) +' + +test_expect_success 'verify after commit-graph-chain corruption' ' + git clone --no-hardlinks . verify-chain && + ( + cd verify-chain && + corrupt_file "$graphdir/commit-graph-chain" 60 "G" && + git commit-graph verify 2>test_err && + grep -v "^+" test_err >err && + test_i18ngrep "invalid commit-graph chain" err && + corrupt_file "$graphdir/commit-graph-chain" 60 "A" && + git commit-graph verify 2>test_err && + grep -v "^+" test_err >err && + test_i18ngrep "unable to find all commit-graph files" err + ) +' + +test_expect_success 'verify across alternates' ' + git clone --no-hardlinks . verify-alt && + ( + cd verify-alt && + rm -rf $graphdir && + altdir="$(pwd)/../.git/objects" && + echo "$altdir" >.git/objects/info/alternates && + git commit-graph verify --object-dir="$altdir/" && + test_commit extra && + git commit-graph write --reachable --split && + tip_file=$graphdir/graph-$(tail -n 1 $graphdir/commit-graph-chain).graph && + corrupt_file "$tip_file" 100 "\01" && + test_must_fail git commit-graph verify --shallow 2>test_err && + grep -v "^+" test_err >err && + test_i18ngrep "commit-graph has incorrect fanout value" err + ) +' + +test_expect_success 'add octopus merge' ' + git reset --hard commits/10 && + git merge commits/3 commits/4 && + git branch merge/octopus && + git commit-graph write --reachable --split && + git commit-graph verify --progress 2>err && + test_line_count = 3 err && + test_i18ngrep ! warning err && + test_line_count = 3 $graphdir/commit-graph-chain +' + +graph_git_behavior 'graph exists' merge/octopus commits/12 + +test_expect_success 'split across alternate where alternate is not split' ' + git commit-graph write --reachable && + test_path_is_file .git/objects/info/commit-graph && + cp .git/objects/info/commit-graph . && + git clone --no-hardlinks . alt-split && + ( + cd alt-split && + rm -f .git/objects/info/commit-graph && + echo "$(pwd)"/../.git/objects >.git/objects/info/alternates && + test_commit 18 && + git commit-graph write --reachable --split && + test_line_count = 1 $graphdir/commit-graph-chain + ) && + test_cmp commit-graph .git/objects/info/commit-graph +' + +test_done diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh index 1c71c0ec77..6b97923964 100755 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@ -708,13 +708,22 @@ do # file with scheme for p in file do - test_expect_success "fetch-pack --diag-url $p://$h/$r" ' + test_expect_success !MINGW "fetch-pack --diag-url $p://$h/$r" ' check_prot_path $p://$h/$r $p "/$r" ' + test_expect_success MINGW "fetch-pack --diag-url $p://$h/$r" ' + check_prot_path $p://$h/$r $p "//$h/$r" + ' + test_expect_success MINGW "fetch-pack --diag-url $p:///$r" ' + check_prot_path $p:///$r $p "/$r" + ' # No "/~" -> "~" conversion for file - test_expect_success "fetch-pack --diag-url $p://$h/~$r" ' + test_expect_success !MINGW "fetch-pack --diag-url $p://$h/~$r" ' check_prot_path $p://$h/~$r $p "/~$r" ' + test_expect_success MINGW "fetch-pack --diag-url $p://$h/~$r" ' + check_prot_path $p://$h/~$r $p "//$h/~$r" + ' done # file without scheme for h in nohost nohost:12 [::1] [::1]:23 [ [:aa @@ -783,6 +792,44 @@ test_expect_success 'clone shallow since selects no commits' ' ) ' +# A few subtle things about the request in this test: +# +# - the server must have commit-graphs present and enabled +# +# - the history is such that our want/have share a common ancestor ("base" +# here) +# +# - we send only a single have, which is fewer than a normal client would +# send. This ensures that we don't parse "base" up front with +# parse_object(), but rather traverse to it as a parent while deciding if we +# can stop the "have" negotiation, and call parse_commit(). The former +# sees the actual object data and so always loads the three oid, whereas the +# latter will try to load it lazily. +# +# - we must use protocol v2, because it handles the "have" negotiation before +# processing the shallow directives +# +test_expect_success 'shallow since with commit graph and already-seen commit' ' + test_create_repo shallow-since-graph && + ( + cd shallow-since-graph && + test_commit base && + test_commit master && + git checkout -b other HEAD^ && + test_commit other && + git commit-graph write --reachable && + git config core.commitGraph true && + + GIT_PROTOCOL=version=2 git upload-pack . <<-EOF >/dev/null + 0012command=fetch + 00010013deepen-since 1 + 0032want $(git rev-parse other) + 0032have $(git rev-parse master) + 0000 + EOF + ) +' + test_expect_success 'shallow clone exclude tag two' ' test_create_repo shallow-exclude && ( @@ -920,4 +967,7 @@ test_expect_success 'fetch with --filter=blob:limit=0 and HTTP' ' fetch_filter_blob_limit_zero "$HTTPD_DOCUMENT_ROOT_PATH/server" "$HTTPD_URL/smart/server" ' +# DO NOT add non-httpd-specific tests here, because the last part of this +# test script is only executed when httpd is available and enabled. + test_done diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh index 7bc706873c..fdfe179b11 100755 --- a/t/t5504-fetch-receive-strict.sh +++ b/t/t5504-fetch-receive-strict.sh @@ -164,9 +164,9 @@ test_expect_success 'fsck with unsorted skipList' ' test_expect_success 'fsck with invalid or bogus skipList input' ' git -c fsck.skipList=/dev/null -c fsck.missingEmail=ignore fsck && test_must_fail git -c fsck.skipList=does-not-exist -c fsck.missingEmail=ignore fsck 2>err && - test_i18ngrep "Could not open skip list: does-not-exist" err && + test_i18ngrep "could not open.*: does-not-exist" err && test_must_fail git -c fsck.skipList=.git/config -c fsck.missingEmail=ignore fsck 2>err && - test_i18ngrep "Invalid SHA-1: \[core\]" err + test_i18ngrep "invalid object name: \[core\]" err ' test_expect_success 'fsck with other accepted skipList input (comments & empty lines)' ' @@ -193,7 +193,7 @@ test_expect_success 'fsck no garbage output from comments & empty lines errors' test_expect_success 'fsck with invalid abbreviated skipList input' ' echo $commit | test_copy_bytes 20 >SKIP.abbreviated && test_must_fail git -c fsck.skipList=SKIP.abbreviated fsck 2>err-abbreviated && - test_i18ngrep "^fatal: Invalid SHA-1: " err-abbreviated + test_i18ngrep "^fatal: invalid object name: " err-abbreviated ' test_expect_success 'fsck with exhaustive accepted skipList input (various types of comments etc.)' ' @@ -226,10 +226,10 @@ test_expect_success 'push with receive.fsck.skipList' ' test_must_fail git push --porcelain dst bogus && git --git-dir=dst/.git config receive.fsck.skipList does-not-exist && test_must_fail git push --porcelain dst bogus 2>err && - test_i18ngrep "Could not open skip list: does-not-exist" err && + test_i18ngrep "could not open.*: does-not-exist" err && git --git-dir=dst/.git config receive.fsck.skipList config && test_must_fail git push --porcelain dst bogus 2>err && - test_i18ngrep "Invalid SHA-1: \[core\]" err && + test_i18ngrep "invalid object name: \[core\]" err && git --git-dir=dst/.git config receive.fsck.skipList SKIP && git push --porcelain dst bogus @@ -255,10 +255,10 @@ test_expect_success 'fetch with fetch.fsck.skipList' ' test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec && git --git-dir=dst/.git config fetch.fsck.skipList does-not-exist && test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec 2>err && - test_i18ngrep "Could not open skip list: does-not-exist" err && + test_i18ngrep "could not open.*: does-not-exist" err && git --git-dir=dst/.git config fetch.fsck.skipList dst/.git/config && test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec 2>err && - test_i18ngrep "Invalid SHA-1: \[core\]" err && + test_i18ngrep "invalid object name: \[core\]" err && git --git-dir=dst/.git config fetch.fsck.skipList dst/.git/SKIP && git --git-dir=dst/.git fetch "file://$(pwd)" $refspec diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index e98d90dd9b..4b60282689 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -570,6 +570,35 @@ test_expect_success 'LHS of refspec follows ref disambiguation rules' ' ) ' +test_expect_success 'fetch.writeCommitGraph' ' + git clone three write && + ( + cd three && + test_commit new + ) && + ( + cd write && + git -c fetch.writeCommitGraph fetch origin && + test_path_is_file .git/objects/info/commit-graphs/commit-graph-chain + ) +' + +test_expect_success 'fetch.writeCommitGraph with submodules' ' + git clone dups super && + ( + cd super && + git submodule add "file://$TRASH_DIRECTORY/three" && + git commit -m "add submodule" + ) && + git clone "super" super-clone && + ( + cd super-clone && + rm -rf .git/objects/info && + git -c fetch.writeCommitGraph=true fetch origin && + test_path_is_file .git/objects/info/commit-graphs/commit-graph-chain + ) +' + # configured prune tests set_config_tristate () { @@ -902,6 +931,29 @@ test_expect_success C_LOCALE_OUTPUT 'fetch compact output' ' test_cmp expect actual ' +test_expect_success '--no-show-forced-updates' ' + mkdir forced-updates && + ( + cd forced-updates && + git init && + test_commit 1 && + test_commit 2 + ) && + git clone forced-updates forced-update-clone && + git clone forced-updates no-forced-update-clone && + git -C forced-updates reset --hard HEAD~1 && + ( + cd forced-update-clone && + git fetch --show-forced-updates origin 2>output && + test_i18ngrep "(forced update)" output + ) && + ( + cd no-forced-update-clone && + git fetch --no-show-forced-updates origin 2>output && + test_i18ngrep ! "(forced update)" output + ) +' + setup_negotiation_tip () { SERVER="$1" URL="$2" @@ -978,4 +1030,7 @@ test_expect_success '--negotiation-tip limits "have" lines sent with HTTP protoc check_negotiation_tip ' +# DO NOT add non-httpd-specific tests here, because the last part of this +# test script is only executed when httpd is available and enabled. + test_done diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh index e3c4a48c85..d7b9f9078f 100755 --- a/t/t5512-ls-remote.sh +++ b/t/t5512-ls-remote.sh @@ -267,8 +267,7 @@ test_expect_success 'ls-remote --symref omits filtered-out matches' ' ' test_lazy_prereq GIT_DAEMON ' - test_tristate GIT_TEST_GIT_DAEMON && - test "$GIT_TEST_GIT_DAEMON" != false + test_bool_env GIT_TEST_GIT_DAEMON true ' # This test spawns a daemon, so run it only if the user would be OK with diff --git a/t/t5514-fetch-multiple.sh b/t/t5514-fetch-multiple.sh index 0030c92e1a..de8e2f1531 100755 --- a/t/t5514-fetch-multiple.sh +++ b/t/t5514-fetch-multiple.sh @@ -105,9 +105,12 @@ test_expect_success 'git fetch --multiple (two remotes)' ' git remote rm origin && git remote add one ../one && git remote add two ../two && - git fetch --multiple one two && + GIT_TRACE=1 git fetch --multiple one two 2>trace && git branch -r > output && - test_cmp ../expect output) + test_cmp ../expect output && + grep "built-in: git gc" trace >gc && + test_line_count = 1 gc + ) ' test_expect_success 'git fetch --multiple (bad remote names)' ' @@ -180,4 +183,15 @@ test_expect_success 'git fetch --all --tags' ' test_cmp expect test8/output ' +test_expect_success 'parallel' ' + git remote add one ./bogus1 && + git remote add two ./bogus2 && + + test_must_fail env GIT_TRACE="$PWD/trace" \ + git fetch --jobs=2 --multiple one two 2>err && + grep "preparing to run up to 2 tasks" trace && + test_i18ngrep "could not fetch .one.*128" err && + test_i18ngrep "could not fetch .two.*128" err +' + test_done diff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh index e55d8474ef..961eb35c99 100755 --- a/t/t5515-fetch-merge-logic.sh +++ b/t/t5515-fetch-merge-logic.sh @@ -12,9 +12,6 @@ GIT_TEST_PROTOCOL_VERSION= . ./test-lib.sh -LF=' -' - test_expect_success setup ' GIT_AUTHOR_DATE="2006-06-26 00:00:00 +0000" && GIT_COMMITTER_DATE="2006-06-26 00:00:00 +0000" && diff --git a/t/t5517-push-mirror.sh b/t/t5517-push-mirror.sh index c05a661400..e4edd56404 100755 --- a/t/t5517-push-mirror.sh +++ b/t/t5517-push-mirror.sh @@ -265,4 +265,14 @@ test_expect_success 'remote.foo.mirror=no has no effect' ' ' +test_expect_success 'push to mirrored repository with refspec fails' ' + mk_repo_pair && + ( + cd master && + echo one >foo && git add foo && git commit -m one && + git config --add remote.up.mirror true && + test_must_fail git push up master + ) +' + test_done diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index cf4cc32fd0..602d996a33 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -5,7 +5,7 @@ test_description='pulling into void' . ./test-lib.sh modify () { - sed -e "$1" <"$2" >"$2.x" && + sed -e "$1" "$2" >"$2.x" && mv "$2.x" "$2" } @@ -15,8 +15,10 @@ test_pull_autostash () { git add new_file && git pull "$@" . copy && test_cmp_rev HEAD^ copy && - test "$(cat new_file)" = dirty && - test "$(cat file)" = "modified again" + echo dirty >expect && + test_cmp expect new_file && + echo "modified again" >expect && + test_cmp expect file } test_pull_autostash_fail () { @@ -39,8 +41,8 @@ test_expect_success 'pulling into void' ' cd cloned && git pull .. ) && - test -f file && - test -f cloned/file && + test_path_is_file file && + test_path_is_file cloned/file && test_cmp file cloned/file ' @@ -50,8 +52,8 @@ test_expect_success 'pulling into void using master:master' ' cd cloned-uho && git pull .. master:master ) && - test -f file && - test -f cloned-uho/file && + test_path_is_file file && + test_path_is_file cloned-uho/file && test_cmp file cloned-uho/file ' @@ -99,7 +101,7 @@ test_expect_success 'pulling into void must not create an octopus' ' ( cd cloned-octopus && test_must_fail git pull .. master master && - ! test -f file + test_path_is_missing file ) ' @@ -110,9 +112,11 @@ test_expect_success 'test . as a remote' ' echo updated >file && git commit -a -m updated && git checkout copy && - test "$(cat file)" = file && + echo file >expect && + test_cmp expect file && git pull && - test "$(cat file)" = updated && + echo updated >expect && + test_cmp expect file && git reflog -1 >reflog.actual && sed "s/^[0-9a-f][0-9a-f]*/OBJID/" reflog.actual >reflog.fuzzy && echo "OBJID HEAD@{0}: pull: Fast-forward" >reflog.expected && @@ -125,9 +129,11 @@ test_expect_success 'the default remote . should not break explicit pull' ' git commit -a -m modified && git checkout copy && git reset --hard HEAD^ && - test "$(cat file)" = file && + echo file >expect && + test_cmp expect file && git pull . second && - test "$(cat file)" = modified && + echo modified >expect && + test_cmp expect file && git reflog -1 >reflog.actual && sed "s/^[0-9a-f][0-9a-f]*/OBJID/" reflog.actual >reflog.fuzzy && echo "OBJID HEAD@{0}: pull . second: Fast-forward" >reflog.expected && @@ -137,10 +143,11 @@ test_expect_success 'the default remote . should not break explicit pull' ' test_expect_success 'fail if wildcard spec does not match any refs' ' git checkout -b test copy^ && test_when_finished "git checkout -f copy && git branch -D test" && - test "$(cat file)" = file && + echo file >expect && + test_cmp expect file && test_must_fail git pull . "refs/nonexisting1/*:refs/nonexisting2/*" 2>err && test_i18ngrep "no candidates for merging" err && - test "$(cat file)" = file + test_cmp expect file ' test_expect_success 'fail if no branches specified with non-default remote' ' @@ -148,11 +155,12 @@ test_expect_success 'fail if no branches specified with non-default remote' ' test_when_finished "git remote remove test_remote" && git checkout -b test copy^ && test_when_finished "git checkout -f copy && git branch -D test" && - test "$(cat file)" = file && + echo file >expect && + test_cmp expect file && test_config branch.test.remote origin && test_must_fail git pull test_remote 2>err && test_i18ngrep "specify a branch on the command line" err && - test "$(cat file)" = file + test_cmp expect file ' test_expect_success 'fail if not on a branch' ' @@ -160,10 +168,11 @@ test_expect_success 'fail if not on a branch' ' test_when_finished "git remote remove origin" && git checkout HEAD^ && test_when_finished "git checkout -f copy" && - test "$(cat file)" = file && + echo file >expect && + test_cmp expect file && test_must_fail git pull 2>err && test_i18ngrep "not currently on a branch" err && - test "$(cat file)" = file + test_cmp expect file ' test_expect_success 'fail if no configuration for current branch' ' @@ -172,10 +181,11 @@ test_expect_success 'fail if no configuration for current branch' ' git checkout -b test copy^ && test_when_finished "git checkout -f copy && git branch -D test" && test_config branch.test.remote test_remote && - test "$(cat file)" = file && + echo file >expect && + test_cmp expect file && test_must_fail git pull 2>err && test_i18ngrep "no tracking information" err && - test "$(cat file)" = file + test_cmp expect file ' test_expect_success 'pull --all: fail if no configuration for current branch' ' @@ -184,10 +194,11 @@ test_expect_success 'pull --all: fail if no configuration for current branch' ' git checkout -b test copy^ && test_when_finished "git checkout -f copy && git branch -D test" && test_config branch.test.remote test_remote && - test "$(cat file)" = file && + echo file >expect && + test_cmp expect file && test_must_fail git pull --all 2>err && test_i18ngrep "There is no tracking information" err && - test "$(cat file)" = file + test_cmp expect file ' test_expect_success 'fail if upstream branch does not exist' ' @@ -195,26 +206,31 @@ test_expect_success 'fail if upstream branch does not exist' ' test_when_finished "git checkout -f copy && git branch -D test" && test_config branch.test.remote . && test_config branch.test.merge refs/heads/nonexisting && - test "$(cat file)" = file && + echo file >expect && + test_cmp expect file && test_must_fail git pull 2>err && test_i18ngrep "no such ref was fetched" err && - test "$(cat file)" = file + test_cmp expect file ' test_expect_success 'fail if the index has unresolved entries' ' git checkout -b third second^ && test_when_finished "git checkout -f copy && git branch -D third" && - test "$(cat file)" = file && + echo file >expect && + test_cmp expect file && test_commit modified2 file && - test -z "$(git ls-files -u)" && + git ls-files -u >unmerged && + test_must_be_empty unmerged && test_must_fail git pull . second && - test -n "$(git ls-files -u)" && + git ls-files -u >unmerged && + test_file_not_empty unmerged && cp file expected && test_must_fail git pull . second 2>err && test_i18ngrep "Pulling is not possible because you have unmerged files." err && test_cmp expected file && git add file && - test -z "$(git ls-files -u)" && + git ls-files -u >unmerged && + test_must_be_empty unmerged && test_must_fail git pull . second 2>err && test_i18ngrep "You have not concluded your merge" err && test_cmp expected file @@ -223,36 +239,42 @@ test_expect_success 'fail if the index has unresolved entries' ' test_expect_success 'fast-forwards working tree if branch head is updated' ' git checkout -b third second^ && test_when_finished "git checkout -f copy && git branch -D third" && - test "$(cat file)" = file && + echo file >expect && + test_cmp expect file && git pull . second:third 2>err && test_i18ngrep "fetch updated the current branch head" err && - test "$(cat file)" = modified && - test "$(git rev-parse third)" = "$(git rev-parse second)" + echo modified >expect && + test_cmp expect file && + test_cmp_rev third second ' test_expect_success 'fast-forward fails with conflicting work tree' ' git checkout -b third second^ && test_when_finished "git checkout -f copy && git branch -D third" && - test "$(cat file)" = file && + echo file >expect && + test_cmp expect file && echo conflict >file && test_must_fail git pull . second:third 2>err && test_i18ngrep "Cannot fast-forward your working tree" err && - test "$(cat file)" = conflict && - test "$(git rev-parse third)" = "$(git rev-parse second)" + echo conflict >expect && + test_cmp expect file && + test_cmp_rev third second ' test_expect_success '--rebase' ' git branch to-rebase && - echo modified again > file && + echo modified again >file && git commit -m file file && git checkout to-rebase && - echo new > file2 && + echo new >file2 && git add file2 && git commit -m "new file" && git tag before-rebase && git pull --rebase . copy && - test "$(git rev-parse HEAD^)" = "$(git rev-parse copy)" && - test new = "$(git show HEAD:file2)" + test_cmp_rev HEAD^ copy && + echo new >expect && + git show HEAD:file2 >actual && + test_cmp expect actual ' test_expect_success '--rebase fast forward' ' @@ -263,7 +285,7 @@ test_expect_success '--rebase fast forward' ' git checkout to-rebase && git pull --rebase . ff && - test "$(git rev-parse HEAD)" = "$(git rev-parse ff)" && + test_cmp_rev HEAD ff && # The above only validates the result. Did we actually bypass rebase? git reflog -1 >reflog.actual && @@ -287,7 +309,7 @@ test_expect_success '--rebase --autostash fast forward' ' git checkout behind && echo dirty >file && git pull --rebase --autostash . to-rebase-ff && - test "$(git rev-parse HEAD)" = "$(git rev-parse to-rebase-ff)" + test_cmp_rev HEAD to-rebase-ff ' test_expect_success '--rebase with conflicts shows advice' ' @@ -325,9 +347,11 @@ test_expect_success 'failed --rebase shows advice' ' test_expect_success '--rebase fails with multiple branches' ' git reset --hard before-rebase && test_must_fail git pull --rebase . copy master 2>err && - test "$(git rev-parse HEAD)" = "$(git rev-parse before-rebase)" && + test_cmp_rev HEAD before-rebase && test_i18ngrep "Cannot rebase onto multiple branches" err && - test modified = "$(git show HEAD:file)" + echo modified >expect && + git show HEAD:file >actual && + test_cmp expect actual ' test_expect_success 'pull --rebase succeeds with dirty working directory and rebase.autostash set' ' @@ -377,8 +401,10 @@ test_expect_success 'pull.rebase' ' git reset --hard before-rebase && test_config pull.rebase true && git pull . copy && - test "$(git rev-parse HEAD^)" = "$(git rev-parse copy)" && - test new = "$(git show HEAD:file2)" + test_cmp_rev HEAD^ copy && + echo new >expect && + git show HEAD:file2 >actual && + test_cmp expect actual ' test_expect_success 'pull --autostash & pull.rebase=true' ' @@ -395,8 +421,10 @@ test_expect_success 'branch.to-rebase.rebase' ' git reset --hard before-rebase && test_config branch.to-rebase.rebase true && git pull . copy && - test "$(git rev-parse HEAD^)" = "$(git rev-parse copy)" && - test new = "$(git show HEAD:file2)" + test_cmp_rev HEAD^ copy && + echo new >expect && + git show HEAD:file2 >actual && + test_cmp expect actual ' test_expect_success 'branch.to-rebase.rebase should override pull.rebase' ' @@ -404,23 +432,29 @@ test_expect_success 'branch.to-rebase.rebase should override pull.rebase' ' test_config pull.rebase true && test_config branch.to-rebase.rebase false && git pull . copy && - test "$(git rev-parse HEAD^)" != "$(git rev-parse copy)" && - test new = "$(git show HEAD:file2)" + test_cmp_rev ! HEAD^ copy && + echo new >expect && + git show HEAD:file2 >actual && + test_cmp expect actual ' -test_expect_success "pull --rebase warns on --verify-signatures" ' +test_expect_success 'pull --rebase warns on --verify-signatures' ' git reset --hard before-rebase && git pull --rebase --verify-signatures . copy 2>err && - test "$(git rev-parse HEAD^)" = "$(git rev-parse copy)" && - test new = "$(git show HEAD:file2)" && + test_cmp_rev HEAD^ copy && + echo new >expect && + git show HEAD:file2 >actual && + test_cmp expect actual && test_i18ngrep "ignoring --verify-signatures for rebase" err ' -test_expect_success "pull --rebase does not warn on --no-verify-signatures" ' +test_expect_success 'pull --rebase does not warn on --no-verify-signatures' ' git reset --hard before-rebase && git pull --rebase --no-verify-signatures . copy 2>err && - test "$(git rev-parse HEAD^)" = "$(git rev-parse copy)" && - test new = "$(git show HEAD:file2)" && + test_cmp_rev HEAD^ copy && + echo new >expect && + git show HEAD:file2 >actual && + test_cmp expect actual && test_i18ngrep ! "verify-signatures" err ' @@ -440,25 +474,31 @@ test_expect_success 'pull.rebase=false create a new merge commit' ' git reset --hard before-preserve-rebase && test_config pull.rebase false && git pull . copy && - test "$(git rev-parse HEAD^1)" = "$(git rev-parse before-preserve-rebase)" && - test "$(git rev-parse HEAD^2)" = "$(git rev-parse copy)" && - test file3 = "$(git show HEAD:file3.t)" + test_cmp_rev HEAD^1 before-preserve-rebase && + test_cmp_rev HEAD^2 copy && + echo file3 >expect && + git show HEAD:file3.t >actual && + test_cmp expect actual ' test_expect_success 'pull.rebase=true flattens keep-merge' ' git reset --hard before-preserve-rebase && test_config pull.rebase true && git pull . copy && - test "$(git rev-parse HEAD^^)" = "$(git rev-parse copy)" && - test file3 = "$(git show HEAD:file3.t)" + test_cmp_rev HEAD^^ copy && + echo file3 >expect && + git show HEAD:file3.t >actual && + test_cmp expect actual ' test_expect_success 'pull.rebase=1 is treated as true and flattens keep-merge' ' git reset --hard before-preserve-rebase && test_config pull.rebase 1 && git pull . copy && - test "$(git rev-parse HEAD^^)" = "$(git rev-parse copy)" && - test file3 = "$(git show HEAD:file3.t)" + test_cmp_rev HEAD^^ copy && + echo file3 >expect && + git show HEAD:file3.t >actual && + test_cmp expect actual ' test_expect_success REBASE_P \ @@ -466,8 +506,8 @@ test_expect_success REBASE_P \ git reset --hard before-preserve-rebase && test_config pull.rebase preserve && git pull . copy && - test "$(git rev-parse HEAD^^)" = "$(git rev-parse copy)" && - test "$(git rev-parse HEAD^2)" = "$(git rev-parse keep-merge)" + test_cmp_rev HEAD^^ copy && + test_cmp_rev HEAD^2 keep-merge ' test_expect_success 'pull.rebase=interactive' ' @@ -478,7 +518,8 @@ test_expect_success 'pull.rebase=interactive' ' test_set_editor "$TRASH_DIRECTORY/fake-editor" && test_when_finished "test_might_fail git rebase --abort" && test_must_fail git pull --rebase=interactive . copy && - test "I was here" = "$(cat fake.out)" + echo "I was here" >expect && + test_cmp expect fake.out ' test_expect_success 'pull --rebase=i' ' @@ -489,30 +530,35 @@ test_expect_success 'pull --rebase=i' ' test_set_editor "$TRASH_DIRECTORY/fake-editor" && test_when_finished "test_might_fail git rebase --abort" && test_must_fail git pull --rebase=i . copy && - test "I was here, too" = "$(cat fake.out)" + echo "I was here, too" >expect && + test_cmp expect fake.out ' test_expect_success 'pull.rebase=invalid fails' ' git reset --hard before-preserve-rebase && test_config pull.rebase invalid && - ! git pull . copy + test_must_fail git pull . copy ' test_expect_success '--rebase=false create a new merge commit' ' git reset --hard before-preserve-rebase && test_config pull.rebase true && git pull --rebase=false . copy && - test "$(git rev-parse HEAD^1)" = "$(git rev-parse before-preserve-rebase)" && - test "$(git rev-parse HEAD^2)" = "$(git rev-parse copy)" && - test file3 = "$(git show HEAD:file3.t)" + test_cmp_rev HEAD^1 before-preserve-rebase && + test_cmp_rev HEAD^2 copy && + echo file3 >expect && + git show HEAD:file3.t >actual && + test_cmp expect actual ' test_expect_success '--rebase=true rebases and flattens keep-merge' ' git reset --hard before-preserve-rebase && test_config pull.rebase preserve && git pull --rebase=true . copy && - test "$(git rev-parse HEAD^^)" = "$(git rev-parse copy)" && - test file3 = "$(git show HEAD:file3.t)" + test_cmp_rev HEAD^^ copy && + echo file3 >expect && + git show HEAD:file3.t >actual && + test_cmp expect actual ' test_expect_success REBASE_P \ @@ -520,58 +566,62 @@ test_expect_success REBASE_P \ git reset --hard before-preserve-rebase && test_config pull.rebase true && git pull --rebase=preserve . copy && - test "$(git rev-parse HEAD^^)" = "$(git rev-parse copy)" && - test "$(git rev-parse HEAD^2)" = "$(git rev-parse keep-merge)" + test_cmp_rev HEAD^^ copy && + test_cmp_rev HEAD^2 keep-merge ' test_expect_success '--rebase=invalid fails' ' git reset --hard before-preserve-rebase && - ! git pull --rebase=invalid . copy + test_must_fail git pull --rebase=invalid . copy ' test_expect_success '--rebase overrides pull.rebase=preserve and flattens keep-merge' ' git reset --hard before-preserve-rebase && test_config pull.rebase preserve && git pull --rebase . copy && - test "$(git rev-parse HEAD^^)" = "$(git rev-parse copy)" && - test file3 = "$(git show HEAD:file3.t)" + test_cmp_rev HEAD^^ copy && + echo file3 >expect && + git show HEAD:file3.t >actual && + test_cmp expect actual ' test_expect_success '--rebase with rebased upstream' ' - git remote add -f me . && git checkout copy && git tag copy-orig && git reset --hard HEAD^ && - echo conflicting modification > file && + echo conflicting modification >file && git commit -m conflict file && git checkout to-rebase && - echo file > file2 && + echo file >file2 && git commit -m to-rebase file2 && git tag to-rebase-orig && git pull --rebase me copy && - test "conflicting modification" = "$(cat file)" && - test file = "$(cat file2)" - + echo "conflicting modification" >expect && + test_cmp expect file && + echo file >expect && + test_cmp expect file2 ' test_expect_success '--rebase -f with rebased upstream' ' test_when_finished "test_might_fail git rebase --abort" && git reset --hard to-rebase-orig && git pull --rebase -f me copy && - test "conflicting modification" = "$(cat file)" && - test file = "$(cat file2)" + echo "conflicting modification" >expect && + test_cmp expect file && + echo file >expect && + test_cmp expect file2 ' test_expect_success '--rebase with rebased default upstream' ' - git update-ref refs/remotes/me/copy copy-orig && git checkout --track -b to-rebase2 me/copy && git reset --hard to-rebase-orig && git pull --rebase && - test "conflicting modification" = "$(cat file)" && - test file = "$(cat file2)" - + echo "conflicting modification" >expect && + test_cmp expect file && + echo file >expect && + test_cmp expect file2 ' test_expect_success 'rebased upstream + fetch + pull --rebase' ' @@ -582,13 +632,14 @@ test_expect_success 'rebased upstream + fetch + pull --rebase' ' git reset --hard to-rebase-orig && git fetch && git pull --rebase && - test "conflicting modification" = "$(cat file)" && - test file = "$(cat file2)" + echo "conflicting modification" >expect && + test_cmp expect file && + echo file >expect && + test_cmp expect file2 ' test_expect_success 'pull --rebase dies early with dirty working directory' ' - git checkout to-rebase && git update-ref refs/remotes/me/copy copy^ && COPY="$(git rev-parse --verify me/copy)" && @@ -596,23 +647,23 @@ test_expect_success 'pull --rebase dies early with dirty working directory' ' test_config branch.to-rebase.remote me && test_config branch.to-rebase.merge refs/heads/copy && test_config branch.to-rebase.rebase true && - echo dirty >> file && + echo dirty >>file && git add file && test_must_fail git pull && - test "$COPY" = "$(git rev-parse --verify me/copy)" && + test_cmp_rev "$COPY" me/copy && git checkout HEAD -- file && git pull && - test "$COPY" != "$(git rev-parse --verify me/copy)" - + test_cmp_rev ! "$COPY" me/copy ' test_expect_success 'pull --rebase works on branch yet to be born' ' git rev-parse master >expect && mkdir empty_repo && - (cd empty_repo && - git init && - git pull --rebase .. master && - git rev-parse HEAD >../actual + ( + cd empty_repo && + git init && + git pull --rebase .. master && + git rev-parse HEAD >../actual ) && test_cmp expect actual ' @@ -624,10 +675,14 @@ test_expect_success 'pull --rebase fails on unborn branch with staged changes' ' cd empty_repo2 && echo staged-file >staged-file && git add staged-file && - test "$(git ls-files)" = staged-file && + echo staged-file >expect && + git ls-files >actual && + test_cmp expect actual && test_must_fail git pull --rebase .. master 2>err && - test "$(git ls-files)" = staged-file && - test "$(git show :staged-file)" = staged-file && + git ls-files >actual && + test_cmp expect actual && + git show :staged-file >actual && + test_cmp expect actual && test_i18ngrep "unborn branch with changes added to the index" err ) ' @@ -638,7 +693,8 @@ test_expect_success 'pull --rebase fails on corrupt HEAD' ' ( cd corrupt && test_commit one && - obj=$(git rev-parse --verify HEAD | sed "s#^..#&/#") && + git rev-parse --verify HEAD >head && + obj=$(sed "s#^..#&/#" head) && rm -f .git/objects/$obj && test_must_fail git pull --rebase ) @@ -646,66 +702,77 @@ test_expect_success 'pull --rebase fails on corrupt HEAD' ' test_expect_success 'setup for detecting upstreamed changes' ' mkdir src && - (cd src && - git init && - printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" > stuff && - git add stuff && - git commit -m "Initial revision" + ( + cd src && + git init && + printf "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n" > stuff && + git add stuff && + git commit -m "Initial revision" ) && git clone src dst && - (cd src && - modify s/5/43/ stuff && - git commit -a -m "5->43" && - modify s/6/42/ stuff && - git commit -a -m "Make it bigger" + ( + cd src && + modify s/5/43/ stuff && + git commit -a -m "5->43" && + modify s/6/42/ stuff && + git commit -a -m "Make it bigger" ) && - (cd dst && - modify s/5/43/ stuff && - git commit -a -m "Independent discovery of 5->43" + ( + cd dst && + modify s/5/43/ stuff && + git commit -a -m "Independent discovery of 5->43" ) ' test_expect_success 'git pull --rebase detects upstreamed changes' ' - (cd dst && - git pull --rebase && - test -z "$(git ls-files -u)" + ( + cd dst && + git pull --rebase && + git ls-files -u >untracked && + test_must_be_empty untracked ) ' test_expect_success 'setup for avoiding reapplying old patches' ' - (cd dst && - test_might_fail git rebase --abort && - git reset --hard origin/master + ( + cd dst && + test_might_fail git rebase --abort && + git reset --hard origin/master ) && git clone --bare src src-replace.git && rm -rf src && mv src-replace.git src && - (cd dst && - modify s/2/22/ stuff && - git commit -a -m "Change 2" && - modify s/3/33/ stuff && - git commit -a -m "Change 3" && - modify s/4/44/ stuff && - git commit -a -m "Change 4" && - git push && - - modify s/44/55/ stuff && - git commit --amend -a -m "Modified Change 4" + ( + cd dst && + modify s/2/22/ stuff && + git commit -a -m "Change 2" && + modify s/3/33/ stuff && + git commit -a -m "Change 3" && + modify s/4/44/ stuff && + git commit -a -m "Change 4" && + git push && + + modify s/44/55/ stuff && + git commit --amend -a -m "Modified Change 4" ) ' test_expect_success 'git pull --rebase does not reapply old patches' ' - (cd dst && - test_must_fail git pull --rebase && - test 1 = $(find .git/rebase-apply -name "000*" | wc -l) + ( + cd dst && + test_must_fail git pull --rebase && + find .git/rebase-apply -name "000*" >patches && + test_line_count = 1 patches ) ' test_expect_success 'git pull --rebase against local branch' ' git checkout -b copy2 to-rebase-orig && git pull --rebase . to-rebase && - test "conflicting modification" = "$(cat file)" && - test file = "$(cat file2)" + echo "conflicting modification" >expect && + test_cmp expect file && + echo file >expect && + test_cmp expect file2 ' test_done diff --git a/t/t5528-push-default.sh b/t/t5528-push-default.sh index 44309566f1..4d1e0c363e 100755 --- a/t/t5528-push-default.sh +++ b/t/t5528-push-default.sh @@ -163,7 +163,7 @@ test_pushdefault_workflow success current master # update parent1's foo (which is our upstream) test_pushdefault_workflow success upstream foo -# upsream is foo which is not the name of the current branch +# upstream is foo which is not the name of the current branch test_pushdefault_workflow failure simple master # master and foo are updated diff --git a/t/t5535-fetch-push-symref.sh b/t/t5535-fetch-push-symref.sh index 8ed58d27f2..e8f6d233ff 100755 --- a/t/t5535-fetch-push-symref.sh +++ b/t/t5535-fetch-push-symref.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='avoiding conflicting update thru symref aliasing' +test_description='avoiding conflicting update through symref aliasing' . ./test-lib.sh diff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh index 66f0b64d39..97a67728ca 100755 --- a/t/t5537-fetch-shallow.sh +++ b/t/t5537-fetch-shallow.sh @@ -255,4 +255,7 @@ test_expect_success 'shallow fetches check connectivity before writing shallow f git -C client fsck ' +# DO NOT add non-httpd-specific tests here, because the last part of this +# test script is only executed when httpd is available and enabled. + test_done diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh index b86ddb60f2..4c970787b0 100755 --- a/t/t5541-http-push-smart.sh +++ b/t/t5541-http-push-smart.sh @@ -184,11 +184,12 @@ test_expect_success 'push --atomic also prevents branch creation, reports collat test_config -C "$d" http.receivepack true && up="$HTTPD_URL"/smart/atomic-branches.git && - # Tell "$up" about two branches for now + # Tell "$up" about three branches for now test_commit atomic1 && test_commit atomic2 && git branch collateral && - git push "$up" master collateral && + git branch other && + git push "$up" master collateral other && # collateral is a valid push, but should be failed by atomic push git checkout collateral && @@ -226,6 +227,41 @@ test_expect_success 'push --atomic also prevents branch creation, reports collat grep "^ ! .*rejected.* collateral -> collateral .*atomic push failed" output ' +test_expect_success 'push --atomic fails on server-side errors' ' + # Use previously set up repository + d=$HTTPD_DOCUMENT_ROOT_PATH/atomic-branches.git && + test_config -C "$d" http.receivepack true && + up="$HTTPD_URL"/smart/atomic-branches.git && + + # break ref updates for other on the remote site + mkdir "$d/refs/heads/other.lock" && + + # add the new commit to other + git branch -f other collateral && + + # --atomic should cause entire push to be rejected + test_must_fail git push --atomic "$up" atomic other 2>output && + + # the new branch should not have been created upstream + test_must_fail git -C "$d" show-ref --verify refs/heads/atomic && + + # upstream should still reflect atomic2, the last thing we pushed + # successfully + git rev-parse atomic2 >expected && + # ...to other. + git -C "$d" rev-parse refs/heads/other >actual && + test_cmp expected actual && + + # the new branch should not have been created upstream + test_must_fail git -C "$d" show-ref --verify refs/heads/atomic && + + # the failed refs should be indicated to the user + grep "^ ! .*rejected.* other -> other .*atomic transaction failed" output && + + # the collateral failure refs should be indicated to the user + grep "^ ! .*rejected.* atomic -> atomic .*atomic transaction failed" output +' + test_expect_success 'push --all can push to empty repo' ' d=$HTTPD_DOCUMENT_ROOT_PATH/empty-all.git && git init --bare "$d" && @@ -262,7 +298,7 @@ test_expect_success TTY 'push shows progress when stderr is a tty' ' cd "$ROOT_PATH"/test_repo_clone && test_commit noisy && test_terminal git push >output 2>&1 && - test_i18ngrep "Writing objects" output + test_i18ngrep "^Writing objects" output ' test_expect_success TTY 'push --quiet silences status and progress' ' @@ -277,7 +313,7 @@ test_expect_success TTY 'push --no-progress silences progress but not status' ' test_commit no-progress && test_terminal git push --no-progress >output 2>&1 && test_i18ngrep "^To http" output && - test_i18ngrep ! "Writing objects" output + test_i18ngrep ! "^Writing objects" output ' test_expect_success 'push --progress shows progress to non-tty' ' @@ -285,7 +321,7 @@ test_expect_success 'push --progress shows progress to non-tty' ' test_commit progress && git push --progress >output 2>&1 && test_i18ngrep "^To http" output && - test_i18ngrep "Writing objects" output + test_i18ngrep "^Writing objects" output ' test_expect_success 'http push gives sane defaults to reflog' ' diff --git a/t/t5545-push-options.sh b/t/t5545-push-options.sh index 6d1d59c9b1..38e6f7340e 100755 --- a/t/t5545-push-options.sh +++ b/t/t5545-push-options.sh @@ -115,7 +115,7 @@ test_expect_success 'push options and submodules' ' git -C parent submodule add ../upstream workbench && git -C parent/workbench remote add up ../../upstream && - git -C parent commit -m "add submoule" && + git -C parent commit -m "add submodule" && test_commit -C parent/workbench two && git -C parent add workbench && @@ -278,4 +278,7 @@ test_expect_success 'push options keep quoted characters intact (http)' ' test_cmp expect "$HTTPD_DOCUMENT_ROOT_PATH"/upstream.git/hooks/pre-receive.push_options ' +# DO NOT add non-httpd-specific tests here, because the last part of this +# test script is only executed when httpd is available and enabled. + test_done diff --git a/t/t5552-skipping-fetch-negotiator.sh b/t/t5552-skipping-fetch-negotiator.sh index 8a14be51a1..f70cbcc9ca 100755 --- a/t/t5552-skipping-fetch-negotiator.sh +++ b/t/t5552-skipping-fetch-negotiator.sh @@ -60,29 +60,6 @@ test_expect_success 'commits with no parents are sent regardless of skip distanc have_not_sent c6 c4 c3 ' -test_expect_success 'unknown fetch.negotiationAlgorithm values error out' ' - rm -rf server client trace && - git init server && - test_commit -C server to_fetch && - - git init client && - test_commit -C client on_client && - git -C client checkout on_client && - - test_config -C client fetch.negotiationAlgorithm invalid && - test_must_fail git -C client fetch "$(pwd)/server" 2>err && - test_i18ngrep "unknown fetch negotiation algorithm" err && - - # Explicit "default" value - test_config -C client fetch.negotiationAlgorithm default && - git -C client -c fetch.negotiationAlgorithm=default fetch "$(pwd)/server" && - - # Implementation detail: If there is nothing to fetch, we will not error out - test_config -C client fetch.negotiationAlgorithm invalid && - git -C client fetch "$(pwd)/server" 2>err && - test_i18ngrep ! "unknown fetch negotiation algorithm" err -' - test_expect_success 'when two skips collide, favor the larger one' ' rm -rf server client trace && git init server && diff --git a/t/t5553-set-upstream.sh b/t/t5553-set-upstream.sh new file mode 100755 index 0000000000..81975ad8f9 --- /dev/null +++ b/t/t5553-set-upstream.sh @@ -0,0 +1,178 @@ +#!/bin/sh + +test_description='"git fetch/pull --set-upstream" basic tests.' +. ./test-lib.sh + +check_config () { + printf "%s\n" "$2" "$3" >"expect.$1" && + { + git config "branch.$1.remote" && git config "branch.$1.merge" + } >"actual.$1" && + test_cmp "expect.$1" "actual.$1" +} + +check_config_missing () { + test_expect_code 1 git config "branch.$1.remote" && + test_expect_code 1 git config "branch.$1.merge" +} + +clear_config () { + for branch in "$@"; do + test_might_fail git config --unset-all "branch.$branch.remote" + test_might_fail git config --unset-all "branch.$branch.merge" + done +} + +ensure_fresh_upstream () { + rm -rf parent && git init --bare parent +} + +test_expect_success 'setup bare parent fetch' ' + ensure_fresh_upstream && + git remote add upstream parent +' + +test_expect_success 'setup commit on master and other fetch' ' + test_commit one && + git push upstream master && + git checkout -b other && + test_commit two && + git push upstream other +' + +# tests for fetch --set-upstream + +test_expect_success 'fetch --set-upstream does not set upstream w/o branch' ' + clear_config master other && + git checkout master && + git fetch --set-upstream upstream && + check_config_missing master && + check_config_missing other +' + +test_expect_success 'fetch --set-upstream upstream master sets branch master but not other' ' + clear_config master other && + git fetch --set-upstream upstream master && + check_config master upstream refs/heads/master && + check_config_missing other +' + +test_expect_success 'fetch --set-upstream upstream other sets branch other' ' + clear_config master other && + git fetch --set-upstream upstream other && + check_config master upstream refs/heads/other && + check_config_missing other +' + +test_expect_success 'fetch --set-upstream master:other does not set the branch other2' ' + clear_config other2 && + git fetch --set-upstream upstream master:other2 && + check_config_missing other2 +' + +test_expect_success 'fetch --set-upstream http://nosuchdomain.example.com fails with invalid url' ' + # master explicitly not cleared, we check that it is not touched from previous value + clear_config other other2 && + test_must_fail git fetch --set-upstream http://nosuchdomain.example.com && + check_config master upstream refs/heads/other && + check_config_missing other && + check_config_missing other2 +' + +test_expect_success 'fetch --set-upstream with valid URL sets upstream to URL' ' + clear_config other other2 && + url="file://'"$PWD"'" && + git fetch --set-upstream "$url" && + check_config master "$url" HEAD && + check_config_missing other && + check_config_missing other2 +' + +# tests for pull --set-upstream + +test_expect_success 'setup bare parent pull' ' + git remote rm upstream && + ensure_fresh_upstream && + git remote add upstream parent +' + +test_expect_success 'setup commit on master and other pull' ' + test_commit three && + git push --tags upstream master && + test_commit four && + git push upstream other +' + +test_expect_success 'pull --set-upstream upstream master sets branch master but not other' ' + clear_config master other && + git pull --set-upstream upstream master && + check_config master upstream refs/heads/master && + check_config_missing other +' + +test_expect_success 'pull --set-upstream master:other2 does not set the branch other2' ' + clear_config other2 && + git pull --set-upstream upstream master:other2 && + check_config_missing other2 +' + +test_expect_success 'pull --set-upstream upstream other sets branch master' ' + clear_config master other && + git pull --set-upstream upstream other && + check_config master upstream refs/heads/other && + check_config_missing other +' + +test_expect_success 'pull --set-upstream upstream tag does not set the tag' ' + clear_config three && + git pull --tags --set-upstream upstream three && + check_config_missing three +' + +test_expect_success 'pull --set-upstream http://nosuchdomain.example.com fails with invalid url' ' + # master explicitly not cleared, we check that it is not touched from previous value + clear_config other other2 three && + test_must_fail git pull --set-upstream http://nosuchdomain.example.com && + check_config master upstream refs/heads/other && + check_config_missing other && + check_config_missing other2 && + check_config_missing three +' + +test_expect_success 'pull --set-upstream upstream HEAD sets branch HEAD' ' + clear_config master other && + git pull --set-upstream upstream HEAD && + check_config master upstream HEAD && + git checkout other && + git pull --set-upstream upstream HEAD && + check_config other upstream HEAD +' + +test_expect_success 'pull --set-upstream upstream with more than one branch does nothing' ' + clear_config master three && + git pull --set-upstream upstream master three && + check_config_missing master && + check_config_missing three +' + +test_expect_success 'pull --set-upstream with valid URL sets upstream to URL' ' + clear_config master other other2 && + git checkout master && + url="file://'"$PWD"'" && + git pull --set-upstream "$url" && + check_config master "$url" HEAD && + check_config_missing other && + check_config_missing other2 +' + +test_expect_success 'pull --set-upstream with valid URL and branch sets branch' ' + clear_config master other other2 && + git checkout master && + url="file://'"$PWD"'" && + git pull --set-upstream "$url" master && + check_config master "$url" refs/heads/master && + check_config_missing other && + check_config_missing other2 +' + +test_done diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index 37d76808d4..ad8c41176e 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -434,7 +434,6 @@ test_expect_success 'double quoted plink.exe in GIT_SSH_COMMAND' ' expect_ssh "-v -P 123" myhost src ' -SQ="'" test_expect_success 'single quoted plink.exe in GIT_SSH_COMMAND' ' copy_ssh_wrapper_as "$TRASH_DIRECTORY/plink.exe" && GIT_SSH_COMMAND="$SQ$TRASH_DIRECTORY/plink.exe$SQ -v" \ @@ -654,7 +653,8 @@ partial_clone () { git -C client fsck && # Ensure that unneeded blobs are not inadvertently fetched. - test_config -C client extensions.partialclone "not a remote" && + test_config -C client remote.origin.promisor "false" && + git -C client config --unset remote.origin.partialclonefilter && test_must_fail git -C client cat-file -e "$HASH1" && # But this blob was fetched, because clone performs an initial checkout @@ -739,4 +739,7 @@ test_expect_success 'partial clone using HTTP' ' partial_clone "$HTTPD_DOCUMENT_ROOT_PATH/server" "$HTTPD_URL/smart/server" ' +# DO NOT add non-httpd-specific tests here, because the last part of this +# test script is only executed when httpd is available and enabled. + test_done diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh index 4320082b1b..4894237ab8 100755 --- a/t/t5604-clone-reference.sh +++ b/t/t5604-clone-reference.sh @@ -221,4 +221,137 @@ test_expect_success 'clone, dissociate from alternates' ' ( cd C && git fsck ) ' +test_expect_success 'setup repo with garbage in objects/*' ' + git init S && + ( + cd S && + test_commit A && + + cd .git/objects && + >.some-hidden-file && + >some-file && + mkdir .some-hidden-dir && + >.some-hidden-dir/some-file && + >.some-hidden-dir/.some-dot-file && + mkdir some-dir && + >some-dir/some-file && + >some-dir/.some-dot-file + ) +' + +test_expect_success 'clone a repo with garbage in objects/*' ' + for option in --local --no-hardlinks --shared --dissociate + do + git clone $option S S$option || return 1 && + git -C S$option fsck || return 1 + done && + find S-* -name "*some*" | sort >actual && + cat >expected <<-EOF && + S--dissociate/.git/objects/.some-hidden-dir + S--dissociate/.git/objects/.some-hidden-dir/.some-dot-file + S--dissociate/.git/objects/.some-hidden-dir/some-file + S--dissociate/.git/objects/.some-hidden-file + S--dissociate/.git/objects/some-dir + S--dissociate/.git/objects/some-dir/.some-dot-file + S--dissociate/.git/objects/some-dir/some-file + S--dissociate/.git/objects/some-file + S--local/.git/objects/.some-hidden-dir + S--local/.git/objects/.some-hidden-dir/.some-dot-file + S--local/.git/objects/.some-hidden-dir/some-file + S--local/.git/objects/.some-hidden-file + S--local/.git/objects/some-dir + S--local/.git/objects/some-dir/.some-dot-file + S--local/.git/objects/some-dir/some-file + S--local/.git/objects/some-file + S--no-hardlinks/.git/objects/.some-hidden-dir + S--no-hardlinks/.git/objects/.some-hidden-dir/.some-dot-file + S--no-hardlinks/.git/objects/.some-hidden-dir/some-file + S--no-hardlinks/.git/objects/.some-hidden-file + S--no-hardlinks/.git/objects/some-dir + S--no-hardlinks/.git/objects/some-dir/.some-dot-file + S--no-hardlinks/.git/objects/some-dir/some-file + S--no-hardlinks/.git/objects/some-file + EOF + test_cmp expected actual +' + +test_expect_success SYMLINKS 'setup repo with manually symlinked or unknown files at objects/' ' + git init T && + ( + cd T && + git config gc.auto 0 && + test_commit A && + git gc && + test_commit B && + + cd .git/objects && + mv pack packs && + ln -s packs pack && + find ?? -type d >loose-dirs && + last_loose=$(tail -n 1 loose-dirs) && + mv $last_loose a-loose-dir && + ln -s a-loose-dir $last_loose && + first_loose=$(head -n 1 loose-dirs) && + rm -f loose-dirs && + + cd $first_loose && + obj=$(ls *) && + mv $obj ../an-object && + ln -s ../an-object $obj && + + cd ../ && + find . -type f | sort >../../../T.objects-files.raw && + find . -type l | sort >../../../T.objects-symlinks.raw && + echo unknown_content >unknown_file + ) && + git -C T fsck && + git -C T rev-list --all --objects >T.objects +' + + +test_expect_success SYMLINKS 'clone repo with symlinked or unknown files at objects/' ' + for option in --local --no-hardlinks --shared --dissociate + do + git clone $option T T$option || return 1 && + git -C T$option fsck || return 1 && + git -C T$option rev-list --all --objects >T$option.objects && + test_cmp T.objects T$option.objects && + ( + cd T$option/.git/objects && + find . -type f | sort >../../../T$option.objects-files.raw && + find . -type l | sort >../../../T$option.objects-symlinks.raw + ) + done && + + for raw in $(ls T*.raw) + do + sed -e "s!/../!/Y/!; s![0-9a-f]\{38,\}!Z!" -e "/commit-graph/d" \ + -e "/multi-pack-index/d" <$raw >$raw.de-sha || return 1 + done && + + cat >expected-files <<-EOF && + ./Y/Z + ./Y/Z + ./a-loose-dir/Z + ./an-object + ./Y/Z + ./info/packs + ./pack/pack-Z.idx + ./pack/pack-Z.pack + ./packs/pack-Z.idx + ./packs/pack-Z.pack + ./unknown_file + EOF + + for option in --local --no-hardlinks --dissociate + do + test_cmp expected-files T$option.objects-files.raw.de-sha || return 1 && + test_must_be_empty T$option.objects-symlinks.raw.de-sha || return 1 + done && + + echo ./info/alternates >expected-files && + test_cmp expected-files T--shared.objects-files.raw && + test_must_be_empty T--shared.objects-symlinks.raw +' + test_done diff --git a/t/t5607-clone-bundle.sh b/t/t5607-clone-bundle.sh index 2a0fb15cf1..b7a3fdf02d 100755 --- a/t/t5607-clone-bundle.sh +++ b/t/t5607-clone-bundle.sh @@ -83,4 +83,15 @@ test_expect_success 'failed bundle creation does not leave cruft' ' test_path_is_missing fail.bundle.lock ' +test_expect_success 'fetch SHA-1 from bundle' ' + test_create_repo foo && + test_commit -C foo x && + git -C foo bundle create tip.bundle -1 master && + git -C foo rev-parse HEAD >hash && + + # Exercise to ensure that fetching a SHA-1 from a bundle works with no + # errors + git fetch --no-tags foo/tip.bundle "$(cat hash)" +' + test_done diff --git a/t/t5608-clone-2gb.sh b/t/t5608-clone-2gb.sh index 2c6bc07344..eee0842888 100755 --- a/t/t5608-clone-2gb.sh +++ b/t/t5608-clone-2gb.sh @@ -3,7 +3,7 @@ test_description='Test cloning a repository larger than 2 gigabyte' . ./test-lib.sh -if test -z "$GIT_TEST_CLONE_2GB" +if ! test_bool_env GIT_TEST_CLONE_2GB false then say 'Skipping expensive 2GB clone test; enable it with GIT_TEST_CLONE_2GB=t' else diff --git a/t/t5616-partial-clone.sh b/t/t5616-partial-clone.sh index b91ef548f8..fea56cda6d 100755 --- a/t/t5616-partial-clone.sh +++ b/t/t5616-partial-clone.sh @@ -42,8 +42,16 @@ test_expect_success 'do partial clone 1' ' test_cmp expect_1.oids observed.oids && test "$(git -C pc1 config --local core.repositoryformatversion)" = "1" && - test "$(git -C pc1 config --local extensions.partialclone)" = "origin" && - test "$(git -C pc1 config --local core.partialclonefilter)" = "blob:none" + test "$(git -C pc1 config --local remote.origin.promisor)" = "true" && + test "$(git -C pc1 config --local remote.origin.partialclonefilter)" = "blob:none" +' + +test_expect_success 'verify that .promisor file contains refs fetched' ' + ls pc1/.git/objects/pack/pack-*.promisor >promisorlist && + test_line_count = 1 promisorlist && + git -C srv.bare rev-list HEAD >headhash && + grep "$(cat headhash) HEAD" $(cat promisorlist) && + grep "$(cat headhash) refs/heads/master" $(cat promisorlist) ' # checkout master to force dynamic object fetch of blobs at HEAD. @@ -208,6 +216,25 @@ test_expect_success 'use fsck before and after manually fetching a missing subtr test_cmp unique_types.expected unique_types.observed ' +test_expect_success 'implicitly construct combine: filter with repeated flags' ' + GIT_TRACE=$(pwd)/trace git clone --bare \ + --filter=blob:none --filter=tree:1 \ + "file://$(pwd)/srv.bare" pc2 && + grep "trace:.* git pack-objects .*--filter=combine:blob:none+tree:1" \ + trace && + git -C pc2 rev-list --objects --missing=allow-any HEAD >objects && + + # We should have gotten some root trees. + grep " $" objects && + # Should not have gotten any non-root trees or blobs. + ! grep " ." objects && + + xargs -n 1 git -C pc2 cat-file -t <objects >types && + sort -u types >unique_types.actual && + test_write_lines commit tree >unique_types.expected && + test_cmp unique_types.expected unique_types.actual +' + test_expect_success 'partial clone fetches blobs pointed to by refs even if normally filtered out' ' rm -rf src dst && git init src && @@ -241,6 +268,112 @@ test_expect_success 'fetch what is specified on CLI even if already promised' ' ! grep "?$(cat blob)" missing_after ' +test_expect_success 'setup src repo for sparse filter' ' + git init sparse-src && + git -C sparse-src config --local uploadpack.allowfilter 1 && + git -C sparse-src config --local uploadpack.allowanysha1inwant 1 && + test_commit -C sparse-src one && + test_commit -C sparse-src two && + echo /one.t >sparse-src/only-one && + git -C sparse-src add . && + git -C sparse-src commit -m "add sparse checkout files" +' + +test_expect_success 'partial clone with sparse filter succeeds' ' + rm -rf dst.git && + git clone --no-local --bare \ + --filter=sparse:oid=master:only-one \ + sparse-src dst.git && + ( + cd dst.git && + git rev-list --objects --missing=print HEAD >out && + grep "^$(git rev-parse HEAD:one.t)" out && + grep "^?$(git rev-parse HEAD:two.t)" out + ) +' + +test_expect_success 'partial clone with unresolvable sparse filter fails cleanly' ' + rm -rf dst.git && + test_must_fail git clone --no-local --bare \ + --filter=sparse:oid=master:no-such-name \ + sparse-src dst.git 2>err && + test_i18ngrep "unable to access sparse blob in .master:no-such-name" err && + test_must_fail git clone --no-local --bare \ + --filter=sparse:oid=master \ + sparse-src dst.git 2>err && + test_i18ngrep "unable to parse sparse filter data in" err +' + +setup_triangle () { + rm -rf big-blob.txt server client promisor-remote && + + printf "line %d\n" $(test_seq 1 100) >big-blob.txt && + + # Create a server with 2 commits: a commit with a big blob and a child + # commit with an incremental change. Also, create a partial clone + # client that only contains the first commit. + git init server && + git -C server config --local uploadpack.allowfilter 1 && + cp big-blob.txt server && + git -C server add big-blob.txt && + git -C server commit -m "initial" && + git clone --bare --filter=tree:0 "file://$(pwd)/server" client && + echo another line >>server/big-blob.txt && + git -C server commit -am "append line to big blob" && + + # Create a promisor remote that only contains the blob from the first + # commit, and set it as the promisor remote of client. Thus, whenever + # the client lazy fetches, the lazy fetch will succeed only if it is + # for this blob. + git init promisor-remote && + test_commit -C promisor-remote one && # so that ref advertisement is not empty + git -C promisor-remote config --local uploadpack.allowanysha1inwant 1 && + git -C promisor-remote hash-object -w --stdin <big-blob.txt && + git -C client remote set-url origin "file://$(pwd)/promisor-remote" +} + +# NEEDSWORK: The tests beginning with "fetch lazy-fetches" below only +# test that "fetch" avoid fetching trees and blobs, but not commits or +# tags. Revisit this if Git is ever taught to support partial clones +# with commits and/or tags filtered out. + +test_expect_success 'fetch lazy-fetches only to resolve deltas' ' + setup_triangle && + + # Exercise to make sure it works. Git will not fetch anything from the + # promisor remote other than for the big blob (because it needs to + # resolve the delta). + GIT_TRACE_PACKET="$(pwd)/trace" git -C client \ + fetch "file://$(pwd)/server" master && + + # Verify the assumption that the client needed to fetch the delta base + # to resolve the delta. + git hash-object big-blob.txt >hash && + grep "want $(cat hash)" trace +' + +test_expect_success 'fetch lazy-fetches only to resolve deltas, protocol v2' ' + setup_triangle && + + git -C server config --local protocol.version 2 && + git -C client config --local protocol.version 2 && + git -C promisor-remote config --local protocol.version 2 && + + # Exercise to make sure it works. Git will not fetch anything from the + # promisor remote other than for the big blob (because it needs to + # resolve the delta). + GIT_TRACE_PACKET="$(pwd)/trace" git -C client \ + fetch "file://$(pwd)/server" master && + + # Verify that protocol version 2 was used. + grep "fetch< version 2" trace && + + # Verify the assumption that the client needed to fetch the delta base + # to resolve the delta. + git hash-object big-blob.txt >hash && + grep "want $(cat hash)" trace +' + . "$TEST_DIRECTORY"/lib-httpd.sh start_httpd @@ -417,4 +550,7 @@ test_expect_success 'tolerate server sending REF_DELTA against missing promisor ! test -e "$HTTPD_ROOT_PATH/one-time-sed" ' +# DO NOT add non-httpd-specific tests here, because the last part of this +# test script is only executed when httpd is available and enabled. + test_done diff --git a/t/t5617-clone-submodules-remote.sh b/t/t5617-clone-submodules-remote.sh new file mode 100755 index 0000000000..37fcce9c40 --- /dev/null +++ b/t/t5617-clone-submodules-remote.sh @@ -0,0 +1,54 @@ +#!/bin/sh + +test_description='Test cloning repos with submodules using remote-tracking branches' + +. ./test-lib.sh + +pwd=$(pwd) + +test_expect_success 'setup' ' + git checkout -b master && + test_commit commit1 && + mkdir sub && + ( + cd sub && + git init && + test_commit subcommit1 && + git tag sub_when_added_to_super + ) && + git submodule add "file://$pwd/sub" sub && + git commit -m "add submodule" && + ( + cd sub && + test_commit subcommit2 + ) +' + +test_expect_success 'clone with --no-remote-submodules' ' + test_when_finished "rm -rf super_clone" && + git clone --recurse-submodules --no-remote-submodules "file://$pwd/." super_clone && + ( + cd super_clone/sub && + git diff --exit-code sub_when_added_to_super + ) +' + +test_expect_success 'clone with --remote-submodules' ' + test_when_finished "rm -rf super_clone" && + git clone --recurse-submodules --remote-submodules "file://$pwd/." super_clone && + ( + cd super_clone/sub && + git diff --exit-code remotes/origin/master + ) +' + +test_expect_success 'check the default is --no-remote-submodules' ' + test_when_finished "rm -rf super_clone" && + git clone --recurse-submodules "file://$pwd/." super_clone && + ( + cd super_clone/sub && + git diff --exit-code sub_when_added_to_super + ) +' + +test_done diff --git a/t/t5618-alternate-refs.sh b/t/t5618-alternate-refs.sh new file mode 100755 index 0000000000..3353216f09 --- /dev/null +++ b/t/t5618-alternate-refs.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +test_description='test handling of --alternate-refs traversal' +. ./test-lib.sh + +# Avoid test_commit because we want a specific and known set of refs: +# +# base -- one +# \ \ +# two -- merged +# +# where "one" and "two" are on separate refs, and "merged" is available only in +# the dependent child repository. +test_expect_success 'set up local refs' ' + git checkout -b one && + test_tick && + git commit --allow-empty -m base && + test_tick && + git commit --allow-empty -m one && + git checkout -b two HEAD^ && + test_tick && + git commit --allow-empty -m two +' + +# We'll enter the child repository after it's set up since that's where +# all of the subsequent tests will want to run (and it's easy to forget a +# "-C child" and get nonsense results). +test_expect_success 'set up shared clone' ' + git clone -s . child && + cd child && + git merge origin/one +' + +test_expect_success 'rev-list --alternate-refs' ' + git rev-list --remotes=origin >expect && + git rev-list --alternate-refs >actual && + test_cmp expect actual +' + +test_expect_success 'rev-list --not --alternate-refs' ' + git rev-parse HEAD >expect && + git rev-list HEAD --not --alternate-refs >actual && + test_cmp expect actual +' + +test_expect_success 'limiting with alternateRefsPrefixes' ' + test_config core.alternateRefsPrefixes refs/heads/one && + git rev-list origin/one >expect && + git rev-list --alternate-refs >actual && + test_cmp expect actual +' + +test_expect_success 'log --source shows .alternate marker' ' + git log --oneline --source --remotes=origin >expect.orig && + sed "s/origin.* /.alternate /" <expect.orig >expect && + git log --oneline --source --alternate-refs >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t5700-protocol-v1.sh b/t/t5700-protocol-v1.sh index 7c9511c593..2571eb90b7 100755 --- a/t/t5700-protocol-v1.sh +++ b/t/t5700-protocol-v1.sh @@ -292,4 +292,7 @@ test_expect_success 'push with http:// using protocol v1' ' grep "git< version 1" log ' +# DO NOT add non-httpd-specific tests here, because the last part of this +# test script is only executed when httpd is available and enabled. + test_done diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index 5b33f625dd..e73067d23f 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -32,7 +32,7 @@ test_expect_success 'list refs with git:// using protocol v2' ' test_cmp expect actual ' -test_expect_success 'ref advertisment is filtered with ls-remote using protocol v2' ' +test_expect_success 'ref advertisement is filtered with ls-remote using protocol v2' ' test_when_finished "rm -f log" && GIT_TRACE_PACKET="$(pwd)/log" git -c protocol.version=2 \ @@ -154,7 +154,7 @@ test_expect_success 'list refs with file:// using protocol v2' ' test_cmp expect actual ' -test_expect_success 'ref advertisment is filtered with ls-remote using protocol v2' ' +test_expect_success 'ref advertisement is filtered with ls-remote using protocol v2' ' test_when_finished "rm -f log" && GIT_TRACE_PACKET="$(pwd)/log" git -c protocol.version=2 \ @@ -225,7 +225,7 @@ test_expect_success 'fetch with file:// using protocol v2' ' grep "fetch< version 2" log ' -test_expect_success 'ref advertisment is filtered during fetch using protocol v2' ' +test_expect_success 'ref advertisement is filtered during fetch using protocol v2' ' test_when_finished "rm -f log" && test_commit -C file_parent three && @@ -499,10 +499,7 @@ test_expect_success 'upload-pack respects client shallows' ' # 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 && + test_commit_bulk -C client --id=c 32 && git -C server checkout -b newbranch base && test_commit -C server client_wants && @@ -634,6 +631,19 @@ test_expect_success 'fetch with http:// using protocol v2' ' grep "git< version 2" log ' +test_expect_success 'fetch with http:// by hash without tag following with protocol v2 does not list refs' ' + test_when_finished "rm -f log" && + + test_commit -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" two_a && + git -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" rev-parse two_a >two_a_hash && + + GIT_TRACE_PACKET="$(pwd)/log" git -C http_child -c protocol.version=2 \ + fetch --no-tags origin $(cat two_a_hash) && + + grep "fetch< version 2" log && + ! grep "fetch> command=ls-refs" log +' + test_expect_success 'fetch from namespaced repo respects namespaces' ' test_when_finished "rm -f log" && @@ -672,9 +682,9 @@ test_expect_success 'push with http:// and a config of v2 does not request v2' ' git -C "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" log -1 --format=%s client_branch >expect && test_cmp expect actual && - # Client didnt request to use protocol v2 + # Client did not request to use protocol v2 ! grep "Git-Protocol: version=2" log && - # Server didnt respond using protocol v2 + # Server did not respond using protocol v2 ! grep "git< version 2" log ' @@ -711,10 +721,7 @@ test_expect_success 'when server does not send "ready", expect FLUSH' ' # 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 && + test_commit_bulk -C http_child --id=c 32 && # After the acknowledgments section, pretend that a DELIM # (0001) was sent instead of a FLUSH (0000). @@ -729,4 +736,7 @@ test_expect_success 'when server does not send "ready", expect FLUSH' ' test_i18ngrep "expected no other sections to be sent after no .ready." err ' +# DO NOT add non-httpd-specific tests here, because the last part of this +# test script is only executed when httpd is available and enabled. + test_done diff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh index 0951d1bbdc..3a2c143c6d 100755 --- a/t/t5703-upload-pack-ref-in-want.sh +++ b/t/t5703-upload-pack-ref-in-want.sh @@ -157,106 +157,6 @@ test_expect_success 'want-ref with ref we already have commit for' ' check_output ' -. "$TEST_DIRECTORY"/lib-httpd.sh -start_httpd - -REPO="$HTTPD_DOCUMENT_ROOT_PATH/repo" -LOCAL_PRISTINE="$(pwd)/local_pristine" - -test_expect_success 'setup repos for change-while-negotiating test' ' - ( - git init "$REPO" && - cd "$REPO" && - >.git/git-daemon-export-ok && - test_commit m1 && - git tag -d m1 && - - # Local repo with many commits (so that negotiation will take - # more than 1 request/response pair) - git clone "http://127.0.0.1:$LIB_HTTPD_PORT/smart/repo" "$LOCAL_PRISTINE" && - cd "$LOCAL_PRISTINE" && - git checkout -b side && - for i in $(test_seq 1 33); do test_commit s$i; done && - - # Add novel commits to upstream - git checkout master && - cd "$REPO" && - test_commit m2 && - test_commit m3 && - git tag -d m2 m3 - ) && - git -C "$LOCAL_PRISTINE" remote set-url origin "http://127.0.0.1:$LIB_HTTPD_PORT/one_time_sed/repo" && - git -C "$LOCAL_PRISTINE" config protocol.version 2 -' - -inconsistency () { - # Simulate that the server initially reports $2 as the ref - # corresponding to $1, and after that, $1 as the ref corresponding to - # $1. This corresponds to the real-life situation where the server's - # repository appears to change during negotiation, for example, when - # different servers in a load-balancing arrangement serve (stateless) - # RPCs during a single negotiation. - printf "s/%s/%s/" \ - $(git -C "$REPO" rev-parse $1 | tr -d "\n") \ - $(git -C "$REPO" rev-parse $2 | tr -d "\n") \ - >"$HTTPD_ROOT_PATH/one-time-sed" -} - -test_expect_success 'server is initially ahead - no ref in want' ' - git -C "$REPO" config uploadpack.allowRefInWant false && - rm -rf local && - cp -r "$LOCAL_PRISTINE" local && - inconsistency master 1234567890123456789012345678901234567890 && - test_must_fail git -C local fetch 2>err && - test_i18ngrep "fatal: remote error: upload-pack: not our ref" err -' - -test_expect_success 'server is initially ahead - ref in want' ' - git -C "$REPO" config uploadpack.allowRefInWant true && - rm -rf local && - cp -r "$LOCAL_PRISTINE" local && - inconsistency master 1234567890123456789012345678901234567890 && - git -C local fetch && - - git -C "$REPO" rev-parse --verify master >expected && - git -C local rev-parse --verify refs/remotes/origin/master >actual && - test_cmp expected actual -' - -test_expect_success 'server is initially behind - no ref in want' ' - git -C "$REPO" config uploadpack.allowRefInWant false && - rm -rf local && - cp -r "$LOCAL_PRISTINE" local && - inconsistency master "master^" && - git -C local fetch && - - git -C "$REPO" rev-parse --verify "master^" >expected && - git -C local rev-parse --verify refs/remotes/origin/master >actual && - test_cmp expected actual -' - -test_expect_success 'server is initially behind - ref in want' ' - git -C "$REPO" config uploadpack.allowRefInWant true && - rm -rf local && - cp -r "$LOCAL_PRISTINE" local && - inconsistency master "master^" && - git -C local fetch && - - git -C "$REPO" rev-parse --verify "master" >expected && - git -C local rev-parse --verify refs/remotes/origin/master >actual && - test_cmp expected actual -' - -test_expect_success 'server loses a ref - ref in want' ' - git -C "$REPO" config uploadpack.allowRefInWant true && - rm -rf local && - cp -r "$LOCAL_PRISTINE" local && - echo "s/master/raster/" >"$HTTPD_ROOT_PATH/one-time-sed" && - test_must_fail git -C local fetch 2>err && - - test_i18ngrep "fatal: remote error: unknown ref refs/heads/raster" err -' - REPO="$(pwd)/repo" LOCAL_PRISTINE="$(pwd)/local_pristine" @@ -287,7 +187,7 @@ test_expect_success 'setup repos for fetching with ref-in-want tests' ' git clone "file://$REPO" "$LOCAL_PRISTINE" && cd "$LOCAL_PRISTINE" && git checkout -b side && - for i in $(test_seq 1 33); do test_commit s$i; done && + test_commit_bulk --id=s 33 && # Add novel commits to upstream git checkout master && @@ -372,4 +272,108 @@ test_expect_success 'fetching with wildcard that matches multiple refs' ' grep "want-ref refs/heads/o/bar" log ' +. "$TEST_DIRECTORY"/lib-httpd.sh +start_httpd + +REPO="$HTTPD_DOCUMENT_ROOT_PATH/repo" +LOCAL_PRISTINE="$(pwd)/local_pristine" + +test_expect_success 'setup repos for change-while-negotiating test' ' + ( + git init "$REPO" && + cd "$REPO" && + >.git/git-daemon-export-ok && + test_commit m1 && + git tag -d m1 && + + # Local repo with many commits (so that negotiation will take + # more than 1 request/response pair) + rm -rf "$LOCAL_PRISTINE" && + git clone "http://127.0.0.1:$LIB_HTTPD_PORT/smart/repo" "$LOCAL_PRISTINE" && + cd "$LOCAL_PRISTINE" && + git checkout -b side && + test_commit_bulk --id=s 33 && + + # Add novel commits to upstream + git checkout master && + cd "$REPO" && + test_commit m2 && + test_commit m3 && + git tag -d m2 m3 + ) && + git -C "$LOCAL_PRISTINE" remote set-url origin "http://127.0.0.1:$LIB_HTTPD_PORT/one_time_sed/repo" && + git -C "$LOCAL_PRISTINE" config protocol.version 2 +' + +inconsistency () { + # Simulate that the server initially reports $2 as the ref + # corresponding to $1, and after that, $1 as the ref corresponding to + # $1. This corresponds to the real-life situation where the server's + # repository appears to change during negotiation, for example, when + # different servers in a load-balancing arrangement serve (stateless) + # RPCs during a single negotiation. + printf "s/%s/%s/" \ + $(git -C "$REPO" rev-parse $1 | tr -d "\n") \ + $(git -C "$REPO" rev-parse $2 | tr -d "\n") \ + >"$HTTPD_ROOT_PATH/one-time-sed" +} + +test_expect_success 'server is initially ahead - no ref in want' ' + git -C "$REPO" config uploadpack.allowRefInWant false && + rm -rf local && + cp -r "$LOCAL_PRISTINE" local && + inconsistency master 1234567890123456789012345678901234567890 && + test_must_fail git -C local fetch 2>err && + test_i18ngrep "fatal: remote error: upload-pack: not our ref" err +' + +test_expect_success 'server is initially ahead - ref in want' ' + git -C "$REPO" config uploadpack.allowRefInWant true && + rm -rf local && + cp -r "$LOCAL_PRISTINE" local && + inconsistency master 1234567890123456789012345678901234567890 && + git -C local fetch && + + git -C "$REPO" rev-parse --verify master >expected && + git -C local rev-parse --verify refs/remotes/origin/master >actual && + test_cmp expected actual +' + +test_expect_success 'server is initially behind - no ref in want' ' + git -C "$REPO" config uploadpack.allowRefInWant false && + rm -rf local && + cp -r "$LOCAL_PRISTINE" local && + inconsistency master "master^" && + git -C local fetch && + + git -C "$REPO" rev-parse --verify "master^" >expected && + git -C local rev-parse --verify refs/remotes/origin/master >actual && + test_cmp expected actual +' + +test_expect_success 'server is initially behind - ref in want' ' + git -C "$REPO" config uploadpack.allowRefInWant true && + rm -rf local && + cp -r "$LOCAL_PRISTINE" local && + inconsistency master "master^" && + git -C local fetch && + + git -C "$REPO" rev-parse --verify "master" >expected && + git -C local rev-parse --verify refs/remotes/origin/master >actual && + test_cmp expected actual +' + +test_expect_success 'server loses a ref - ref in want' ' + git -C "$REPO" config uploadpack.allowRefInWant true && + rm -rf local && + cp -r "$LOCAL_PRISTINE" local && + echo "s/master/raster/" >"$HTTPD_ROOT_PATH/one-time-sed" && + test_must_fail git -C local fetch 2>err && + + test_i18ngrep "fatal: remote error: unknown ref refs/heads/raster" err +' + +# DO NOT add non-httpd-specific tests here, because the last part of this +# test script is only executed when httpd is available and enabled. + test_done diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh index 2d6c4a281e..121e5c6edb 100755 --- a/t/t5801-remote-helpers.sh +++ b/t/t5801-remote-helpers.sh @@ -247,7 +247,6 @@ clean_mark () { test_expect_success 'proper failure checks for fetching' ' (cd local && test_must_fail env GIT_REMOTE_TESTGIT_FAILURE=1 git fetch 2>error && - cat error && test_i18ngrep -q "error while running fast-import" error ) ' diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh index 0507999729..b8cf82349b 100755 --- a/t/t6000-rev-list-misc.sh +++ b/t/t6000-rev-list-misc.sh @@ -48,6 +48,26 @@ test_expect_success 'rev-list --objects with pathspecs and copied files' ' ! grep one output ' +test_expect_success 'rev-list --objects --no-object-names has no space/names' ' + git rev-list --objects --no-object-names HEAD >output && + ! grep wanted_file output && + ! grep unwanted_file output && + ! grep " " output +' + +test_expect_success 'rev-list --objects --no-object-names works with cat-file' ' + git rev-list --objects --no-object-names --all >list-output && + git cat-file --batch-check <list-output >cat-output && + ! grep missing cat-output +' + +test_expect_success '--no-object-names and --object-names are last-one-wins' ' + git rev-list --objects --no-object-names --object-names --all >output && + grep wanted_file output && + git rev-list --objects --object-names --no-object-names --all >output && + ! grep wanted_file output +' + test_expect_success 'rev-list A..B and rev-list ^A B are the same' ' git commit --allow-empty -m another && git tag -a -m "annotated" v1.0 && @@ -120,4 +140,12 @@ test_expect_success '--header shows a NUL after each commit' ' test_cmp expect actual ' +test_expect_success 'rev-list --end-of-options' ' + git update-ref refs/heads/--output=yikes HEAD && + git rev-list --end-of-options --output=yikes >actual && + test_path_is_missing yikes && + git rev-list HEAD >expect && + test_cmp expect actual +' + test_done diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh index da113d975b..ebdc49c496 100755 --- a/t/t6006-rev-list-format.sh +++ b/t/t6006-rev-list-format.sh @@ -109,31 +109,35 @@ commit $head1 EOF # we don't test relative here -test_format author %an%n%ae%n%ad%n%aD%n%at <<EOF +test_format author %an%n%ae%n%al%n%ad%n%aD%n%at <<EOF commit $head2 -A U Thor -author@example.com +$GIT_AUTHOR_NAME +$GIT_AUTHOR_EMAIL +$TEST_AUTHOR_LOCALNAME Thu Apr 7 15:13:13 2005 -0700 Thu, 7 Apr 2005 15:13:13 -0700 1112911993 commit $head1 -A U Thor -author@example.com +$GIT_AUTHOR_NAME +$GIT_AUTHOR_EMAIL +$TEST_AUTHOR_LOCALNAME Thu Apr 7 15:13:13 2005 -0700 Thu, 7 Apr 2005 15:13:13 -0700 1112911993 EOF -test_format committer %cn%n%ce%n%cd%n%cD%n%ct <<EOF +test_format committer %cn%n%ce%n%cl%n%cd%n%cD%n%ct <<EOF commit $head2 -C O Mitter -committer@example.com +$GIT_COMMITTER_NAME +$GIT_COMMITTER_EMAIL +$TEST_COMMITTER_LOCALNAME Thu Apr 7 15:13:13 2005 -0700 Thu, 7 Apr 2005 15:13:13 -0700 1112911993 commit $head1 -C O Mitter -committer@example.com +$GIT_COMMITTER_NAME +$GIT_COMMITTER_EMAIL +$TEST_COMMITTER_LOCALNAME Thu Apr 7 15:13:13 2005 -0700 Thu, 7 Apr 2005 15:13:13 -0700 1112911993 @@ -410,7 +414,7 @@ test_expect_success 'empty email' ' test_tick && C=$(GIT_AUTHOR_EMAIL= git commit-tree HEAD^{tree} </dev/null) && A=$(git show --pretty=format:%an,%ae,%ad%n -s $C) && - verbose test "$A" = "A U Thor,,Thu Apr 7 15:14:13 2005 -0700" + verbose test "$A" = "$GIT_AUTHOR_NAME,,Thu Apr 7 15:14:13 2005 -0700" ' test_expect_success 'del LF before empty (1)' ' @@ -495,15 +499,14 @@ test_expect_success '%gd shortens ref name' ' ' test_expect_success 'reflog identity' ' - echo "C O Mitter:committer@example.com" >expect && + echo "$GIT_COMMITTER_NAME:$GIT_COMMITTER_EMAIL" >expect && git log -g -1 --format="%gn:%ge" >actual && test_cmp expect actual ' test_expect_success 'oneline with empty message' ' - git commit -m "dummy" --allow-empty && - git commit -m "dummy" --allow-empty && - git filter-branch --msg-filter "sed -e s/dummy//" HEAD^^.. && + git commit --allow-empty --cleanup=verbatim -m "$LF" && + git commit --allow-empty --allow-empty-message && git rev-list --oneline HEAD >test.txt && test_line_count = 5 test.txt && git rev-list --oneline --graph HEAD >testg.txt && diff --git a/t/t6011-rev-list-with-bad-commit.sh b/t/t6011-rev-list-with-bad-commit.sh index 545b461e51..bad02cf5b8 100755 --- a/t/t6011-rev-list-with-bad-commit.sh +++ b/t/t6011-rev-list-with-bad-commit.sh @@ -42,7 +42,7 @@ test_expect_success 'corrupt second commit object' \ ' test_expect_success 'rev-list should fail' ' - test_must_fail env GIT_TEST_COMMIT_GRAPH=0 git rev-list --all > /dev/null + test_must_fail env GIT_TEST_COMMIT_GRAPH=0 git -c core.commitGraph=false rev-list --all > /dev/null ' test_expect_success 'git repack _MUST_ fail' \ diff --git a/t/t6016-rev-list-graph-simplify-history.sh b/t/t6016-rev-list-graph-simplify-history.sh index f7181d1d6a..f5e6e92f5b 100755 --- a/t/t6016-rev-list-graph-simplify-history.sh +++ b/t/t6016-rev-list-graph-simplify-history.sh @@ -67,11 +67,10 @@ test_expect_success '--graph --all' ' echo "| * $C4" >> expected && echo "| * $C3" >> expected && echo "* | $A5" >> expected && - echo "| | " >> expected && - echo "| \\ " >> expected && - echo "*-. \\ $A4" >> expected && - echo "|\\ \\ \\ " >> expected && - echo "| | |/ " >> expected && + echo "| | " >> expected && + echo "| \\ " >> expected && + echo "*-. | $A4" >> expected && + echo "|\\ \\| " >> expected && echo "| | * $C2" >> expected && echo "| | * $C1" >> expected && echo "| * | $B2" >> expected && @@ -97,11 +96,10 @@ test_expect_success '--graph --simplify-by-decoration' ' echo "| * $C4" >> expected && echo "| * $C3" >> expected && echo "* | $A5" >> expected && - echo "| | " >> expected && - echo "| \\ " >> expected && - echo "*-. \\ $A4" >> expected && - echo "|\\ \\ \\ " >> expected && - echo "| | |/ " >> expected && + echo "| | " >> expected && + echo "| \\ " >> expected && + echo "*-. | $A4" >> expected && + echo "|\\ \\| " >> expected && echo "| | * $C2" >> expected && echo "| | * $C1" >> expected && echo "| * | $B2" >> expected && @@ -131,9 +129,8 @@ test_expect_success '--graph --simplify-by-decoration prune branch B' ' echo "| * $C4" >> expected && echo "| * $C3" >> expected && echo "* | $A5" >> expected && - echo "* | $A4" >> expected && - echo "|\\ \\ " >> expected && - echo "| |/ " >> expected && + echo "* | $A4" >> expected && + echo "|\\| " >> expected && echo "| * $C2" >> expected && echo "| * $C1" >> expected && echo "* | $A3" >> expected && @@ -151,9 +148,8 @@ test_expect_success '--graph --full-history -- bar.txt' ' echo "|\\ " >> expected && echo "| * $C4" >> expected && echo "* | $A5" >> expected && - echo "* | $A4" >> expected && - echo "|\\ \\ " >> expected && - echo "| |/ " >> expected && + echo "* | $A4" >> expected && + echo "|\\| " >> expected && echo "* | $A3" >> expected && echo "|/ " >> expected && echo "* $A2" >> expected && @@ -255,7 +251,7 @@ test_expect_success '--graph --boundary ^C3' ' echo "* | | | $A3" >> expected && echo "o | | | $A2" >> expected && echo "|/ / / " >> expected && - echo "o | | $A1" >> expected && + echo "o / / $A1" >> expected && echo " / / " >> expected && echo "| o $C3" >> expected && echo "|/ " >> expected && diff --git a/t/t6019-rev-list-ancestry-path.sh b/t/t6019-rev-list-ancestry-path.sh index beadaf6cca..353f84313f 100755 --- a/t/t6019-rev-list-ancestry-path.sh +++ b/t/t6019-rev-list-ancestry-path.sh @@ -143,14 +143,14 @@ test_expect_success 'setup criss-cross' ' test_expect_success 'criss-cross: rev-list --ancestry-path cb..bc' ' (cd criss-cross && git rev-list --ancestry-path xcb..xbc > actual && - test -z "$(cat actual)") + test_must_be_empty actual) ' # no commits in repository descend from cb test_expect_success 'criss-cross: rev-list --ancestry-path --all ^cb' ' (cd criss-cross && git rev-list --ancestry-path --all ^xcb > actual && - test -z "$(cat actual)") + test_must_be_empty actual) ' test_done diff --git a/t/t6021-merge-criss-cross.sh b/t/t6021-merge-criss-cross.sh index 213deecab1..d254e020b6 100755 --- a/t/t6021-merge-criss-cross.sh +++ b/t/t6021-merge-criss-cross.sh @@ -3,7 +3,7 @@ # Copyright (c) 2005 Fredrik Kuivinen # -# See http://marc.info/?l=git&m=111463358500362&w=2 for a +# See https://lore.kernel.org/git/Pine.LNX.4.44.0504271254120.4678-100000@wax.eds.org/ for a # nice description of what this is about. diff --git a/t/t6024-recursive-merge.sh b/t/t6024-recursive-merge.sh index 27c7de90ce..0c9e3c20e8 100755 --- a/t/t6024-recursive-merge.sh +++ b/t/t6024-recursive-merge.sh @@ -14,85 +14,90 @@ test_description='Test merge without common ancestors' GIT_COMMITTER_DATE="2006-12-12 23:28:00 +0100" export GIT_COMMITTER_DATE -test_expect_success "setup tests" ' -echo 1 > a1 && -git add a1 && -GIT_AUTHOR_DATE="2006-12-12 23:00:00" git commit -m 1 a1 && - -git checkout -b A master && -echo A > a1 && -GIT_AUTHOR_DATE="2006-12-12 23:00:01" git commit -m A a1 && - -git checkout -b B master && -echo B > a1 && -GIT_AUTHOR_DATE="2006-12-12 23:00:02" git commit -m B a1 && - -git checkout -b D A && -git rev-parse B > .git/MERGE_HEAD && -echo D > a1 && -git update-index a1 && -GIT_AUTHOR_DATE="2006-12-12 23:00:03" git commit -m D && - -git symbolic-ref HEAD refs/heads/other && -echo 2 > a1 && -GIT_AUTHOR_DATE="2006-12-12 23:00:04" git commit -m 2 a1 && - -git checkout -b C && -echo C > a1 && -GIT_AUTHOR_DATE="2006-12-12 23:00:05" git commit -m C a1 && - -git checkout -b E C && -git rev-parse B > .git/MERGE_HEAD && -echo E > a1 && -git update-index a1 && -GIT_AUTHOR_DATE="2006-12-12 23:00:06" git commit -m E && - -git checkout -b G E && -git rev-parse A > .git/MERGE_HEAD && -echo G > a1 && -git update-index a1 && -GIT_AUTHOR_DATE="2006-12-12 23:00:07" git commit -m G && - -git checkout -b F D && -git rev-parse C > .git/MERGE_HEAD && -echo F > a1 && -git update-index a1 && -GIT_AUTHOR_DATE="2006-12-12 23:00:08" git commit -m F +test_expect_success 'setup tests' ' + echo 1 >a1 && + git add a1 && + GIT_AUTHOR_DATE="2006-12-12 23:00:00" git commit -m 1 a1 && + + git checkout -b A master && + echo A >a1 && + GIT_AUTHOR_DATE="2006-12-12 23:00:01" git commit -m A a1 && + + git checkout -b B master && + echo B >a1 && + GIT_AUTHOR_DATE="2006-12-12 23:00:02" git commit -m B a1 && + + git checkout -b D A && + git rev-parse B >.git/MERGE_HEAD && + echo D >a1 && + git update-index a1 && + GIT_AUTHOR_DATE="2006-12-12 23:00:03" git commit -m D && + + git symbolic-ref HEAD refs/heads/other && + echo 2 >a1 && + GIT_AUTHOR_DATE="2006-12-12 23:00:04" git commit -m 2 a1 && + + git checkout -b C && + echo C >a1 && + GIT_AUTHOR_DATE="2006-12-12 23:00:05" git commit -m C a1 && + + git checkout -b E C && + git rev-parse B >.git/MERGE_HEAD && + echo E >a1 && + git update-index a1 && + GIT_AUTHOR_DATE="2006-12-12 23:00:06" git commit -m E && + + git checkout -b G E && + git rev-parse A >.git/MERGE_HEAD && + echo G >a1 && + git update-index a1 && + GIT_AUTHOR_DATE="2006-12-12 23:00:07" git commit -m G && + + git checkout -b F D && + git rev-parse C >.git/MERGE_HEAD && + echo F >a1 && + git update-index a1 && + GIT_AUTHOR_DATE="2006-12-12 23:00:08" git commit -m F ' test_expect_success 'combined merge conflicts' ' test_must_fail env GIT_TEST_COMMIT_GRAPH=0 git merge -m final G ' -cat > expect << EOF -<<<<<<< HEAD -F -======= -G ->>>>>>> G -EOF +test_expect_success 'result contains a conflict' ' + cat >expect <<-\EOF && + <<<<<<< HEAD + F + ======= + G + >>>>>>> G + EOF -test_expect_success "result contains a conflict" "test_cmp expect a1" + test_cmp expect a1 +' + +test_expect_success 'virtual trees were processed' ' + git ls-files --stage >out && -git ls-files --stage > out -cat > expect << EOF -100644 ec3fe2a791706733f2d8fa7ad45d9a9672031f5e 1 a1 -100644 cf84443e49e1b366fac938711ddf4be2d4d1d9e9 2 a1 -100644 fd7923529855d0b274795ae3349c5e0438333979 3 a1 -EOF + cat >expect <<-\EOF && + 100644 ec3fe2a791706733f2d8fa7ad45d9a9672031f5e 1 a1 + 100644 cf84443e49e1b366fac938711ddf4be2d4d1d9e9 2 a1 + 100644 fd7923529855d0b274795ae3349c5e0438333979 3 a1 + EOF -test_expect_success "virtual trees were processed" "test_cmp expect out" + test_cmp expect out +' test_expect_success 'refuse to merge binary files' ' git reset --hard && - printf "\0" > binary-file && + printf "\0" >binary-file && git add binary-file && git commit -m binary && git checkout G && - printf "\0\0" > binary-file && + printf "\0\0" >binary-file && git add binary-file && git commit -m binary2 && - test_must_fail git merge F > merge.out 2> merge.err && + test_must_fail git merge F >merge.out 2>merge.err && grep "Cannot merge binary files: binary-file (HEAD vs. F)" merge.err ' @@ -116,7 +121,6 @@ test_expect_success 'mark rename/delete as unmerged' ' test 1 = $(git ls-files --unmerged | wc -l) && test_must_fail git rev-parse --verify :2:a2 && git rev-parse --verify :3:a2 - ' test_done diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index 49a394bd75..bdc42e9440 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -615,6 +615,7 @@ test_expect_success 'broken branch creation' ' git add missing/MISSING && git commit -m "6(broken): Added file that will be deleted" && git tag BROKEN_HASH6 && + deleted=$(git rev-parse --verify HEAD:missing) && add_line_into_file "7(broken): second line on a broken branch" hello2 && git tag BROKEN_HASH7 && add_line_into_file "8(broken): third line on a broken branch" hello2 && @@ -622,12 +623,12 @@ test_expect_success 'broken branch creation' ' git rm missing/MISSING && git commit -m "9(broken): Remove missing file" && git tag BROKEN_HASH9 && - rm .git/objects/39/f7e61a724187ab767d2e08442d9b6b9dab587d + rm .git/objects/$(test_oid_to_path $deleted) ' echo "" > expected.ok cat > expected.missing-tree.default <<EOF -fatal: unable to read tree 39f7e61a724187ab767d2e08442d9b6b9dab587d +fatal: unable to read tree $deleted EOF test_expect_success 'bisect fails if tree is broken on start commit' ' @@ -713,12 +714,12 @@ test_expect_success 'bisect: demonstrate identification of damage boundary' " " cat > expected.bisect-log <<EOF -# bad: [32a594a3fdac2d57cf6d02987e30eec68511498c] Add <4: Ciao for now> into <hello>. -# good: [7b7f204a749c3125d5224ed61ea2ae1187ad046f] Add <2: A new day for git> into <hello>. -git bisect start '32a594a3fdac2d57cf6d02987e30eec68511498c' '7b7f204a749c3125d5224ed61ea2ae1187ad046f' -# good: [3de952f2416b6084f557ec417709eac740c6818c] Add <3: Another new day for git> into <hello>. -git bisect good 3de952f2416b6084f557ec417709eac740c6818c -# first bad commit: [32a594a3fdac2d57cf6d02987e30eec68511498c] Add <4: Ciao for now> into <hello>. +# bad: [$HASH4] Add <4: Ciao for now> into <hello>. +# good: [$HASH2] Add <2: A new day for git> into <hello>. +git bisect start '$HASH4' '$HASH2' +# good: [$HASH3] Add <3: Another new day for git> into <hello>. +git bisect good $HASH3 +# first bad commit: [$HASH4] Add <4: Ciao for now> into <hello>. EOF test_expect_success 'bisect log: successful result' ' @@ -731,14 +732,14 @@ test_expect_success 'bisect log: successful result' ' ' cat > expected.bisect-skip-log <<EOF -# bad: [32a594a3fdac2d57cf6d02987e30eec68511498c] Add <4: Ciao for now> into <hello>. -# good: [7b7f204a749c3125d5224ed61ea2ae1187ad046f] Add <2: A new day for git> into <hello>. -git bisect start '32a594a3fdac2d57cf6d02987e30eec68511498c' '7b7f204a749c3125d5224ed61ea2ae1187ad046f' -# skip: [3de952f2416b6084f557ec417709eac740c6818c] Add <3: Another new day for git> into <hello>. -git bisect skip 3de952f2416b6084f557ec417709eac740c6818c +# bad: [$HASH4] Add <4: Ciao for now> into <hello>. +# good: [$HASH2] Add <2: A new day for git> into <hello>. +git bisect start '$HASH4' '$HASH2' +# skip: [$HASH3] Add <3: Another new day for git> into <hello>. +git bisect skip $HASH3 # only skipped commits left to test -# possible first bad commit: [32a594a3fdac2d57cf6d02987e30eec68511498c] Add <4: Ciao for now> into <hello>. -# possible first bad commit: [3de952f2416b6084f557ec417709eac740c6818c] Add <3: Another new day for git> into <hello>. +# possible first bad commit: [$HASH4] Add <4: Ciao for now> into <hello>. +# possible first bad commit: [$HASH3] Add <3: Another new day for git> into <hello>. EOF test_expect_success 'bisect log: only skip commits left' ' diff --git a/t/t6036-recursive-corner-cases.sh b/t/t6036-recursive-corner-cases.sh index d23b948f27..7d73afdcda 100755 --- a/t/t6036-recursive-corner-cases.sh +++ b/t/t6036-recursive-corner-cases.sh @@ -1532,7 +1532,7 @@ test_expect_success 'setup nested conflicts' ' mv -f b_R1 b && mv -f a_R1 a && git add b a && - test_tick && git commit -m "verson R1 of files" && + test_tick && git commit -m "version R1 of files" && git tag R1 && # Create first merge on left side @@ -1562,6 +1562,7 @@ test_expect_success 'check nested conflicts' ' cd nested_conflicts && git clean -f && + MASTER=$(git rev-parse --short master) && git checkout L2^0 && # Merge must fail; there is a conflict @@ -1582,7 +1583,7 @@ test_expect_success 'check nested conflicts' ' git cat-file -p R1:a >theirs && test_must_fail git merge-file --diff3 \ -L "Temporary merge branch 1" \ - -L "merged common ancestors" \ + -L "$MASTER" \ -L "Temporary merge branch 2" \ ours \ base \ @@ -1594,7 +1595,7 @@ test_expect_success 'check nested conflicts' ' git cat-file -p R1:b >theirs && test_must_fail git merge-file --diff3 \ -L "Temporary merge branch 1" \ - -L "merged common ancestors" \ + -L "$MASTER" \ -L "Temporary merge branch 2" \ ours \ base \ @@ -1695,7 +1696,7 @@ test_expect_success 'setup virtual merge base with nested conflicts' ' git checkout R && echo right >>content && git add content && - test_tick && git commit -m "verson R1 of content" && + test_tick && git commit -m "version R1 of content" && git tag R1 && # Create L2 @@ -1732,6 +1733,7 @@ test_expect_success 'check virtual merge base with nested conflicts' ' ( cd virtual_merge_base_has_nested_conflicts && + MASTER=$(git rev-parse --short master) && git checkout L3^0 && # Merge must fail; there is a conflict @@ -1760,7 +1762,7 @@ test_expect_success 'check virtual merge base with nested conflicts' ' cp left merged-once && test_must_fail git merge-file --diff3 \ -L "Temporary merge branch 1" \ - -L "merged common ancestors" \ + -L "$MASTER" \ -L "Temporary merge branch 2" \ merged-once \ base \ diff --git a/t/t6040-tracking-info.sh b/t/t6040-tracking-info.sh index 716283b274..ad1922b999 100755 --- a/t/t6040-tracking-info.sh +++ b/t/t6040-tracking-info.sh @@ -38,7 +38,7 @@ test_expect_success setup ' advance h ' -script='s/^..\(b.\) *[0-9a-f]* \(.*\)$/\1 \2/p' +t6040_script='s/^..\(b.\) *[0-9a-f]* \(.*\)$/\1 \2/p' cat >expect <<\EOF b1 [ahead 1, behind 1] d b2 [ahead 1, behind 1] d @@ -53,7 +53,7 @@ test_expect_success 'branch -v' ' cd test && git branch -v ) | - sed -n -e "$script" >actual && + sed -n -e "$t6040_script" >actual && test_i18ncmp expect actual ' @@ -71,7 +71,7 @@ test_expect_success 'branch -vv' ' cd test && git branch -vv ) | - sed -n -e "$script" >actual && + sed -n -e "$t6040_script" >actual && test_i18ncmp expect actual ' @@ -160,6 +160,19 @@ test_expect_success 'status -s -b --no-ahead-behind (diverged from upstream)' ' ' cat >expect <<\EOF +## b1...origin/master [different] +EOF + +test_expect_success 'status.aheadbehind=false status -s -b (diverged from upstream)' ' + ( + cd test && + git checkout b1 >/dev/null && + git -c status.aheadbehind=false status -s -b | head -1 + ) >actual && + test_i18ncmp expect actual +' + +cat >expect <<\EOF On branch b1 Your branch and 'origin/master' have diverged, and have 1 and 1 different commits each, respectively. @@ -174,6 +187,15 @@ test_expect_success 'status --long --branch' ' test_i18ncmp expect actual ' +test_expect_success 'status --long --branch' ' + ( + cd test && + git checkout b1 >/dev/null && + git -c status.aheadbehind=true status --long -b | head -3 + ) >actual && + test_i18ncmp expect actual +' + cat >expect <<\EOF On branch b1 Your branch and 'origin/master' refer to different commits. @@ -188,6 +210,15 @@ test_expect_success 'status --long --branch --no-ahead-behind' ' test_i18ncmp expect actual ' +test_expect_success 'status.aheadbehind=false status --long --branch' ' + ( + cd test && + git checkout b1 >/dev/null && + git -c status.aheadbehind=false status --long -b | head -2 + ) >actual && + test_i18ncmp expect actual +' + cat >expect <<\EOF ## b5...brokenbase [gone] EOF diff --git a/t/t6042-merge-rename-corner-cases.sh b/t/t6042-merge-rename-corner-cases.sh index c5b57f40c3..b047cf1c1c 100755 --- a/t/t6042-merge-rename-corner-cases.sh +++ b/t/t6042-merge-rename-corner-cases.sh @@ -5,7 +5,7 @@ test_description="recursive merge corner cases w/ renames but not criss-crosses" . ./test-lib.sh -test_expect_success 'setup rename/delete + untracked file' ' +test_setup_rename_delete_untracked () { test_create_repo rename-delete-untracked && ( cd rename-delete-untracked && @@ -29,9 +29,10 @@ test_expect_success 'setup rename/delete + untracked file' ' git commit -m track-people-instead-of-objects && echo "Myyy PRECIOUSSS" >ring ) -' +} test_expect_success "Does git preserve Gollum's precious artifact?" ' + test_setup_rename_delete_untracked && ( cd rename-delete-untracked && @@ -49,7 +50,7 @@ test_expect_success "Does git preserve Gollum's precious artifact?" ' # # We should be able to merge B & C cleanly -test_expect_success 'setup rename/modify/add-source conflict' ' +test_setup_rename_modify_add_source () { test_create_repo rename-modify-add-source && ( cd rename-modify-add-source && @@ -70,9 +71,10 @@ test_expect_success 'setup rename/modify/add-source conflict' ' git add a && git commit -m C ) -' +} test_expect_failure 'rename/modify/add-source conflict resolvable' ' + test_setup_rename_modify_add_source && ( cd rename-modify-add-source && @@ -88,7 +90,7 @@ test_expect_failure 'rename/modify/add-source conflict resolvable' ' ) ' -test_expect_success 'setup resolvable conflict missed if rename missed' ' +test_setup_break_detection_1 () { test_create_repo break-detection-1 && ( cd break-detection-1 && @@ -110,9 +112,10 @@ test_expect_success 'setup resolvable conflict missed if rename missed' ' git add a && git commit -m C ) -' +} test_expect_failure 'conflict caused if rename not detected' ' + test_setup_break_detection_1 && ( cd break-detection-1 && @@ -135,7 +138,7 @@ test_expect_failure 'conflict caused if rename not detected' ' ) ' -test_expect_success 'setup conflict resolved wrong if rename missed' ' +test_setup_break_detection_2 () { test_create_repo break-detection-2 && ( cd break-detection-2 && @@ -160,9 +163,10 @@ test_expect_success 'setup conflict resolved wrong if rename missed' ' git add a && git commit -m E ) -' +} test_expect_failure 'missed conflict if rename not detected' ' + test_setup_break_detection_2 && ( cd break-detection-2 && @@ -182,7 +186,7 @@ test_expect_failure 'missed conflict if rename not detected' ' # Commit B: rename a->b # Commit C: rename a->b, add unrelated a -test_expect_success 'setup undetected rename/add-source causes data loss' ' +test_setup_break_detection_3 () { test_create_repo break-detection-3 && ( cd break-detection-3 && @@ -202,9 +206,10 @@ test_expect_success 'setup undetected rename/add-source causes data loss' ' git add a && git commit -m C ) -' +} test_expect_failure 'detect rename/add-source and preserve all data' ' + test_setup_break_detection_3 && ( cd break-detection-3 && @@ -231,6 +236,7 @@ test_expect_failure 'detect rename/add-source and preserve all data' ' ' test_expect_failure 'detect rename/add-source and preserve all data, merge other way' ' + test_setup_break_detection_3 && ( cd break-detection-3 && @@ -256,10 +262,10 @@ test_expect_failure 'detect rename/add-source and preserve all data, merge other ) ' -test_expect_success 'setup content merge + rename/directory conflict' ' - test_create_repo rename-directory-1 && +test_setup_rename_directory () { + test_create_repo rename-directory-$1 && ( - cd rename-directory-1 && + cd rename-directory-$1 && printf "1\n2\n3\n4\n5\n6\n" >file && git add file && @@ -290,11 +296,12 @@ test_expect_success 'setup content merge + rename/directory conflict' ' test_tick && git commit -m left ) -' +} test_expect_success 'rename/directory conflict + clean content merge' ' + test_setup_rename_directory 1a && ( - cd rename-directory-1 && + cd rename-directory-1a && git checkout left-clean^0 && @@ -320,8 +327,9 @@ test_expect_success 'rename/directory conflict + clean content merge' ' ' test_expect_success 'rename/directory conflict + content merge conflict' ' + test_setup_rename_directory 1b && ( - cd rename-directory-1 && + cd rename-directory-1b && git reset --hard && git clean -fdqx && @@ -358,7 +366,7 @@ test_expect_success 'rename/directory conflict + content merge conflict' ' ) ' -test_expect_success 'setup content merge + rename/directory conflict w/ disappearing dir' ' +test_setup_rename_directory_2 () { test_create_repo rename-directory-2 && ( cd rename-directory-2 && @@ -385,9 +393,10 @@ test_expect_success 'setup content merge + rename/directory conflict w/ disappea test_tick && git commit -m left ) -' +} test_expect_success 'disappearing dir in rename/directory conflict handled' ' + test_setup_rename_directory_2 && ( cd rename-directory-2 && @@ -416,10 +425,10 @@ test_expect_success 'disappearing dir in rename/directory conflict handled' ' # Commit A: rename a->b, modifying b too # Commit B: modify a, add different b -test_expect_success 'setup rename-with-content-merge vs. add' ' - test_create_repo rename-with-content-merge-and-add && +test_setup_rename_with_content_merge_and_add () { + test_create_repo rename-with-content-merge-and-add-$1 && ( - cd rename-with-content-merge-and-add && + cd rename-with-content-merge-and-add-$1 && test_seq 1 5 >a && git add a && @@ -438,11 +447,12 @@ test_expect_success 'setup rename-with-content-merge vs. add' ' git add a b && git commit -m B ) -' +} test_expect_success 'handle rename-with-content-merge vs. add' ' + test_setup_rename_with_content_merge_and_add AB && ( - cd rename-with-content-merge-and-add && + cd rename-with-content-merge-and-add-AB && git checkout A^0 && @@ -483,8 +493,9 @@ test_expect_success 'handle rename-with-content-merge vs. add' ' ' test_expect_success 'handle rename-with-content-merge vs. add, merge other way' ' + test_setup_rename_with_content_merge_and_add BA && ( - cd rename-with-content-merge-and-add && + cd rename-with-content-merge-and-add-BA && git reset --hard && git clean -fdx && @@ -539,7 +550,7 @@ test_expect_success 'handle rename-with-content-merge vs. add, merge other way' # * The working copy should have two files, both of form c~<unique>; does it? # * Nothing else should be present. Is anything? -test_expect_success 'setup rename/rename (2to1) + modify/modify' ' +test_setup_rename_rename_2to1 () { test_create_repo rename-rename-2to1 && ( cd rename-rename-2to1 && @@ -562,9 +573,10 @@ test_expect_success 'setup rename/rename (2to1) + modify/modify' ' git add a && git commit -m C ) -' +} test_expect_success 'handle rename/rename (2to1) conflict correctly' ' + test_setup_rename_rename_2to1 && ( cd rename-rename-2to1 && @@ -610,7 +622,7 @@ test_expect_success 'handle rename/rename (2to1) conflict correctly' ' # Commit A: new file: a # Commit B: rename a->b # Commit C: rename a->c -test_expect_success 'setup simple rename/rename (1to2) conflict' ' +test_setup_rename_rename_1to2 () { test_create_repo rename-rename-1to2 && ( cd rename-rename-1to2 && @@ -631,9 +643,10 @@ test_expect_success 'setup simple rename/rename (1to2) conflict' ' test_tick && git commit -m C ) -' +} test_expect_success 'merge has correct working tree contents' ' + test_setup_rename_rename_1to2 && ( cd rename-rename-1to2 && @@ -667,7 +680,7 @@ test_expect_success 'merge has correct working tree contents' ' # # Merging of B & C should NOT be clean; there's a rename/rename conflict -test_expect_success 'setup rename/rename(1to2)/add-source conflict' ' +test_setup_rename_rename_1to2_add_source_1 () { test_create_repo rename-rename-1to2-add-source-1 && ( cd rename-rename-1to2-add-source-1 && @@ -687,9 +700,10 @@ test_expect_success 'setup rename/rename(1to2)/add-source conflict' ' git add a && git commit -m C ) -' +} test_expect_failure 'detect conflict with rename/rename(1to2)/add-source merge' ' + test_setup_rename_rename_1to2_add_source_1 && ( cd rename-rename-1to2-add-source-1 && @@ -714,7 +728,7 @@ test_expect_failure 'detect conflict with rename/rename(1to2)/add-source merge' ) ' -test_expect_success 'setup rename/rename(1to2)/add-source resolvable conflict' ' +test_setup_rename_rename_1to2_add_source_2 () { test_create_repo rename-rename-1to2-add-source-2 && ( cd rename-rename-1to2-add-source-2 && @@ -737,9 +751,10 @@ test_expect_success 'setup rename/rename(1to2)/add-source resolvable conflict' ' test_tick && git commit -m two ) -' +} test_expect_failure 'rename/rename/add-source still tracks new a file' ' + test_setup_rename_rename_1to2_add_source_2 && ( cd rename-rename-1to2-add-source-2 && @@ -759,7 +774,7 @@ test_expect_failure 'rename/rename/add-source still tracks new a file' ' ) ' -test_expect_success 'setup rename/rename(1to2)/add-dest conflict' ' +test_setup_rename_rename_1to2_add_dest () { test_create_repo rename-rename-1to2-add-dest && ( cd rename-rename-1to2-add-dest && @@ -784,9 +799,10 @@ test_expect_success 'setup rename/rename(1to2)/add-dest conflict' ' test_tick && git commit -m two ) -' +} test_expect_success 'rename/rename/add-dest merge still knows about conflicting file versions' ' + test_setup_rename_rename_1to2_add_dest && ( cd rename-rename-1to2-add-dest && @@ -838,7 +854,7 @@ test_expect_success 'rename/rename/add-dest merge still knows about conflicting # Commit B: rename foo->bar # Expected: CONFLICT (rename/add/delete), two-way merged bar -test_expect_success 'rad-setup: rename/add/delete conflict' ' +test_setup_rad () { test_create_repo rad && ( cd rad && @@ -860,9 +876,10 @@ test_expect_success 'rad-setup: rename/add/delete conflict' ' git mv foo bar && git commit -m "rename foo to bar" ) -' +} test_expect_failure 'rad-check: rename/add/delete conflict' ' + test_setup_rad && ( cd rad && @@ -904,7 +921,7 @@ test_expect_failure 'rad-check: rename/add/delete conflict' ' # Commit B: rename bar->baz, rm foo # Expected: CONFLICT (rename/rename/delete/delete), two-way merged baz -test_expect_success 'rrdd-setup: rename/rename(2to1)/delete/delete conflict' ' +test_setup_rrdd () { test_create_repo rrdd && ( cd rrdd && @@ -927,9 +944,10 @@ test_expect_success 'rrdd-setup: rename/rename(2to1)/delete/delete conflict' ' git rm foo && git commit -m "Rename bar, remove foo" ) -' +} test_expect_failure 'rrdd-check: rename/rename(2to1)/delete/delete conflict' ' + test_setup_rrdd && ( cd rrdd && @@ -973,7 +991,7 @@ test_expect_failure 'rrdd-check: rename/rename(2to1)/delete/delete conflict' ' # Expected: six CONFLICT(rename/rename) messages, each path in two of the # multi-way merged contents found in two, four, six -test_expect_success 'mod6-setup: chains of rename/rename(1to2) and rename/rename(2to1)' ' +test_setup_mod6 () { test_create_repo mod6 && ( cd mod6 && @@ -1009,9 +1027,10 @@ test_expect_success 'mod6-setup: chains of rename/rename(1to2) and rename/rename test_tick && git commit -m "B" ) -' +} test_expect_failure 'mod6-check: chains of rename/rename(1to2) and rename/rename(2to1)' ' + test_setup_mod6 && ( cd mod6 && @@ -1108,7 +1127,8 @@ test_conflicts_with_adds_and_renames() { # 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_setup_collision_conflict () { + #test_expect_success "setup simple $sideL/$sideR conflict" ' test_create_repo simple_${sideL}_${sideR} && ( cd simple_${sideL}_${sideR} && @@ -1185,9 +1205,11 @@ test_conflicts_with_adds_and_renames() { fi && test_tick && git commit -m R ) - ' + #' + } test_expect_success "check simple $sideL/$sideR conflict" ' + test_setup_collision_conflict && ( cd simple_${sideL}_${sideR} && @@ -1254,7 +1276,7 @@ test_conflicts_with_adds_and_renames add add # # 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_setup_nested_conflicts_from_rename_rename () { test_create_repo nested_conflicts_from_rename_rename && ( cd nested_conflicts_from_rename_rename && @@ -1305,9 +1327,10 @@ test_expect_success 'setup nested conflicts from rename/rename(2to1)' ' git add one three && test_tick && git commit -m german ) -' +} test_expect_success 'check nested conflicts from rename/rename(2to1)' ' + test_setup_nested_conflicts_from_rename_rename && ( cd nested_conflicts_from_rename_rename && diff --git a/t/t6043-merge-rename-directories.sh b/t/t6043-merge-rename-directories.sh index 50b7543483..83792c5ef1 100755 --- a/t/t6043-merge-rename-directories.sh +++ b/t/t6043-merge-rename-directories.sh @@ -38,7 +38,7 @@ test_description="recursive merge with directory renames" # Commit B: z/{b,c,d,e/f} # Expected: y/{b,c,d,e/f} -test_expect_success '1a-setup: Simple directory rename detection' ' +test_setup_1a () { test_create_repo 1a && ( cd 1a && @@ -67,9 +67,10 @@ test_expect_success '1a-setup: Simple directory rename detection' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '1a-check: Simple directory rename detection' ' +test_expect_success '1a: Simple directory rename detection' ' + test_setup_1a && ( cd 1a && @@ -103,7 +104,7 @@ test_expect_success '1a-check: Simple directory rename detection' ' # Commit B: y/{b,c,d} # Expected: y/{b,c,d,e} -test_expect_success '1b-setup: Merge a directory with another' ' +test_setup_1b () { test_create_repo 1b && ( cd 1b && @@ -134,9 +135,10 @@ test_expect_success '1b-setup: Merge a directory with another' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '1b-check: Merge a directory with another' ' +test_expect_success '1b: Merge a directory with another' ' + test_setup_1b && ( cd 1b && @@ -165,7 +167,7 @@ test_expect_success '1b-check: Merge a directory with another' ' # Commit B: z/{b,c,d} # Expected: y/{b,c,d} (because x/d -> z/d -> y/d) -test_expect_success '1c-setup: Transitive renaming' ' +test_setup_1c () { test_create_repo 1c && ( cd 1c && @@ -193,9 +195,10 @@ test_expect_success '1c-setup: Transitive renaming' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '1c-check: Transitive renaming' ' +test_expect_success '1c: Transitive renaming' ' + test_setup_1c && ( cd 1c && @@ -227,7 +230,7 @@ test_expect_success '1c-check: Transitive renaming' ' # Note: y/m & z/n should definitely move into x. By the same token, both # y/wham_1 & z/wham_2 should too...giving us a conflict. -test_expect_success '1d-setup: Directory renames cause a rename/rename(2to1) conflict' ' +test_setup_1d () { test_create_repo 1d && ( cd 1d && @@ -262,9 +265,10 @@ test_expect_success '1d-setup: Directory renames cause a rename/rename(2to1) con test_tick && git commit -m "B" ) -' +} -test_expect_success '1d-check: Directory renames cause a rename/rename(2to1) conflict' ' +test_expect_success '1d: Directory renames cause a rename/rename(2to1) conflict' ' + test_setup_1d && ( cd 1d && @@ -313,7 +317,7 @@ test_expect_success '1d-check: Directory renames cause a rename/rename(2to1) con # Commit B: z/{oldb,oldc,d} # Expected: y/{newb,newc,d} -test_expect_success '1e-setup: Renamed directory, with all files being renamed too' ' +test_setup_1e () { test_create_repo 1e && ( cd 1e && @@ -342,9 +346,10 @@ test_expect_success '1e-setup: Renamed directory, with all files being renamed t test_tick && git commit -m "B" ) -' +} -test_expect_success '1e-check: Renamed directory, with all files being renamed too' ' +test_expect_success '1e: Renamed directory, with all files being renamed too' ' + test_setup_1e && ( cd 1e && @@ -371,7 +376,7 @@ test_expect_success '1e-check: Renamed directory, with all files being renamed t # Commit B: y/{b,c}, x/{d,e,f} # Expected: y/{b,c}, x/{d,e,f,g} -test_expect_success '1f-setup: Split a directory into two other directories' ' +test_setup_1f () { test_create_repo 1f && ( cd 1f && @@ -408,9 +413,10 @@ test_expect_success '1f-setup: Split a directory into two other directories' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '1f-check: Split a directory into two other directories' ' +test_expect_success '1f: Split a directory into two other directories' ' + test_setup_1f && ( cd 1f && @@ -459,7 +465,7 @@ test_expect_success '1f-check: Split a directory into two other directories' ' # Commit A: y/b, w/c # Commit B: z/{b,c,d} # Expected: y/b, w/c, z/d, with warning about z/ -> (y/ vs. w/) conflict -test_expect_success '2a-setup: Directory split into two on one side, with equal numbers of paths' ' +test_setup_2a () { test_create_repo 2a && ( cd 2a && @@ -489,9 +495,10 @@ test_expect_success '2a-setup: Directory split into two on one side, with equal test_tick && git commit -m "B" ) -' +} -test_expect_success '2a-check: Directory split into two on one side, with equal numbers of paths' ' +test_expect_success '2a: Directory split into two on one side, with equal numbers of paths' ' + test_setup_2a && ( cd 2a && @@ -520,7 +527,7 @@ test_expect_success '2a-check: Directory split into two on one side, with equal # Commit A: y/b, w/c # Commit B: z/{b,c}, x/d # Expected: y/b, w/c, x/d; No warning about z/ -> (y/ vs. w/) conflict -test_expect_success '2b-setup: Directory split into two on one side, with equal numbers of paths' ' +test_setup_2b () { test_create_repo 2b && ( cd 2b && @@ -551,9 +558,10 @@ test_expect_success '2b-setup: Directory split into two on one side, with equal test_tick && git commit -m "B" ) -' +} -test_expect_success '2b-check: Directory split into two on one side, with equal numbers of paths' ' +test_expect_success '2b: Directory split into two on one side, with equal numbers of paths' ' + test_setup_2b && ( cd 2b && @@ -601,7 +609,7 @@ test_expect_success '2b-check: Directory split into two on one side, with equal # Commit A: z/{b,c,d} (no change) # Commit B: y/{b,c}, x/d # Expected: y/{b,c}, x/d -test_expect_success '3a-setup: Avoid implicit rename if involved as source on other side' ' +test_setup_3a () { test_create_repo 3a && ( cd 3a && @@ -632,9 +640,10 @@ test_expect_success '3a-setup: Avoid implicit rename if involved as source on ot test_tick && git commit -m "B" ) -' +} -test_expect_success '3a-check: Avoid implicit rename if involved as source on other side' ' +test_expect_success '3a: Avoid implicit rename if involved as source on other side' ' + test_setup_3a && ( cd 3a && @@ -664,7 +673,7 @@ test_expect_success '3a-check: Avoid implicit rename if involved as source on ot # get it involved in directory rename detection. If it were, we might # end up with CONFLICT:(z/d -> y/d vs. x/d vs. w/d), i.e. a # rename/rename/rename(1to3) conflict, which is just weird. -test_expect_success '3b-setup: Avoid implicit rename if involved as source on current side' ' +test_setup_3b () { test_create_repo 3b && ( cd 3b && @@ -697,9 +706,10 @@ test_expect_success '3b-setup: Avoid implicit rename if involved as source on cu test_tick && git commit -m "B" ) -' +} -test_expect_success '3b-check: Avoid implicit rename if involved as source on current side' ' +test_expect_success '3b: Avoid implicit rename if involved as source on current side' ' + test_setup_3b && ( cd 3b && @@ -744,7 +754,7 @@ test_expect_success '3b-check: Avoid implicit rename if involved as source on cu # # What if we were to attempt to do directory rename detection when someone # "mostly" moved a directory but still left some files around, or, -# equivalently, fully renamed a directory in one commmit and then recreated +# equivalently, fully renamed a directory in one commit and then recreated # that directory in a later commit adding some new files and then tried to # merge? # @@ -786,7 +796,7 @@ test_expect_success '3b-check: Avoid implicit rename if involved as source on cu # Expected: y/{b,c,d}, z/{e,f} # NOTE: Even though most files from z moved to y, we don't want f to follow. -test_expect_success '4a-setup: Directory split, with original directory still present' ' +test_setup_4a () { test_create_repo 4a && ( cd 4a && @@ -818,9 +828,10 @@ test_expect_success '4a-setup: Directory split, with original directory still pr test_tick && git commit -m "B" ) -' +} -test_expect_success '4a-check: Directory split, with original directory still present' ' +test_expect_success '4a: Directory split, with original directory still present' ' + test_setup_4a && ( cd 4a && @@ -874,7 +885,7 @@ test_expect_success '4a-check: Directory split, with original directory still pr # of history, giving us no way to represent this conflict in the # index. -test_expect_success '5a-setup: Merge directories, other side adds files to original and target' ' +test_setup_5a () { test_create_repo 5a && ( cd 5a && @@ -907,9 +918,10 @@ test_expect_success '5a-setup: Merge directories, other side adds files to origi test_tick && git commit -m "B" ) -' +} -test_expect_success '5a-check: Merge directories, other side adds files to original and target' ' +test_expect_success '5a: Merge directories, other side adds files to original and target' ' + test_setup_5a && ( cd 5a && @@ -941,14 +953,14 @@ test_expect_success '5a-check: Merge directories, other side adds files to origi # Commit B: z/{b,c,d_1,e}, y/d_3 # Expected: y/{b,c,e}, CONFLICT(add/add: y/d_2 vs. y/d_3) # NOTE: If z/d_1 in commit B were to be involved in dir rename detection, as -# we normaly would since z/ is being renamed to y/, then this would be +# we normally would since z/ is being renamed to y/, then this would be # a rename/delete (z/d_1 -> y/d_1 vs. deleted) AND an add/add/add # conflict of y/d_1 vs. y/d_2 vs. y/d_3. Add/add/add is not # representable in the index, so the existence of y/d_3 needs to # cause us to bail on directory rename detection for that path, falling # back to git behavior without the directory rename detection. -test_expect_success '5b-setup: Rename/delete in order to get add/add/add conflict' ' +test_setup_5b () { test_create_repo 5b && ( cd 5b && @@ -981,9 +993,10 @@ test_expect_success '5b-setup: Rename/delete in order to get add/add/add conflic test_tick && git commit -m "B" ) -' +} -test_expect_success '5b-check: Rename/delete in order to get add/add/add conflict' ' +test_expect_success '5b: Rename/delete in order to get add/add/add conflict' ' + test_setup_5b && ( cd 5b && @@ -1024,7 +1037,7 @@ test_expect_success '5b-check: Rename/delete in order to get add/add/add conflic # y/d are y/d_2 and y/d_4. We still do the move from z/e to y/e, # though, because it doesn't have anything in the way. -test_expect_success '5c-setup: Transitive rename would cause rename/rename/rename/add/add/add' ' +test_setup_5c () { test_create_repo 5c && ( cd 5c && @@ -1061,9 +1074,10 @@ test_expect_success '5c-setup: Transitive rename would cause rename/rename/renam test_tick && git commit -m "B" ) -' +} -test_expect_success '5c-check: Transitive rename would cause rename/rename/rename/add/add/add' ' +test_expect_success '5c: Transitive rename would cause rename/rename/rename/add/add/add' ' + test_setup_5c && ( cd 5c && @@ -1113,7 +1127,7 @@ test_expect_success '5c-check: Transitive rename would cause rename/rename/renam # detection for z/d_2, but that doesn't prevent us from applying the # directory rename detection for z/f -> y/f. -test_expect_success '5d-setup: Directory/file/file conflict due to directory rename' ' +test_setup_5d () { test_create_repo 5d && ( cd 5d && @@ -1145,9 +1159,10 @@ test_expect_success '5d-setup: Directory/file/file conflict due to directory ren test_tick && git commit -m "B" ) -' +} -test_expect_success '5d-check: Directory/file/file conflict due to directory rename' ' +test_expect_success '5d: Directory/file/file conflict due to directory rename' ' + test_setup_5d && ( cd 5d && @@ -1205,7 +1220,7 @@ test_expect_success '5d-check: Directory/file/file conflict due to directory ren # them under y/ doesn't accidentally catch z/d and make it look like # it is also involved in a rename/delete conflict. -test_expect_success '6a-setup: Tricky rename/delete' ' +test_setup_6a () { test_create_repo 6a && ( cd 6a && @@ -1235,9 +1250,10 @@ test_expect_success '6a-setup: Tricky rename/delete' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '6a-check: Tricky rename/delete' ' +test_expect_success '6a: Tricky rename/delete' ' + test_setup_6a && ( cd 6a && @@ -1271,7 +1287,7 @@ test_expect_success '6a-check: Tricky rename/delete' ' # but B did that rename and still decided to put the file into z/, # so we probably shouldn't apply directory rename detection for it. -test_expect_success '6b-setup: Same rename done on both sides' ' +test_setup_6b () { test_create_repo 6b && ( cd 6b && @@ -1300,9 +1316,10 @@ test_expect_success '6b-setup: Same rename done on both sides' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '6b-check: Same rename done on both sides' ' +test_expect_success '6b: Same rename done on both sides' ' + test_setup_6b && ( cd 6b && @@ -1334,7 +1351,7 @@ test_expect_success '6b-check: Same rename done on both sides' ' # NOTE: Seems obvious, but just checking that the implementation doesn't # "accidentally detect a rename" and give us y/{b,c,d}. -test_expect_success '6c-setup: Rename only done on same side' ' +test_setup_6c () { test_create_repo 6c && ( cd 6c && @@ -1362,9 +1379,10 @@ test_expect_success '6c-setup: Rename only done on same side' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '6c-check: Rename only done on same side' ' +test_expect_success '6c: Rename only done on same side' ' + test_setup_6c && ( cd 6c && @@ -1396,7 +1414,7 @@ test_expect_success '6c-check: Rename only done on same side' ' # NOTE: Again, this seems obvious but just checking that the implementation # doesn't "accidentally detect a rename" and give us y/{b,c,d}. -test_expect_success '6d-setup: We do not always want transitive renaming' ' +test_setup_6d () { test_create_repo 6d && ( cd 6d && @@ -1424,9 +1442,10 @@ test_expect_success '6d-setup: We do not always want transitive renaming' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '6d-check: We do not always want transitive renaming' ' +test_expect_success '6d: We do not always want transitive renaming' ' + test_setup_6d && ( cd 6d && @@ -1458,7 +1477,7 @@ test_expect_success '6d-check: We do not always want transitive renaming' ' # doesn't "accidentally detect a rename" and give us y/{b,c} + # add/add conflict on y/d_1 vs y/d_2. -test_expect_success '6e-setup: Add/add from one side' ' +test_setup_6e () { test_create_repo 6e && ( cd 6e && @@ -1487,9 +1506,10 @@ test_expect_success '6e-setup: Add/add from one side' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '6e-check: Add/add from one side' ' +test_expect_success '6e: Add/add from one side' ' + test_setup_6e && ( cd 6e && @@ -1552,7 +1572,7 @@ test_expect_success '6e-check: Add/add from one side' ' # Expected: y/d, CONFLICT(rename/rename for both z/b and z/c) # NOTE: There's a rename of z/ here, y/ has more renames, so z/d -> y/d. -test_expect_success '7a-setup: rename-dir vs. rename-dir (NOT split evenly) PLUS add-other-file' ' +test_setup_7a () { test_create_repo 7a && ( cd 7a && @@ -1583,9 +1603,10 @@ test_expect_success '7a-setup: rename-dir vs. rename-dir (NOT split evenly) PLUS test_tick && git commit -m "B" ) -' +} -test_expect_success '7a-check: rename-dir vs. rename-dir (NOT split evenly) PLUS add-other-file' ' +test_expect_success '7a: rename-dir vs. rename-dir (NOT split evenly) PLUS add-other-file' ' + test_setup_7a && ( cd 7a && @@ -1623,7 +1644,7 @@ test_expect_success '7a-check: rename-dir vs. rename-dir (NOT split evenly) PLUS # Commit B: z/{b,c,d_1}, w/d_2 # Expected: y/{b,c}, CONFLICT(rename/rename(2to1): x/d_1, w/d_2 -> y_d) -test_expect_success '7b-setup: rename/rename(2to1), but only due to transitive rename' ' +test_setup_7b () { test_create_repo 7b && ( cd 7b && @@ -1655,9 +1676,10 @@ test_expect_success '7b-setup: rename/rename(2to1), but only due to transitive r test_tick && git commit -m "B" ) -' +} -test_expect_success '7b-check: rename/rename(2to1), but only due to transitive rename' ' +test_expect_success '7b: rename/rename(2to1), but only due to transitive rename' ' + test_setup_7b && ( cd 7b && @@ -1702,7 +1724,7 @@ test_expect_success '7b-check: rename/rename(2to1), but only due to transitive r # neither CONFLICT(x/d -> w/d vs. z/d) # nor CONFLiCT x/d -> w/d vs. y/d vs. z/d) -test_expect_success '7c-setup: rename/rename(1to...2or3); transitive rename may add complexity' ' +test_setup_7c () { test_create_repo 7c && ( cd 7c && @@ -1732,9 +1754,10 @@ test_expect_success '7c-setup: rename/rename(1to...2or3); transitive rename may test_tick && git commit -m "B" ) -' +} -test_expect_success '7c-check: rename/rename(1to...2or3); transitive rename may add complexity' ' +test_expect_success '7c: rename/rename(1to...2or3); transitive rename may add complexity' ' + test_setup_7c && ( cd 7c && @@ -1766,7 +1789,7 @@ test_expect_success '7c-check: rename/rename(1to...2or3); transitive rename may # Expected: y/{b,c}, CONFLICT(delete x/d vs rename to y/d) # NOTE: z->y so NOT CONFLICT(delete x/d vs rename to z/d) -test_expect_success '7d-setup: transitive rename involved in rename/delete; how is it reported?' ' +test_setup_7d () { test_create_repo 7d && ( cd 7d && @@ -1796,9 +1819,10 @@ test_expect_success '7d-setup: transitive rename involved in rename/delete; how test_tick && git commit -m "B" ) -' +} -test_expect_success '7d-check: transitive rename involved in rename/delete; how is it reported?' ' +test_expect_success '7d: transitive rename involved in rename/delete; how is it reported?' ' + test_setup_7d && ( cd 7d && @@ -1851,7 +1875,7 @@ test_expect_success '7d-check: transitive rename involved in rename/delete; how # see testcases 9c and 9d for further discussion of this issue and # how it's resolved. -test_expect_success '7e-setup: transitive rename in rename/delete AND dirs in the way' ' +test_setup_7e () { test_create_repo 7e && ( cd 7e && @@ -1886,9 +1910,10 @@ test_expect_success '7e-setup: transitive rename in rename/delete AND dirs in th test_tick && git commit -m "B" ) -' +} -test_expect_success '7e-check: transitive rename in rename/delete AND dirs in the way' ' +test_expect_success '7e: transitive rename in rename/delete AND dirs in the way' ' + test_setup_7e && ( cd 7e && @@ -1945,7 +1970,7 @@ test_expect_success '7e-check: transitive rename in rename/delete AND dirs in th # simple rule from section 5 prevents me from handling this as optimally as # we potentially could. -test_expect_success '8a-setup: Dual-directory rename, one into the others way' ' +test_setup_8a () { test_create_repo 8a && ( cd 8a && @@ -1977,9 +2002,10 @@ test_expect_success '8a-setup: Dual-directory rename, one into the others way' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '8a-check: Dual-directory rename, one into the others way' ' +test_expect_success '8a: Dual-directory rename, one into the others way' ' + test_setup_8a && ( cd 8a && @@ -2023,7 +2049,7 @@ test_expect_success '8a-check: Dual-directory rename, one into the others way' ' # making us fall back to pre-directory-rename-detection behavior for both # e_1 and e_2. -test_expect_success '8b-setup: Dual-directory rename, one into the others way, with conflicting filenames' ' +test_setup_8b () { test_create_repo 8b && ( cd 8b && @@ -2055,9 +2081,10 @@ test_expect_success '8b-setup: Dual-directory rename, one into the others way, w test_tick && git commit -m "B" ) -' +} -test_expect_success '8b-check: Dual-directory rename, one into the others way, with conflicting filenames' ' +test_expect_success '8b: Dual-directory rename, one into the others way, with conflicting filenames' ' + test_setup_8b && ( cd 8b && @@ -2089,14 +2116,14 @@ test_expect_success '8b-check: Dual-directory rename, one into the others way, w # # Note: It could easily be argued that the correct resolution here is # y/{b,c,e}, CONFLICT(rename/delete: z/d -> y/d vs deleted) -# and that the modifed version of d should be present in y/ after +# and that the modified version of d should be present in y/ after # the merge, just marked as conflicted. Indeed, I previously did # argue that. But applying directory renames to the side of # history where a file is merely modified results in spurious # rename/rename(1to2) conflicts -- see testcase 9h. See also # notes in 8d. -test_expect_success '8c-setup: modify/delete or rename+modify/delete?' ' +test_setup_8c () { test_create_repo 8c && ( cd 8c && @@ -2127,9 +2154,10 @@ test_expect_success '8c-setup: modify/delete or rename+modify/delete?' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '8c-check: modify/delete or rename+modify/delete' ' +test_expect_success '8c: modify/delete or rename+modify/delete' ' + test_setup_8c && ( cd 8c && @@ -2175,7 +2203,7 @@ test_expect_success '8c-check: modify/delete or rename+modify/delete' ' # during merging are supposed to be about opposite sides doing things # differently. -test_expect_success '8d-setup: rename/delete...or not?' ' +test_setup_8d () { test_create_repo 8d && ( cd 8d && @@ -2204,9 +2232,10 @@ test_expect_success '8d-setup: rename/delete...or not?' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '8d-check: rename/delete...or not?' ' +test_expect_success '8d: rename/delete...or not?' ' + test_setup_8d && ( cd 8d && @@ -2250,7 +2279,7 @@ test_expect_success '8d-check: rename/delete...or not?' ' # about the ramifications of doing that, I didn't know how to rule out # that opening other weird edge and corner cases so I just punted. -test_expect_success '8e-setup: Both sides rename, one side adds to original directory' ' +test_setup_8e () { test_create_repo 8e && ( cd 8e && @@ -2279,9 +2308,10 @@ test_expect_success '8e-setup: Both sides rename, one side adds to original dire test_tick && git commit -m "B" ) -' +} -test_expect_success '8e-check: Both sides rename, one side adds to original directory' ' +test_expect_success '8e: Both sides rename, one side adds to original directory' ' + test_setup_8e && ( cd 8e && @@ -2333,7 +2363,7 @@ test_expect_success '8e-check: Both sides rename, one side adds to original dire # of which one had the most paths going to it. A naive implementation # of that could take the new file in commit B at z/i to x/w/i or x/i. -test_expect_success '9a-setup: Inner renamed directory within outer renamed directory' ' +test_setup_9a () { test_create_repo 9a && ( cd 9a && @@ -2366,9 +2396,10 @@ test_expect_success '9a-setup: Inner renamed directory within outer renamed dire test_tick && git commit -m "B" ) -' +} -test_expect_success '9a-check: Inner renamed directory within outer renamed directory' ' +test_expect_success '9a: Inner renamed directory within outer renamed directory' ' + test_setup_9a && ( cd 9a && @@ -2404,7 +2435,7 @@ test_expect_success '9a-check: Inner renamed directory within outer renamed dire # Commit B: z/{b,c,d_3} # Expected: y/{b,c,d_merged} -test_expect_success '9b-setup: Transitive rename with content merge' ' +test_setup_9b () { test_create_repo 9b && ( cd 9b && @@ -2436,9 +2467,10 @@ test_expect_success '9b-setup: Transitive rename with content merge' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '9b-check: Transitive rename with content merge' ' +test_expect_success '9b: Transitive rename with content merge' ' + test_setup_9b && ( cd 9b && @@ -2491,7 +2523,7 @@ test_expect_success '9b-check: Transitive rename with content merge' ' # away, then ignore that particular rename from the other side of # history for any implicit directory renames. -test_expect_success '9c-setup: Doubly transitive rename?' ' +test_setup_9c () { test_create_repo 9c && ( cd 9c && @@ -2526,9 +2558,10 @@ test_expect_success '9c-setup: Doubly transitive rename?' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '9c-check: Doubly transitive rename?' ' +test_expect_success '9c: Doubly transitive rename?' ' + test_setup_9c && ( cd 9c && @@ -2579,7 +2612,7 @@ test_expect_success '9c-check: Doubly transitive rename?' ' # simple rules that are consistent with what we need for all the other # testcases and simplifies things for the user. -test_expect_success '9d-setup: N-way transitive rename?' ' +test_setup_9d () { test_create_repo 9d && ( cd 9d && @@ -2614,9 +2647,10 @@ test_expect_success '9d-setup: N-way transitive rename?' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '9d-check: N-way transitive rename?' ' +test_expect_success '9d: N-way transitive rename?' ' + test_setup_9d && ( cd 9d && @@ -2653,7 +2687,7 @@ test_expect_success '9d-check: N-way transitive rename?' ' # Expected: combined/{a,b,c,d,e,f,g,h,i,j,k,l}, CONFLICT(Nto1) warnings, # dir1/yo, dir2/yo, dir3/yo, dirN/yo -test_expect_success '9e-setup: N-to-1 whammo' ' +test_setup_9e () { test_create_repo 9e && ( cd 9e && @@ -2696,9 +2730,10 @@ test_expect_success '9e-setup: N-to-1 whammo' ' test_tick && git commit -m "B" ) -' +} -test_expect_success C_LOCALE_OUTPUT '9e-check: N-to-1 whammo' ' +test_expect_success C_LOCALE_OUTPUT '9e: N-to-1 whammo' ' + test_setup_9e && ( cd 9e && @@ -2745,7 +2780,7 @@ test_expect_success C_LOCALE_OUTPUT '9e-check: N-to-1 whammo' ' # Commit B: goal/{a,b}/$more_files, goal/c # Expected: priority/{a,b}/$more_files, priority/c -test_expect_success '9f-setup: Renamed directory that only contained immediate subdirs' ' +test_setup_9f () { test_create_repo 9f && ( cd 9f && @@ -2774,9 +2809,10 @@ test_expect_success '9f-setup: Renamed directory that only contained immediate s test_tick && git commit -m "B" ) -' +} -test_expect_success '9f-check: Renamed directory that only contained immediate subdirs' ' +test_expect_success '9f: Renamed directory that only contained immediate subdirs' ' + test_setup_9f && ( cd 9f && @@ -2809,7 +2845,7 @@ test_expect_success '9f-check: Renamed directory that only contained immediate s # Commit B: goal/{a,b}/$more_files, goal/c # Expected: priority/{alpha,bravo}/$more_files, priority/c -test_expect_success '9g-setup: Renamed directory that only contained immediate subdirs, immediate subdirs renamed' ' +test_setup_9g () { test_create_repo 9g && ( cd 9g && @@ -2841,9 +2877,9 @@ test_expect_success '9g-setup: Renamed directory that only contained immediate s test_tick && git commit -m "B" ) -' +} -test_expect_failure '9g-check: Renamed directory that only contained immediate subdirs, immediate subdirs renamed' ' +test_expect_failure '9g: Renamed directory that only contained immediate subdirs, immediate subdirs renamed' ' ( cd 9g && @@ -2877,7 +2913,7 @@ test_expect_failure '9g-check: Renamed directory that only contained immediate s # Expected: y/{b,c}, x/d_2 # NOTE: If we applied the z/ -> y/ rename to z/d, then we'd end up with # a rename/rename(1to2) conflict (z/d -> y/d vs. x/d) -test_expect_success '9h-setup: Avoid dir rename on merely modified path' ' +test_setup_9h () { test_create_repo 9h && ( cd 9h && @@ -2910,9 +2946,10 @@ test_expect_success '9h-setup: Avoid dir rename on merely modified path' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '9h-check: Avoid dir rename on merely modified path' ' +test_expect_success '9h: Avoid dir rename on merely modified path' ' + test_setup_9h && ( cd 9h && @@ -2957,7 +2994,7 @@ test_expect_success '9h-check: Avoid dir rename on merely modified path' ' # Expected: Aborted Merge + # ERROR_MSG(untracked working tree files would be overwritten by merge) -test_expect_success '10a-setup: Overwrite untracked with normal rename/delete' ' +test_setup_10a () { test_create_repo 10a && ( cd 10a && @@ -2983,9 +3020,10 @@ test_expect_success '10a-setup: Overwrite untracked with normal rename/delete' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '10a-check: Overwrite untracked with normal rename/delete' ' +test_expect_success '10a: Overwrite untracked with normal rename/delete' ' + test_setup_10a && ( cd 10a && @@ -3021,7 +3059,7 @@ test_expect_success '10a-check: Overwrite untracked with normal rename/delete' ' # z/c_1 -> z/d_1 rename recorded at stage 3 for y/d + # ERROR_MSG(refusing to lose untracked file at 'y/d') -test_expect_success '10b-setup: Overwrite untracked with dir rename + delete' ' +test_setup_10b () { test_create_repo 10b && ( cd 10b && @@ -3050,9 +3088,10 @@ test_expect_success '10b-setup: Overwrite untracked with dir rename + delete' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '10b-check: Overwrite untracked with dir rename + delete' ' +test_expect_success '10b: Overwrite untracked with dir rename + delete' ' + test_setup_10b && ( cd 10b && @@ -3098,10 +3137,10 @@ test_expect_success '10b-check: Overwrite untracked with dir rename + delete' ' # y/c~B^0 + # ERROR_MSG(Refusing to lose untracked file at y/c) -test_expect_success '10c-setup: Overwrite untracked with dir rename/rename(1to2)' ' - test_create_repo 10c && +test_setup_10c () { + test_create_repo 10c_$1 && ( - cd 10c && + cd 10c_$1 && mkdir z x && echo a >z/a && @@ -3128,11 +3167,12 @@ test_expect_success '10c-setup: Overwrite untracked with dir rename/rename(1to2) test_tick && git commit -m "B" ) -' +} -test_expect_success '10c-check: Overwrite untracked with dir rename/rename(1to2)' ' +test_expect_success '10c1: Overwrite untracked with dir rename/rename(1to2)' ' + test_setup_10c 1 && ( - cd 10c && + cd 10c_1 && git checkout A^0 && echo important >y/c && @@ -3163,9 +3203,10 @@ 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' ' +test_expect_success '10c2: Overwrite untracked with dir rename/rename(1to2), other direction' ' + test_setup_10c 2 && ( - cd 10c && + cd 10c_2 && git reset --hard && git clean -fdqx && @@ -3208,7 +3249,7 @@ test_expect_success '10c-check: Overwrite untracked with dir rename/rename(1to2) # CONFLICT(rename/rename) z/c_1 vs x/f_2 -> y/wham # ERROR_MSG(Refusing to lose untracked file at y/wham) -test_expect_success '10d-setup: Delete untracked with dir rename/rename(2to1)' ' +test_setup_10d () { test_create_repo 10d && ( cd 10d && @@ -3240,9 +3281,10 @@ test_expect_success '10d-setup: Delete untracked with dir rename/rename(2to1)' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '10d-check: Delete untracked with dir rename/rename(2to1)' ' +test_expect_success '10d: Delete untracked with dir rename/rename(2to1)' ' + test_setup_10d && ( cd 10d && @@ -3290,7 +3332,7 @@ test_expect_success '10d-check: Delete untracked with dir rename/rename(2to1)' ' # Commit B: z/{a,b,c} # Expected: y/{a,b,c} + untracked z/c -test_expect_success '10e-setup: Does git complain about untracked file that is not really in the way?' ' +test_setup_10e () { test_create_repo 10e && ( cd 10e && @@ -3317,9 +3359,9 @@ test_expect_success '10e-setup: Does git complain about untracked file that is n test_tick && git commit -m "B" ) -' +} -test_expect_failure '10e-check: Does git complain about untracked file that is not really in the way?' ' +test_expect_failure '10e: Does git complain about untracked file that is not really in the way?' ' ( cd 10e && @@ -3371,7 +3413,7 @@ test_expect_failure '10e-check: Does git complain about untracked file that is n # z/c~HEAD with contents of B:z/b_v2, # z/c with uncommitted mods on top of A:z/c_v1 -test_expect_success '11a-setup: Avoid losing dirty contents with simple rename' ' +test_setup_11a () { test_create_repo 11a && ( cd 11a && @@ -3398,9 +3440,10 @@ test_expect_success '11a-setup: Avoid losing dirty contents with simple rename' test_tick && git commit -m "B" ) -' +} -test_expect_success '11a-check: Avoid losing dirty contents with simple rename' ' +test_expect_success '11a: Avoid losing dirty contents with simple rename' ' + test_setup_11a && ( cd 11a && @@ -3441,7 +3484,7 @@ test_expect_success '11a-check: Avoid losing dirty contents with simple rename' # ERROR_MSG(Refusing to lose dirty file at z/c) -test_expect_success '11b-setup: Avoid losing dirty file involved in directory rename' ' +test_setup_11b () { test_create_repo 11b && ( cd 11b && @@ -3470,9 +3513,10 @@ test_expect_success '11b-setup: Avoid losing dirty file involved in directory re test_tick && git commit -m "B" ) -' +} -test_expect_success '11b-check: Avoid losing dirty file involved in directory rename' ' +test_expect_success '11b: Avoid losing dirty file involved in directory rename' ' + test_setup_11b && ( cd 11b && @@ -3515,7 +3559,7 @@ test_expect_success '11b-check: Avoid losing dirty file involved in directory re # Expected: Abort_msg("following files would be overwritten by merge") + # y/c left untouched (still has uncommitted mods) -test_expect_success '11c-setup: Avoid losing not-uptodate with rename + D/F conflict' ' +test_setup_11c () { test_create_repo 11c && ( cd 11c && @@ -3545,9 +3589,10 @@ test_expect_success '11c-setup: Avoid losing not-uptodate with rename + D/F conf test_tick && git commit -m "B" ) -' +} -test_expect_success '11c-check: Avoid losing not-uptodate with rename + D/F conflict' ' +test_expect_success '11c: Avoid losing not-uptodate with rename + D/F conflict' ' + test_setup_11c && ( cd 11c && @@ -3581,7 +3626,7 @@ test_expect_success '11c-check: Avoid losing not-uptodate with rename + D/F conf # Warning_Msg("Refusing to lose dirty file at z/c) + # y/{a,c~HEAD,c/d}, x/b, now-untracked z/c_v1 with uncommitted mods -test_expect_success '11d-setup: Avoid losing not-uptodate with rename + D/F conflict' ' +test_setup_11d () { test_create_repo 11d && ( cd 11d && @@ -3612,9 +3657,10 @@ test_expect_success '11d-setup: Avoid losing not-uptodate with rename + D/F conf test_tick && git commit -m "B" ) -' +} -test_expect_success '11d-check: Avoid losing not-uptodate with rename + D/F conflict' ' +test_expect_success '11d: Avoid losing not-uptodate with rename + D/F conflict' ' + test_setup_11d && ( cd 11d && @@ -3659,7 +3705,7 @@ test_expect_success '11d-check: Avoid losing not-uptodate with rename + D/F conf # y/c~HEAD has A:y/c_2 contents # y/c has dirty file from before merge -test_expect_success '11e-setup: Avoid deleting not-uptodate with dir rename/rename(1to2)/add' ' +test_setup_11e () { test_create_repo 11e && ( cd 11e && @@ -3691,9 +3737,10 @@ test_expect_success '11e-setup: Avoid deleting not-uptodate with dir rename/rena test_tick && git commit -m "B" ) -' +} -test_expect_success '11e-check: Avoid deleting not-uptodate with dir rename/rename(1to2)/add' ' +test_expect_success '11e: Avoid deleting not-uptodate with dir rename/rename(1to2)/add' ' + test_setup_11e && ( cd 11e && @@ -3744,7 +3791,7 @@ test_expect_success '11e-check: Avoid deleting not-uptodate with dir rename/rena # CONFLICT(rename/rename) x/c vs x/d -> y/wham # ERROR_MSG(Refusing to lose dirty file at y/wham) -test_expect_success '11f-setup: Avoid deleting not-uptodate with dir rename/rename(2to1)' ' +test_setup_11f () { test_create_repo 11f && ( cd 11f && @@ -3773,9 +3820,10 @@ test_expect_success '11f-setup: Avoid deleting not-uptodate with dir rename/rena test_tick && git commit -m "B" ) -' +} -test_expect_success '11f-check: Avoid deleting not-uptodate with dir rename/rename(2to1)' ' +test_expect_success '11f: Avoid deleting not-uptodate with dir rename/rename(2to1)' ' + test_setup_11f && ( cd 11f && @@ -3832,7 +3880,7 @@ test_expect_success '11f-check: Avoid deleting not-uptodate with dir rename/rena # Commit B: node1/{leaf1,leaf2,leaf5}, node2/{leaf3,leaf4,leaf6} # Expected: node1/{leaf1,leaf2,leaf5,node2/{leaf3,leaf4,leaf6}} -test_expect_success '12a-setup: Moving one directory hierarchy into another' ' +test_setup_12a () { test_create_repo 12a && ( cd 12a && @@ -3862,9 +3910,10 @@ test_expect_success '12a-setup: Moving one directory hierarchy into another' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '12a-check: Moving one directory hierarchy into another' ' +test_expect_success '12a: Moving one directory hierarchy into another' ' + test_setup_12a && ( cd 12a && @@ -3910,7 +3959,7 @@ test_expect_success '12a-check: Moving one directory hierarchy into another' ' # To which, I can do no more than shrug my shoulders and say that # even simple rules give weird results when given weird inputs. -test_expect_success '12b-setup: Moving two directory hierarchies into each other' ' +test_setup_12b () { test_create_repo 12b && ( cd 12b && @@ -3938,9 +3987,10 @@ test_expect_success '12b-setup: Moving two directory hierarchies into each other test_tick && git commit -m "B" ) -' +} -test_expect_success '12b-check: Moving two directory hierarchies into each other' ' +test_expect_success '12b: Moving two directory hierarchies into each other' ' + test_setup_12b && ( cd 12b && @@ -3976,7 +4026,7 @@ test_expect_success '12b-check: Moving two directory hierarchies into each other # NOTE: This is *exactly* like 12c, except that every path is modified on # each side of the merge. -test_expect_success '12c-setup: Moving one directory hierarchy into another w/ content merge' ' +test_setup_12c () { test_create_repo 12c && ( cd 12c && @@ -4008,9 +4058,10 @@ test_expect_success '12c-setup: Moving one directory hierarchy into another w/ c test_tick && git commit -m "B" ) -' +} -test_expect_success '12c-check: Moving one directory hierarchy into another w/ content merge' ' +test_expect_success '12c: Moving one directory hierarchy into another w/ content merge' ' + test_setup_12c && ( cd 12c && @@ -4051,6 +4102,122 @@ test_expect_success '12c-check: Moving one directory hierarchy into another w/ c ) ' +# Testcase 12d, Rename/merge of subdirectory into the root +# Commit O: a/b/subdir/foo +# Commit A: subdir/foo +# Commit B: a/b/subdir/foo, a/b/bar +# Expected: subdir/foo, bar + +test_setup_12d () { + test_create_repo 12d && + ( + cd 12d && + + mkdir -p a/b/subdir && + test_commit a/b/subdir/foo && + + git branch O && + git branch A && + git branch B && + + git checkout A && + mkdir subdir && + git mv a/b/subdir/foo.t subdir/foo.t && + test_tick && + git commit -m "A" && + + git checkout B && + test_commit a/b/bar + ) +} + +test_expect_success '12d: Rename/merge subdir into the root, variant 1' ' + test_setup_12d && + ( + cd 12d && + + git checkout A^0 && + + git -c merge.directoryRenames=true merge -s recursive B^0 && + + git ls-files -s >out && + test_line_count = 2 out && + + git rev-parse >actual \ + HEAD:subdir/foo.t HEAD:bar.t && + git rev-parse >expect \ + O:a/b/subdir/foo.t B:a/b/bar.t && + test_cmp expect actual && + + git hash-object bar.t >actual && + git rev-parse B:a/b/bar.t >expect && + test_cmp expect actual && + + test_must_fail git rev-parse HEAD:a/b/subdir/foo.t && + test_must_fail git rev-parse HEAD:a/b/bar.t && + test_path_is_missing a/ && + test_path_is_file bar.t + ) +' + +# Testcase 12e, Rename/merge of subdirectory into the root +# Commit O: a/b/foo +# Commit A: foo +# Commit B: a/b/foo, a/b/bar +# Expected: foo, bar + +test_setup_12e () { + test_create_repo 12e && + ( + cd 12e && + + mkdir -p a/b && + test_commit a/b/foo && + + git branch O && + git branch A && + git branch B && + + git checkout A && + mkdir subdir && + git mv a/b/foo.t foo.t && + test_tick && + git commit -m "A" && + + git checkout B && + test_commit a/b/bar + ) +} + +test_expect_success '12e: Rename/merge subdir into the root, variant 2' ' + test_setup_12e && + ( + cd 12e && + + git checkout A^0 && + + git -c merge.directoryRenames=true merge -s recursive B^0 && + + git ls-files -s >out && + test_line_count = 2 out && + + git rev-parse >actual \ + HEAD:foo.t HEAD:bar.t && + git rev-parse >expect \ + O:a/b/foo.t B:a/b/bar.t && + test_cmp expect actual && + + git hash-object bar.t >actual && + git rev-parse B:a/b/bar.t >expect && + test_cmp expect actual && + + test_must_fail git rev-parse HEAD:a/b/foo.t && + test_must_fail git rev-parse HEAD:a/b/bar.t && + test_path_is_missing a/ && + test_path_is_file bar.t + ) +' + ########################################################################### # SECTION 13: Checking informational and conflict messages # @@ -4068,10 +4235,10 @@ test_expect_success '12c-check: Moving one directory hierarchy into another w/ c # Commit B: z/{b,c,d,e/f} # Expected: y/{b,c,d,e/f}, with notices/conflicts for both y/d and y/e/f -test_expect_success '13a-setup: messages for newly added files' ' - test_create_repo 13a && +test_setup_13a () { + test_create_repo 13a_$1 && ( - cd 13a && + cd 13a_$1 && mkdir z && echo b >z/b && @@ -4097,11 +4264,12 @@ test_expect_success '13a-setup: messages for newly added files' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '13a-check(conflict): messages for newly added files' ' +test_expect_success '13a(conflict): messages for newly added files' ' + test_setup_13a conflict && ( - cd 13a && + cd 13a_conflict && git checkout A^0 && @@ -4121,9 +4289,10 @@ test_expect_success '13a-check(conflict): messages for newly added files' ' ) ' -test_expect_success '13a-check(info): messages for newly added files' ' +test_expect_success '13a(info): messages for newly added files' ' + test_setup_13a info && ( - cd 13a && + cd 13a_info && git reset --hard && git checkout A^0 && @@ -4153,10 +4322,10 @@ test_expect_success '13a-check(info): messages for newly added files' ' # Expected: y/{b,c,d_merged}, with two conflict messages for y/d, # one about content, and one about file location -test_expect_success '13b-setup: messages for transitive rename with conflicted content' ' - test_create_repo 13b && +test_setup_13b () { + test_create_repo 13b_$1 && ( - cd 13b && + cd 13b_$1 && mkdir x && mkdir z && @@ -4185,11 +4354,12 @@ test_expect_success '13b-setup: messages for transitive rename with conflicted c test_tick && git commit -m "B" ) -' +} -test_expect_success '13b-check(conflict): messages for transitive rename with conflicted content' ' +test_expect_success '13b(conflict): messages for transitive rename with conflicted content' ' + test_setup_13b conflict && ( - cd 13b && + cd 13b_conflict && git checkout A^0 && @@ -4207,9 +4377,10 @@ test_expect_success '13b-check(conflict): messages for transitive rename with co ) ' -test_expect_success '13b-check(info): messages for transitive rename with conflicted content' ' +test_expect_success '13b(info): messages for transitive rename with conflicted content' ' + test_setup_13b info && ( - cd 13b && + cd 13b_info && git reset --hard && git checkout A^0 && @@ -4238,10 +4409,10 @@ test_expect_success '13b-check(info): messages for transitive rename with confli # d and B had full knowledge, but that's a slippery slope as # shown in testcase 13d. -test_expect_success '13c-setup: messages for rename/rename(1to1) via transitive rename' ' - test_create_repo 13c && +test_setup_13c () { + test_create_repo 13c_$1 && ( - cd 13c && + cd 13c_$1 && mkdir x && mkdir z && @@ -4269,11 +4440,12 @@ test_expect_success '13c-setup: messages for rename/rename(1to1) via transitive test_tick && git commit -m "B" ) -' +} -test_expect_success '13c-check(conflict): messages for rename/rename(1to1) via transitive rename' ' +test_expect_success '13c(conflict): messages for rename/rename(1to1) via transitive rename' ' + test_setup_13c conflict && ( - cd 13c && + cd 13c_conflict && git checkout A^0 && @@ -4290,9 +4462,10 @@ test_expect_success '13c-check(conflict): messages for rename/rename(1to1) via t ) ' -test_expect_success '13c-check(info): messages for rename/rename(1to1) via transitive rename' ' +test_expect_success '13c(info): messages for rename/rename(1to1) via transitive rename' ' + test_setup_13c info && ( - cd 13c && + cd 13c_info && git reset --hard && git checkout A^0 && @@ -4324,10 +4497,10 @@ test_expect_success '13c-check(info): messages for rename/rename(1to1) via trans # * B renames a/y to c/y, and A renames c/->d/ => a/y -> d/y # No conflict in where a/y ends up, so put it in d/y. -test_expect_success '13d-setup: messages for rename/rename(1to1) via dual transitive rename' ' - test_create_repo 13d && +test_setup_13d () { + test_create_repo 13d_$1 && ( - cd 13d && + cd 13d_$1 && mkdir a && mkdir b && @@ -4356,11 +4529,12 @@ test_expect_success '13d-setup: messages for rename/rename(1to1) via dual transi test_tick && git commit -m "B" ) -' +} -test_expect_success '13d-check(conflict): messages for rename/rename(1to1) via dual transitive rename' ' +test_expect_success '13d(conflict): messages for rename/rename(1to1) via dual transitive rename' ' + test_setup_13d conflict && ( - cd 13d && + cd 13d_conflict && git checkout A^0 && @@ -4380,9 +4554,10 @@ test_expect_success '13d-check(conflict): messages for rename/rename(1to1) via d ) ' -test_expect_success '13d-check(info): messages for rename/rename(1to1) via dual transitive rename' ' +test_expect_success '13d(info): messages for rename/rename(1to1) via dual transitive rename' ' + test_setup_13d info && ( - cd 13d && + cd 13d_info && git reset --hard && git checkout A^0 && @@ -4403,4 +4578,116 @@ test_expect_success '13d-check(info): messages for rename/rename(1to1) via dual ) ' +# Testcase 13e, directory rename in virtual merge base +# +# This testcase has a slightly different setup than all the above cases, in +# order to include a recursive case: +# +# A C +# o - o +# / \ / \ +# O o X ? +# \ / \ / +# o o +# B D +# +# Commit O: a/{z,y} +# Commit A: b/{z,y} +# Commit B: a/{z,y,x} +# Commit C: b/{z,y,x} +# Commit D: b/{z,y}, a/x +# Expected: b/{z,y,x} (sort of; see below for why this might not be expected) +# +# NOTES: 'X' represents a virtual merge base. With the default of +# directory rename detection yielding conflicts, merging A and B +# results in a conflict complaining about whether 'x' should be +# under 'a/' or 'b/'. However, when creating the virtual merge +# base 'X', since virtual merge bases need to be written out as a +# tree, we cannot have a conflict, so some resolution has to be +# picked. +# +# In choosing the right resolution, it's worth noting here that +# commits C & D are merges of A & B that choose different +# locations for 'x' (i.e. they resolve the conflict differently), +# and so it would be nice when merging C & D if git could detect +# this difference of opinion and report a conflict. But the only +# way to do so that I can think of would be to have the virtual +# merge base place 'x' in some directory other than either 'a/' or +# 'b/', which seems a little weird -- especially since it'd result +# in a rename/rename(1to2) conflict with a source path that never +# existed in any version. +# +# So, for now, when directory rename detection is set to +# 'conflict' just avoid doing directory rename detection at all in +# the recursive case. This will not allow us to detect a conflict +# in the outer merge for this special kind of setup, but it at +# least avoids hitting a BUG(). +# +test_setup_13e () { + test_create_repo 13e && + ( + cd 13e && + + mkdir a && + echo z >a/z && + echo y >a/y && + git add a && + test_tick && + git commit -m "O" && + + git branch O && + git branch A && + git branch B && + + git checkout A && + git mv a/ b/ && + test_tick && + git commit -m "A" && + + git checkout B && + echo x >a/x && + git add a && + test_tick && + git commit -m "B" && + + git branch C A && + git branch D B && + + git checkout C && + test_must_fail git -c merge.directoryRenames=conflict merge B && + git add b/x && + test_tick && + git commit -m "C" && + + + git checkout D && + test_must_fail git -c merge.directoryRenames=conflict merge A && + git add b/x && + mkdir a && + git mv b/x a/x && + test_tick && + git commit -m "D" + ) +} + +test_expect_success '13e: directory rename detection in recursive case' ' + test_setup_13e && + ( + cd 13e && + + git checkout --quiet D^0 && + + git -c merge.directoryRenames=conflict merge -s recursive C^0 >out 2>err && + + test_i18ngrep ! CONFLICT out && + test_i18ngrep ! BUG: err && + test_i18ngrep ! core.dumped err && + test_must_be_empty err && + + git ls-files >paths && + ! grep a/x paths && + grep b/x paths + ) +' + test_done diff --git a/t/t6046-merge-skip-unneeded-updates.sh b/t/t6046-merge-skip-unneeded-updates.sh index 3a47623ed3..b7e4669832 100755 --- a/t/t6046-merge-skip-unneeded-updates.sh +++ b/t/t6046-merge-skip-unneeded-updates.sh @@ -36,10 +36,10 @@ test_description="merge cases" # Commit B: b_3 # Expected: b_2 -test_expect_success '1a-setup: Modify(A)/Modify(B), change on B subset of A' ' - test_create_repo 1a && +test_setup_1a () { + test_create_repo 1a_$1 && ( - cd 1a && + cd 1a_$1 && test_write_lines 1 2 3 4 5 6 7 8 9 10 >b && git add b && @@ -62,13 +62,12 @@ test_expect_success '1a-setup: Modify(A)/Modify(B), change on B subset of A' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '1a-check-L: Modify(A)/Modify(B), change on B subset of A' ' - test_when_finished "git -C 1a reset --hard" && - test_when_finished "git -C 1a clean -fd" && +test_expect_success '1a-L: Modify(A)/Modify(B), change on B subset of A' ' + test_setup_1a L && ( - cd 1a && + cd 1a_L && git checkout A^0 && @@ -96,11 +95,10 @@ test_expect_success '1a-check-L: Modify(A)/Modify(B), change on B subset of A' ' ) ' -test_expect_success '1a-check-R: Modify(A)/Modify(B), change on B subset of A' ' - test_when_finished "git -C 1a reset --hard" && - test_when_finished "git -C 1a clean -fd" && +test_expect_success '1a-R: Modify(A)/Modify(B), change on B subset of A' ' + test_setup_1a R && ( - cd 1a && + cd 1a_R && git checkout B^0 && @@ -133,10 +131,10 @@ test_expect_success '1a-check-R: Modify(A)/Modify(B), change on B subset of A' ' # Commit B: c_1 # Expected: c_2 -test_expect_success '2a-setup: Modify(A)/rename(B)' ' - test_create_repo 2a && +test_setup_2a () { + test_create_repo 2a_$1 && ( - cd 2a && + cd 2a_$1 && test_seq 1 10 >b && git add b && @@ -158,13 +156,12 @@ test_expect_success '2a-setup: Modify(A)/rename(B)' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '2a-check-L: Modify/rename, merge into modify side' ' - test_when_finished "git -C 2a reset --hard" && - test_when_finished "git -C 2a clean -fd" && +test_expect_success '2a-L: Modify/rename, merge into modify side' ' + test_setup_2a L && ( - cd 2a && + cd 2a_L && git checkout A^0 && @@ -189,11 +186,10 @@ test_expect_success '2a-check-L: Modify/rename, merge into modify side' ' ) ' -test_expect_success '2a-check-R: Modify/rename, merge into rename side' ' - test_when_finished "git -C 2a reset --hard" && - test_when_finished "git -C 2a clean -fd" && +test_expect_success '2a-R: Modify/rename, merge into rename side' ' + test_setup_2a R && ( - cd 2a && + cd 2a_R && git checkout B^0 && @@ -224,10 +220,10 @@ test_expect_success '2a-check-R: Modify/rename, merge into rename side' ' # Commit B: b_3 # Expected: c_2 -test_expect_success '2b-setup: Rename+Mod(A)/Mod(B), B mods subset of A' ' - test_create_repo 2b && +test_setup_2b () { + test_create_repo 2b_$1 && ( - cd 2b && + cd 2b_$1 && test_write_lines 1 2 3 4 5 6 7 8 9 10 >b && git add b && @@ -251,13 +247,12 @@ test_expect_success '2b-setup: Rename+Mod(A)/Mod(B), B mods subset of A' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '2b-check-L: Rename+Mod(A)/Mod(B), B mods subset of A' ' - test_when_finished "git -C 2b reset --hard" && - test_when_finished "git -C 2b clean -fd" && +test_expect_success '2b-L: Rename+Mod(A)/Mod(B), B mods subset of A' ' + test_setup_2b L && ( - cd 2b && + cd 2b_L && git checkout A^0 && @@ -288,11 +283,10 @@ test_expect_success '2b-check-L: Rename+Mod(A)/Mod(B), B mods subset of A' ' ) ' -test_expect_success '2b-check-R: Rename+Mod(A)/Mod(B), B mods subset of A' ' - test_when_finished "git -C 2b reset --hard" && - test_when_finished "git -C 2b clean -fd" && +test_expect_success '2b-R: Rename+Mod(A)/Mod(B), B mods subset of A' ' + test_setup_2b R && ( - cd 2b && + cd 2b_R && git checkout B^0 && @@ -332,7 +326,7 @@ test_expect_success '2b-check-R: Rename+Mod(A)/Mod(B), B mods subset of A' ' # skip the update, then we're in trouble. This test verifies we do # not make that particular mistake. -test_expect_success '2c-setup: Modify b & add c VS rename b->c' ' +test_setup_2c () { test_create_repo 2c && ( cd 2c && @@ -358,9 +352,10 @@ test_expect_success '2c-setup: Modify b & add c VS rename b->c' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '2c-check: Modify b & add c VS rename b->c' ' +test_expect_success '2c: Modify b & add c VS rename b->c' ' + test_setup_2c && ( cd 2c && @@ -428,10 +423,10 @@ test_expect_success '2c-check: Modify b & add c VS rename b->c' ' # Commit B: bq_1, bar/whatever # Expected: bar/{bq_2, whatever} -test_expect_success '3a-setup: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' - test_create_repo 3a && +test_setup_3a () { + test_create_repo 3a_$1 && ( - cd 3a && + cd 3a_$1 && mkdir foo && test_seq 1 10 >bq && @@ -456,13 +451,12 @@ test_expect_success '3a-setup: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '3a-check-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' - test_when_finished "git -C 3a reset --hard" && - test_when_finished "git -C 3a clean -fd" && +test_expect_success '3a-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' + test_setup_3a L && ( - cd 3a && + cd 3a_L && git checkout A^0 && @@ -487,11 +481,10 @@ test_expect_success '3a-check-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' ) ' -test_expect_success '3a-check-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' - test_when_finished "git -C 3a reset --hard" && - test_when_finished "git -C 3a clean -fd" && +test_expect_success '3a-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' + test_setup_3a R && ( - cd 3a && + cd 3a_R && git checkout B^0 && @@ -522,10 +515,10 @@ test_expect_success '3a-check-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' # Commit B: bq_2, bar/whatever # Expected: bar/{bq_2, whatever} -test_expect_success '3b-setup: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' - test_create_repo 3b && +test_setup_3b () { + test_create_repo 3b_$1 && ( - cd 3b && + cd 3b_$1 && mkdir foo && test_seq 1 10 >bq && @@ -550,13 +543,12 @@ test_expect_success '3b-setup: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' test_tick && git commit -m "B" ) -' +} -test_expect_success '3b-check-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' - test_when_finished "git -C 3b reset --hard" && - test_when_finished "git -C 3b clean -fd" && +test_expect_success '3b-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' + test_setup_3b L && ( - cd 3b && + cd 3b_L && git checkout A^0 && @@ -581,11 +573,10 @@ test_expect_success '3b-check-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' ) ' -test_expect_success '3b-check-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' - test_when_finished "git -C 3b reset --hard" && - test_when_finished "git -C 3b clean -fd" && +test_expect_success '3b-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' + test_setup_3b R && ( - cd 3b && + cd 3b_R && git checkout B^0 && @@ -621,7 +612,7 @@ test_expect_success '3b-check-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' # Working copy: b_4 # Expected: b_2 for merge, b_4 in working copy -test_expect_success '4a-setup: Change on A, change on B subset of A, dirty mods present' ' +test_setup_4a () { test_create_repo 4a && ( cd 4a && @@ -647,7 +638,7 @@ test_expect_success '4a-setup: Change on A, change on B subset of A, dirty mods test_tick && git commit -m "B" ) -' +} # NOTE: For as long as we continue using unpack_trees() without index_only # set to true, it will error out on a case like this claiming the the locally @@ -655,9 +646,8 @@ test_expect_success '4a-setup: Change on A, change on B subset of A, dirty mods # correct requires doing the merge in-memory first, then realizing that no # updates to the file are necessary, and thus that we can just leave the path # alone. -test_expect_failure '4a-check: Change on A, change on B subset of A, dirty mods present' ' - test_when_finished "git -C 4a reset --hard" && - test_when_finished "git -C 4a clean -fd" && +test_expect_failure '4a: Change on A, change on B subset of A, dirty mods present' ' + test_setup_4a && ( cd 4a && @@ -695,7 +685,7 @@ test_expect_failure '4a-check: Change on A, change on B subset of A, dirty mods # Working copy: c_4 # Expected: c_2 -test_expect_success '4b-setup: Rename+Mod(A)/Mod(B), change on B subset of A, dirty mods present' ' +test_setup_4b () { test_create_repo 4b && ( cd 4b && @@ -722,11 +712,10 @@ test_expect_success '4b-setup: Rename+Mod(A)/Mod(B), change on B subset of A, di test_tick && git commit -m "B" ) -' +} -test_expect_success '4b-check: Rename+Mod(A)/Mod(B), change on B subset of A, dirty mods present' ' - test_when_finished "git -C 4b reset --hard" && - test_when_finished "git -C 4b clean -fd" && +test_expect_success '4b: Rename+Mod(A)/Mod(B), change on B subset of A, dirty mods present' ' + test_setup_4b && ( cd 4b && diff --git a/t/t6047-diff3-conflict-markers.sh b/t/t6047-diff3-conflict-markers.sh new file mode 100755 index 0000000000..860542aad0 --- /dev/null +++ b/t/t6047-diff3-conflict-markers.sh @@ -0,0 +1,202 @@ +#!/bin/sh + +test_description='recursive merge diff3 style conflict markers' + +. ./test-lib.sh + +# Setup: +# L1 +# \ +# ? +# / +# R1 +# +# Where: +# L1 and R1 both have a file named 'content' but have no common history +# + +test_expect_success 'setup no merge base' ' + test_create_repo no_merge_base && + ( + cd no_merge_base && + + git checkout -b L && + test_commit A content A && + + git checkout --orphan R && + test_commit B content B + ) +' + +test_expect_success 'check no merge base' ' + ( + cd no_merge_base && + + git checkout L^0 && + + test_must_fail git -c merge.conflictstyle=diff3 merge --allow-unrelated-histories -s recursive R^0 && + + grep "|||||| empty tree" content + ) +' + +# Setup: +# L1 +# / \ +# master ? +# \ / +# R1 +# +# Where: +# L1 and R1 have modified the same file ('content') in conflicting ways +# + +test_expect_success 'setup unique merge base' ' + test_create_repo unique_merge_base && + ( + cd unique_merge_base && + + test_commit base content "1 +2 +3 +4 +5 +" && + + git branch L && + git branch R && + + git checkout L && + test_commit L content "1 +2 +3 +4 +5 +7" && + + git checkout R && + git rm content && + test_commit R renamed "1 +2 +3 +4 +5 +six" + ) +' + +test_expect_success 'check unique merge base' ' + ( + cd unique_merge_base && + + git checkout L^0 && + MASTER=$(git rev-parse --short master) && + + test_must_fail git -c merge.conflictstyle=diff3 merge -s recursive R^0 && + + grep "|||||| $MASTER:content" renamed + ) +' + +# Setup: +# L1---L2--L3 +# / \ / \ +# master X1 ? +# \ / \ / +# R1---R2--R3 +# +# Where: +# commits L1 and R1 have modified the same file in non-conflicting ways +# X1 is an auto-generated merge-base used when merging L1 and R1 +# commits L2 and R2 are merges of R1 and L1 into L1 and R1, respectively +# commits L3 and R3 both modify 'content' in conflicting ways +# + +test_expect_success 'setup multiple merge bases' ' + test_create_repo multiple_merge_bases && + ( + cd multiple_merge_bases && + + test_commit initial content "1 +2 +3 +4 +5" && + + git branch L && + git branch R && + + # Create L1 + git checkout L && + test_commit L1 content "0 +1 +2 +3 +4 +5" && + + # Create R1 + git checkout R && + test_commit R1 content "1 +2 +3 +4 +5 +6" && + + # Create L2 + git checkout L && + git merge R1 && + + # Create R2 + git checkout R && + git merge L1 && + + # Create L3 + git checkout L && + test_commit L3 content "0 +1 +2 +3 +4 +5 +A" && + + # Create R3 + git checkout R && + git rm content && + test_commit R3 renamed "0 +2 +3 +4 +5 +six" + ) +' + +test_expect_success 'check multiple merge bases' ' + ( + cd multiple_merge_bases && + + git checkout L^0 && + + test_must_fail git -c merge.conflictstyle=diff3 merge -s recursive R^0 && + + grep "|||||| merged common ancestors:content" renamed + ) +' + +test_expect_success 'rebase describes fake ancestor base' ' + test_create_repo rebase && + ( + cd rebase && + test_commit base file && + test_commit master file && + git checkout -b side HEAD^ && + test_commit side file && + test_must_fail git -c merge.conflictstyle=diff3 rebase master && + grep "||||||| constructed merge base" file + ) +' + +test_done diff --git a/t/t6102-rev-list-unexpected-objects.sh b/t/t6102-rev-list-unexpected-objects.sh index 28611c978e..52cde097dd 100755 --- a/t/t6102-rev-list-unexpected-objects.sh +++ b/t/t6102-rev-list-unexpected-objects.sh @@ -52,7 +52,7 @@ test_expect_success 'traverse unexpected non-commit parent (lone)' ' ' test_expect_success 'traverse unexpected non-commit parent (seen)' ' - test_must_fail git rev-list --objects $commit $broken_commit \ + test_must_fail git rev-list --objects $blob $broken_commit \ >output 2>&1 && test_i18ngrep "not a commit" output ' diff --git a/t/t6112-rev-list-filters-objects.sh b/t/t6112-rev-list-filters-objects.sh index acd7f5ab80..de0e5a5d36 100755 --- a/t/t6112-rev-list-filters-objects.sh +++ b/t/t6112-rev-list-filters-objects.sh @@ -278,7 +278,19 @@ test_expect_success 'verify skipping tree iteration when not collecting omits' ' test_line_count = 2 actual && # Make sure no other trees were considered besides the root. - ! grep "Skipping contents of tree [^.]" filter_trace + ! grep "Skipping contents of tree [^.]" filter_trace && + + # Try this again with "combine:". If both sub-filters are skipping + # trees, the composite filter should also skip trees. This is not + # important unless the user does combine:tree:X+tree:Y or another filter + # besides "tree:" is implemented in the future which can skip trees. + GIT_TRACE=1 git -C r3 rev-list \ + --objects --filter=combine:tree:1+tree:3 HEAD 2>filter_trace && + + # Only skip the dir1/ tree, which is shared between the two commits. + grep "Skipping contents of tree " filter_trace >actual && + test_write_lines "Skipping contents of tree dir1/..." >expected && + test_cmp expected actual ' # Test tree:# filters. @@ -330,6 +342,148 @@ test_expect_success 'verify tree:3 includes everything expected' ' test_line_count = 10 actual ' +test_expect_success 'combine:... for a simple combination' ' + git -C r3 rev-list --objects --filter=combine:tree:2+blob:none HEAD \ + >actual && + + expect_has HEAD "" && + expect_has HEAD~1 "" && + expect_has HEAD dir1 && + + # There are also 2 commit objects + test_line_count = 5 actual && + + cp actual expected && + + # Try again using repeated --filter - this is equivalent to a manual + # combine with "combine:...+..." + git -C r3 rev-list --objects --filter=combine:tree:2 \ + --filter=blob:none HEAD >actual && + + test_cmp expected actual +' + +test_expect_success 'combine:... with URL encoding' ' + git -C r3 rev-list --objects \ + --filter=combine:tree%3a2+blob:%6Eon%65 HEAD >actual && + + expect_has HEAD "" && + expect_has HEAD~1 "" && + expect_has HEAD dir1 && + + # There are also 2 commit objects + test_line_count = 5 actual +' + +expect_invalid_filter_spec () { + spec="$1" && + err="$2" && + + test_must_fail git -C r3 rev-list --objects --filter="$spec" HEAD \ + >actual 2>actual_stderr && + test_must_be_empty actual && + test_i18ngrep "$err" actual_stderr +} + +test_expect_success 'combine:... while URL-encoding things that should not be' ' + expect_invalid_filter_spec combine%3Atree:2+blob:none \ + "invalid filter-spec" +' + +test_expect_success 'combine: with nothing after the :' ' + expect_invalid_filter_spec combine: "expected something after combine:" +' + +test_expect_success 'parse error in first sub-filter in combine:' ' + expect_invalid_filter_spec combine:tree:asdf+blob:none \ + "expected .tree:<depth>." +' + +test_expect_success 'combine:... with non-encoded reserved chars' ' + expect_invalid_filter_spec combine:tree:2+sparse:@xyz \ + "must escape char in sub-filter-spec: .@." && + expect_invalid_filter_spec combine:tree:2+sparse:\` \ + "must escape char in sub-filter-spec: .\`." && + expect_invalid_filter_spec combine:tree:2+sparse:~abc \ + "must escape char in sub-filter-spec: .\~." +' + +test_expect_success 'validate err msg for "combine:<valid-filter>+"' ' + expect_invalid_filter_spec combine:tree:2+ "expected .tree:<depth>." +' + +test_expect_success 'combine:... with edge-case hex digits: Ff Aa 0 9' ' + git -C r3 rev-list --objects --filter="combine:tree:2+bl%6Fb:n%6fne" \ + HEAD >actual && + test_line_count = 5 actual && + git -C r3 rev-list --objects --filter="combine:tree%3A2+blob%3anone" \ + HEAD >actual && + test_line_count = 5 actual && + git -C r3 rev-list --objects --filter="combine:tree:%30" HEAD >actual && + test_line_count = 2 actual && + git -C r3 rev-list --objects --filter="combine:tree:%39+blob:none" \ + HEAD >actual && + test_line_count = 5 actual +' + +test_expect_success 'add sparse pattern blobs whose paths have reserved chars' ' + cp r3/pattern r3/pattern1+renamed% && + cp r3/pattern "r3/p;at%ter+n" && + cp r3/pattern r3/^~pattern && + git -C r3 add pattern1+renamed% "p;at%ter+n" ^~pattern && + git -C r3 commit -m "add sparse pattern files with reserved chars" +' + +test_expect_success 'combine:... with more than two sub-filters' ' + git -C r3 rev-list --objects \ + --filter=combine:tree:3+blob:limit=40+sparse:oid=master:pattern \ + HEAD >actual && + + expect_has HEAD "" && + expect_has HEAD~1 "" && + expect_has HEAD~2 "" && + expect_has HEAD dir1 && + expect_has HEAD dir1/sparse1 && + expect_has HEAD dir1/sparse2 && + + # Should also have 3 commits + test_line_count = 9 actual && + + # Try again, this time making sure the last sub-filter is only + # URL-decoded once. + cp actual expect && + + git -C r3 rev-list --objects \ + --filter=combine:tree:3+blob:limit=40+sparse:oid=master:pattern1%2brenamed%25 \ + HEAD >actual && + test_cmp expect actual && + + # Use the same composite filter again, but with a pattern file name that + # requires encoding multiple characters, and use implicit filter + # combining. + test_when_finished "rm -f trace1" && + GIT_TRACE=$(pwd)/trace1 git -C r3 rev-list --objects \ + --filter=tree:3 --filter=blob:limit=40 \ + --filter=sparse:oid="master:p;at%ter+n" \ + HEAD >actual && + + test_cmp expect actual && + grep "Add to combine filter-spec: sparse:oid=master:p%3bat%25ter%2bn" \ + trace1 && + + # Repeat the above test, but this time, the characters to encode are in + # the LHS of the combined filter. + test_when_finished "rm -f trace2" && + GIT_TRACE=$(pwd)/trace2 git -C r3 rev-list --objects \ + --filter=sparse:oid=master:^~pattern \ + --filter=tree:3 --filter=blob:limit=40 \ + HEAD >actual && + + test_cmp expect actual && + grep "Add to combine filter-spec: sparse:oid=master:%5e%7epattern" \ + trace2 +' + # Test provisional omit collection logic with a repo that has objects appearing # at multiple depths - first deeper than the filter's threshold, then shallow. @@ -373,6 +527,37 @@ test_expect_success 'verify skipping tree iteration when collecting omits' ' test_cmp expect actual ' +test_expect_success 'setup r5' ' + git init r5 && + mkdir -p r5/subdir && + + echo 1 >r5/short-root && + echo 12345 >r5/long-root && + echo a >r5/subdir/short-subdir && + echo abcde >r5/subdir/long-subdir && + + git -C r5 add short-root long-root subdir && + git -C r5 commit -m "commit msg" +' + +test_expect_success 'verify collecting omits in combined: filter' ' + # Note that this test guards against the naive implementation of simply + # giving both filters the same "omits" set and expecting it to + # automatically merge them. + git -C r5 rev-list --objects --quiet --filter-print-omitted \ + --filter=combine:tree:2+blob:limit=3 HEAD >actual && + + # Expect 0 trees/commits, 3 blobs omitted (all blobs except short-root) + omitted_1=$(echo 12345 | git hash-object --stdin) && + omitted_2=$(echo a | git hash-object --stdin) && + omitted_3=$(echo abcde | git hash-object --stdin) && + + grep ~$omitted_1 actual && + grep ~$omitted_2 actual && + grep ~$omitted_3 actual && + test_line_count = 3 actual +' + # Test tree:<depth> where a tree is iterated to twice - once where a subentry is # too deep to be included, and again where the blob inside it is shallow enough # to be included. This makes sure we don't use LOFR_MARK_SEEN incorrectly (we @@ -441,11 +626,4 @@ test_expect_success 'expand blob limit in protocol' ' grep "blob:limit=1024" trace ' -test_expect_success 'expand tree depth limit in protocol' ' - GIT_TRACE_PACKET="$(pwd)/tree_trace" git -c protocol.version=2 clone \ - --filter=tree:0k "file://$(pwd)/r2" tree && - ! grep "tree:0k" tree_trace && - grep "tree:0" tree_trace -' - test_done diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh index 2b883d8174..45047d0a72 100755 --- a/t/t6120-describe.sh +++ b/t/t6120-describe.sh @@ -424,4 +424,19 @@ test_expect_success 'describe complains about missing object' ' test_must_fail git describe $ZERO_OID ' +test_expect_success 'name-rev a rev shortly after epoch' ' + test_when_finished "git checkout master" && + + git checkout --orphan no-timestamp-underflow && + # Any date closer to epoch than the CUTOFF_DATE_SLOP constant + # in builtin/name-rev.c. + GIT_COMMITTER_DATE="@1234 +0000" \ + git commit -m "committer date shortly after epoch" && + old_commit_oid=$(git rev-parse HEAD) && + + echo "$old_commit_oid no-timestamp-underflow" >expect && + git name-rev $old_commit_oid >actual && + test_cmp expect actual +' + test_done diff --git a/t/t6130-pathspec-noglob.sh b/t/t6130-pathspec-noglob.sh index 37760233a5..ba7902c9cd 100755 --- a/t/t6130-pathspec-noglob.sh +++ b/t/t6130-pathspec-noglob.sh @@ -10,6 +10,7 @@ test_expect_success 'create commits with glob characters' ' # the name "f*" in the worktree, because it is not allowed # on Windows (the tests below do not depend on the presence # of the file in the worktree) + git config core.protectNTFS false && git update-index --add --cacheinfo 100644 "$(git rev-parse HEAD:foo)" "f*" && test_tick && git commit -m star && diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh index 93f23cfa82..8a72b4c43a 100755 --- a/t/t6200-fmt-merge-msg.sh +++ b/t/t6200-fmt-merge-msg.sh @@ -66,12 +66,7 @@ test_expect_success setup ' git commit -a -m "Right #5" && git checkout -b long && - i=0 && - while test $i -lt 30 - do - test_commit $i one && - i=$(($i+1)) - done && + test_commit_bulk --start=0 --message=%s --filename=one 30 && git show-branch && diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index d9235217fc..9c910ce746 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -346,6 +346,32 @@ test_expect_success 'Verify descending sort' ' ' cat >expected <<\EOF +refs/tags/testtag +refs/tags/testtag-2 +EOF + +test_expect_success 'exercise patterns with prefixes' ' + git tag testtag-2 && + test_when_finished "git tag -d testtag-2" && + git for-each-ref --format="%(refname)" \ + refs/tags/testtag refs/tags/testtag-2 >actual && + test_cmp expected actual +' + +cat >expected <<\EOF +refs/tags/testtag +refs/tags/testtag-2 +EOF + +test_expect_success 'exercise glob patterns with prefixes' ' + git tag testtag-2 && + test_when_finished "git tag -d testtag-2" && + git for-each-ref --format="%(refname)" \ + refs/tags/testtag "refs/tags/testtag-*" >actual && + test_cmp expected actual +' + +cat >expected <<\EOF 'refs/heads/master' 'refs/remotes/origin/master' 'refs/tags/testtag' @@ -500,6 +526,25 @@ test_expect_success 'Check ambiguous head and tag refs II (loose)' ' test_cmp expected actual ' +test_expect_success 'create tag without tagger' ' + git tag -a -m "Broken tag" taggerless && + git tag -f taggerless $(git cat-file tag taggerless | + sed -e "/^tagger /d" | + git hash-object --stdin -w -t tag) +' + +test_atom refs/tags/taggerless type 'commit' +test_atom refs/tags/taggerless tag 'taggerless' +test_atom refs/tags/taggerless tagger '' +test_atom refs/tags/taggerless taggername '' +test_atom refs/tags/taggerless taggeremail '' +test_atom refs/tags/taggerless taggerdate '' +test_atom refs/tags/taggerless committer '' +test_atom refs/tags/taggerless committername '' +test_atom refs/tags/taggerless committeremail '' +test_atom refs/tags/taggerless committerdate '' +test_atom refs/tags/taggerless subject 'Broken tag' + test_expect_success 'an unusual tag with an incomplete line' ' git tag -m "bogo" bogo && diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh index fc067ed672..35408d53fd 100755 --- a/t/t6302-for-each-ref-filter.sh +++ b/t/t6302-for-each-ref-filter.sh @@ -441,4 +441,17 @@ test_expect_success '--merged is incompatible with --no-merged' ' test_must_fail git for-each-ref --merged HEAD --no-merged HEAD ' +test_expect_success 'validate worktree atom' ' + cat >expect <<-EOF && + master: $(pwd) + master_worktree: $(pwd)/worktree_dir + side: not checked out + EOF + git worktree add -b master_worktree worktree_dir master && + git for-each-ref --format="%(refname:short): %(if)%(worktreepath)%(then)%(worktreepath)%(else)not checked out%(end)" refs/heads/ >actual && + rm -r worktree_dir && + git worktree prune && + test_cmp expect actual +' + test_done diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh index c0f04dc6b0..0a69a67117 100755 --- a/t/t6500-gc.sh +++ b/t/t6500-gc.sh @@ -103,14 +103,14 @@ test_expect_success 'auto gc with too many loose objects does not attempt to cre ' test_expect_success 'gc --no-quiet' ' - git -c gc.writeCommitGraph=true gc --no-quiet >stdout 2>stderr && + GIT_PROGRESS_DELAY=0 git -c gc.writeCommitGraph=true gc --no-quiet >stdout 2>stderr && test_must_be_empty stdout && - test_line_count = 1 stderr && test_i18ngrep "Computing commit graph generation numbers" stderr ' test_expect_success TTY 'with TTY: gc --no-quiet' ' - test_terminal git -c gc.writeCommitGraph=true gc --no-quiet >stdout 2>stderr && + test_terminal env GIT_PROGRESS_DELAY=0 \ + git -c gc.writeCommitGraph=true gc --no-quiet >stdout 2>stderr && test_must_be_empty stdout && test_i18ngrep "Enumerating objects" stderr && test_i18ngrep "Computing commit graph generation numbers" stderr diff --git a/t/t6501-freshen-objects.sh b/t/t6501-freshen-objects.sh index 033871ee5f..f30b4849b6 100755 --- a/t/t6501-freshen-objects.sh +++ b/t/t6501-freshen-objects.sh @@ -137,7 +137,7 @@ test_expect_success 'do not complain about existing broken links (commit)' ' some message EOF commit=$(git hash-object -t commit -w broken-commit) && - git gc 2>stderr && + git gc -q 2>stderr && verbose git cat-file -e $commit && test_must_be_empty stderr ' @@ -147,7 +147,7 @@ test_expect_success 'do not complain about existing broken links (tree)' ' 100644 blob 0000000000000000000000000000000000000003 foo EOF tree=$(git mktree --missing <broken-tree) && - git gc 2>stderr && + git gc -q 2>stderr && git cat-file -e $tree && test_must_be_empty stderr ' @@ -162,7 +162,7 @@ test_expect_success 'do not complain about existing broken links (tag)' ' this is a broken tag EOF tag=$(git hash-object -t tag -w broken-tag) && - git gc 2>stderr && + git gc -q 2>stderr && git cat-file -e $tag && test_must_be_empty stderr ' diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index 6aeeb279a0..4a09bea1d6 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -227,10 +227,10 @@ test_expect_success \ test_expect_success \ 'trying to delete two tags, existing and not, should fail in the 2nd' ' tag_exists mytag && - ! tag_exists myhead && - test_must_fail git tag -d mytag anothertag && + ! tag_exists nonexistingtag && + test_must_fail git tag -d mytag nonexistingtag && ! tag_exists mytag && - ! tag_exists myhead + ! tag_exists nonexistingtag ' test_expect_success 'trying to delete an already deleted tag should fail' \ @@ -932,6 +932,27 @@ test_expect_success GPG \ test_cmp expect actual ' +get_tag_header gpgsign-enabled $commit commit $time >expect +echo "A message" >>expect +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG \ + 'git tag configured tag.gpgsign enables GPG sign' \ + 'test_config tag.gpgsign true && + git tag -m "A message" gpgsign-enabled && + get_tag_msg gpgsign-enabled>actual && + test_cmp expect actual +' + +get_tag_header no-sign $commit commit $time >expect +echo "A message" >>expect +test_expect_success GPG \ + 'git tag --no-sign configured tag.gpgsign skip GPG sign' \ + 'test_config tag.gpgsign true && + git tag -a --no-sign -m "A message" no-sign && + get_tag_msg no-sign>actual && + test_cmp expect actual +' + test_expect_success GPG \ 'trying to create a signed tag with non-existing -F file should fail' ' ! test -f nonexistingfile && @@ -1399,7 +1420,7 @@ test_expect_success \ get_tag_header reuse $commit commit $time >expect echo "An annotation to be reused" >> expect test_expect_success \ - 'overwriting an annoted tag should use its previous body' ' + 'overwriting an annotated tag should use its previous body' ' git tag -a -m "An annotation to be reused" reuse && GIT_EDITOR=true git tag -f -a reuse && get_tag_msg reuse >actual && diff --git a/t/t7009-filter-branch-null-sha1.sh b/t/t7008-filter-branch-null-sha1.sh index 9ba9f24ad2..9ba9f24ad2 100755 --- a/t/t7009-filter-branch-null-sha1.sh +++ b/t/t7008-filter-branch-null-sha1.sh diff --git a/t/t7012-skip-worktree-writing.sh b/t/t7012-skip-worktree-writing.sh index 9d1abe50ef..7476781979 100755 --- a/t/t7012-skip-worktree-writing.sh +++ b/t/t7012-skip-worktree-writing.sh @@ -134,6 +134,21 @@ test_expect_success 'git-clean, dirty case' ' test_i18ncmp expected result ' +test_expect_success '--ignore-skip-worktree-entries leaves worktree alone' ' + test_commit keep-me && + git update-index --skip-worktree keep-me.t && + rm keep-me.t && + + : ignoring the worktree && + git update-index --remove --ignore-skip-worktree-entries keep-me.t && + git diff-index --cached --exit-code HEAD && + + : not ignoring the worktree, a deletion is staged && + git update-index --remove keep-me.t && + test_must_fail git diff-index --cached --exit-code HEAD \ + --diff-filter=D -- keep-me.t +' + #TODO test_expect_failure 'git-apply adds file' false #TODO test_expect_failure 'git-apply updates file' false #TODO test_expect_failure 'git-apply removes file' false diff --git a/t/t7030-verify-tag.sh b/t/t7030-verify-tag.sh index 041e319e79..8f077bea60 100755 --- a/t/t7030-verify-tag.sh +++ b/t/t7030-verify-tag.sh @@ -44,8 +44,8 @@ test_expect_success GPG 'create signed tags' ' test_expect_success GPGSM 'create signed tags x509 ' ' test_config gpg.format x509 && test_config user.signingkey $GIT_COMMITTER_EMAIL && - echo 9 >file && test_tick && git commit -a -m "nineth gpgsm-signed" && - git tag -s -m nineth nineth-signed-x509 + echo 9 >file && test_tick && git commit -a -m "ninth gpgsm-signed" && + git tag -s -m ninth ninth-signed-x509 ' test_expect_success GPG 'verify and show signatures' ' @@ -80,10 +80,10 @@ test_expect_success GPG 'verify and show signatures' ' ' test_expect_success GPGSM 'verify and show signatures x509' ' - git verify-tag nineth-signed-x509 2>actual && + git verify-tag ninth-signed-x509 2>actual && grep "Good signature from" actual && ! grep "BAD signature from" actual && - echo nineth-signed-x509 OK + echo ninth-signed-x509 OK ' test_expect_success GPG 'detect fudged signature' ' @@ -127,10 +127,10 @@ test_expect_success GPG 'verify signatures with --raw' ' ' test_expect_success GPGSM 'verify signatures with --raw x509' ' - git verify-tag --raw nineth-signed-x509 2>actual && + git verify-tag --raw ninth-signed-x509 2>actual && grep "GOODSIG" actual && ! grep "BADSIG" actual && - echo nineth-signed-x509 OK + echo ninth-signed-x509 OK ' test_expect_success GPG 'verify multiple tags' ' @@ -147,7 +147,7 @@ test_expect_success GPG 'verify multiple tags' ' ' test_expect_success GPGSM 'verify multiple tags x509' ' - tags="seventh-signed nineth-signed-x509" && + tags="seventh-signed ninth-signed-x509" && for i in $tags do git verify-tag -v --raw $i || return 1 diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh index 53cf42fac1..d5218743e9 100755 --- a/t/t7060-wtstatus.sh +++ b/t/t7060-wtstatus.sh @@ -38,7 +38,6 @@ You have unmerged paths. Unmerged paths: (use "git add/rm <file>..." as appropriate to mark resolution) - deleted by us: foo no changes added to commit (use "git add" and/or "git commit -a") @@ -143,7 +142,6 @@ You have unmerged paths. Unmerged paths: (use "git add/rm <file>..." as appropriate to mark resolution) - both added: conflict.txt deleted by them: main.txt @@ -177,7 +175,6 @@ You have unmerged paths. Unmerged paths: (use "git add/rm <file>..." as appropriate to mark resolution) - both deleted: main.txt added by them: sub_master.txt added by us: sub_second.txt @@ -201,12 +198,10 @@ You have unmerged paths. (use "git merge --abort" to abort the merge) Changes to be committed: - new file: sub_master.txt Unmerged paths: (use "git rm <file>..." to mark resolution) - both deleted: main.txt Untracked files not listed (use -u option to show untracked files) diff --git a/t/t7064-wtstatus-pv2.sh b/t/t7064-wtstatus-pv2.sh index 11eccc231a..537787e598 100755 --- a/t/t7064-wtstatus-pv2.sh +++ b/t/t7064-wtstatus-pv2.sh @@ -445,6 +445,14 @@ test_expect_success 'verify --[no-]ahead-behind with V2 format' ' EOF git status --ahead-behind --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual && + + # Confirm that "status.aheadbehind" DOES NOT work on V2 format. + git -c status.aheadbehind=false status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual && + + # Confirm that "status.aheadbehind" DOES NOT work on V2 format. + git -c status.aheadbehind=true status --porcelain=v2 --branch --untracked-files=all >actual && test_cmp expect actual ) ' diff --git a/t/t7105-reset-patch.sh b/t/t7105-reset-patch.sh index bd10a96727..fc2a6cf5c7 100755 --- a/t/t7105-reset-patch.sh +++ b/t/t7105-reset-patch.sh @@ -38,6 +38,27 @@ test_expect_success PERL 'git reset -p HEAD^' ' test_i18ngrep "Apply" output ' +test_expect_success PERL 'git reset -p HEAD^^{tree}' ' + test_write_lines n y | git reset -p HEAD^^{tree} >output && + verify_state dir/foo work parent && + verify_saved_state bar && + test_i18ngrep "Apply" output +' + +test_expect_success PERL 'git reset -p HEAD^:dir/foo (blob fails)' ' + set_and_save_state dir/foo work work && + test_must_fail git reset -p HEAD^:dir/foo && + verify_saved_state dir/foo && + verify_saved_state bar +' + +test_expect_success PERL 'git reset -p aaaaaaaa (unknown fails)' ' + set_and_save_state dir/foo work work && + test_must_fail git reset -p aaaaaaaa && + verify_saved_state dir/foo && + verify_saved_state bar +' + # The idea in the rest is that bar sorts first, so we always say 'y' # first and if the path limiter fails it'll apply to bar instead of # dir/foo. There's always an extra 'n' to reject edits to dir/foo in diff --git a/t/t7107-reset-pathspec-file.sh b/t/t7107-reset-pathspec-file.sh new file mode 100755 index 0000000000..6b1a731fff --- /dev/null +++ b/t/t7107-reset-pathspec-file.sh @@ -0,0 +1,155 @@ +#!/bin/sh + +test_description='reset --pathspec-from-file' + +. ./test-lib.sh + +test_tick + +test_expect_success setup ' + echo A >fileA.t && + echo B >fileB.t && + echo C >fileC.t && + echo D >fileD.t && + git add . && + git commit --include . -m "Commit" && + git tag checkpoint +' + +restore_checkpoint () { + git reset --hard checkpoint +} + +verify_expect () { + git status --porcelain -- fileA.t fileB.t fileC.t fileD.t >actual && + test_cmp expect actual +} + +test_expect_success '--pathspec-from-file from stdin' ' + restore_checkpoint && + + git rm fileA.t && + echo fileA.t | git reset --pathspec-from-file=- && + + cat >expect <<-\EOF && + D fileA.t + EOF + verify_expect +' + +test_expect_success '--pathspec-from-file from file' ' + restore_checkpoint && + + git rm fileA.t && + echo fileA.t >list && + git reset --pathspec-from-file=list && + + cat >expect <<-\EOF && + D fileA.t + EOF + verify_expect +' + +test_expect_success 'NUL delimiters' ' + restore_checkpoint && + + git rm fileA.t fileB.t && + printf "fileA.t\0fileB.t\0" | git reset --pathspec-from-file=- --pathspec-file-nul && + + cat >expect <<-\EOF && + D fileA.t + D fileB.t + EOF + verify_expect +' + +test_expect_success 'LF delimiters' ' + restore_checkpoint && + + git rm fileA.t fileB.t && + printf "fileA.t\nfileB.t\n" | git reset --pathspec-from-file=- && + + cat >expect <<-\EOF && + D fileA.t + D fileB.t + EOF + verify_expect +' + +test_expect_success 'no trailing delimiter' ' + restore_checkpoint && + + git rm fileA.t fileB.t && + printf "fileA.t\nfileB.t" | git reset --pathspec-from-file=- && + + cat >expect <<-\EOF && + D fileA.t + D fileB.t + EOF + verify_expect +' + +test_expect_success 'CRLF delimiters' ' + restore_checkpoint && + + git rm fileA.t fileB.t && + printf "fileA.t\r\nfileB.t\r\n" | git reset --pathspec-from-file=- && + + cat >expect <<-\EOF && + D fileA.t + D fileB.t + EOF + verify_expect +' + +test_expect_success 'quotes' ' + restore_checkpoint && + + git rm fileA.t && + printf "\"file\\101.t\"" | git reset --pathspec-from-file=- && + + cat >expect <<-\EOF && + D fileA.t + EOF + verify_expect +' + +test_expect_success 'quotes not compatible with --pathspec-file-nul' ' + restore_checkpoint && + + git rm fileA.t && + printf "\"file\\101.t\"" >list && + # Note: "git reset" has not yet learned to fail on wrong pathspecs + git reset --pathspec-from-file=list --pathspec-file-nul && + + cat >expect <<-\EOF && + D fileA.t + EOF + test_must_fail verify_expect +' + +test_expect_success '--pathspec-from-file is not compatible with --soft or --hard' ' + restore_checkpoint && + + git rm fileA.t && + echo fileA.t >list && + test_must_fail git reset --soft --pathspec-from-file=list && + test_must_fail git reset --hard --pathspec-from-file=list +' + +test_expect_success 'only touches what was listed' ' + restore_checkpoint && + + git rm fileA.t fileB.t fileC.t fileD.t && + printf "fileB.t\nfileC.t\n" | git reset --pathspec-from-file=- && + + cat >expect <<-\EOF && + D fileA.t + D fileB.t + D fileC.t + D fileD.t + EOF + verify_expect +' + +test_done diff --git a/t/t7201-co.sh b/t/t7201-co.sh index 5990299fc9..b696bae5f5 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -249,7 +249,7 @@ 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_TEST_GETTEXT_POISON= git checkout renamer^ 2>messages && + GIT_TEST_GETTEXT_POISON=false git checkout renamer^ 2>messages && grep "HEAD is now at 7329388" messages && test_line_count -gt 1 messages && H=$(git rev-parse --verify HEAD) && diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh index a2c45d1902..6e6d24c1c3 100755 --- a/t/t7300-clean.sh +++ b/t/t7300-clean.sh @@ -117,6 +117,7 @@ test_expect_success C_LOCALE_OUTPUT 'git clean with relative prefix' ' would_clean=$( cd docs && git clean -n ../src | + grep part3 | sed -n -e "s|^Would remove ||p" ) && verbose test "$would_clean" = ../src/part3.c @@ -129,6 +130,7 @@ test_expect_success C_LOCALE_OUTPUT 'git clean with absolute path' ' would_clean=$( cd docs && git clean -n "$(pwd)/../src" | + grep part3 | sed -n -e "s|^Would remove ||p" ) && verbose test "$would_clean" = ../src/part3.c @@ -547,7 +549,7 @@ test_expect_failure 'nested (non-empty) bare repositories should be cleaned even test_path_is_missing strange_bare ' -test_expect_success 'giving path in nested git work tree will remove it' ' +test_expect_success 'giving path in nested git work tree will NOT remove it' ' rm -fr repo && mkdir repo && ( @@ -559,7 +561,7 @@ test_expect_success 'giving path in nested git work tree will remove it' ' git clean -f -d repo/bar/baz && test_path_is_file repo/.git/HEAD && test_path_is_dir repo/bar/ && - test_path_is_missing repo/bar/baz + test_path_is_file repo/bar/baz/hello.world ' test_expect_success 'giving path to nested .git will not remove it' ' @@ -577,7 +579,7 @@ test_expect_success 'giving path to nested .git will not remove it' ' test_path_is_dir untracked/ ' -test_expect_success 'giving path to nested .git/ will remove contents' ' +test_expect_success 'giving path to nested .git/ will NOT remove contents' ' rm -fr repo untracked && mkdir repo untracked && ( @@ -587,7 +589,7 @@ test_expect_success 'giving path to nested .git/ will remove contents' ' ) && git clean -f -d repo/.git/ && test_path_is_dir repo/.git && - test_dir_is_empty repo/.git && + test_path_is_file repo/.git/HEAD && test_path_is_dir untracked/ ' @@ -669,6 +671,60 @@ test_expect_success 'git clean -d skips untracked dirs containing ignored files' test_path_is_missing foo/b/bb ' +test_expect_success 'git clean -d skips nested repo containing ignored files' ' + test_when_finished "rm -rf nested-repo-with-ignored-file" && + + git init nested-repo-with-ignored-file && + ( + cd nested-repo-with-ignored-file && + >file && + git add file && + git commit -m Initial && + + # This file is ignored by a .gitignore rule in the outer repo + # added in the previous test. + >ignoreme + ) && + + git clean -fd && + + test_path_is_file nested-repo-with-ignored-file/.git/index && + test_path_is_file nested-repo-with-ignored-file/ignoreme && + test_path_is_file nested-repo-with-ignored-file/file +' + +test_expect_success 'git clean handles being told what to clean' ' + mkdir -p d1 d2 && + touch d1/ut d2/ut && + git clean -f */ut && + test_path_is_missing d1/ut && + test_path_is_missing d2/ut +' + +test_expect_success 'git clean handles being told what to clean, with -d' ' + mkdir -p d1 d2 && + touch d1/ut d2/ut && + git clean -ffd */ut && + test_path_is_missing d1/ut && + test_path_is_missing d2/ut +' + +test_expect_success 'git clean works if a glob is passed without -d' ' + mkdir -p d1 d2 && + touch d1/ut d2/ut && + git clean -f "*ut" && + test_path_is_missing d1/ut && + test_path_is_missing d2/ut +' + +test_expect_success 'git clean works if a glob is passed with -d' ' + mkdir -p d1 d2 && + touch d1/ut d2/ut && + git clean -ffd "*ut" && + test_path_is_missing d1/ut && + test_path_is_missing d2/ut +' + test_expect_success MINGW 'handle clean & core.longpaths = false nicely' ' test_config core.longpaths false && a50=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa && diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index a208cb26e1..7f75bb1be6 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -356,6 +356,28 @@ test_expect_success 'status should only print one line' ' test_line_count = 1 lines ' +test_expect_success 'status from subdirectory should have the same SHA1' ' + test_when_finished "rmdir addtest/subdir" && + ( + cd addtest && + mkdir subdir && + git submodule status >output && + awk "{print \$1}" <output >expect && + cd subdir && + git submodule status >../output && + awk "{print \$1}" <../output >../actual && + test_cmp ../expect ../actual && + git -C ../submod checkout HEAD^ && + git submodule status >../output && + awk "{print \$1}" <../output >../actual2 && + cd .. && + git submodule status >output && + awk "{print \$1}" <output >expect2 && + test_cmp expect2 actual2 && + ! test_cmp actual actual2 + ) +' + test_expect_success 'setup - fetch commit name from submodule' ' rev1=$(cd .subrepo && git rev-parse HEAD) && printf "rev1: %s\n" "$rev1" && @@ -527,7 +549,6 @@ test_expect_success 'update --init' ' test_must_fail git config submodule.example.url && git submodule update init 2> update.out && - cat update.out && test_i18ngrep "not initialized" update.out && test_must_fail git rev-parse --resolve-git-dir init/.git && @@ -545,7 +566,6 @@ test_expect_success 'update --init from subdirectory' ' ( cd sub && git submodule update ../init 2>update.out && - cat update.out && test_i18ngrep "not initialized" update.out && test_must_fail git rev-parse --resolve-git-dir ../init/.git && diff --git a/t/t7405-submodule-merge.sh b/t/t7405-submodule-merge.sh index 7855bd8648..aa33978ed2 100755 --- a/t/t7405-submodule-merge.sh +++ b/t/t7405-submodule-merge.sh @@ -417,7 +417,7 @@ test_expect_failure 'directory/submodule conflict; keep submodule clean' ' ) ' -test_expect_failure 'directory/submodule conflict; should not treat submodule files as untracked or in the way' ' +test_expect_failure !FAIL_PREREQS 'directory/submodule conflict; should not treat submodule files as untracked or in the way' ' test_when_finished "git -C directory-submodule/path reset --hard" && test_when_finished "git -C directory-submodule reset --hard" && ( diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index c973278300..7478f7ab7e 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -158,7 +158,6 @@ test_expect_success 'submodule update --init from and of subdirectory' ' test_i18ncmp expect2 actual2 ' -apos="'"; test_expect_success 'submodule update does not fetch already present commits' ' (cd submodule && echo line3 >> file && @@ -168,7 +167,7 @@ test_expect_success 'submodule update does not fetch already present commits' ' ) && (cd super/submodule && head=$(git rev-parse --verify HEAD) && - echo "Submodule path ${apos}submodule$apos: checked out $apos$head$apos" > ../../expected && + echo "Submodule path ${SQ}submodule$SQ: checked out $SQ$head$SQ" > ../../expected && git reset --hard HEAD~1 ) && (cd super && @@ -407,12 +406,26 @@ test_expect_success 'submodule update - command in .git/config' ' ) ' -test_expect_success 'submodule update - command in .gitmodules is ignored' ' +test_expect_success 'submodule update - command in .gitmodules is rejected' ' test_when_finished "git -C super reset --hard HEAD^" && git -C super config -f .gitmodules submodule.submodule.update "!false" && git -C super commit -a -m "add command to .gitmodules file" && git -C super/submodule reset --hard $submodulesha1^ && - git -C super submodule update submodule + test_must_fail git -C super submodule update submodule +' + +test_expect_success 'fsck detects command in .gitmodules' ' + git init command-in-gitmodules && + ( + cd command-in-gitmodules && + git submodule add ../submodule submodule && + test_commit adding-submodule && + + git config -f .gitmodules submodule.submodule.update "!false" && + git add .gitmodules && + test_commit configuring-update && + test_must_fail git fsck + ) ' cat << EOF >expect @@ -481,6 +494,9 @@ test_expect_success 'recursive submodule update - command in .git/config catches ' test_expect_success 'submodule init does not copy command into .git/config' ' + test_when_finished "git -C super update-index --force-remove submodule1" && + test_when_finished git config -f super/.gitmodules \ + --remove-section submodule.submodule1 && (cd super && git ls-files -s submodule >out && H=$(cut -d" " -f2 out) && @@ -489,10 +505,9 @@ test_expect_success 'submodule init does not copy command into .git/config' ' git config -f .gitmodules submodule.submodule1.path submodule1 && git config -f .gitmodules submodule.submodule1.url ../submodule && git config -f .gitmodules submodule.submodule1.update !false && - git submodule init submodule1 && - echo "none" >expect && - git config submodule.submodule1.update >actual && - test_cmp expect actual + test_must_fail git submodule init submodule1 && + test_expect_code 1 git config submodule.submodule1.update >actual && + test_must_be_empty actual ) ' diff --git a/t/t7415-submodule-names.sh b/t/t7415-submodule-names.sh index 49a37efe9c..905a557585 100755 --- a/t/t7415-submodule-names.sh +++ b/t/t7415-submodule-names.sh @@ -191,4 +191,60 @@ test_expect_success 'fsck detects corrupt .gitmodules' ' ) ' +test_expect_success MINGW 'prevent git~1 squatting on Windows' ' + git init squatting && + ( + cd squatting && + mkdir a && + touch a/..git && + git add a/..git && + test_tick && + git commit -m initial && + + modules="$(test_write_lines \ + "[submodule \"b.\"]" "url = ." "path = c" \ + "[submodule \"b\"]" "url = ." "path = d\\\\a" | + git hash-object -w --stdin)" && + rev="$(git rev-parse --verify HEAD)" && + hash="$(echo x | git hash-object -w --stdin)" && + git -c core.protectNTFS=false update-index --add \ + --cacheinfo 100644,$modules,.gitmodules \ + --cacheinfo 160000,$rev,c \ + --cacheinfo 160000,$rev,d\\a \ + --cacheinfo 100644,$hash,d./a/x \ + --cacheinfo 100644,$hash,d./a/..git && + test_tick && + git -c core.protectNTFS=false commit -m "module" && + test_must_fail git show HEAD: 2>err && + test_i18ngrep backslash err + ) && + test_must_fail git -c core.protectNTFS=false \ + clone --recurse-submodules squatting squatting-clone 2>err && + test_i18ngrep -e "directory not empty" -e "not an empty directory" err && + ! grep gitdir squatting-clone/d/a/git~2 +' + +test_expect_success 'git dirs of sibling submodules must not be nested' ' + git init nested && + test_commit -C nested nested && + ( + cd nested && + cat >.gitmodules <<-EOF && + [submodule "hippo"] + url = . + path = thing1 + [submodule "hippo/hooks"] + url = . + path = thing2 + EOF + git clone . thing1 && + git clone . thing2 && + git add .gitmodules thing1 thing2 && + test_tick && + git commit -m nested + ) && + test_must_fail git clone --recurse-submodules nested clone 2>err && + test_i18ngrep "is inside git dir" err +' + test_done diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh index 1cd2c1c1ea..5ba041f537 100755 --- a/t/t7416-submodule-dash-url.sh +++ b/t/t7416-submodule-dash-url.sh @@ -46,4 +46,18 @@ test_expect_success 'fsck rejects unprotected dash' ' grep gitmodulesUrl err ' +test_expect_success 'trailing backslash is handled correctly' ' + git init testmodule && + test_commit -C testmodule c && + git submodule add ./testmodule && + : ensure that the name ends in a double backslash && + sed -e "s|\\(submodule \"testmodule\\)\"|\\1\\\\\\\\\"|" \ + -e "s|url = .*|url = \" --should-not-be-an-option\"|" \ + <.gitmodules >.new && + mv .new .gitmodules && + git commit -am "Add testmodule" && + test_must_fail git clone --verbose --recurse-submodules . dolly 2>err && + test_i18ngrep ! "unknown option" err +' + test_done diff --git a/t/t7417-submodule-path-url.sh b/t/t7417-submodule-path-url.sh index 756af8c4d6..f7e7e94d7b 100755 --- a/t/t7417-submodule-path-url.sh +++ b/t/t7417-submodule-path-url.sh @@ -25,4 +25,21 @@ test_expect_success 'fsck rejects unprotected dash' ' grep gitmodulesPath err ' +test_expect_success MINGW 'submodule paths disallows trailing spaces' ' + git init super && + test_must_fail git -C super submodule add ../upstream "sub " && + + : add "sub", then rename "sub" to "sub ", the hard way && + git -C super submodule add ../upstream sub && + tree=$(git -C super write-tree) && + git -C super ls-tree $tree >tree && + sed "s/sub/sub /" <tree >tree.new && + tree=$(git -C super mktree <tree.new) && + commit=$(echo with space | git -C super commit-tree $tree) && + git -C super update-ref refs/heads/master $commit && + + test_must_fail git clone --recurse-submodules super dst 2>err && + test_i18ngrep "sub " err +' + test_done diff --git a/t/t7419-submodule-set-branch.sh b/t/t7419-submodule-set-branch.sh index c4b370ea85..fd25f786a3 100755 --- a/t/t7419-submodule-set-branch.sh +++ b/t/t7419-submodule-set-branch.sh @@ -34,7 +34,7 @@ test_expect_success 'submodule config cache setup' ' test_expect_success 'ensure submodule branch is unset' ' (cd super && - test_must_fail grep branch .gitmodules + ! grep branch .gitmodules ) ' @@ -54,7 +54,7 @@ test_expect_success 'test submodule set-branch --branch' ' test_expect_success 'test submodule set-branch --default' ' (cd super && git submodule set-branch --default submodule && - test_must_fail grep branch .gitmodules && + ! grep branch .gitmodules && git submodule update --remote && cat <<-\EOF >expect && a @@ -80,7 +80,7 @@ test_expect_success 'test submodule set-branch -b' ' test_expect_success 'test submodule set-branch -d' ' (cd super && git submodule set-branch -d submodule && - test_must_fail grep branch .gitmodules && + ! grep branch .gitmodules && git submodule update --remote && cat <<-\EOF >expect && a diff --git a/t/t7420-submodule-set-url.sh b/t/t7420-submodule-set-url.sh new file mode 100755 index 0000000000..ef0cb6e8e1 --- /dev/null +++ b/t/t7420-submodule-set-url.sh @@ -0,0 +1,55 @@ +#!/bin/sh +# +# Copyright (c) 2019 Denton Liu +# + +test_description='Test submodules set-url subcommand + +This test verifies that the set-url subcommand of git-submodule is working +as expected. +' + +TEST_NO_CREATE_REPO=1 +. ./test-lib.sh + +test_expect_success 'submodule config cache setup' ' + mkdir submodule && + ( + cd submodule && + git init && + echo a >file && + git add file && + git commit -ma + ) && + mkdir super && + ( + cd super && + git init && + git submodule add ../submodule && + git commit -m "add submodule" + ) +' + +test_expect_success 'test submodule set-url' ' + # add a commit and move the submodule (change the url) + ( + cd submodule && + echo b >>file && + git add file && + git commit -mb + ) && + mv submodule newsubmodule && + + git -C newsubmodule show >expect && + ( + cd super && + test_must_fail git submodule update --remote && + git submodule set-url submodule ../newsubmodule && + grep -F "url = ../newsubmodule" .gitmodules && + git submodule update --remote + ) && + git -C super/submodule show >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh index 5733d9cd34..14c92e4c25 100755 --- a/t/t7502-commit-porcelain.sh +++ b/t/t7502-commit-porcelain.sh @@ -402,7 +402,7 @@ echo editor started >"$(pwd)/.git/result" exit 0 EOF -test_expect_success !AUTOIDENT 'do not fire editor when committer is bogus' ' +test_expect_success !FAIL_PREREQS,!AUTOIDENT 'do not fire editor when committer is bogus' ' >.git/result && echo >>negative && diff --git a/t/t7503-pre-commit-and-pre-merge-commit-hooks.sh b/t/t7503-pre-commit-and-pre-merge-commit-hooks.sh new file mode 100755 index 0000000000..b3485450a2 --- /dev/null +++ b/t/t7503-pre-commit-and-pre-merge-commit-hooks.sh @@ -0,0 +1,281 @@ +#!/bin/sh + +test_description='pre-commit and pre-merge-commit hooks' + +. ./test-lib.sh + +HOOKDIR="$(git rev-parse --git-dir)/hooks" +PRECOMMIT="$HOOKDIR/pre-commit" +PREMERGE="$HOOKDIR/pre-merge-commit" + +# Prepare sample scripts that write their $0 to actual_hooks +test_expect_success 'sample script setup' ' + mkdir -p "$HOOKDIR" && + write_script "$HOOKDIR/success.sample" <<-\EOF && + echo $0 >>actual_hooks + exit 0 + EOF + write_script "$HOOKDIR/fail.sample" <<-\EOF && + echo $0 >>actual_hooks + exit 1 + EOF + write_script "$HOOKDIR/non-exec.sample" <<-\EOF && + echo $0 >>actual_hooks + exit 1 + EOF + chmod -x "$HOOKDIR/non-exec.sample" && + write_script "$HOOKDIR/require-prefix.sample" <<-\EOF && + echo $0 >>actual_hooks + test $GIT_PREFIX = "success/" + EOF + write_script "$HOOKDIR/check-author.sample" <<-\EOF + echo $0 >>actual_hooks + test "$GIT_AUTHOR_NAME" = "New Author" && + test "$GIT_AUTHOR_EMAIL" = "newauthor@example.com" + EOF +' + +test_expect_success 'root commit' ' + echo "root" >file && + git add file && + git commit -m "zeroth" && + git checkout -b side && + echo "foo" >foo && + git add foo && + git commit -m "make it non-ff" && + git branch side-orig side && + git checkout master +' + +test_expect_success 'setup conflicting branches' ' + test_when_finished "git checkout master" && + git checkout -b conflicting-a master && + echo a >conflicting && + git add conflicting && + git commit -m conflicting-a && + git checkout -b conflicting-b master && + echo b >conflicting && + git add conflicting && + git commit -m conflicting-b +' + +test_expect_success 'with no hook' ' + test_when_finished "rm -f actual_hooks" && + echo "foo" >file && + git add file && + git commit -m "first" && + test_path_is_missing actual_hooks +' + +test_expect_success 'with no hook (merge)' ' + test_when_finished "rm -f actual_hooks" && + git branch -f side side-orig && + git checkout side && + git merge -m "merge master" master && + git checkout master && + test_path_is_missing actual_hooks +' + +test_expect_success '--no-verify with no hook' ' + test_when_finished "rm -f actual_hooks" && + echo "bar" >file && + git add file && + git commit --no-verify -m "bar" && + test_path_is_missing actual_hooks +' + +test_expect_success '--no-verify with no hook (merge)' ' + test_when_finished "rm -f actual_hooks" && + git branch -f side side-orig && + git checkout side && + git merge --no-verify -m "merge master" master && + git checkout master && + test_path_is_missing actual_hooks +' + +test_expect_success 'with succeeding hook' ' + test_when_finished "rm -f \"$PRECOMMIT\" expected_hooks actual_hooks" && + cp "$HOOKDIR/success.sample" "$PRECOMMIT" && + echo "$PRECOMMIT" >expected_hooks && + echo "more" >>file && + git add file && + git commit -m "more" && + test_cmp expected_hooks actual_hooks +' + +test_expect_success 'with succeeding hook (merge)' ' + test_when_finished "rm -f \"$PREMERGE\" expected_hooks actual_hooks" && + cp "$HOOKDIR/success.sample" "$PREMERGE" && + echo "$PREMERGE" >expected_hooks && + git checkout side && + git merge -m "merge master" master && + git checkout master && + test_cmp expected_hooks actual_hooks +' + +test_expect_success 'automatic merge fails; both hooks are available' ' + test_when_finished "rm -f \"$PREMERGE\" \"$PRECOMMIT\"" && + test_when_finished "rm -f expected_hooks actual_hooks" && + test_when_finished "git checkout master" && + cp "$HOOKDIR/success.sample" "$PREMERGE" && + cp "$HOOKDIR/success.sample" "$PRECOMMIT" && + + git checkout conflicting-a && + test_must_fail git merge -m "merge conflicting-b" conflicting-b && + test_path_is_missing actual_hooks && + + echo "$PRECOMMIT" >expected_hooks && + echo a+b >conflicting && + git add conflicting && + git commit -m "resolve conflict" && + test_cmp expected_hooks actual_hooks +' + +test_expect_success '--no-verify with succeeding hook' ' + test_when_finished "rm -f \"$PRECOMMIT\" actual_hooks" && + cp "$HOOKDIR/success.sample" "$PRECOMMIT" && + echo "even more" >>file && + git add file && + git commit --no-verify -m "even more" && + test_path_is_missing actual_hooks +' + +test_expect_success '--no-verify with succeeding hook (merge)' ' + test_when_finished "rm -f \"$PREMERGE\" actual_hooks" && + cp "$HOOKDIR/success.sample" "$PREMERGE" && + git branch -f side side-orig && + git checkout side && + git merge --no-verify -m "merge master" master && + git checkout master && + test_path_is_missing actual_hooks +' + +test_expect_success 'with failing hook' ' + test_when_finished "rm -f \"$PRECOMMIT\" expected_hooks actual_hooks" && + cp "$HOOKDIR/fail.sample" "$PRECOMMIT" && + echo "$PRECOMMIT" >expected_hooks && + echo "another" >>file && + git add file && + test_must_fail git commit -m "another" && + test_cmp expected_hooks actual_hooks +' + +test_expect_success '--no-verify with failing hook' ' + test_when_finished "rm -f \"$PRECOMMIT\" actual_hooks" && + cp "$HOOKDIR/fail.sample" "$PRECOMMIT" && + echo "stuff" >>file && + git add file && + git commit --no-verify -m "stuff" && + test_path_is_missing actual_hooks +' + +test_expect_success 'with failing hook (merge)' ' + test_when_finished "rm -f \"$PREMERGE\" expected_hooks actual_hooks" && + cp "$HOOKDIR/fail.sample" "$PREMERGE" && + echo "$PREMERGE" >expected_hooks && + git checkout side && + test_must_fail git merge -m "merge master" master && + git checkout master && + test_cmp expected_hooks actual_hooks +' + +test_expect_success '--no-verify with failing hook (merge)' ' + test_when_finished "rm -f \"$PREMERGE\" actual_hooks" && + cp "$HOOKDIR/fail.sample" "$PREMERGE" && + git branch -f side side-orig && + git checkout side && + git merge --no-verify -m "merge master" master && + git checkout master && + test_path_is_missing actual_hooks +' + +test_expect_success POSIXPERM 'with non-executable hook' ' + test_when_finished "rm -f \"$PRECOMMIT\" actual_hooks" && + cp "$HOOKDIR/non-exec.sample" "$PRECOMMIT" && + echo "content" >>file && + git add file && + git commit -m "content" && + test_path_is_missing actual_hooks +' + +test_expect_success POSIXPERM '--no-verify with non-executable hook' ' + test_when_finished "rm -f \"$PRECOMMIT\" actual_hooks" && + cp "$HOOKDIR/non-exec.sample" "$PRECOMMIT" && + echo "more content" >>file && + git add file && + git commit --no-verify -m "more content" && + test_path_is_missing actual_hooks +' + +test_expect_success POSIXPERM 'with non-executable hook (merge)' ' + test_when_finished "rm -f \"$PREMERGE\" actual_hooks" && + cp "$HOOKDIR/non-exec.sample" "$PREMERGE" && + git branch -f side side-orig && + git checkout side && + git merge -m "merge master" master && + git checkout master && + test_path_is_missing actual_hooks +' + +test_expect_success POSIXPERM '--no-verify with non-executable hook (merge)' ' + test_when_finished "rm -f \"$PREMERGE\" actual_hooks" && + cp "$HOOKDIR/non-exec.sample" "$PREMERGE" && + git branch -f side side-orig && + git checkout side && + git merge --no-verify -m "merge master" master && + git checkout master && + test_path_is_missing actual_hooks +' + +test_expect_success 'with hook requiring GIT_PREFIX' ' + test_when_finished "rm -rf \"$PRECOMMIT\" expected_hooks actual_hooks success" && + cp "$HOOKDIR/require-prefix.sample" "$PRECOMMIT" && + echo "$PRECOMMIT" >expected_hooks && + echo "more content" >>file && + git add file && + mkdir success && + ( + cd success && + git commit -m "hook requires GIT_PREFIX = success/" + ) && + test_cmp expected_hooks actual_hooks +' + +test_expect_success 'with failing hook requiring GIT_PREFIX' ' + test_when_finished "rm -rf \"$PRECOMMIT\" expected_hooks actual_hooks fail" && + cp "$HOOKDIR/require-prefix.sample" "$PRECOMMIT" && + echo "$PRECOMMIT" >expected_hooks && + echo "more content" >>file && + git add file && + mkdir fail && + ( + cd fail && + test_must_fail git commit -m "hook must fail" + ) && + git checkout -- file && + test_cmp expected_hooks actual_hooks +' + +test_expect_success 'check the author in hook' ' + test_when_finished "rm -f \"$PRECOMMIT\" expected_hooks actual_hooks" && + cp "$HOOKDIR/check-author.sample" "$PRECOMMIT" && + cat >expected_hooks <<-EOF && + $PRECOMMIT + $PRECOMMIT + $PRECOMMIT + EOF + test_must_fail git commit --allow-empty -m "by a.u.thor" && + ( + GIT_AUTHOR_NAME="New Author" && + GIT_AUTHOR_EMAIL="newauthor@example.com" && + export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL && + git commit --allow-empty -m "by new.author via env" && + git show -s + ) && + git commit --author="New Author <newauthor@example.com>" \ + --allow-empty -m "by new.author via command line" && + git show -s && + test_cmp expected_hooks actual_hooks +' + +test_done diff --git a/t/t7503-pre-commit-hook.sh b/t/t7503-pre-commit-hook.sh deleted file mode 100755 index 984889b39d..0000000000 --- a/t/t7503-pre-commit-hook.sh +++ /dev/null @@ -1,139 +0,0 @@ -#!/bin/sh - -test_description='pre-commit hook' - -. ./test-lib.sh - -test_expect_success 'with no hook' ' - - echo "foo" > file && - git add file && - git commit -m "first" - -' - -test_expect_success '--no-verify with no hook' ' - - echo "bar" > file && - git add file && - git commit --no-verify -m "bar" - -' - -# now install hook that always succeeds -HOOKDIR="$(git rev-parse --git-dir)/hooks" -HOOK="$HOOKDIR/pre-commit" -mkdir -p "$HOOKDIR" -cat > "$HOOK" <<EOF -#!/bin/sh -exit 0 -EOF -chmod +x "$HOOK" - -test_expect_success 'with succeeding hook' ' - - echo "more" >> file && - git add file && - git commit -m "more" - -' - -test_expect_success '--no-verify with succeeding hook' ' - - echo "even more" >> file && - git add file && - git commit --no-verify -m "even more" - -' - -# now a hook that fails -cat > "$HOOK" <<EOF -#!/bin/sh -exit 1 -EOF - -test_expect_success 'with failing hook' ' - - echo "another" >> file && - git add file && - test_must_fail git commit -m "another" - -' - -test_expect_success '--no-verify with failing hook' ' - - echo "stuff" >> file && - git add file && - git commit --no-verify -m "stuff" - -' - -chmod -x "$HOOK" -test_expect_success POSIXPERM 'with non-executable hook' ' - - echo "content" >> file && - git add file && - git commit -m "content" - -' - -test_expect_success POSIXPERM '--no-verify with non-executable hook' ' - - echo "more content" >> file && - git add file && - git commit --no-verify -m "more content" - -' -chmod +x "$HOOK" - -# a hook that checks $GIT_PREFIX and succeeds inside the -# success/ subdirectory only -cat > "$HOOK" <<EOF -#!/bin/sh -test \$GIT_PREFIX = success/ -EOF - -test_expect_success 'with hook requiring GIT_PREFIX' ' - - echo "more content" >> file && - git add file && - mkdir success && - ( - cd success && - git commit -m "hook requires GIT_PREFIX = success/" - ) && - rmdir success -' - -test_expect_success 'with failing hook requiring GIT_PREFIX' ' - - echo "more content" >> file && - git add file && - mkdir fail && - ( - cd fail && - test_must_fail git commit -m "hook must fail" - ) && - rmdir fail && - git checkout -- file -' - -test_expect_success 'check the author in hook' ' - write_script "$HOOK" <<-\EOF && - test "$GIT_AUTHOR_NAME" = "New Author" && - test "$GIT_AUTHOR_EMAIL" = "newauthor@example.com" - EOF - test_must_fail git commit --allow-empty -m "by a.u.thor" && - ( - GIT_AUTHOR_NAME="New Author" && - GIT_AUTHOR_EMAIL="newauthor@example.com" && - export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL && - git commit --allow-empty -m "by new.author via env" && - git show -s - ) && - git commit --author="New Author <newauthor@example.com>" \ - --allow-empty -m "by new.author via command line" && - git show -s -' - -test_done diff --git a/t/t7505-prepare-commit-msg-hook.sh b/t/t7505-prepare-commit-msg-hook.sh index ba8bd1b514..94f85cdf83 100755 --- a/t/t7505-prepare-commit-msg-hook.sh +++ b/t/t7505-prepare-commit-msg-hook.sh @@ -241,13 +241,7 @@ test_rebase () { git add b && git rebase --continue ) && - if test "$mode" = -p # reword amended after pick - then - n=18 - else - n=17 - fi && - git log --pretty=%s -g -n$n HEAD@{1} >actual && + git log --pretty=%s -g -n18 HEAD@{1} >actual && test_cmp "$TEST_DIRECTORY/t7505/expected-rebase${mode:--i}" actual ' } diff --git a/t/t7505/expected-rebase-i b/t/t7505/expected-rebase-i index c514bdbb94..93bada596e 100644 --- a/t/t7505/expected-rebase-i +++ b/t/t7505/expected-rebase-i @@ -7,7 +7,8 @@ message (no editor) [edit rebase-10] message [fixup rebase-9] message (no editor) [fixup rebase-8] message (no editor) [squash rebase-7] -message [reword rebase-6] +HEAD [reword rebase-6] +message (no editor) [reword rebase-6] message [squash rebase-5] message (no editor) [fixup rebase-4] message (no editor) [pick rebase-3] diff --git a/t/t7508-status.sh b/t/t7508-status.sh index e1f11293e2..482ce3510e 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -94,19 +94,16 @@ test_expect_success 'status --column' ' # (use "git pull" to merge the remote branch into yours) # # Changes to be committed: -# (use "git reset HEAD <file>..." to unstage) -# +# (use "git restore --staged <file>..." to unstage) # new file: dir2/added # # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) -# (use "git checkout -- <file>..." to discard changes in working directory) -# +# (use "git restore <file>..." to discard changes in working directory) # modified: dir1/modified # # Untracked files: # (use "git add <file>..." to include in what will be committed) -# # dir1/untracked dir2/untracked # dir2/modified untracked # @@ -128,19 +125,16 @@ cat >expect <<\EOF # (use "git pull" to merge the remote branch into yours) # # Changes to be committed: -# (use "git reset HEAD <file>..." to unstage) -# +# (use "git restore --staged <file>..." to unstage) # new file: dir2/added # # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) -# (use "git checkout -- <file>..." to discard changes in working directory) -# +# (use "git restore <file>..." to discard changes in working directory) # modified: dir1/modified # # Untracked files: # (use "git add <file>..." to include in what will be committed) -# # dir1/untracked # dir2/modified # dir2/untracked @@ -278,24 +272,20 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) - + (use "git restore --staged <file>..." to unstage) new file: dir2/added Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified Untracked files: (use "git add <file>..." to include in what will be committed) - dir2/modified Ignored files: (use "git add -f <file>..." to include in what will be committed) - .gitignore dir1/untracked dir2/untracked @@ -347,19 +337,16 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) - + (use "git restore --staged <file>..." to unstage) new file: dir2/added Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified Ignored files: (use "git add -f <file>..." to include in what will be committed) - .gitignore dir1/untracked dir2/modified @@ -420,14 +407,12 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) - + (use "git restore --staged <file>..." to unstage) new file: dir2/added Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified Untracked files not listed (use -u option to show untracked files) @@ -484,19 +469,16 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) - + (use "git restore --staged <file>..." to unstage) new file: dir2/added Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified Untracked files: (use "git add <file>..." to include in what will be committed) - dir1/untracked dir2/modified dir2/untracked @@ -542,19 +524,16 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) - + (use "git restore --staged <file>..." to unstage) new file: dir2/added Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified Untracked files: (use "git add <file>..." to include in what will be committed) - dir1/untracked dir2/modified dir2/untracked @@ -605,19 +584,16 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) - + (use "git restore --staged <file>..." to unstage) new file: ../dir2/added Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: modified Untracked files: (use "git add <file>..." to include in what will be committed) - untracked ../dir2/modified ../dir2/untracked @@ -676,19 +652,16 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) - + (use "git restore --staged <file>..." to unstage) <GREEN>new file: dir2/added<RESET> Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) <RED>modified: dir1/modified<RESET> Untracked files: (use "git add <file>..." to include in what will be committed) - <BLUE>dir1/untracked<RESET> <BLUE>dir2/modified<RESET> <BLUE>dir2/untracked<RESET> @@ -802,19 +775,16 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) - + (use "git restore --staged <file>..." to unstage) new file: dir2/added Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified Untracked files: (use "git add <file>..." to include in what will be committed) - dir1/untracked dir2/modified dir2/untracked @@ -852,13 +822,11 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) - + (use "git restore --staged <file>..." to unstage) modified: dir1/modified Untracked files: (use "git add <file>..." to include in what will be committed) - dir1/untracked dir2/ untracked @@ -896,20 +864,17 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) - + (use "git restore --staged <file>..." to unstage) new file: dir2/added new file: sm Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified Untracked files: (use "git add <file>..." to include in what will be committed) - dir1/untracked dir2/modified dir2/untracked @@ -956,15 +921,13 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) - + (use "git restore --staged <file>..." to unstage) new file: dir2/added new file: sm Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified Submodule changes to be committed: @@ -974,7 +937,6 @@ Submodule changes to be committed: Untracked files: (use "git add <file>..." to include in what will be committed) - dir1/untracked dir2/modified dir2/untracked @@ -1019,13 +981,11 @@ and have 2 and 2 different commits each, respectively. Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified Untracked files: (use "git add <file>..." to include in what will be committed) - dir1/untracked dir2/modified dir2/untracked @@ -1068,15 +1028,13 @@ and have 2 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD^1 <file>..." to unstage) - + (use "git restore --source=HEAD^1 --staged <file>..." to unstage) new file: dir2/added new file: sm Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified Submodule changes to be committed: @@ -1086,7 +1044,6 @@ Submodule changes to be committed: Untracked files: (use "git add <file>..." to include in what will be committed) - dir1/untracked dir2/modified dir2/untracked @@ -1123,14 +1080,12 @@ and have 2 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) - + (use "git restore --staged <file>..." to unstage) modified: sm Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified Submodule changes to be committed: @@ -1140,7 +1095,6 @@ Submodule changes to be committed: Untracked files: (use "git add <file>..." to include in what will be committed) - .gitmodules dir1/untracked dir2/modified @@ -1235,15 +1189,13 @@ and have 2 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) - + (use "git restore --staged <file>..." to unstage) modified: sm Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) (commit or discard the untracked or modified content in submodules) - modified: dir1/modified modified: sm (modified content) @@ -1254,7 +1206,6 @@ Submodule changes to be committed: Untracked files: (use "git add <file>..." to include in what will be committed) - .gitmodules dir1/untracked dir2/modified @@ -1295,14 +1246,12 @@ and have 2 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) - + (use "git restore --staged <file>..." to unstage) modified: sm Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified modified: sm (new commits) @@ -1318,7 +1267,6 @@ Submodules changed but not updated: Untracked files: (use "git add <file>..." to include in what will be committed) - .gitmodules dir1/untracked dir2/modified @@ -1379,14 +1327,12 @@ cat > expect << EOF ; (use "git pull" to merge the remote branch into yours) ; ; Changes to be committed: -; (use "git reset HEAD <file>..." to unstage) -; +; (use "git restore --staged <file>..." to unstage) ; modified: sm ; ; Changes not staged for commit: ; (use "git add <file>..." to update what will be committed) -; (use "git checkout -- <file>..." to discard changes in working directory) -; +; (use "git restore <file>..." to discard changes in working directory) ; modified: dir1/modified ; modified: sm (new commits) ; @@ -1402,7 +1348,6 @@ cat > expect << EOF ; ; Untracked files: ; (use "git add <file>..." to include in what will be committed) -; ; .gitmodules ; dir1/untracked ; dir2/modified @@ -1431,13 +1376,11 @@ and have 2 and 2 different commits each, respectively. Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified Untracked files: (use "git add <file>..." to include in what will be committed) - .gitmodules dir1/untracked dir2/modified @@ -1458,19 +1401,16 @@ and have 2 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) - + (use "git restore --staged <file>..." to unstage) modified: sm Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified Untracked files: (use "git add <file>..." to include in what will be committed) - .gitmodules dir1/untracked dir2/modified @@ -1581,14 +1521,12 @@ and have 2 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) - + (use "git restore --staged <file>..." to unstage) modified: sm Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified Untracked files not listed (use -u option to show untracked files) @@ -1633,7 +1571,7 @@ test_expect_success '"status.showStash=true" weaker than "--no-show-stash"' ' test_cmp expected_without_stash actual ' -test_expect_success 'no additionnal info if no stash entries' ' +test_expect_success 'no additional info if no stash entries' ' git stash clear && git -c status.showStash=true status >actual && test_cmp expected_without_stash actual diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh index c1eb72555d..66d7a62797 100755 --- a/t/t7512-status-help.sh +++ b/t/t7512-status-help.sh @@ -33,7 +33,6 @@ You have unmerged paths. Unmerged paths: (use "git add <file>..." to mark resolution) - both modified: main.txt no changes added to commit (use "git add" and/or "git commit -a") @@ -54,7 +53,6 @@ All conflicts fixed but you are still merging. (use "git commit" to conclude merge) Changes to be committed: - modified: main.txt Untracked files not listed (use -u option to show untracked files) @@ -85,9 +83,8 @@ You are currently rebasing branch '\''rebase_conflicts'\'' on '\''$ONTO'\''. (use "git rebase --abort" to check out the original branch) Unmerged paths: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) (use "git add <file>..." to mark resolution) - both modified: main.txt no changes added to commit (use "git add" and/or "git commit -a") @@ -110,8 +107,7 @@ You are currently rebasing branch '\''rebase_conflicts'\'' on '\''$ONTO'\''. (all conflicts fixed: run "git rebase --continue") Changes to be committed: - (use "git reset HEAD <file>..." to unstage) - + (use "git restore --staged <file>..." to unstage) modified: main.txt Untracked files not listed (use -u option to show untracked files) @@ -148,9 +144,8 @@ You are currently rebasing branch '\''rebase_i_conflicts_second'\'' on '\''$ONTO (use "git rebase --abort" to check out the original branch) Unmerged paths: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) (use "git add <file>..." to mark resolution) - both modified: main.txt no changes added to commit (use "git add" and/or "git commit -a") @@ -176,8 +171,7 @@ You are currently rebasing branch '\''rebase_i_conflicts_second'\'' on '\''$ONTO (all conflicts fixed: run "git rebase --continue") Changes to be committed: - (use "git reset HEAD <file>..." to unstage) - + (use "git restore --staged <file>..." to unstage) modified: main.txt Untracked files not listed (use -u option to show untracked files) @@ -246,8 +240,7 @@ You are currently splitting a commit while rebasing branch '\''split_commit'\'' Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: main.txt no changes added to commit (use "git add" and/or "git commit -a") @@ -354,8 +347,7 @@ You are currently splitting a commit while rebasing branch '\''several_edits'\'' Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: main.txt no changes added to commit (use "git add" and/or "git commit -a") @@ -453,8 +445,7 @@ You are currently splitting a commit while rebasing branch '\''several_edits'\'' Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: main.txt no changes added to commit (use "git add" and/or "git commit -a") @@ -557,8 +548,7 @@ You are currently splitting a commit while rebasing branch '\''several_edits'\'' Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) - + (use "git restore <file>..." to discard changes in working directory) modified: main.txt no changes added to commit (use "git add" and/or "git commit -a") @@ -743,11 +733,11 @@ test_expect_success 'status when cherry-picking before resolving conflicts' ' On branch cherry_branch You are currently cherry-picking commit $TO_CHERRY_PICK. (fix conflicts and run "git cherry-pick --continue") + (use "git cherry-pick --skip" to skip this patch) (use "git cherry-pick --abort" to cancel the cherry-pick operation) Unmerged paths: (use "git add <file>..." to mark resolution) - both modified: main.txt no changes added to commit (use "git add" and/or "git commit -a") @@ -768,10 +758,10 @@ test_expect_success 'status when cherry-picking after resolving conflicts' ' On branch cherry_branch You are currently cherry-picking commit $TO_CHERRY_PICK. (all conflicts fixed: run "git cherry-pick --continue") + (use "git cherry-pick --skip" to skip this patch) (use "git cherry-pick --abort" to cancel the cherry-pick operation) Changes to be committed: - modified: main.txt Untracked files not listed (use -u option to show untracked files) @@ -790,6 +780,7 @@ test_expect_success 'status when cherry-picking after committing conflict resolu On branch cherry_branch Cherry-pick currently in progress. (run "git cherry-pick --continue" to continue) + (use "git cherry-pick --skip" to skip this patch) (use "git cherry-pick --abort" to cancel the cherry-pick operation) nothing to commit (use -u to show untracked files) @@ -798,6 +789,22 @@ EOF test_i18ncmp expected actual ' +test_expect_success 'status shows cherry-pick with invalid oid' ' + mkdir .git/sequencer && + test_write_lines "pick invalid-oid" >.git/sequencer/todo && + git status --untracked-files=no >actual 2>err && + git cherry-pick --quit && + test_must_be_empty err && + test_i18ncmp expected actual +' + +test_expect_success 'status does not show error if .git/sequencer is a file' ' + test_when_finished "rm .git/sequencer" && + test_write_lines hello >.git/sequencer && + git status --untracked-files=no 2>err && + test_must_be_empty err +' + test_expect_success 'status showing detached at and from a tag' ' test_commit atag tagging && git checkout atag && @@ -831,12 +838,12 @@ test_expect_success 'status while reverting commit (conflicts)' ' On branch master You are currently reverting commit $TO_REVERT. (fix conflicts and run "git revert --continue") + (use "git revert --skip" to skip this patch) (use "git revert --abort" to cancel the revert operation) Unmerged paths: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) (use "git add <file>..." to mark resolution) - both modified: to-revert.txt no changes added to commit (use "git add" and/or "git commit -a") @@ -852,11 +859,11 @@ test_expect_success 'status while reverting commit (conflicts resolved)' ' On branch master You are currently reverting commit $TO_REVERT. (all conflicts fixed: run "git revert --continue") + (use "git revert --skip" to skip this patch) (use "git revert --abort" to cancel the revert operation) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) - + (use "git restore --staged <file>..." to unstage) modified: to-revert.txt Untracked files not listed (use -u option to show untracked files) @@ -885,6 +892,7 @@ test_expect_success 'status while reverting after committing conflict resolution On branch master Revert currently in progress. (run "git revert --continue" to continue) + (use "git revert --skip" to skip this patch) (use "git revert --abort" to cancel the revert operation) nothing to commit (use -u to show untracked files) diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh index f19202b509..6602790b5f 100755 --- a/t/t7513-interpret-trailers.sh +++ b/t/t7513-interpret-trailers.sh @@ -1234,7 +1234,7 @@ test_expect_success 'with simple command' ' test_cmp expected actual ' -test_expect_success 'with command using commiter information' ' +test_expect_success 'with command using committer information' ' git config trailer.sign.ifExists "addIfDifferent" && git config trailer.sign.command "echo \"\$GIT_COMMITTER_NAME <\$GIT_COMMITTER_EMAIL>\"" && cat complex_message_body >expected && diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh index 81a375fa0f..cf0fda2d5a 100755 --- a/t/t7519-status-fsmonitor.sh +++ b/t/t7519-status-fsmonitor.sh @@ -106,6 +106,8 @@ EOF # test that "update-index --fsmonitor-valid" sets the fsmonitor valid bit test_expect_success 'update-index --fsmonitor-valid" sets the fsmonitor valid bit' ' + write_script .git/hooks/fsmonitor-test<<-\EOF && + EOF git update-index --fsmonitor && git update-index --fsmonitor-valid dir1/modified && git update-index --fsmonitor-valid dir2/modified && @@ -164,6 +166,8 @@ EOF # test that newly added files are marked valid test_expect_success 'newly added files are marked valid' ' + write_script .git/hooks/fsmonitor-test<<-\EOF && + EOF git add new && git add dir1/new && git add dir2/new && @@ -218,11 +222,12 @@ test_expect_success '*only* files returned by the integration script get flagged # Ensure commands that call refresh_index() to move the index back in time # properly invalidate the fsmonitor cache test_expect_success 'refresh_index() invalidates fsmonitor cache' ' - write_script .git/hooks/fsmonitor-test<<-\EOF && - EOF clean_repo && dirty_repo && + write_integration_script && git add . && + write_script .git/hooks/fsmonitor-test<<-\EOF && + EOF git commit -m "to reset" && git reset HEAD~1 && git status >actual && @@ -294,7 +299,7 @@ do done done -# test that splitting the index dosn't interfere +# test that splitting the index doesn't interfere test_expect_success 'splitting the index results in the same state' ' write_integration_script && dirty_repo && @@ -354,4 +359,23 @@ test_expect_success 'discard_index() also discards fsmonitor info' ' test_cmp expect actual ' +# Test unstaging entries that: +# - Are not flagged with CE_FSMONITOR_VALID +# - Have a position in the index >= the number of entries present in the index +# after unstaging. +test_expect_success 'status succeeds after staging/unstaging' ' + test_create_repo fsmonitor-stage-unstage && + ( + cd fsmonitor-stage-unstage && + test_commit initial && + git update-index --fsmonitor && + removed=$(test_seq 1 100 | sed "s/^/z/") && + touch $removed && + git add $removed && + git config core.fsmonitor "$TEST_DIRECTORY/t7519/fsmonitor-env" && + FSMONITOR_LIST="$removed" git restore -S $removed && + FSMONITOR_LIST="$removed" git status + ) +' + test_done diff --git a/t/t7519/fsmonitor-env b/t/t7519/fsmonitor-env new file mode 100755 index 0000000000..8f1f7ab164 --- /dev/null +++ b/t/t7519/fsmonitor-env @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An test hook script to integrate with git to test fsmonitor. +# +# The hook is passed a version (currently 1) and a time in nanoseconds +# formatted as a string and outputs to stdout all files that have been +# modified since the given time. Paths must be relative to the root of +# the working tree and separated by a single NUL. +# +#echo "$0 $*" >&2 + +if test "$#" -ne 2 +then + echo "$0: exactly 2 arguments expected" >&2 + exit 2 +fi + +if test "$1" != 1 +then + echo "Unsupported core.fsmonitor hook version." >&2 + exit 1 +fi + +printf '%s\n' $FSMONITOR_LIST diff --git a/t/t7519/fsmonitor-watchman b/t/t7519/fsmonitor-watchman index 5514edcf68..d8e7a1e5ba 100755 --- a/t/t7519/fsmonitor-watchman +++ b/t/t7519/fsmonitor-watchman @@ -23,7 +23,8 @@ my ($version, $time) = @ARGV; if ($version == 1) { # convert nanoseconds to seconds - $time = int $time / 1000000000; + # subtract one second to make sure watchman will return all changes + $time = int ($time / 1000000000) - 1; } else { die "Unsupported query-fsmonitor hook version '$version'.\n" . "Falling back to scanning...\n"; @@ -54,18 +55,12 @@ sub launch_watchman { # # To accomplish this, we're using the "since" generator to use the # recency index to select candidate nodes and "fields" to limit the - # output to file names only. Then we're using the "expression" term to - # further constrain the results. - # - # The category of transient files that we want to ignore will have a - # creation clock (cclock) newer than $time_t value and will also not - # currently exist. + # output to file names only. my $query = <<" END"; ["query", "$git_work_tree", { "since": $time, - "fields": ["name"], - "expression": ["not", ["allof", ["since", $time, "cclock"], ["not", "exists"]]] + "fields": ["name"] }] END diff --git a/t/t7526-commit-pathspec-file.sh b/t/t7526-commit-pathspec-file.sh new file mode 100755 index 0000000000..a06b683534 --- /dev/null +++ b/t/t7526-commit-pathspec-file.sh @@ -0,0 +1,130 @@ +#!/bin/sh + +test_description='commit --pathspec-from-file' + +. ./test-lib.sh + +test_tick + +test_expect_success setup ' + test_commit file0 && + git tag checkpoint && + + echo A >fileA.t && + echo B >fileB.t && + echo C >fileC.t && + echo D >fileD.t && + git add fileA.t fileB.t fileC.t fileD.t +' + +restore_checkpoint () { + git reset --soft checkpoint +} + +verify_expect () { + git diff-tree --no-commit-id --name-status -r HEAD >actual && + test_cmp expect actual +} + +test_expect_success '--pathspec-from-file from stdin' ' + restore_checkpoint && + + echo fileA.t | git commit --pathspec-from-file=- -m "Commit" && + + cat >expect <<-\EOF && + A fileA.t + EOF + verify_expect +' + +test_expect_success '--pathspec-from-file from file' ' + restore_checkpoint && + + echo fileA.t >list && + git commit --pathspec-from-file=list -m "Commit" && + + cat >expect <<-\EOF && + A fileA.t + EOF + verify_expect +' + +test_expect_success 'NUL delimiters' ' + restore_checkpoint && + + printf "fileA.t\0fileB.t\0" | git commit --pathspec-from-file=- --pathspec-file-nul -m "Commit" && + + cat >expect <<-\EOF && + A fileA.t + A fileB.t + EOF + verify_expect +' + +test_expect_success 'LF delimiters' ' + restore_checkpoint && + + printf "fileA.t\nfileB.t\n" | git commit --pathspec-from-file=- -m "Commit" && + + cat >expect <<-\EOF && + A fileA.t + A fileB.t + EOF + verify_expect +' + +test_expect_success 'no trailing delimiter' ' + restore_checkpoint && + + printf "fileA.t\nfileB.t" | git commit --pathspec-from-file=- -m "Commit" && + + cat >expect <<-\EOF && + A fileA.t + A fileB.t + EOF + verify_expect +' + +test_expect_success 'CRLF delimiters' ' + restore_checkpoint && + + printf "fileA.t\r\nfileB.t\r\n" | git commit --pathspec-from-file=- -m "Commit" && + + cat >expect <<-\EOF && + A fileA.t + A fileB.t + EOF + verify_expect +' + +test_expect_success 'quotes' ' + restore_checkpoint && + + printf "\"file\\101.t\"" | git commit --pathspec-from-file=- -m "Commit" && + + cat >expect <<-\EOF && + A fileA.t + EOF + verify_expect expect +' + +test_expect_success 'quotes not compatible with --pathspec-file-nul' ' + restore_checkpoint && + + printf "\"file\\101.t\"" >list && + test_must_fail git commit --pathspec-from-file=list --pathspec-file-nul -m "Commit" +' + +test_expect_success 'only touches what was listed' ' + restore_checkpoint && + + printf "fileB.t\nfileC.t\n" | git commit --pathspec-from-file=- -m "Commit" && + + cat >expect <<-\EOF && + A fileB.t + A fileC.t + EOF + verify_expect +' + +test_done diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh index 4ec5d9ec79..132608879a 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -873,4 +873,50 @@ test_expect_success EXECKEEPSPID 'killed merge can be completed with --continue' verify_parents $c0 $c1 ' +test_expect_success 'merge --quit' ' + git init merge-quit && + ( + cd merge-quit && + test_commit base && + echo one >>base.t && + git commit -am one && + git branch one && + git checkout base && + echo two >>base.t && + git commit -am two && + test_must_fail git -c rerere.enabled=true merge one && + test_path_is_file .git/MERGE_HEAD && + test_path_is_file .git/MERGE_MODE && + test_path_is_file .git/MERGE_MSG && + git rerere status >rerere.before && + git merge --quit && + test_path_is_missing .git/MERGE_HEAD && + test_path_is_missing .git/MERGE_MODE && + test_path_is_missing .git/MERGE_MSG && + git rerere status >rerere.after && + test_must_be_empty rerere.after && + ! test_cmp rerere.after rerere.before + ) +' + +test_expect_success 'merge suggests matching remote refname' ' + git commit --allow-empty -m not-local && + git update-ref refs/remotes/origin/not-local HEAD && + git reset --hard HEAD^ && + + # This is white-box testing hackery; we happen to know + # that reading packed refs is more picky about the memory + # ownership of strings we pass to for_each_ref() callbacks. + git pack-refs --all --prune && + + test_must_fail git merge not-local 2>stderr && + grep origin/not-local stderr +' + +test_expect_success 'suggested names are not ambiguous' ' + git update-ref refs/heads/origin/not-local HEAD && + test_must_fail git merge not-local 2>stderr && + grep remotes/origin/not-local stderr +' + test_done diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh index 5b61c10a9c..ad288ddc69 100755 --- a/t/t7610-mergetool.sh +++ b/t/t7610-mergetool.sh @@ -131,17 +131,21 @@ test_expect_success 'custom mergetool' ' git checkout -b test$test_count branch1 && git submodule update -N && test_must_fail git merge master && - ( yes "" | git mergetool both ) && - ( yes "" | git mergetool file1 file1 ) && - ( yes "" | git mergetool file2 "spaced name" ) && - ( yes "" | git mergetool subdir/file3 ) && - ( yes "d" | git mergetool file11 ) && - ( yes "d" | git mergetool file12 ) && - ( yes "l" | git mergetool submod ) && - test "$(cat file1)" = "master updated" && - test "$(cat file2)" = "master new" && - test "$(cat subdir/file3)" = "master new sub" && - test "$(cat submod/bar)" = "branch1 submodule" && + yes "" | git mergetool both && + yes "" | git mergetool file1 file1 && + yes "" | git mergetool file2 "spaced name" && + yes "" | git mergetool subdir/file3 && + yes "d" | git mergetool file11 && + yes "d" | git mergetool file12 && + yes "l" | git mergetool submod && + echo "master updated" >expect && + test_cmp expect file1 && + echo "master new" >expect && + test_cmp expect file2 && + echo "master new sub" >expect && + test_cmp expect subdir/file3 && + echo "branch1 submodule" >expect && + test_cmp expect submod/bar && git commit -m "branch1 resolved with mergetool" ' @@ -153,17 +157,21 @@ test_expect_success 'gui mergetool' ' git checkout -b test$test_count branch1 && git submodule update -N && test_must_fail git merge master && - ( yes "" | git mergetool --gui both ) && - ( yes "" | git mergetool -g file1 file1 ) && - ( yes "" | git mergetool --gui file2 "spaced name" ) && - ( yes "" | git mergetool --gui subdir/file3 ) && - ( yes "d" | git mergetool --gui file11 ) && - ( yes "d" | git mergetool --gui file12 ) && - ( yes "l" | git mergetool --gui submod ) && - test "$(cat file1)" = "gui master updated" && - test "$(cat file2)" = "gui master new" && - test "$(cat subdir/file3)" = "gui master new sub" && - test "$(cat submod/bar)" = "branch1 submodule" && + yes "" | git mergetool --gui both && + yes "" | git mergetool -g file1 file1 && + yes "" | git mergetool --gui file2 "spaced name" && + yes "" | git mergetool --gui subdir/file3 && + yes "d" | git mergetool --gui file11 && + yes "d" | git mergetool --gui file12 && + yes "l" | git mergetool --gui submod && + echo "gui master updated" >expect && + test_cmp expect file1 && + echo "gui master new" >expect && + test_cmp expect file2 && + echo "gui master new sub" >expect && + test_cmp expect subdir/file3 && + echo "branch1 submodule" >expect && + test_cmp expect submod/bar && git commit -m "branch1 resolved with mergetool" ' @@ -172,17 +180,21 @@ test_expect_success 'gui mergetool without merge.guitool set falls back to merge git checkout -b test$test_count branch1 && git submodule update -N && test_must_fail git merge master && - ( yes "" | git mergetool --gui both ) && - ( yes "" | git mergetool -g file1 file1 ) && - ( yes "" | git mergetool --gui file2 "spaced name" ) && - ( yes "" | git mergetool --gui subdir/file3 ) && - ( yes "d" | git mergetool --gui file11 ) && - ( yes "d" | git mergetool --gui file12 ) && - ( yes "l" | git mergetool --gui submod ) && - test "$(cat file1)" = "master updated" && - test "$(cat file2)" = "master new" && - test "$(cat subdir/file3)" = "master new sub" && - test "$(cat submod/bar)" = "branch1 submodule" && + yes "" | git mergetool --gui both && + yes "" | git mergetool -g file1 file1 && + yes "" | git mergetool --gui file2 "spaced name" && + yes "" | git mergetool --gui subdir/file3 && + yes "d" | git mergetool --gui file11 && + yes "d" | git mergetool --gui file12 && + yes "l" | git mergetool --gui submod && + echo "master updated" >expect && + test_cmp expect file1 && + echo "master new" >expect && + test_cmp expect file2 && + echo "master new sub" >expect && + test_cmp expect subdir/file3 && + echo "branch1 submodule" >expect && + test_cmp expect submod/bar && git commit -m "branch1 resolved with mergetool" ' @@ -195,19 +207,20 @@ test_expect_success 'mergetool crlf' ' test_config core.autocrlf true && git checkout -b test$test_count branch1 && test_must_fail git merge master && - ( yes "" | git mergetool file1 ) && - ( yes "" | git mergetool file2 ) && - ( yes "" | git mergetool "spaced name" ) && - ( yes "" | git mergetool both ) && - ( yes "" | git mergetool subdir/file3 ) && - ( yes "d" | git mergetool file11 ) && - ( yes "d" | git mergetool file12 ) && - ( yes "r" | git mergetool submod ) && + yes "" | git mergetool file1 && + yes "" | git mergetool file2 && + yes "" | git mergetool "spaced name" && + yes "" | git mergetool both && + yes "" | git mergetool subdir/file3 && + yes "d" | git mergetool file11 && + yes "d" | git mergetool file12 && + yes "r" | git mergetool submod && test "$(printf x | cat file1 -)" = "$(printf "master updated\r\nx")" && test "$(printf x | cat file2 -)" = "$(printf "master new\r\nx")" && test "$(printf x | cat subdir/file3 -)" = "$(printf "master new sub\r\nx")" && git submodule update -N && - test "$(cat submod/bar)" = "master submodule" && + echo "master submodule" >expect && + test_cmp expect submod/bar && git commit -m "branch1 resolved with mergetool - autocrlf" ' @@ -218,8 +231,9 @@ test_expect_success 'mergetool in subdir' ' ( cd subdir && test_must_fail git merge master && - ( yes "" | git mergetool file3 ) && - test "$(cat file3)" = "master new sub" + yes "" | git mergetool file3 && + echo "master new sub" >expect && + test_cmp expect file3 ) ' @@ -230,16 +244,19 @@ test_expect_success 'mergetool on file in parent dir' ' ( cd subdir && test_must_fail git merge master && - ( yes "" | git mergetool file3 ) && - ( yes "" | git mergetool ../file1 ) && - ( yes "" | git mergetool ../file2 ../spaced\ name ) && - ( yes "" | git mergetool ../both ) && - ( yes "d" | git mergetool ../file11 ) && - ( yes "d" | git mergetool ../file12 ) && - ( yes "l" | git mergetool ../submod ) && - test "$(cat ../file1)" = "master updated" && - test "$(cat ../file2)" = "master new" && - test "$(cat ../submod/bar)" = "branch1 submodule" && + yes "" | git mergetool file3 && + yes "" | git mergetool ../file1 && + yes "" | git mergetool ../file2 ../spaced\ name && + yes "" | git mergetool ../both && + yes "d" | git mergetool ../file11 && + yes "d" | git mergetool ../file12 && + yes "l" | git mergetool ../submod && + echo "master updated" >expect && + test_cmp expect ../file1 && + echo "master new" >expect && + test_cmp expect ../file2 && + echo "branch1 submodule" >expect && + test_cmp expect ../submod/bar && git commit -m "branch1 resolved with mergetool - subdir" ) ' @@ -250,9 +267,9 @@ test_expect_success 'mergetool skips autoresolved' ' git submodule update -N && test_must_fail git merge master && test -n "$(git ls-files -u)" && - ( yes "d" | git mergetool file11 ) && - ( yes "d" | git mergetool file12 ) && - ( yes "l" | git mergetool submod ) && + yes "d" | git mergetool file11 && + yes "d" | git mergetool file12 && + yes "l" | git mergetool submod && output="$(git mergetool --no-prompt)" && test "$output" = "No files need merging" ' @@ -264,13 +281,17 @@ test_expect_success 'mergetool merges all from subdir (rerere disabled)' ' ( cd subdir && test_must_fail git merge master && - ( yes "r" | git mergetool ../submod ) && - ( yes "d" "d" | git mergetool --no-prompt ) && - test "$(cat ../file1)" = "master updated" && - test "$(cat ../file2)" = "master new" && - test "$(cat file3)" = "master new sub" && + yes "r" | git mergetool ../submod && + yes "d" "d" | git mergetool --no-prompt && + echo "master updated" >expect && + test_cmp expect ../file1 && + echo "master new" >expect && + test_cmp expect ../file2 && + echo "master new sub" >expect && + test_cmp expect file3 && ( cd .. && git submodule update -N ) && - test "$(cat ../submod/bar)" = "master submodule" && + echo "master submodule" >expect && + test_cmp expect ../submod/bar && git commit -m "branch2 resolved by mergetool from subdir" ) ' @@ -283,13 +304,17 @@ test_expect_success 'mergetool merges all from subdir (rerere enabled)' ' ( cd subdir && test_must_fail git merge master && - ( yes "r" | git mergetool ../submod ) && - ( yes "d" "d" | git mergetool --no-prompt ) && - test "$(cat ../file1)" = "master updated" && - test "$(cat ../file2)" = "master new" && - test "$(cat file3)" = "master new sub" && + yes "r" | git mergetool ../submod && + yes "d" "d" | git mergetool --no-prompt && + echo "master updated" >expect && + test_cmp expect ../file1 && + echo "master new" >expect && + test_cmp expect ../file2 && + echo "master new sub" >expect && + test_cmp expect file3 && ( cd .. && git submodule update -N ) && - test "$(cat ../submod/bar)" = "master submodule" && + echo "master submodule" >expect && + test_cmp expect ../submod/bar && git commit -m "branch2 resolved by mergetool from subdir" ) ' @@ -301,8 +326,8 @@ test_expect_success 'mergetool skips resolved paths when rerere is active' ' git checkout -b test$test_count branch1 && git submodule update -N && test_must_fail git merge master && - ( yes "l" | git mergetool --no-prompt submod ) && - ( yes "d" "d" | git mergetool --no-prompt ) && + yes "l" | git mergetool --no-prompt submod && + yes "d" "d" | git mergetool --no-prompt && git submodule update -N && output="$(yes "n" | git mergetool --no-prompt)" && test "$output" = "No files need merging" @@ -343,9 +368,10 @@ test_expect_success 'mergetool takes partial path' ' git submodule update -N && test_must_fail git merge master && - ( yes "" | git mergetool subdir ) && + yes "" | git mergetool subdir && - test "$(cat subdir/file3)" = "master new sub" + echo "master new sub" >expect && + test_cmp expect subdir/file3 ' test_expect_success 'mergetool delete/delete conflict' ' @@ -410,14 +436,16 @@ test_expect_success 'deleted vs modified submodule' ' git checkout -b test$test_count.a test$test_count && test_must_fail git merge master && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) && - ( yes "" | git mergetool both ) && - ( yes "d" | git mergetool file11 file12 ) && - ( yes "r" | git mergetool submod ) && + yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && + yes "" | git mergetool both && + yes "d" | git mergetool file11 file12 && + yes "r" | git mergetool submod && rmdir submod && mv submod-movedaside submod && - test "$(cat submod/bar)" = "branch1 submodule" && + echo "branch1 submodule" >expect && + test_cmp expect submod/bar && git submodule update -N && - test "$(cat submod/bar)" = "master submodule" && + echo "master submodule" >expect && + test_cmp expect submod/bar && output="$(git mergetool --no-prompt)" && test "$output" = "No files need merging" && git commit -m "Merge resolved by keeping module" && @@ -427,10 +455,10 @@ test_expect_success 'deleted vs modified submodule' ' git submodule update -N && test_must_fail git merge master && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) && - ( yes "" | git mergetool both ) && - ( yes "d" | git mergetool file11 file12 ) && - ( yes "l" | git mergetool submod ) && + yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && + yes "" | git mergetool both && + yes "d" | git mergetool file11 file12 && + yes "l" | git mergetool submod && test ! -e submod && output="$(git mergetool --no-prompt)" && test "$output" = "No files need merging" && @@ -441,10 +469,10 @@ test_expect_success 'deleted vs modified submodule' ' git submodule update -N && test_must_fail git merge test$test_count && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) && - ( yes "" | git mergetool both ) && - ( yes "d" | git mergetool file11 file12 ) && - ( yes "r" | git mergetool submod ) && + yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && + yes "" | git mergetool both && + yes "d" | git mergetool file11 file12 && + yes "r" | git mergetool submod && test ! -e submod && test -d submod.orig && git submodule update -N && @@ -457,13 +485,15 @@ test_expect_success 'deleted vs modified submodule' ' git submodule update -N && test_must_fail git merge test$test_count && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) && - ( yes "" | git mergetool both ) && - ( yes "d" | git mergetool file11 file12 ) && - ( yes "l" | git mergetool submod ) && - test "$(cat submod/bar)" = "master submodule" && - git submodule update -N && - test "$(cat submod/bar)" = "master submodule" && + yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && + yes "" | git mergetool both && + yes "d" | git mergetool file11 file12 && + yes "l" | git mergetool submod && + echo "master submodule" >expect && + test_cmp expect submod/bar && + git submodule update -N && + echo "master submodule" >expect && + test_cmp expect submod/bar && output="$(git mergetool --no-prompt)" && test "$output" = "No files need merging" && git commit -m "Merge resolved by keeping module" @@ -481,14 +511,16 @@ test_expect_success 'file vs modified submodule' ' git checkout -b test$test_count.a branch1 && test_must_fail git merge master && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) && - ( yes "" | git mergetool both ) && - ( yes "d" | git mergetool file11 file12 ) && - ( yes "r" | git mergetool submod ) && + yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && + yes "" | git mergetool both && + yes "d" | git mergetool file11 file12 && + yes "r" | git mergetool submod && rmdir submod && mv submod-movedaside submod && - test "$(cat submod/bar)" = "branch1 submodule" && + echo "branch1 submodule" >expect && + test_cmp expect submod/bar && git submodule update -N && - test "$(cat submod/bar)" = "master submodule" && + echo "master submodule" >expect && + test_cmp expect submod/bar && output="$(git mergetool --no-prompt)" && test "$output" = "No files need merging" && git commit -m "Merge resolved by keeping module" && @@ -497,12 +529,13 @@ test_expect_success 'file vs modified submodule' ' git checkout -b test$test_count.b test$test_count && test_must_fail git merge master && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) && - ( yes "" | git mergetool both ) && - ( yes "d" | git mergetool file11 file12 ) && - ( yes "l" | git mergetool submod ) && + yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && + yes "" | git mergetool both && + yes "d" | git mergetool file11 file12 && + yes "l" | git mergetool submod && git submodule update -N && - test "$(cat submod)" = "not a submodule" && + echo "not a submodule" >expect && + test_cmp expect submod && output="$(git mergetool --no-prompt)" && test "$output" = "No files need merging" && git commit -m "Merge resolved by keeping file" && @@ -513,13 +546,14 @@ test_expect_success 'file vs modified submodule' ' git submodule update -N && test_must_fail git merge test$test_count && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) && - ( yes "" | git mergetool both ) && - ( yes "d" | git mergetool file11 file12 ) && - ( yes "r" | git mergetool submod ) && + yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && + yes "" | git mergetool both && + yes "d" | git mergetool file11 file12 && + yes "r" | git mergetool submod && test -d submod.orig && git submodule update -N && - test "$(cat submod)" = "not a submodule" && + echo "not a submodule" >expect && + test_cmp expect submod && output="$(git mergetool --no-prompt)" && test "$output" = "No files need merging" && git commit -m "Merge resolved by keeping file" && @@ -529,13 +563,15 @@ test_expect_success 'file vs modified submodule' ' git submodule update -N && test_must_fail git merge test$test_count && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) && - ( yes "" | git mergetool both ) && - ( yes "d" | git mergetool file11 file12 ) && - ( yes "l" | git mergetool submod ) && - test "$(cat submod/bar)" = "master submodule" && - git submodule update -N && - test "$(cat submod/bar)" = "master submodule" && + yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && + yes "" | git mergetool both && + yes "d" | git mergetool file11 file12 && + yes "l" | git mergetool submod && + echo "master submodule" >expect && + test_cmp expect submod/bar && + git submodule update -N && + echo "master submodule" >expect && + test_cmp expect submod/bar && output="$(git mergetool --no-prompt)" && test "$output" = "No files need merging" && git commit -m "Merge resolved by keeping module" @@ -587,19 +623,23 @@ test_expect_success 'submodule in subdirectory' ' test_must_fail git merge test$test_count.a && ( cd subdir && - ( yes "l" | git mergetool subdir_module ) + yes "l" | git mergetool subdir_module ) && - test "$(cat subdir/subdir_module/file15)" = "test$test_count.b" && + echo "test$test_count.b" >expect && + test_cmp expect subdir/subdir_module/file15 && git submodule update -N && - test "$(cat subdir/subdir_module/file15)" = "test$test_count.b" && + echo "test$test_count.b" >expect && + test_cmp expect subdir/subdir_module/file15 && git reset --hard && git submodule update -N && test_must_fail git merge test$test_count.a && - ( yes "r" | git mergetool subdir/subdir_module ) && - test "$(cat subdir/subdir_module/file15)" = "test$test_count.b" && + yes "r" | git mergetool subdir/subdir_module && + echo "test$test_count.b" >expect && + test_cmp expect subdir/subdir_module/file15 && git submodule update -N && - test "$(cat subdir/subdir_module/file15)" = "test$test_count.a" && + echo "test$test_count.a" >expect && + test_cmp expect subdir/subdir_module/file15 && git commit -m "branch1 resolved with mergetool" ' @@ -615,22 +655,25 @@ test_expect_success 'directory vs modified submodule' ' test_must_fail git merge master && test -n "$(git ls-files -u)" && - ( yes "l" | git mergetool submod ) && - test "$(cat submod/file16)" = "not a submodule" && + yes "l" | git mergetool submod && + echo "not a submodule" >expect && + test_cmp expect submod/file16 && rm -rf submod.orig && git reset --hard && test_must_fail git merge master && test -n "$(git ls-files -u)" && test ! -e submod.orig && - ( yes "r" | git mergetool submod ) && + yes "r" | git mergetool submod && test -d submod.orig && - test "$(cat submod.orig/file16)" = "not a submodule" && + echo "not a submodule" >expect && + test_cmp expect submod.orig/file16 && rm -r submod.orig && mv submod-movedaside/.git submod && ( cd submod && git clean -f && git reset --hard ) && git submodule update -N && - test "$(cat submod/bar)" = "master submodule" && + echo "master submodule" >expect && + test_cmp expect submod/bar && git reset --hard && rm -rf submod-movedaside && @@ -638,17 +681,19 @@ test_expect_success 'directory vs modified submodule' ' git submodule update -N && test_must_fail git merge test$test_count && test -n "$(git ls-files -u)" && - ( yes "l" | git mergetool submod ) && + yes "l" | git mergetool submod && git submodule update -N && - test "$(cat submod/bar)" = "master submodule" && + echo "master submodule" >expect && + test_cmp expect submod/bar && git reset --hard && git submodule update -N && test_must_fail git merge test$test_count && test -n "$(git ls-files -u)" && test ! -e submod.orig && - ( yes "r" | git mergetool submod ) && - test "$(cat submod/file16)" = "not a submodule" && + yes "r" | git mergetool submod && + echo "not a submodule" >expect && + test_cmp expect submod/file16 && git reset --hard master && ( cd submod && git clean -f && git reset --hard ) && diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh index 86d05160a3..4e855bc21b 100755 --- a/t/t7700-repack.sh +++ b/t/t7700-repack.sh @@ -239,4 +239,27 @@ test_expect_success 'bitmaps can be disabled on bare repos' ' test -z "$bitmap" ' +test_expect_success 'no bitmaps created if .keep files present' ' + pack=$(ls bare.git/objects/pack/*.pack) && + test_path_is_file "$pack" && + keep=${pack%.pack}.keep && + test_when_finished "rm -f \"\$keep\"" && + >"$keep" && + git -C bare.git repack -ad 2>stderr && + test_must_be_empty stderr && + find bare.git/objects/pack/ -type f -name "*.bitmap" >actual && + test_must_be_empty actual +' + +test_expect_success 'auto-bitmaps do not complain if unavailable' ' + test_config -C bare.git pack.packSizeLimit 1M && + blob=$(test-tool genrandom big $((1024*1024)) | + git -C bare.git hash-object -w --stdin) && + git -C bare.git update-ref refs/tags/big $blob && + git -C bare.git repack -ad 2>stderr && + test_must_be_empty stderr && + find bare.git/objects/pack -type f -name "*.bitmap" >actual && + test_must_be_empty actual +' + test_done diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index 2e1bb61b41..7d7b396c23 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -412,7 +412,7 @@ do test_cmp expected actual ' - test_expect_success !PCRE "grep $L with grep.patterntype=perl errors without PCRE" ' + test_expect_success !FAIL_PREREQS,!PCRE "grep $L with grep.patterntype=perl errors without PCRE" ' test_must_fail git -c grep.patterntype=perl grep "foo.*bar" ' @@ -1234,7 +1234,7 @@ test_expect_success PCRE 'grep --perl-regexp pattern' ' test_cmp expected actual ' -test_expect_success !PCRE 'grep --perl-regexp pattern errors without PCRE' ' +test_expect_success !FAIL_PREREQS,!PCRE 'grep --perl-regexp pattern errors without PCRE' ' test_must_fail git grep --perl-regexp "foo.*bar" ' @@ -1249,7 +1249,7 @@ test_expect_success LIBPCRE2 "grep -P with (*NO_JIT) doesn't error out" ' ' -test_expect_success !PCRE 'grep -P pattern errors without PCRE' ' +test_expect_success !FAIL_PREREQS,!PCRE 'grep -P pattern errors without PCRE' ' test_must_fail git grep -P "foo.*bar" ' diff --git a/t/t7811-grep-open.sh b/t/t7811-grep-open.sh index d1ebfd88c7..a98785da79 100755 --- a/t/t7811-grep-open.sh +++ b/t/t7811-grep-open.sh @@ -113,7 +113,6 @@ test_expect_success 'modified file' ' subdir/grep.c unrelated EOF - >empty && echo "enum grep_pat_token" >unrelated && test_when_finished "git checkout HEAD unrelated" && diff --git a/t/t7812-grep-icase-non-ascii.sh b/t/t7812-grep-icase-non-ascii.sh index 0c685d3598..03dba6685a 100755 --- a/t/t7812-grep-icase-non-ascii.sh +++ b/t/t7812-grep-icase-non-ascii.sh @@ -53,4 +53,35 @@ test_expect_success REGEX_LOCALE 'pickaxe -i on non-ascii' ' test_cmp expected actual ' +test_expect_success GETTEXT_LOCALE,LIBPCRE2 'PCRE v2: setup invalid UTF-8 data' ' + printf "\\200\\n" >invalid-0x80 && + echo "ævar" >expected && + cat expected >>invalid-0x80 && + git add invalid-0x80 +' + +test_expect_success GETTEXT_LOCALE,LIBPCRE2 'PCRE v2: grep ASCII from invalid UTF-8 data' ' + git grep -h "var" invalid-0x80 >actual && + test_cmp expected actual && + git grep -h "(*NO_JIT)var" invalid-0x80 >actual && + test_cmp expected actual +' + +test_expect_success GETTEXT_LOCALE,LIBPCRE2 'PCRE v2: grep non-ASCII from invalid UTF-8 data' ' + git grep -h "æ" invalid-0x80 >actual && + test_cmp expected actual && + git grep -h "(*NO_JIT)æ" invalid-0x80 >actual && + test_cmp expected actual +' + +test_expect_success GETTEXT_LOCALE,LIBPCRE2 'PCRE v2: grep non-ASCII from invalid UTF-8 data with -i' ' + test_might_fail git grep -hi "Æ" invalid-0x80 >actual && + if test -s actual + then + test_cmp expected actual + fi && + test_must_fail git grep -hi "(*NO_JIT)Æ" invalid-0x80 >actual && + ! test_cmp expected actual +' + test_done diff --git a/t/t7814-grep-recurse-submodules.sh b/t/t7814-grep-recurse-submodules.sh index 134a694516..946f91fa57 100755 --- a/t/t7814-grep-recurse-submodules.sh +++ b/t/t7814-grep-recurse-submodules.sh @@ -14,12 +14,14 @@ test_expect_success 'setup directory structure and submodule' ' echo "(3|4)" >b/b && git add a b && git commit -m "add a and b" && + test_tick && git init submodule && echo "(1|2)d(3|4)" >submodule/a && git -C submodule add a && git -C submodule commit -m "add a" && git submodule add ./submodule && - git commit -m "added submodule" + git commit -m "added submodule" && + test_tick ' test_expect_success 'grep correctly finds patterns in a submodule' ' @@ -65,11 +67,14 @@ test_expect_success 'grep and nested submodules' ' echo "(1|2)d(3|4)" >submodule/sub/a && git -C submodule/sub add a && git -C submodule/sub commit -m "add a" && + test_tick && git -C submodule submodule add ./sub && git -C submodule add sub && git -C submodule commit -m "added sub" && + test_tick && git add submodule && git commit -m "updated submodule" && + test_tick && cat >expect <<-\EOF && a:(1|2)d(3|4) @@ -179,15 +184,18 @@ test_expect_success !MINGW 'grep recurse submodule colon in name' ' echo "(1|2)d(3|4)" >"parent/fi:le" && git -C parent add "fi:le" && git -C parent commit -m "add fi:le" && + test_tick && git init "su:b" && test_when_finished "rm -rf su:b" && echo "(1|2)d(3|4)" >"su:b/fi:le" && git -C "su:b" add "fi:le" && git -C "su:b" commit -m "add fi:le" && + test_tick && git -C parent submodule add "../su:b" "su:b" && git -C parent commit -m "add submodule" && + test_tick && cat >expect <<-\EOF && fi:le:(1|2)d(3|4) @@ -210,15 +218,18 @@ test_expect_success 'grep history with moved submoules' ' echo "(1|2)d(3|4)" >parent/file && git -C parent add file && git -C parent commit -m "add file" && + test_tick && git init sub && test_when_finished "rm -rf sub" && echo "(1|2)d(3|4)" >sub/file && git -C sub add file && git -C sub commit -m "add file" && + test_tick && git -C parent submodule add ../sub dir/sub && git -C parent commit -m "add submodule" && + test_tick && cat >expect <<-\EOF && dir/sub/file:(1|2)d(3|4) @@ -229,6 +240,7 @@ test_expect_success 'grep history with moved submoules' ' git -C parent mv dir/sub sub-moved && git -C parent commit -m "moved submodule" && + test_tick && cat >expect <<-\EOF && file:(1|2)d(3|4) @@ -251,6 +263,7 @@ test_expect_success 'grep using relative path' ' echo "(1|2)d(3|4)" >sub/file && git -C sub add file && git -C sub commit -m "add file" && + test_tick && git init parent && echo "(1|2)d(3|4)" >parent/file && @@ -260,6 +273,7 @@ test_expect_success 'grep using relative path' ' git -C parent add src/file2 && git -C parent submodule add ../sub && git -C parent commit -m "add files and submodule" && + test_tick && # From top works cat >expect <<-\EOF && @@ -293,6 +307,7 @@ test_expect_success 'grep from a subdir' ' echo "(1|2)d(3|4)" >sub/file && git -C sub add file && git -C sub commit -m "add file" && + test_tick && git init parent && mkdir parent/src && @@ -301,6 +316,7 @@ test_expect_success 'grep from a subdir' ' git -C parent submodule add ../sub src/sub && git -C parent submodule add ../sub sub && git -C parent commit -m "add files and submodules" && + test_tick && # Verify grep from root works cat >expect <<-\EOF && @@ -392,4 +408,25 @@ test_expect_success 'grep --recurse-submodules with submodules without .gitmodul test_cmp expect actual ' +reset_and_clean () { + git reset --hard && + git clean -fd && + git submodule foreach --recursive 'git reset --hard' && + git submodule foreach --recursive 'git clean -fd' +} + +test_expect_success 'grep --recurse-submodules without --cached considers worktree modifications' ' + reset_and_clean && + echo "A modified line in submodule" >>submodule/a && + echo "submodule/a:A modified line in submodule" >expect && + git grep --recurse-submodules "A modified line in submodule" >actual && + test_cmp expect actual +' + +test_expect_success 'grep --recurse-submodules with --cached ignores worktree modifications' ' + reset_and_clean && + echo "A modified line in submodule" >>submodule/a && + test_must_fail git grep --recurse-submodules --cached "A modified line in submodule" >actual 2>&1 && + test_must_be_empty actual +' test_done diff --git a/t/t7008-grep-binary.sh b/t/t7815-grep-binary.sh index 2d87c49b75..90ebb64f46 100755 --- a/t/t7008-grep-binary.sh +++ b/t/t7815-grep-binary.sh @@ -4,41 +4,6 @@ test_description='git grep in binary files' . ./test-lib.sh -nul_match () { - matches=$1 - flags=$2 - pattern=$3 - pattern_human=$(echo "$pattern" | sed 's/Q/<NUL>/g') - - if test "$matches" = 1 - then - test_expect_success "git grep -f f $flags '$pattern_human' a" " - printf '$pattern' | q_to_nul >f && - git grep -f f $flags a - " - elif test "$matches" = 0 - then - test_expect_success "git grep -f f $flags '$pattern_human' a" " - printf '$pattern' | q_to_nul >f && - test_must_fail git grep -f f $flags a - " - elif test "$matches" = T1 - then - test_expect_failure "git grep -f f $flags '$pattern_human' a" " - printf '$pattern' | q_to_nul >f && - git grep -f f $flags a - " - elif test "$matches" = T0 - then - test_expect_failure "git grep -f f $flags '$pattern_human' a" " - printf '$pattern' | q_to_nul >f && - test_must_fail git grep -f f $flags a - " - else - test_expect_success "PANIC: Test framework error. Unknown matches value $matches" 'false' - fi -} - test_expect_success 'setup' " echo 'binaryQfileQm[*]cQ*æQð' | q_to_nul >a && git add a && @@ -102,72 +67,6 @@ test_expect_failure 'git grep .fi a' ' git grep .fi a ' -nul_match 1 '-F' 'yQf' -nul_match 0 '-F' 'yQx' -nul_match 1 '-Fi' 'YQf' -nul_match 0 '-Fi' 'YQx' -nul_match 1 '' 'yQf' -nul_match 0 '' 'yQx' -nul_match 1 '' 'æQð' -nul_match 1 '-F' 'eQm[*]c' -nul_match 1 '-Fi' 'EQM[*]C' - -# Regex patterns that would match but shouldn't with -F -nul_match 0 '-F' 'yQ[f]' -nul_match 0 '-F' '[y]Qf' -nul_match 0 '-Fi' 'YQ[F]' -nul_match 0 '-Fi' '[Y]QF' -nul_match 0 '-F' 'æQ[ð]' -nul_match 0 '-F' '[æ]Qð' -nul_match 0 '-Fi' 'ÆQ[Ð]' -nul_match 0 '-Fi' '[Æ]QÐ' - -# kwset is disabled on -i & non-ASCII. No way to match non-ASCII \0 -# patterns case-insensitively. -nul_match T1 '-i' 'ÆQÐ' - -# \0 implicitly disables regexes. This is an undocumented internal -# limitation. -nul_match T1 '' 'yQ[f]' -nul_match T1 '' '[y]Qf' -nul_match T1 '-i' 'YQ[F]' -nul_match T1 '-i' '[Y]Qf' -nul_match T1 '' 'æQ[ð]' -nul_match T1 '' '[æ]Qð' -nul_match T1 '-i' 'ÆQ[Ð]' - -# ... because of \0 implicitly disabling regexes regexes that -# should/shouldn't match don't do the right thing. -nul_match T1 '' 'eQm.*cQ' -nul_match T1 '-i' 'EQM.*cQ' -nul_match T0 '' 'eQm[*]c' -nul_match T0 '-i' 'EQM[*]C' - -# Due to the REG_STARTEND extension when kwset() is disabled on -i & -# non-ASCII the string will be matched in its entirety, but the -# pattern will be cut off at the first \0. -nul_match 0 '-i' 'NOMATCHQð' -nul_match T0 '-i' '[Æ]QNOMATCH' -nul_match T0 '-i' '[æ]QNOMATCH' -# Matches, but for the wrong reasons, just stops at [æ] -nul_match 1 '-i' '[Æ]Qð' -nul_match 1 '-i' '[æ]Qð' - -# Ensure that the matcher doesn't regress to something that stops at -# \0 -nul_match 0 '-F' 'yQ[f]' -nul_match 0 '-Fi' 'YQ[F]' -nul_match 0 '' 'yQNOMATCH' -nul_match 0 '' 'QNOMATCH' -nul_match 0 '-i' 'YQNOMATCH' -nul_match 0 '-i' 'QNOMATCH' -nul_match 0 '-F' 'æQ[ð]' -nul_match 0 '-Fi' 'ÆQ[Ð]' -nul_match 0 '' 'yQNÓMATCH' -nul_match 0 '' 'QNÓMATCH' -nul_match 0 '-i' 'YQNÓMATCH' -nul_match 0 '-i' 'QNÓMATCH' - test_expect_success 'grep respects binary diff attribute' ' echo text >t && git add t && diff --git a/t/t7816-grep-binary-pattern.sh b/t/t7816-grep-binary-pattern.sh new file mode 100755 index 0000000000..60bab291e4 --- /dev/null +++ b/t/t7816-grep-binary-pattern.sh @@ -0,0 +1,127 @@ +#!/bin/sh + +test_description='git grep with a binary pattern files' + +. ./lib-gettext.sh + +nul_match_internal () { + matches=$1 + prereqs=$2 + lc_all=$3 + extra_flags=$4 + flags=$5 + pattern=$6 + pattern_human=$(echo "$pattern" | sed 's/Q/<NUL>/g') + + if test "$matches" = 1 + then + test_expect_success $prereqs "LC_ALL='$lc_all' git grep $extra_flags -f f $flags '$pattern_human' a" " + printf '$pattern' | q_to_nul >f && + LC_ALL='$lc_all' git grep $extra_flags -f f $flags a + " + elif test "$matches" = 0 + then + test_expect_success $prereqs "LC_ALL='$lc_all' git grep $extra_flags -f f $flags '$pattern_human' a" " + >stderr && + printf '$pattern' | q_to_nul >f && + test_must_fail env LC_ALL=\"$lc_all\" git grep $extra_flags -f f $flags a 2>stderr && + test_i18ngrep ! 'This is only supported with -P under PCRE v2' stderr + " + elif test "$matches" = P + then + test_expect_success $prereqs "error, PCRE v2 only: LC_ALL='$lc_all' git grep -f f $flags '$pattern_human' a" " + >stderr && + printf '$pattern' | q_to_nul >f && + test_must_fail env LC_ALL=\"$lc_all\" git grep -f f $flags a 2>stderr && + test_i18ngrep 'This is only supported with -P under PCRE v2' stderr + " + else + test_expect_success "PANIC: Test framework error. Unknown matches value $matches" 'false' + fi +} + +nul_match () { + matches=$1 + matches_pcre2=$2 + matches_pcre2_locale=$3 + flags=$4 + pattern=$5 + pattern_human=$(echo "$pattern" | sed 's/Q/<NUL>/g') + + nul_match_internal "$matches" "" "C" "" "$flags" "$pattern" + nul_match_internal "$matches_pcre2" "LIBPCRE2" "C" "-P" "$flags" "$pattern" + nul_match_internal "$matches_pcre2_locale" "LIBPCRE2,GETTEXT_LOCALE" "$is_IS_locale" "-P" "$flags" "$pattern" +} + +test_expect_success 'setup' " + echo 'binaryQfileQm[*]cQ*æQð' | q_to_nul >a && + git add a && + git commit -m. +" + +# Simple fixed-string matching that can use kwset (no -i && non-ASCII) +nul_match P P P '-F' 'yQf' +nul_match P P P '-F' 'yQx' +nul_match P P P '-Fi' 'YQf' +nul_match P P P '-Fi' 'YQx' +nul_match P P 1 '' 'yQf' +nul_match P P 0 '' 'yQx' +nul_match P P 1 '' 'æQð' +nul_match P P P '-F' 'eQm[*]c' +nul_match P P P '-Fi' 'EQM[*]C' + +# Regex patterns that would match but shouldn't with -F +nul_match P P P '-F' 'yQ[f]' +nul_match P P P '-F' '[y]Qf' +nul_match P P P '-Fi' 'YQ[F]' +nul_match P P P '-Fi' '[Y]QF' +nul_match P P P '-F' 'æQ[ð]' +nul_match P P P '-F' '[æ]Qð' + +# The -F kwset codepath can't handle -i && non-ASCII... +nul_match P 1 1 '-i' '[æ]Qð' + +# ...PCRE v2 only matches non-ASCII with -i casefolding under UTF-8 +# semantics +nul_match P P P '-Fi' 'ÆQ[Ð]' +nul_match P 0 1 '-i' 'ÆQ[Ð]' +nul_match P 0 1 '-i' '[Æ]QÐ' +nul_match P 0 1 '-i' '[Æ]Qð' +nul_match P 0 1 '-i' 'ÆQÐ' + +# \0 in regexes can only work with -P & PCRE v2 +nul_match P P 1 '' 'yQ[f]' +nul_match P P 1 '' '[y]Qf' +nul_match P P 1 '-i' 'YQ[F]' +nul_match P P 1 '-i' '[Y]Qf' +nul_match P P 1 '' 'æQ[ð]' +nul_match P P 1 '' '[æ]Qð' +nul_match P P 1 '-i' 'ÆQ[Ð]' +nul_match P P 1 '' 'eQm.*cQ' +nul_match P P 1 '-i' 'EQM.*cQ' +nul_match P P 0 '' 'eQm[*]c' +nul_match P P 0 '-i' 'EQM[*]C' + +# Assert that we're using REG_STARTEND and the pattern doesn't match +# just because it's cut off at the first \0. +nul_match P P 0 '-i' 'NOMATCHQð' +nul_match P P 0 '-i' '[Æ]QNOMATCH' +nul_match P P 0 '-i' '[æ]QNOMATCH' + +# Ensure that the matcher doesn't regress to something that stops at +# \0 +nul_match P P P '-F' 'yQ[f]' +nul_match P P P '-Fi' 'YQ[F]' +nul_match P P 0 '' 'yQNOMATCH' +nul_match P P 0 '' 'QNOMATCH' +nul_match P P 0 '-i' 'YQNOMATCH' +nul_match P P 0 '-i' 'QNOMATCH' +nul_match P P P '-F' 'æQ[ð]' +nul_match P P P '-Fi' 'ÆQ[Ð]' +nul_match P P 1 '-i' 'ÆQ[Ð]' +nul_match P P 0 '' 'yQNÓMATCH' +nul_match P P 0 '' 'QNÓMATCH' +nul_match P P 0 '-i' 'YQNÓMATCH' +nul_match P P 0 '-i' 'QNÓMATCH' + +test_done diff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh index c92a47b6d5..1c5fb1d1f8 100755 --- a/t/t8003-blame-corner-cases.sh +++ b/t/t8003-blame-corner-cases.sh @@ -275,4 +275,40 @@ test_expect_success 'blame file with CRLF core.autocrlf=true' ' grep "A U Thor" actual ' +# Tests the splitting and merging of blame entries in blame_coalesce(). +# The output of blame is the same, regardless of whether blame_coalesce() runs +# or not, so we'd likely only notice a problem if blame crashes or assigned +# blame to the "splitting" commit ('SPLIT' below). +test_expect_success 'blame coalesce' ' + cat >giraffe <<-\EOF && + ABC + DEF + EOF + git add giraffe && + git commit -m "original file" && + oid=$(git rev-parse HEAD) && + + cat >giraffe <<-\EOF && + ABC + SPLIT + DEF + EOF + git add giraffe && + git commit -m "interior SPLIT line" && + + cat >giraffe <<-\EOF && + ABC + DEF + EOF + git add giraffe && + git commit -m "same contents as original" && + + cat >expect <<-EOF && + $oid 1) ABC + $oid 2) DEF + EOF + git -c core.abbrev=40 blame -s giraffe >actual && + test_cmp expect actual +' + test_done diff --git a/t/t8013-blame-ignore-revs.sh b/t/t8013-blame-ignore-revs.sh new file mode 100755 index 0000000000..36dc31eb39 --- /dev/null +++ b/t/t8013-blame-ignore-revs.sh @@ -0,0 +1,274 @@ +#!/bin/sh + +test_description='ignore revisions when blaming' +. ./test-lib.sh + +# Creates: +# A--B--X +# A added line 1 and B added line 2. X makes changes to those lines. Sanity +# check that X is blamed for both lines. +test_expect_success setup ' + test_commit A file line1 && + + echo line2 >>file && + git add file && + test_tick && + git commit -m B && + git tag B && + + test_write_lines line-one line-two >file && + git add file && + test_tick && + git commit -m X && + git tag X && + + git blame --line-porcelain file >blame_raw && + + grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual && + git rev-parse X >expect && + test_cmp expect actual && + + grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual && + git rev-parse X >expect && + test_cmp expect actual + ' + +# Ignore X, make sure A is blamed for line 1 and B for line 2. +test_expect_success ignore_rev_changing_lines ' + git blame --line-porcelain --ignore-rev X file >blame_raw && + + grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual && + git rev-parse A >expect && + test_cmp expect actual && + + grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual && + git rev-parse B >expect && + test_cmp expect actual + ' + +# For ignored revs that have added 'unblamable' lines, attribute those to the +# ignored commit. +# A--B--X--Y +# Where Y changes lines 1 and 2, and adds lines 3 and 4. The added lines ought +# to have nothing in common with "line-one" or "line-two", to keep any +# heuristics from matching them with any lines in the parent. +test_expect_success ignore_rev_adding_unblamable_lines ' + test_write_lines line-one-change line-two-changed y3 y4 >file && + git add file && + test_tick && + git commit -m Y && + git tag Y && + + git rev-parse Y >expect && + git blame --line-porcelain file --ignore-rev Y >blame_raw && + + grep -E "^[0-9a-f]+ [0-9]+ 3" blame_raw | sed -e "s/ .*//" >actual && + test_cmp expect actual && + + grep -E "^[0-9a-f]+ [0-9]+ 4" blame_raw | sed -e "s/ .*//" >actual && + test_cmp expect actual + ' + +# Ignore X and Y, both in separate files. Lines 1 == A, 2 == B. +test_expect_success ignore_revs_from_files ' + git rev-parse X >ignore_x && + git rev-parse Y >ignore_y && + git blame --line-porcelain file --ignore-revs-file ignore_x --ignore-revs-file ignore_y >blame_raw && + + grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual && + git rev-parse A >expect && + test_cmp expect actual && + + grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual && + git rev-parse B >expect && + test_cmp expect actual + ' + +# Ignore X from the config option, Y from a file. +test_expect_success ignore_revs_from_configs_and_files ' + git config --add blame.ignoreRevsFile ignore_x && + git blame --line-porcelain file --ignore-revs-file ignore_y >blame_raw && + + grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual && + git rev-parse A >expect && + test_cmp expect actual && + + grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual && + git rev-parse B >expect && + test_cmp expect actual + ' + +# Override blame.ignoreRevsFile (ignore_x) with an empty string. X should be +# blamed now for lines 1 and 2, since we are no longer ignoring X. +test_expect_success override_ignore_revs_file ' + git blame --line-porcelain file --ignore-revs-file "" --ignore-revs-file ignore_y >blame_raw && + git rev-parse X >expect && + + grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual && + test_cmp expect actual && + + grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual && + test_cmp expect actual + ' +test_expect_success bad_files_and_revs ' + test_must_fail git blame file --ignore-rev NOREV 2>err && + test_i18ngrep "cannot find revision NOREV to ignore" err && + + test_must_fail git blame file --ignore-revs-file NOFILE 2>err && + test_i18ngrep "could not open.*: NOFILE" err && + + echo NOREV >ignore_norev && + test_must_fail git blame file --ignore-revs-file ignore_norev 2>err && + test_i18ngrep "invalid object name: NOREV" err + ' + +# For ignored revs that have added 'unblamable' lines, mark those lines with a +# '*' +# A--B--X--Y +# Lines 3 and 4 are from Y and unblamable. This was set up in +# ignore_rev_adding_unblamable_lines. +test_expect_success mark_unblamable_lines ' + git config --add blame.markUnblamableLines true && + + git blame --ignore-rev Y file >blame_raw && + echo "*" >expect && + + sed -n "3p" blame_raw | cut -c1 >actual && + test_cmp expect actual && + + sed -n "4p" blame_raw | cut -c1 >actual && + test_cmp expect actual + ' + +# Commit Z will touch the first two lines. Y touched all four. +# A--B--X--Y--Z +# The blame output when ignoring Z should be: +# ?Y ... 1) +# ?Y ... 2) +# Y ... 3) +# Y ... 4) +# We're checking only the first character +test_expect_success mark_ignored_lines ' + git config --add blame.markIgnoredLines true && + + test_write_lines line-one-Z line-two-Z y3 y4 >file && + git add file && + test_tick && + git commit -m Z && + git tag Z && + + git blame --ignore-rev Z file >blame_raw && + echo "?" >expect && + + sed -n "1p" blame_raw | cut -c1 >actual && + test_cmp expect actual && + + sed -n "2p" blame_raw | cut -c1 >actual && + test_cmp expect actual && + + sed -n "3p" blame_raw | cut -c1 >actual && + ! test_cmp expect actual && + + sed -n "4p" blame_raw | cut -c1 >actual && + ! test_cmp expect actual + ' + +# For ignored revs that added 'unblamable' lines and more recent commits changed +# the blamable lines, mark the unblamable lines with a +# '*' +# A--B--X--Y--Z +# Lines 3 and 4 are from Y and unblamable, as set up in +# ignore_rev_adding_unblamable_lines. Z changed lines 1 and 2. +test_expect_success mark_unblamable_lines_intermediate ' + git config --add blame.markUnblamableLines true && + + git blame --ignore-rev Y file >blame_raw 2>stderr && + echo "*" >expect && + + sed -n "3p" blame_raw | cut -c1 >actual && + test_cmp expect actual && + + sed -n "4p" blame_raw | cut -c1 >actual && + test_cmp expect actual + ' + +# The heuristic called by guess_line_blames() tries to find the size of a +# blame_entry 'e' in the parent's address space. Those calculations need to +# check for negative or zero values for when a blame entry is completely outside +# the window of the parent's version of a file. +# +# This happens when one commit adds several lines (commit B below). A later +# commit (C) changes one line in the middle of B's change. Commit C gets blamed +# for its change, and that breaks up B's change into multiple blame entries. +# When processing B, one of the blame_entries is outside A's window (which was +# zero - it had no lines added on its side of the diff). +# +# A--B--C, ignore B to test the ignore heuristic's boundary checks. +test_expect_success ignored_chunk_negative_parent_size ' + rm -rf .git/ && + git init && + + test_write_lines L1 L2 L7 L8 L9 >file && + git add file && + test_tick && + git commit -m A && + git tag A && + + test_write_lines L1 L2 L3 L4 L5 L6 L7 L8 L9 >file && + git add file && + test_tick && + git commit -m B && + git tag B && + + test_write_lines L1 L2 L3 L4 xxx L6 L7 L8 L9 >file && + git add file && + test_tick && + git commit -m C && + git tag C && + + git blame file --ignore-rev B >blame_raw + ' + +# Resetting the repo and creating: +# +# A--B--M +# \ / +# C-+ +# +# 'A' creates a file. B changes line 1, and C changes line 9. M merges. +test_expect_success ignore_merge ' + rm -rf .git/ && + git init && + + test_write_lines L1 L2 L3 L4 L5 L6 L7 L8 L9 >file && + git add file && + test_tick && + git commit -m A && + git tag A && + + test_write_lines BB L2 L3 L4 L5 L6 L7 L8 L9 >file && + git add file && + test_tick && + git commit -m B && + git tag B && + + git reset --hard A && + test_write_lines L1 L2 L3 L4 L5 L6 L7 L8 CC >file && + git add file && + test_tick && + git commit -m C && + git tag C && + + test_merge M B && + git blame --line-porcelain file --ignore-rev M >blame_raw && + + grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual && + git rev-parse B >expect && + test_cmp expect actual && + + grep -E "^[0-9a-f]+ [0-9]+ 9" blame_raw | sed -e "s/ .*//" >actual && + git rev-parse C >expect && + test_cmp expect actual + ' + +test_done diff --git a/t/t8014-blame-ignore-fuzzy.sh b/t/t8014-blame-ignore-fuzzy.sh new file mode 100755 index 0000000000..6e61882b6f --- /dev/null +++ b/t/t8014-blame-ignore-fuzzy.sh @@ -0,0 +1,437 @@ +#!/bin/sh + +test_description='git blame ignore fuzzy heuristic' +. ./test-lib.sh + +pick_author='s/^[0-9a-f^]* *(\([^ ]*\) .*/\1/' + +# Each test is composed of 4 variables: +# titleN - the test name +# aN - the initial content +# bN - the final content +# expectedN - the line numbers from aN that we expect git blame +# on bN to identify, or "Final" if bN itself should +# be identified as the origin of that line. + +# We start at test 2 because setup will show as test 1 +title2="Regression test for partially overlapping search ranges" +cat <<EOF >a2 +1 +2 +3 +abcdef +5 +6 +7 +ijkl +9 +10 +11 +pqrs +13 +14 +15 +wxyz +17 +18 +19 +EOF +cat <<EOF >b2 +abcde +ijk +pqr +wxy +EOF +cat <<EOF >expected2 +4 +8 +12 +16 +EOF + +title3="Combine 3 lines into 2" +cat <<EOF >a3 +if ((maxgrow==0) || + ( single_line_field && (field->dcols < maxgrow)) || + (!single_line_field && (field->drows < maxgrow))) +EOF +cat <<EOF >b3 +if ((maxgrow == 0) || (single_line_field && (field->dcols < maxgrow)) || + (!single_line_field && (field->drows < maxgrow))) { +EOF +cat <<EOF >expected3 +2 +3 +EOF + +title4="Add curly brackets" +cat <<EOF >a4 + if (rows) *rows = field->rows; + if (cols) *cols = field->cols; + if (frow) *frow = field->frow; + if (fcol) *fcol = field->fcol; +EOF +cat <<EOF >b4 + if (rows) { + *rows = field->rows; + } + if (cols) { + *cols = field->cols; + } + if (frow) { + *frow = field->frow; + } + if (fcol) { + *fcol = field->fcol; + } +EOF +cat <<EOF >expected4 +1 +1 +Final +2 +2 +Final +3 +3 +Final +4 +4 +Final +EOF + + +title5="Combine many lines and change case" +cat <<EOF >a5 +for(row=0,pBuffer=field->buf; + row<height; + row++,pBuffer+=width ) +{ + if ((len = (int)( After_End_Of_Data( pBuffer, width ) - pBuffer )) > 0) + { + wmove( win, row, 0 ); + waddnstr( win, pBuffer, len ); +EOF +cat <<EOF >b5 +for (Row = 0, PBuffer = field->buf; Row < Height; Row++, PBuffer += Width) { + if ((Len = (int)(afterEndOfData(PBuffer, Width) - PBuffer)) > 0) { + wmove(win, Row, 0); + waddnstr(win, PBuffer, Len); +EOF +cat <<EOF >expected5 +1 +5 +7 +8 +EOF + +title6="Rename and combine lines" +cat <<EOF >a6 +bool need_visual_update = ((form != (FORM *)0) && + (form->status & _POSTED) && + (form->current==field)); + +if (need_visual_update) + Synchronize_Buffer(form); + +if (single_line_field) +{ + growth = field->cols * amount; + if (field->maxgrow) + growth = Minimum(field->maxgrow - field->dcols,growth); + field->dcols += growth; + if (field->dcols == field->maxgrow) +EOF +cat <<EOF >b6 +bool NeedVisualUpdate = ((Form != (FORM *)0) && (Form->status & _POSTED) && + (Form->current == field)); + +if (NeedVisualUpdate) { + synchronizeBuffer(Form); +} + +if (SingleLineField) { + Growth = field->cols * amount; + if (field->maxgrow) { + Growth = Minimum(field->maxgrow - field->dcols, Growth); + } + field->dcols += Growth; + if (field->dcols == field->maxgrow) { +EOF +cat <<EOF >expected6 +1 +3 +4 +5 +6 +Final +7 +8 +10 +11 +12 +Final +13 +14 +EOF + +# Both lines match identically so position must be used to tie-break. +title7="Same line twice" +cat <<EOF >a7 +abc +abc +EOF +cat <<EOF >b7 +abcd +abcd +EOF +cat <<EOF >expected7 +1 +2 +EOF + +title8="Enforce line order" +cat <<EOF >a8 +abcdef +ghijkl +ab +EOF +cat <<EOF >b8 +ghijk +abcd +EOF +cat <<EOF >expected8 +2 +3 +EOF + +title9="Expand lines and rename variables" +cat <<EOF >a9 +int myFunction(int ArgumentOne, Thing *ArgTwo, Blah XuglyBug) { + Squiggle FabulousResult = squargle(ArgumentOne, *ArgTwo, + XuglyBug) + EwwwGlobalWithAReallyLongNameYepTooLong; + return FabulousResult * 42; +} +EOF +cat <<EOF >b9 +int myFunction(int argument_one, Thing *arg_asdfgh, + Blah xugly_bug) { + Squiggle fabulous_result = squargle(argument_one, + *arg_asdfgh, xugly_bug) + + g_ewww_global_with_a_really_long_name_yep_too_long; + return fabulous_result * 42; +} +EOF +cat <<EOF >expected9 +1 +1 +2 +3 +3 +4 +5 +EOF + +title10="Two close matches versus one less close match" +cat <<EOF >a10 +abcdef +abcdef +ghijkl +EOF +cat <<EOF >b10 +gh +abcdefx +EOF +cat <<EOF >expected10 +Final +2 +EOF + +# The first line of b matches best with the last line of a, but the overall +# match is better if we match it with the the first line of a. +title11="Piggy in the middle" +cat <<EOF >a11 +abcdefg +ijklmn +abcdefgh +EOF +cat <<EOF >b11 +abcdefghx +ijklm +EOF +cat <<EOF >expected11 +1 +2 +EOF + +title12="No trailing newline" +printf "abc\ndef" >a12 +printf "abx\nstu" >b12 +cat <<EOF >expected12 +1 +Final +EOF + +title13="Reorder includes" +cat <<EOF >a13 +#include "c.h" +#include "b.h" +#include "a.h" +#include "e.h" +#include "d.h" +EOF +cat <<EOF >b13 +#include "a.h" +#include "b.h" +#include "c.h" +#include "d.h" +#include "e.h" +EOF +cat <<EOF >expected13 +3 +2 +1 +5 +4 +EOF + +last_test=13 + +test_expect_success setup ' + for i in $(test_seq 2 $last_test) + do + # Append each line in a separate commit to make it easy to + # check which original line the blame output relates to. + + line_count=0 && + while IFS= read line + do + line_count=$((line_count+1)) && + echo "$line" >>"$i" && + git add "$i" && + test_tick && + GIT_AUTHOR_NAME="$line_count" git commit -m "$line_count" + done <"a$i" + done && + + for i in $(test_seq 2 $last_test) + do + # Overwrite the files with the final content. + cp b$i $i && + git add $i + done && + test_tick && + + # Commit the final content all at once so it can all be + # referred to with the same commit ID. + GIT_AUTHOR_NAME=Final git commit -m Final && + + IGNOREME=$(git rev-parse HEAD) +' + +for i in $(test_seq 2 $last_test); do + eval title="\$title$i" + test_expect_success "$title" \ + "git blame -M9 --ignore-rev $IGNOREME $i >output && + sed -e \"$pick_author\" output >actual && + test_cmp expected$i actual" +done + +# This invoked a null pointer dereference when the chunk callback was called +# with a zero length parent chunk and there were no more suspects. +test_expect_success 'Diff chunks with no suspects' ' + test_write_lines xy1 A B C xy1 >file && + git add file && + test_tick && + GIT_AUTHOR_NAME=1 git commit -m 1 && + + test_write_lines xy2 A B xy2 C xy2 >file && + git add file && + test_tick && + GIT_AUTHOR_NAME=2 git commit -m 2 && + REV_2=$(git rev-parse HEAD) && + + test_write_lines xy3 A >file && + git add file && + test_tick && + GIT_AUTHOR_NAME=3 git commit -m 3 && + REV_3=$(git rev-parse HEAD) && + + test_write_lines 1 1 >expected && + + git blame --ignore-rev $REV_2 --ignore-rev $REV_3 file >output && + sed -e "$pick_author" output >actual && + + test_cmp expected actual + ' + +test_expect_success 'position matching' ' + test_write_lines abc def >file2 && + git add file2 && + test_tick && + GIT_AUTHOR_NAME=1 git commit -m 1 && + + test_write_lines abc def abc def >file2 && + git add file2 && + test_tick && + GIT_AUTHOR_NAME=2 git commit -m 2 && + + test_write_lines abcx defx abcx defx >file2 && + git add file2 && + test_tick && + GIT_AUTHOR_NAME=3 git commit -m 3 && + REV_3=$(git rev-parse HEAD) && + + test_write_lines abcy defy abcx defx >file2 && + git add file2 && + test_tick && + GIT_AUTHOR_NAME=4 git commit -m 4 && + REV_4=$(git rev-parse HEAD) && + + test_write_lines 1 1 2 2 >expected && + + git blame --ignore-rev $REV_3 --ignore-rev $REV_4 file2 >output && + sed -e "$pick_author" output >actual && + + test_cmp expected actual + ' + +# This fails if each blame entry is processed independently instead of +# processing each diff change in full. +test_expect_success 'preserve order' ' + test_write_lines bcde >file3 && + git add file3 && + test_tick && + GIT_AUTHOR_NAME=1 git commit -m 1 && + + test_write_lines bcde fghij >file3 && + git add file3 && + test_tick && + GIT_AUTHOR_NAME=2 git commit -m 2 && + + test_write_lines bcde fghij abcd >file3 && + git add file3 && + test_tick && + GIT_AUTHOR_NAME=3 git commit -m 3 && + + test_write_lines abcdx fghijx bcdex >file3 && + git add file3 && + test_tick && + GIT_AUTHOR_NAME=4 git commit -m 4 && + REV_4=$(git rev-parse HEAD) && + + test_write_lines abcdx fghijy bcdex >file3 && + git add file3 && + test_tick && + GIT_AUTHOR_NAME=5 git commit -m 5 && + REV_5=$(git rev-parse HEAD) && + + test_write_lines 1 2 3 >expected && + + git blame --ignore-rev $REV_4 --ignore-rev $REV_5 file3 >output && + sed -e "$pick_author" output >actual && + + test_cmp expected actual + ' + +test_done diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index 1e3ac3c384..a834afab4d 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -1204,7 +1204,7 @@ test_expect_success $PREREQ 'no in-reply-to and no threading' ' --from="Example <nobody@example.com>" \ --to=nobody@example.com \ --no-thread \ - $patches $patches >stdout && + $patches >stdout && ! grep "In-Reply-To: " stdout ' @@ -1224,17 +1224,72 @@ test_expect_success $PREREQ 'sendemail.to works' ' git send-email \ --dry-run \ --from="Example <nobody@example.com>" \ - $patches $patches >stdout && + $patches >stdout && grep "To: Somebody <somebody@ex.com>" stdout ' +test_expect_success $PREREQ 'setup sendemail.identity' ' + git config --replace-all sendemail.to "default@example.com" && + git config --replace-all sendemail.isp.to "isp@example.com" && + git config --replace-all sendemail.cloud.to "cloud@example.com" +' + +test_expect_success $PREREQ 'sendemail.identity: reads the correct identity config' ' + git -c sendemail.identity=cloud send-email \ + --dry-run \ + --from="nobody@example.com" \ + $patches >stdout && + grep "To: cloud@example.com" stdout +' + +test_expect_success $PREREQ 'sendemail.identity: identity overrides sendemail.identity' ' + git -c sendemail.identity=cloud send-email \ + --identity=isp \ + --dry-run \ + --from="nobody@example.com" \ + $patches >stdout && + grep "To: isp@example.com" stdout +' + +test_expect_success $PREREQ 'sendemail.identity: --no-identity clears previous identity' ' + git -c sendemail.identity=cloud send-email \ + --no-identity \ + --dry-run \ + --from="nobody@example.com" \ + $patches >stdout && + grep "To: default@example.com" stdout +' + +test_expect_success $PREREQ 'sendemail.identity: bool identity variable existence overrides' ' + git -c sendemail.identity=cloud \ + -c sendemail.xmailer=true \ + -c sendemail.cloud.xmailer=false \ + send-email \ + --dry-run \ + --from="nobody@example.com" \ + $patches >stdout && + grep "To: cloud@example.com" stdout && + ! grep "X-Mailer" stdout +' + +test_expect_success $PREREQ 'sendemail.identity: bool variable fallback' ' + git -c sendemail.identity=cloud \ + -c sendemail.xmailer=false \ + send-email \ + --dry-run \ + --from="nobody@example.com" \ + $patches >stdout && + grep "To: cloud@example.com" stdout && + ! grep "X-Mailer" stdout +' + test_expect_success $PREREQ '--no-to overrides sendemail.to' ' git send-email \ --dry-run \ --from="Example <nobody@example.com>" \ --no-to \ --to=nobody@example.com \ - $patches $patches >stdout && + $patches >stdout && grep "To: nobody@example.com" stdout && ! grep "To: Somebody <somebody@ex.com>" stdout ' @@ -1245,7 +1300,7 @@ test_expect_success $PREREQ 'sendemail.cc works' ' --dry-run \ --from="Example <nobody@example.com>" \ --to=nobody@example.com \ - $patches $patches >stdout && + $patches >stdout && grep "Cc: Somebody <somebody@ex.com>" stdout ' @@ -1256,7 +1311,7 @@ test_expect_success $PREREQ '--no-cc overrides sendemail.cc' ' --no-cc \ --cc=bodies@example.com \ --to=nobody@example.com \ - $patches $patches >stdout && + $patches >stdout && grep "Cc: bodies@example.com" stdout && ! grep "Cc: Somebody <somebody@ex.com>" stdout ' @@ -1268,7 +1323,7 @@ test_expect_success $PREREQ 'sendemail.bcc works' ' --from="Example <nobody@example.com>" \ --to=nobody@example.com \ --smtp-server relay.example.com \ - $patches $patches >stdout && + $patches >stdout && grep "RCPT TO:<other@ex.com>" stdout ' @@ -1280,7 +1335,7 @@ test_expect_success $PREREQ '--no-bcc overrides sendemail.bcc' ' --bcc=bodies@example.com \ --to=nobody@example.com \ --smtp-server relay.example.com \ - $patches $patches >stdout && + $patches >stdout && grep "RCPT TO:<bodies@example.com>" stdout && ! grep "RCPT TO:<other@ex.com>" stdout ' @@ -1437,10 +1492,10 @@ test_expect_success $PREREQ 'setup expect' ' EOF ' -test_expect_success $PREREQ 'sendemail.transferencoding=7bit fails on 8bit data' ' +test_expect_success $PREREQ '--transfer-encoding overrides sendemail.transferEncoding' ' clean_fake_sendmail && - git config sendemail.transferEncoding 7bit && - test_must_fail git send-email \ + test_must_fail git -c sendemail.transferEncoding=8bit \ + send-email \ --transfer-encoding=7bit \ --smtp-server="$(pwd)/fake.sendmail" \ email-using-8bit \ @@ -1449,11 +1504,10 @@ test_expect_success $PREREQ 'sendemail.transferencoding=7bit fails on 8bit data' test -z "$(ls msgtxt*)" ' -test_expect_success $PREREQ '--transfer-encoding overrides sendemail.transferEncoding' ' +test_expect_success $PREREQ 'sendemail.transferEncoding via config' ' clean_fake_sendmail && - git config sendemail.transferEncoding 8bit && - test_must_fail git send-email \ - --transfer-encoding=7bit \ + test_must_fail git -c sendemail.transferEncoding=7bit \ + send-email \ --smtp-server="$(pwd)/fake.sendmail" \ email-using-8bit \ 2>errors >out && @@ -1461,16 +1515,15 @@ test_expect_success $PREREQ '--transfer-encoding overrides sendemail.transferEnc test -z "$(ls msgtxt*)" ' -test_expect_success $PREREQ 'sendemail.transferencoding=8bit' ' +test_expect_success $PREREQ 'sendemail.transferEncoding via cli' ' clean_fake_sendmail && - git send-email \ - --transfer-encoding=8bit \ + test_must_fail git send-email \ + --transfer-encoding=7bit \ --smtp-server="$(pwd)/fake.sendmail" \ email-using-8bit \ 2>errors >out && - sed '1,/^$/d' msgtxt1 >actual && - sed '1,/^$/d' email-using-8bit >expected && - test_cmp expected actual + grep "cannot send message as 7bit" errors && + test -z "$(ls msgtxt*)" ' test_expect_success $PREREQ 'setup expect' ' @@ -1787,6 +1840,15 @@ test_expect_success '--dump-aliases must be used alone' ' test_must_fail git send-email --dump-aliases --to=janice@example.com -1 refs/heads/accounting ' +test_expect_success $PREREQ 'aliases and sendemail.identity' ' + test_must_fail git \ + -c sendemail.identity=cloud \ + -c sendemail.aliasesfile=default-aliases \ + -c sendemail.cloud.aliasesfile=cloud-aliases \ + send-email -1 2>stderr && + test_i18ngrep "cloud-aliases" stderr +' + test_sendmail_aliases () { msg="$1" && shift && expect="$@" && @@ -2004,7 +2066,7 @@ test_expect_success $PREREQ 'leading and trailing whitespaces are removed' ' TO1=$(echo "QTo 1 <to1@example.com>" | q_to_tab) && TO2=$(echo "QZto2" | qz_to_tab_space) && CC1=$(echo "cc1" | append_cr) && - BCC1=$(echo "Q bcc1@example.com Q" | q_to_nul) && + BCC1=$(echo " bcc1@example.com Q" | q_to_nul) && git send-email \ --dry-run \ --from=" Example <from@example.com>" \ diff --git a/t/t9010-svn-fe.sh b/t/t9010-svn-fe.sh index 0b20b07e68..c90fdc5c89 100755 --- a/t/t9010-svn-fe.sh +++ b/t/t9010-svn-fe.sh @@ -53,8 +53,6 @@ text_no_props () { printf "%s\n" "$text" } ->empty - test_expect_success 'empty dump' ' reinit_git && echo "SVN-fs-dump-format-version: 2" >input && @@ -208,7 +206,7 @@ test_expect_failure 'timestamp and empty file' ' test_cmp expect.date actual.date && test_cmp expect.files actual.files && git checkout HEAD empty-file && - test_cmp empty file + test_must_be_empty file ' test_expect_success 'directory with files' ' diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 3668263c40..05f07a1671 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -85,6 +85,36 @@ test_expect_success 'A: create pack from stdin' ' An annotated tag that annotates a blob. EOF + tag to-be-deleted + from :3 + data <<EOF + Another annotated tag that annotates a blob. + EOF + + reset refs/tags/to-be-deleted + from 0000000000000000000000000000000000000000 + + tag nested + mark :6 + from :4 + data <<EOF + Tag of our lovely commit + EOF + + reset refs/tags/nested + from 0000000000000000000000000000000000000000 + + tag nested + mark :7 + from :6 + data <<EOF + Tag of tag of our lovely commit + EOF + + alias + mark :8 + to :5 + INPUT_END git fast-import --export-marks=marks.out <input && git whatchanged master @@ -157,12 +187,19 @@ test_expect_success 'A: verify tag/series-A-blob' ' test_cmp expect actual ' +test_expect_success 'A: verify tag deletion is successful' ' + test_must_fail git rev-parse --verify refs/tags/to-be-deleted +' + test_expect_success 'A: verify marks output' ' cat >expect <<-EOF && :2 $(git rev-parse --verify master:file2) :3 $(git rev-parse --verify master:file3) :4 $(git rev-parse --verify master:file4) :5 $(git rev-parse --verify master^0) + :6 $(git cat-file tag nested | grep object | cut -d" " -f 2) + :7 $(git rev-parse --verify nested) + :8 $(git rev-parse --verify master^0) EOF test_cmp expect marks.out ' @@ -2106,12 +2143,27 @@ test_expect_success 'R: abort on receiving feature after data command' ' test_must_fail git fast-import <input ' +test_expect_success 'R: import-marks features forbidden by default' ' + >git.marks && + echo "feature import-marks=git.marks" >input && + test_must_fail git fast-import <input && + echo "feature import-marks-if-exists=git.marks" >input && + test_must_fail git fast-import <input +' + test_expect_success 'R: only one import-marks feature allowed per stream' ' + >git.marks && + >git2.marks && cat >input <<-EOF && feature import-marks=git.marks feature import-marks=git2.marks EOF + test_must_fail git fast-import --allow-unsafe-features <input +' + +test_expect_success 'R: export-marks feature forbidden by default' ' + echo "feature export-marks=git.marks" >input && test_must_fail git fast-import <input ' @@ -2125,19 +2177,29 @@ test_expect_success 'R: export-marks feature results in a marks file being creat EOF - cat input | git fast-import && + git fast-import --allow-unsafe-features <input && grep :1 git.marks ' test_expect_success 'R: export-marks options can be overridden by commandline options' ' - cat input | git fast-import --export-marks=other.marks && - grep :1 other.marks + cat >input <<-\EOF && + feature export-marks=feature-sub/git.marks + blob + mark :1 + data 3 + hi + + EOF + git fast-import --allow-unsafe-features \ + --export-marks=cmdline-sub/other.marks <input && + grep :1 cmdline-sub/other.marks && + test_path_is_missing feature-sub ' test_expect_success 'R: catch typo in marks file name' ' test_must_fail git fast-import --import-marks=nonexistent.marks </dev/null && echo "feature import-marks=nonexistent.marks" | - test_must_fail git fast-import + test_must_fail git fast-import --allow-unsafe-features ' test_expect_success 'R: import and output marks can be the same file' ' @@ -2192,7 +2254,8 @@ test_expect_success 'R: --import-marks-if-exists' ' test_expect_success 'R: feature import-marks-if-exists' ' rm -f io.marks && - git fast-import --export-marks=io.marks <<-\EOF && + git fast-import --export-marks=io.marks \ + --allow-unsafe-features <<-\EOF && feature import-marks-if-exists=not_io.marks EOF test_must_be_empty io.marks && @@ -2203,7 +2266,8 @@ test_expect_success 'R: feature import-marks-if-exists' ' echo ":1 $blob" >expect && echo ":2 $blob" >>expect && - git fast-import --export-marks=io.marks <<-\EOF && + git fast-import --export-marks=io.marks \ + --allow-unsafe-features <<-\EOF && feature import-marks-if-exists=io.marks blob mark :2 @@ -2216,7 +2280,8 @@ test_expect_success 'R: feature import-marks-if-exists' ' echo ":3 $blob" >>expect && git fast-import --import-marks=io.marks \ - --export-marks=io.marks <<-\EOF && + --export-marks=io.marks \ + --allow-unsafe-features <<-\EOF && feature import-marks-if-exists=not_io.marks blob mark :3 @@ -2227,7 +2292,8 @@ test_expect_success 'R: feature import-marks-if-exists' ' test_cmp expect io.marks && git fast-import --import-marks-if-exists=not_io.marks \ - --export-marks=io.marks <<-\EOF && + --export-marks=io.marks \ + --allow-unsafe-features <<-\EOF && feature import-marks-if-exists=io.marks EOF test_must_be_empty io.marks @@ -2239,7 +2305,7 @@ test_expect_success 'R: import to output marks works without any content' ' feature export-marks=marks.new EOF - cat input | git fast-import && + git fast-import --allow-unsafe-features <input && test_cmp marks.out marks.new ' @@ -2249,7 +2315,7 @@ test_expect_success 'R: import marks prefers commandline marks file over the str feature export-marks=marks.new EOF - cat input | git fast-import --import-marks=marks.out && + git fast-import --import-marks=marks.out --allow-unsafe-features <input && test_cmp marks.out marks.new ' @@ -2262,7 +2328,8 @@ test_expect_success 'R: multiple --import-marks= should be honoured' ' head -n2 marks.out > one.marks && tail -n +3 marks.out > two.marks && - git fast-import --import-marks=one.marks --import-marks=two.marks <input && + git fast-import --import-marks=one.marks --import-marks=two.marks \ + --allow-unsafe-features <input && test_cmp marks.out combined.marks ' @@ -2275,7 +2342,7 @@ test_expect_success 'R: feature relative-marks should be honoured' ' mkdir -p .git/info/fast-import/ && cp marks.new .git/info/fast-import/relative.in && - git fast-import <input && + git fast-import --allow-unsafe-features <input && test_cmp marks.new .git/info/fast-import/relative.out ' @@ -2287,7 +2354,7 @@ test_expect_success 'R: feature no-relative-marks should be honoured' ' feature export-marks=non-relative.out EOF - git fast-import <input && + git fast-import --allow-unsafe-features <input && test_cmp marks.new non-relative.out ' @@ -2440,9 +2507,6 @@ test_expect_success PIPE 'R: copy using cat-file' ' echo $expect_id blob $expect_len >expect.response && rm -f blobs && - cat >frontend <<-\FRONTEND_END && - #!/bin/sh - FRONTEND_END mkfifo blobs && ( @@ -2557,7 +2621,7 @@ test_expect_success 'R: quiet option results in no stats being output' ' EOF - cat input | git fast-import 2> output && + git fast-import 2>output <input && test_must_be_empty output ' @@ -2781,7 +2845,6 @@ test_expect_success 'S: filemodify with garbage after mark must fail' ' COMMIT M 100644 :403x hello.c EOF - cat err && test_i18ngrep "space after mark" err ' @@ -2798,7 +2861,6 @@ test_expect_success 'S: filemodify with garbage after inline must fail' ' inline BLOB EOF - cat err && test_i18ngrep "nvalid dataref" err ' @@ -2812,7 +2874,6 @@ test_expect_success 'S: filemodify with garbage after sha1 must fail' ' COMMIT M 100644 ${sha1}x hello.c EOF - cat err && test_i18ngrep "space after SHA1" err ' @@ -2828,7 +2889,6 @@ test_expect_success 'S: notemodify with garbage after mark dataref must fail' ' COMMIT N :202x :302 EOF - cat err && test_i18ngrep "space after mark" err ' @@ -2844,7 +2904,6 @@ test_expect_success 'S: notemodify with garbage after inline dataref must fail' note blob BLOB EOF - cat err && test_i18ngrep "nvalid dataref" err ' @@ -2858,7 +2917,6 @@ test_expect_success 'S: notemodify with garbage after sha1 dataref must fail' ' COMMIT N ${sha1}x :302 EOF - cat err && test_i18ngrep "space after SHA1" err ' @@ -2874,7 +2932,6 @@ test_expect_success 'S: notemodify with garbage after mark commit-ish must fail' COMMIT N :202 :302x EOF - cat err && test_i18ngrep "after mark" err ' @@ -2908,7 +2965,6 @@ test_expect_success 'S: from with garbage after mark must fail' ' EOF # now evaluate the error - cat err && test_i18ngrep "after mark" err ' @@ -2928,7 +2984,6 @@ test_expect_success 'S: merge with garbage after mark must fail' ' merge :303x M 100644 :403 hello.c EOF - cat err && test_i18ngrep "after mark" err ' @@ -2944,7 +2999,6 @@ test_expect_success 'S: tag with garbage after mark must fail' ' tag S TAG EOF - cat err && test_i18ngrep "after mark" err ' @@ -2955,7 +3009,6 @@ test_expect_success 'S: cat-blob with garbage after mark must fail' ' test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && cat-blob :403x EOF - cat err && test_i18ngrep "after mark" err ' @@ -2966,7 +3019,6 @@ test_expect_success 'S: ls with garbage after mark must fail' ' test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && ls :302x hello.c EOF - cat err && test_i18ngrep "space after mark" err ' @@ -2975,7 +3027,6 @@ test_expect_success 'S: ls with garbage after sha1 must fail' ' test_must_fail git fast-import --import-marks=marks <<-EOF 2>err && ls ${sha1}x hello.c EOF - cat err && test_i18ngrep "space after tree-ish" err ' @@ -3299,4 +3350,24 @@ test_expect_success !MINGW 'W: get-mark & empty orphan commit with erroneous thi sed -e s/LFs/LLL/ W-input | tr L "\n" | test_must_fail git fast-import ' +### +### series X (other new features) +### + +test_expect_success 'X: handling encoding' ' + test_tick && + cat >input <<-INPUT_END && + commit refs/heads/encoding + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + encoding iso-8859-7 + data <<COMMIT + INPUT_END + + printf "Pi: \360\nCOMMIT\n" >>input && + + git fast-import <input && + git cat-file -p encoding | grep $(printf "\360") && + git log -1 --format=%B encoding | grep $(printf "\317\200") +' + test_done diff --git a/t/t9301-fast-import-notes.sh b/t/t9301-fast-import-notes.sh index dadc70b7d5..ca223dca98 100755 --- a/t/t9301-fast-import-notes.sh +++ b/t/t9301-fast-import-notes.sh @@ -275,7 +275,7 @@ $whitespace third note for first commit EXPECT_END -test_expect_success 'add concatentation notes with M command' ' +test_expect_success 'add concatenation notes with M command' ' git fast-import <input && GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual && diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index 5690fe2810..690c90fb82 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -53,6 +53,33 @@ test_expect_success 'fast-export | fast-import' ' ' +test_expect_success 'fast-export ^muss^{commit} muss' ' + git fast-export --tag-of-filtered-object=rewrite ^muss^{commit} muss >actual && + cat >expected <<-EOF && + tag muss + from $(git rev-parse --verify muss^{commit}) + $(git cat-file tag muss | grep tagger) + data 9 + valentin + + EOF + test_cmp expected actual +' + +test_expect_success 'fast-export --mark-tags ^muss^{commit} muss' ' + git fast-export --mark-tags --tag-of-filtered-object=rewrite ^muss^{commit} muss >actual && + cat >expected <<-EOF && + tag muss + mark :1 + from $(git rev-parse --verify muss^{commit}) + $(git cat-file tag muss | grep tagger) + data 9 + valentin + + EOF + test_cmp expected actual +' + test_expect_success 'fast-export master~2..master' ' git fast-export master~2..master >actual && @@ -94,22 +121,83 @@ test_expect_success 'fast-export --show-original-ids | git fast-import' ' test $MUSS = $(git rev-parse --verify refs/tags/muss) ' -test_expect_success 'iso-8859-1' ' +test_expect_success 'reencoding iso-8859-7' ' - git config i18n.commitencoding ISO8859-1 && - # use author and committer name in ISO-8859-1 to match it. - . "$TEST_DIRECTORY"/t3901/8859-1.txt && + test_when_finished "git reset --hard HEAD~1" && + test_config i18n.commitencoding iso-8859-7 && test_tick && echo rosten >file && - git commit -s -m den file && - git fast-export wer^..wer >iso8859-1.fi && - sed "s/wer/i18n/" iso8859-1.fi | + git commit -s -F "$TEST_DIRECTORY/t9350/simple-iso-8859-7-commit-message.txt" file && + git fast-export --reencode=yes wer^..wer >iso-8859-7.fi && + sed "s/wer/i18n/" iso-8859-7.fi | (cd new && git fast-import && + # The commit object, if not re-encoded, would be 240 bytes. + # Removing the "encoding iso-8859-7\n" header drops 20 bytes. + # Re-encoding the Pi character from \xF0 (\360) in iso-8859-7 + # to \xCF\x80 (\317\200) in UTF-8 adds a byte. Check for + # the expected size. + test 221 -eq "$(git cat-file -s i18n)" && + # ...and for the expected translation of bytes. git cat-file commit i18n >actual && - grep "Áéí óú" actual) + grep $(printf "\317\200") actual && + # Also make sure the commit does not have the "encoding" header + ! grep ^encoding actual) +' + +test_expect_success 'aborting on iso-8859-7' ' + test_when_finished "git reset --hard HEAD~1" && + test_config i18n.commitencoding iso-8859-7 && + echo rosten >file && + git commit -s -F "$TEST_DIRECTORY/t9350/simple-iso-8859-7-commit-message.txt" file && + test_must_fail git fast-export --reencode=abort wer^..wer >iso-8859-7.fi ' + +test_expect_success 'preserving iso-8859-7' ' + + test_when_finished "git reset --hard HEAD~1" && + test_config i18n.commitencoding iso-8859-7 && + echo rosten >file && + git commit -s -F "$TEST_DIRECTORY/t9350/simple-iso-8859-7-commit-message.txt" file && + git fast-export --reencode=no wer^..wer >iso-8859-7.fi && + sed "s/wer/i18n-no-recoding/" iso-8859-7.fi | + (cd new && + git fast-import && + # The commit object, if not re-encoded, is 240 bytes. + # Removing the "encoding iso-8859-7\n" header would drops 20 + # bytes. Re-encoding the Pi character from \xF0 (\360) in + # iso-8859-7 to \xCF\x80 (\317\200) in UTF-8 adds a byte. + # Check for the expected size... + test 240 -eq "$(git cat-file -s i18n-no-recoding)" && + # ...as well as the expected byte. + git cat-file commit i18n-no-recoding >actual && + grep $(printf "\360") actual && + # Also make sure the commit has the "encoding" header + grep ^encoding actual) +' + +test_expect_success 'encoding preserved if reencoding fails' ' + + test_when_finished "git reset --hard HEAD~1" && + test_config i18n.commitencoding iso-8859-7 && + echo rosten >file && + git commit -s -F "$TEST_DIRECTORY/t9350/broken-iso-8859-7-commit-message.txt" file && + git fast-export --reencode=yes wer^..wer >iso-8859-7.fi && + sed "s/wer/i18n-invalid/" iso-8859-7.fi | + (cd new && + git fast-import && + git cat-file commit i18n-invalid >actual && + # Make sure the commit still has the encoding header + grep ^encoding actual && + # Verify that the commit has the expected size; i.e. + # that no bytes were re-encoded to a different encoding. + test 252 -eq "$(git cat-file -s i18n-invalid)" && + # ...and check for the original special bytes + grep $(printf "\360") actual && + grep $(printf "\377") actual) +' + test_expect_success 'import/export-marks' ' git checkout -b marks master && @@ -224,7 +312,6 @@ GIT_COMMITTER_NAME='C O Mitter'; export GIT_COMMITTER_NAME test_expect_success 'setup copies' ' - git config --unset i18n.commitencoding && git checkout -b copy rein && git mv file file3 && git commit -m move1 && @@ -453,10 +540,41 @@ test_expect_success 'tree_tag' ' ' # NEEDSWORK: not just check return status, but validate the output +# Note that these tests DO NOTHING other than print a warning that +# they are omitting the one tag we asked them to export (because the +# tags resolve to a tree). They exist just to make sure we do not +# abort but instead just warn. test_expect_success 'tree_tag-obj' 'git fast-export tree_tag-obj' test_expect_success 'tag-obj_tag' 'git fast-export tag-obj_tag' test_expect_success 'tag-obj_tag-obj' 'git fast-export tag-obj_tag-obj' +test_expect_success 'handling tags of blobs' ' + git tag -a -m "Tag of a blob" blobtag $(git rev-parse master:file) && + git fast-export blobtag >actual && + cat >expect <<-EOF && + blob + mark :1 + data 9 + die Luft + + tag blobtag + from :1 + tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + data 14 + Tag of a blob + + EOF + test_cmp expect actual +' + +test_expect_success 'handling nested tags' ' + git tag -a -m "This is a nested tag" nested muss && + git fast-export --mark-tags nested >output && + grep "^from $ZERO_OID$" output && + grep "^tag nested$" output >tag_lines && + test_line_count = 2 tag_lines +' + test_expect_success 'directory becomes symlink' ' git init dirtosymlink && git init result && @@ -482,9 +600,10 @@ test_expect_success 'directory becomes symlink' ' test_expect_success 'fast-export quotes pathnames' ' git init crazy-paths && + test_config -C crazy-paths core.protectNTFS false && (cd crazy-paths && blob=$(echo foo | git hash-object -w --stdin) && - git update-index --add \ + git -c core.protectNTFS=false update-index --add \ --cacheinfo 100644 $blob "$(printf "path with\\nnewline")" \ --cacheinfo 100644 $blob "path with \"quote\"" \ --cacheinfo 100644 $blob "path with \\backslash" \ @@ -507,17 +626,15 @@ test_expect_success 'fast-export quotes pathnames' ' ' test_expect_success 'test bidirectionality' ' - >marks-cur && - >marks-new && git init marks-test && - git fast-export --export-marks=marks-cur --import-marks=marks-cur --branches | \ - git --git-dir=marks-test/.git fast-import --export-marks=marks-new --import-marks=marks-new && + git fast-export --export-marks=marks-cur --import-marks-if-exists=marks-cur --branches | \ + git --git-dir=marks-test/.git fast-import --export-marks=marks-new --import-marks-if-exists=marks-new && (cd marks-test && git reset --hard && echo Wohlauf > file && git commit -a -m "back in time") && - git --git-dir=marks-test/.git fast-export --export-marks=marks-new --import-marks=marks-new --branches | \ - git fast-import --export-marks=marks-cur --import-marks=marks-cur + git --git-dir=marks-test/.git fast-export --export-marks=marks-new --import-marks-if-exists=marks-new --branches | \ + git fast-import --export-marks=marks-cur --import-marks-if-exists=marks-cur ' cat > expected << EOF diff --git a/t/t9350/broken-iso-8859-7-commit-message.txt b/t/t9350/broken-iso-8859-7-commit-message.txt new file mode 100644 index 0000000000..d06ad75b44 --- /dev/null +++ b/t/t9350/broken-iso-8859-7-commit-message.txt @@ -0,0 +1 @@ +Pi: ; Invalid:
\ No newline at end of file diff --git a/t/t9350/simple-iso-8859-7-commit-message.txt b/t/t9350/simple-iso-8859-7-commit-message.txt new file mode 100644 index 0000000000..8b3f0c3dba --- /dev/null +++ b/t/t9350/simple-iso-8859-7-commit-message.txt @@ -0,0 +1 @@ +Pi:
\ No newline at end of file diff --git a/t/t9502-gitweb-standalone-parse-output.sh b/t/t9502-gitweb-standalone-parse-output.sh index 0796a438bc..e38cbc97d3 100755 --- a/t/t9502-gitweb-standalone-parse-output.sh +++ b/t/t9502-gitweb-standalone-parse-output.sh @@ -188,8 +188,8 @@ test_expect_success 'forks: project_index lists all projects (incl. forks)' ' ' xss() { - echo >&2 "Checking $1..." && - gitweb_run "$1" && + echo >&2 "Checking $*..." && + gitweb_run "$@" && if grep "$TAG" gitweb.body; then echo >&2 "xss: $TAG should have been quoted in output" return 1 @@ -200,7 +200,8 @@ xss() { test_expect_success 'xss checks' ' TAG="<magic-xss-tag>" && xss "a=rss&p=$TAG" && - xss "a=rss&p=foo.git&f=$TAG" + xss "a=rss&p=foo.git&f=$TAG" && + xss "" "$TAG+" ' test_done diff --git a/t/t9801-git-p4-branch.sh b/t/t9801-git-p4-branch.sh index 38d6b9043b..67ff2711f5 100755 --- a/t/t9801-git-p4-branch.sh +++ b/t/t9801-git-p4-branch.sh @@ -411,6 +411,46 @@ test_expect_failure 'git p4 clone file subset branch' ' ) ' +# Check that excluded files are omitted during import +test_expect_success 'git p4 clone complex branches with excluded files' ' + test_when_finished cleanup_git && + test_create_repo "$git" && + ( + cd "$git" && + git config git-p4.branchList branch1:branch2 && + git config --add git-p4.branchList branch1:branch3 && + git config --add git-p4.branchList branch1:branch4 && + git config --add git-p4.branchList branch1:branch5 && + git config --add git-p4.branchList branch1:branch6 && + git p4 clone --dest=. --detect-branches -//depot/branch1/file2 -//depot/branch2/file2 -//depot/branch3/file2 -//depot/branch4/file2 -//depot/branch5/file2 -//depot/branch6/file2 //depot@all && + git log --all --graph --decorate --stat && + git reset --hard p4/depot/branch1 && + test_path_is_file file1 && + test_path_is_missing file2 && + test_path_is_file file3 && + git reset --hard p4/depot/branch2 && + test_path_is_file file1 && + test_path_is_missing file2 && + test_path_is_missing file3 && + git reset --hard p4/depot/branch3 && + test_path_is_file file1 && + test_path_is_missing file2 && + test_path_is_missing file3 && + git reset --hard p4/depot/branch4 && + test_path_is_file file1 && + test_path_is_missing file2 && + test_path_is_file file3 && + git reset --hard p4/depot/branch5 && + test_path_is_file file1 && + test_path_is_missing file2 && + test_path_is_file file3 && + git reset --hard p4/depot/branch6 && + test_path_is_file file1 && + test_path_is_missing file2 && + test_path_is_missing file3 + ) +' + # From a report in http://stackoverflow.com/questions/11893688 # where --use-client-spec caused branch prefixes not to be removed; # every file in git appeared into a subdirectory of the branch name. @@ -610,4 +650,96 @@ test_expect_success 'Update a file in git side and submit to P4 using client vie ) ' +test_expect_success 'restart p4d (case folding enabled)' ' + stop_and_cleanup_p4d && + start_p4d -C1 +' + +# +# 1: //depot/main/mf1 +# 2: integrate //depot/main/... -> //depot/branch1/... +# 3: //depot/main/mf2 +# 4: //depot/BRANCH1/B1f3 +# 5: //depot/branch1/b1f4 +# +test_expect_success !CASE_INSENSITIVE_FS 'basic p4 branches for case folding' ' + ( + cd "$cli" && + mkdir -p main && + + echo mf1 >main/mf1 && + p4 add main/mf1 && + p4 submit -d "main/mf1" && + + p4 integrate //depot/main/... //depot/branch1/... && + p4 submit -d "integrate main to branch1" && + + echo mf2 >main/mf2 && + p4 add main/mf2 && + p4 submit -d "main/mf2" && + + mkdir BRANCH1 && + echo B1f3 >BRANCH1/B1f3 && + p4 add BRANCH1/B1f3 && + p4 submit -d "BRANCH1/B1f3" && + + echo b1f4 >branch1/b1f4 && + p4 add branch1/b1f4 && + p4 submit -d "branch1/b1f4" + ) +' + +# Check that files are properly split across branches when ignorecase is set +test_expect_success !CASE_INSENSITIVE_FS 'git p4 clone, branchList branch definition, ignorecase' ' + test_when_finished cleanup_git && + test_create_repo "$git" && + ( + cd "$git" && + git config git-p4.branchList main:branch1 && + git config --type=bool core.ignoreCase true && + git p4 clone --dest=. --detect-branches //depot@all && + + git log --all --graph --decorate --stat && + + git reset --hard p4/master && + test_path_is_file mf1 && + test_path_is_file mf2 && + test_path_is_missing B1f3 && + test_path_is_missing b1f4 && + + git reset --hard p4/depot/branch1 && + test_path_is_file mf1 && + test_path_is_missing mf2 && + test_path_is_file B1f3 && + test_path_is_file b1f4 + ) +' + +# Check that files are properly split across branches when ignorecase is set, use-client-spec case +test_expect_success !CASE_INSENSITIVE_FS 'git p4 clone with client-spec, branchList branch definition, ignorecase' ' + client_view "//depot/... //client/..." && + test_when_finished cleanup_git && + test_create_repo "$git" && + ( + cd "$git" && + git config git-p4.branchList main:branch1 && + git config --type=bool core.ignoreCase true && + git p4 clone --dest=. --use-client-spec --detect-branches //depot@all && + + git log --all --graph --decorate --stat && + + git reset --hard p4/master && + test_path_is_file mf1 && + test_path_is_file mf2 && + test_path_is_missing B1f3 && + test_path_is_missing b1f4 && + + git reset --hard p4/depot/branch1 && + test_path_is_file mf1 && + test_path_is_missing mf2 && + test_path_is_file B1f3 && + test_path_is_file b1f4 + ) +' + test_done diff --git a/t/t9809-git-p4-client-view.sh b/t/t9809-git-p4-client-view.sh index 3cff1fce1b..9c9710d8c7 100755 --- a/t/t9809-git-p4-client-view.sh +++ b/t/t9809-git-p4-client-view.sh @@ -407,7 +407,7 @@ test_expect_success 'reinit depot' ' ' # -# What happens when two files of the same name are overlayed together? +# What happens when two files of the same name are overlaid together? # The last-listed file should take preference. # # //depot diff --git a/t/t9817-git-p4-exclude.sh b/t/t9817-git-p4-exclude.sh index 96d25f0c02..ec3d937c6a 100755 --- a/t/t9817-git-p4-exclude.sh +++ b/t/t9817-git-p4-exclude.sh @@ -22,7 +22,9 @@ test_expect_success 'create exclude repo' ' mkdir -p wanted discard && echo wanted >wanted/foo && echo discard >discard/foo && - p4 add wanted/foo discard/foo && + echo discard_file >discard_file && + echo discard_file_not >discard_file_not && + p4 add wanted/foo discard/foo discard_file discard_file_not && p4 submit -d "initial revision" ) ' @@ -33,7 +35,9 @@ test_expect_success 'check the repo was created correctly' ' ( cd "$git" && test_path_is_file wanted/foo && - test_path_is_file discard/foo + test_path_is_file discard/foo && + test_path_is_file discard_file && + test_path_is_file discard_file_not ) ' @@ -43,7 +47,21 @@ test_expect_success 'clone, excluding part of repo' ' ( cd "$git" && test_path_is_file wanted/foo && - test_path_is_missing discard/foo + test_path_is_missing discard/foo && + test_path_is_file discard_file && + test_path_is_file discard_file_not + ) +' + +test_expect_success 'clone, excluding single file, no trailing /' ' + test_when_finished cleanup_git && + git p4 clone -//depot/discard_file --dest="$git" //depot/...@all && + ( + cd "$git" && + test_path_is_file wanted/foo && + test_path_is_file discard/foo && + test_path_is_missing discard_file && + test_path_is_file discard_file_not ) ' @@ -52,15 +70,38 @@ test_expect_success 'clone, then sync with exclude' ' git p4 clone -//depot/discard/... --dest="$git" //depot/...@all && ( cd "$cli" && - p4 edit wanted/foo discard/foo && + p4 edit wanted/foo discard/foo discard_file_not && date >>wanted/foo && date >>discard/foo && + date >>discard_file_not && p4 submit -d "updating" && cd "$git" && git p4 sync -//depot/discard/... && test_path_is_file wanted/foo && - test_path_is_missing discard/foo + test_path_is_missing discard/foo && + test_path_is_file discard_file && + test_path_is_file discard_file_not + ) +' + +test_expect_success 'clone, then sync with exclude, no trailing /' ' + test_when_finished cleanup_git && + git p4 clone -//depot/discard/... -//depot/discard_file --dest="$git" //depot/...@all && + ( + cd "$cli" && + p4 edit wanted/foo discard/foo discard_file_not && + date >>wanted/foo && + date >>discard/foo && + date >>discard_file_not && + p4 submit -d "updating" && + + cd "$git" && + git p4 sync -//depot/discard/... -//depot/discard_file && + test_path_is_file wanted/foo && + test_path_is_missing discard/foo && + test_path_is_missing discard_file && + test_path_is_file discard_file_not ) ' diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh index 43cf313a1c..ec3eccfd3d 100755 --- a/t/t9902-completion.sh +++ b/t/t9902-completion.sh @@ -28,10 +28,10 @@ complete () # # (2) A test makes sure that common subcommands are included in the # completion for "git <TAB>", and a plumbing is excluded. "add", -# "filter-branch" and "ls-files" are listed for this. +# "rebase" and "ls-files" are listed for this. -GIT_TESTING_ALL_COMMAND_LIST='add checkout check-attr filter-branch ls-files' -GIT_TESTING_PORCELAIN_COMMAND_LIST='add checkout filter-branch' +GIT_TESTING_ALL_COMMAND_LIST='add checkout check-attr rebase ls-files' +GIT_TESTING_PORCELAIN_COMMAND_LIST='add checkout rebase' . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" @@ -378,7 +378,7 @@ test_expect_success '__gitdir - finds repo' ' ' -test_expect_success '__gitdir - returns error when cant find repo' ' +test_expect_success '__gitdir - returns error when cannot find repo' ' ( __git_dir="non-existing" && test_must_fail __gitdir >"$actual" @@ -945,7 +945,7 @@ test_expect_success 'setup for filtering matching refs' ' rm -f .git/FETCH_HEAD ' -test_expect_success '__git_refs - dont filter refs unless told so' ' +test_expect_success '__git_refs - do not filter refs unless told so' ' cat >expected <<-EOF && HEAD master @@ -1257,7 +1257,7 @@ test_path_completion () # In the following tests calling this function we only # care about how __git_complete_index_file() deals with # unusual characters in path names. By requesting only - # untracked files we dont have to bother adding any + # untracked files we do not have to bother adding any # paths to the index in those tests. __git_complete_index_file --others && print_comp @@ -1392,12 +1392,12 @@ test_expect_success 'basic' ' # built-in grep -q "^add \$" out && # script - grep -q "^filter-branch \$" out && + grep -q "^rebase \$" out && # plumbing ! grep -q "^ls-files \$" out && - run_completion "git f" && - ! grep -q -v "^f" out + run_completion "git r" && + ! grep -q -v "^r" out ' test_expect_success 'double dash "git" itself' ' @@ -1548,7 +1548,10 @@ test_expect_success 'complete tree filename with metacharacters' ' ' test_expect_success PERL 'send-email' ' - test_completion "git send-email --cov" "--cover-letter " && + test_completion "git send-email --cov" <<-\EOF && + --cover-from-description=Z + --cover-letter Z + EOF test_completion "git send-email ma" "master " ' @@ -1698,6 +1701,69 @@ do ' done +test_expect_success 'git config - section' ' + test_completion "git config br" <<-\EOF + branch.Z + browser.Z + EOF +' + +test_expect_success 'git config - variable name' ' + test_completion "git config log.d" <<-\EOF + log.date Z + log.decorate Z + EOF +' + +test_expect_success 'git config - value' ' + test_completion "git config color.pager " <<-\EOF + false Z + true Z + EOF +' + +test_expect_success 'git -c - section' ' + test_completion "git -c br" <<-\EOF + branch.Z + browser.Z + EOF +' + +test_expect_success 'git -c - variable name' ' + test_completion "git -c log.d" <<-\EOF + log.date=Z + log.decorate=Z + EOF +' + +test_expect_success 'git -c - value' ' + test_completion "git -c color.pager=" <<-\EOF + false Z + true Z + EOF +' + +test_expect_success 'git clone --config= - section' ' + test_completion "git clone --config=br" <<-\EOF + branch.Z + browser.Z + EOF +' + +test_expect_success 'git clone --config= - variable name' ' + test_completion "git clone --config=log.d" <<-\EOF + log.date=Z + log.decorate=Z + EOF +' + +test_expect_success 'git clone --config= - value' ' + test_completion "git clone --config=color.pager=" <<-\EOF + false Z + true Z + EOF +' + test_expect_success 'sourcing the completion script clears cached commands' ' __git_compute_all_commands && verbose test -n "$__git_all_commands" && @@ -1706,7 +1772,7 @@ test_expect_success 'sourcing the completion script clears cached commands' ' ' test_expect_success 'sourcing the completion script clears cached merge strategies' ' - GIT_TEST_GETTEXT_POISON= && + GIT_TEST_GETTEXT_POISON=false && __git_compute_merge_strategies && verbose test -n "$__git_merge_strategies" && . "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" && diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh index 5cadedb2a9..88bc733ad6 100755 --- a/t/t9903-bash-prompt.sh +++ b/t/t9903-bash-prompt.sh @@ -211,8 +211,24 @@ test_expect_success 'prompt - merge' ' test_expect_success 'prompt - cherry-pick' ' printf " (master|CHERRY-PICKING)" >expected && - test_must_fail git cherry-pick b1 && - test_when_finished "git reset --hard" && + test_must_fail git cherry-pick b1 b1^ && + test_when_finished "git cherry-pick --abort" && + __git_ps1 >"$actual" && + test_cmp expected "$actual" && + git reset --merge && + test_must_fail git rev-parse CHERRY_PICK_HEAD && + __git_ps1 >"$actual" && + test_cmp expected "$actual" +' + +test_expect_success 'prompt - revert' ' + printf " (master|REVERTING)" >expected && + test_must_fail git revert b1^ b1 && + test_when_finished "git revert --abort" && + __git_ps1 >"$actual" && + test_cmp expected "$actual" && + git reset --merge && + test_must_fail git rev-parse REVERT_HEAD && __git_ps1 >"$actual" && test_cmp expected "$actual" ' diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index f233522f43..284c52d076 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -228,9 +228,134 @@ test_commit () { # can be a tag pointing to the commit-to-merge. test_merge () { + label="$1" && + shift && test_tick && - git merge -m "$1" "$2" && - git tag "$1" + git merge -m "$label" "$@" && + git tag "$label" +} + +# Efficiently create <nr> commits, each with a unique number (from 1 to <nr> +# by default) in the commit message. +# +# Usage: test_commit_bulk [options] <nr> +# -C <dir>: +# Run all git commands in directory <dir> +# --ref=<n>: +# ref on which to create commits (default: HEAD) +# --start=<n>: +# number commit messages from <n> (default: 1) +# --message=<msg>: +# use <msg> as the commit mesasge (default: "commit %s") +# --filename=<fn>: +# modify <fn> in each commit (default: %s.t) +# --contents=<string>: +# place <string> in each file (default: "content %s") +# --id=<string>: +# shorthand to use <string> and %s in message, filename, and contents +# +# The message, filename, and contents strings are evaluated by printf, with the +# first "%s" replaced by the current commit number. So you can do: +# +# test_commit_bulk --filename=file --contents="modification %s" +# +# to have every commit touch the same file, but with unique content. +# +test_commit_bulk () { + tmpfile=.bulk-commit.input + indir=. + ref=HEAD + n=1 + message='commit %s' + filename='%s.t' + contents='content %s' + while test $# -gt 0 + do + case "$1" in + -C) + indir=$2 + shift + ;; + --ref=*) + ref=${1#--*=} + ;; + --start=*) + n=${1#--*=} + ;; + --message=*) + message=${1#--*=} + ;; + --filename=*) + filename=${1#--*=} + ;; + --contents=*) + contents=${1#--*=} + ;; + --id=*) + message="${1#--*=} %s" + filename="${1#--*=}-%s.t" + contents="${1#--*=} %s" + ;; + -*) + BUG "invalid test_commit_bulk option: $1" + ;; + *) + break + ;; + esac + shift + done + total=$1 + + add_from= + if git -C "$indir" rev-parse --quiet --verify "$ref" + then + add_from=t + fi + + while test "$total" -gt 0 + do + test_tick && + echo "commit $ref" + printf 'author %s <%s> %s\n' \ + "$GIT_AUTHOR_NAME" \ + "$GIT_AUTHOR_EMAIL" \ + "$GIT_AUTHOR_DATE" + printf 'committer %s <%s> %s\n' \ + "$GIT_COMMITTER_NAME" \ + "$GIT_COMMITTER_EMAIL" \ + "$GIT_COMMITTER_DATE" + echo "data <<EOF" + printf "$message\n" $n + echo "EOF" + if test -n "$add_from" + then + echo "from $ref^0" + add_from= + fi + printf "M 644 inline $filename\n" $n + echo "data <<EOF" + printf "$contents\n" $n + echo "EOF" + echo + n=$((n + 1)) + total=$((total - 1)) + done >"$tmpfile" + + git -C "$indir" \ + -c fastimport.unpacklimit=0 \ + fast-import <"$tmpfile" || return 1 + + # This will be left in place on failure, which may aid debugging. + rm -f "$tmpfile" + + # If we updated HEAD, then be nice and update the index and working + # tree, too. + if test "$ref" = "HEAD" + then + git -C "$indir" checkout -f HEAD || return 1 + fi + } # This function helps systems where core.filemode=false is set. @@ -309,6 +434,26 @@ test_unset_prereq () { } test_set_prereq () { + if test -n "$GIT_TEST_FAIL_PREREQS_INTERNAL" + then + case "$1" in + # The "!" case is handled below with + # test_unset_prereq() + !*) + ;; + # (Temporary?) whitelist of things we can't easily + # pretend not to support + SYMLINKS) + ;; + # Inspecting whether GIT_TEST_FAIL_PREREQS is on + # should be unaffected. + FAIL_PREREQS) + ;; + *) + return + esac + fi + case "$1" in !*) test_unset_prereq "${1#!}" @@ -437,7 +582,7 @@ test_expect_failure () { export test_prereq if ! test_skip "$@" then - say >&3 "checking known breakage: $2" + say >&3 "checking known breakage of $TEST_NUMBER.$test_count '$1': $2" if test_run_ "$2" expecting_failure then test_known_broken_ok_ "$1" @@ -457,7 +602,7 @@ test_expect_success () { export test_prereq if ! test_skip "$@" then - say >&3 "expecting success: $2" + say >&3 "expecting success of $TEST_NUMBER.$test_count '$1': $2" if test_run_ "$2" then test_ok_ "$1" @@ -867,19 +1012,30 @@ test_must_be_empty () { fi } -# Tests that its two parameters refer to the same revision +# Tests that its two parameters refer to the same revision, or if '!' is +# provided first, that its other two parameters refer to different +# revisions. test_cmp_rev () { + local op='=' wrong_result=different + + if test $# -ge 1 && test "x$1" = 'x!' + then + op='!=' + wrong_result='the same' + shift + fi 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" + r2=$(git rev-parse --verify "$2") || return 1 + + if ! test "$r1" "$op" "$r2" then cat >&4 <<-EOF - error: two revisions point to different objects: + error: two revisions point to $wrong_result objects: '$1': $r1 '$2': $r2 EOF @@ -1030,62 +1186,48 @@ perl () { command "$PERL_PATH" "$@" 2>&7 } 7>&2 2>&4 -# Is the value one of the various ways to spell a boolean true/false? -test_normalize_bool () { - git -c magic.variable="$1" config --bool magic.variable 2>/dev/null -} - -# Given a variable $1, normalize the value of it to one of "true", -# "false", or "auto" and store the result to it. -# -# test_tristate GIT_TEST_HTTPD +# Given the name of an environment variable with a bool value, normalize +# its value to a 0 (true) or 1 (false or empty string) return code. # -# A variable set to an empty string is set to 'false'. -# A variable set to 'false' or 'auto' keeps its value. -# Anything else is set to 'true'. -# An unset variable defaults to 'auto'. +# test_bool_env GIT_TEST_HTTPD <default-value> # -# The last rule is to allow people to set the variable to an empty -# string and export it to decline testing the particular feature -# for versions both before and after this change. We used to treat -# both unset and empty variable as a signal for "do not test" and -# took any non-empty string as "please test". - -test_tristate () { - if eval "test x\"\${$1+isset}\" = xisset" +# Return with code corresponding to the given default value if the variable +# is unset. +# Abort the test script if either the value of the variable or the default +# are not valid bool values. + +test_bool_env () { + if test $# != 2 then - # explicitly set - eval " - case \"\$$1\" in - '') $1=false ;; - auto) ;; - *) $1=\$(test_normalize_bool \$$1 || echo true) ;; - esac - " - else - eval "$1=auto" + BUG "test_bool_env requires two parameters (variable name and default value)" fi + + git env--helper --type=bool --default="$2" --exit-code "$1" + ret=$? + case $ret in + 0|1) # unset or valid bool value + ;; + *) # invalid bool value or something unexpected + error >&7 "test_bool_env requires bool values both for \$$1 and for the default fallback" + ;; + esac + return $ret } # Exit the test suite, either by skipping all remaining tests or by -# exiting with an error. If "$1" is "auto", we then we assume we were -# opportunistically trying to set up some tests and we skip. If it is -# "true", then we report a failure. +# exiting with an error. If our prerequisite variable $1 falls back +# on a default assume we were opportunistically trying to set up some +# tests and we skip. If it is explicitly "true", then we report a failure. # # The error/skip message should be given by $2. # test_skip_or_die () { - case "$1" in - auto) + if ! test_bool_env "$1" false + then skip_all=$2 test_done - ;; - true) - error "$2" - ;; - *) - error "BUG: test tristate is '$1' (real error: $2)" - esac + fi + error "$2" } # The following mingw_* functions obey POSIX shell syntax, but are actually @@ -1329,6 +1471,13 @@ test_oid () { eval "printf '%s' \"\${$var}\"" } +# Insert a slash into an object ID so it can be used to reference a location +# under ".git/objects". For example, "deadbeef..." becomes "de/adbeef..". +test_oid_to_path () { + local basename=${1#??} + echo "${1%$basename}/$basename" +} + # Choose a port number based on the test script's number and store it in # the given variable name, unless that variable already contains a number. test_set_port () { diff --git a/t/test-lib.sh b/t/test-lib.sh index 599fd70e14..5fbf4d25ed 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -212,6 +212,8 @@ fi TEST_STRESS_JOB_SFX="${GIT_TEST_STRESS_JOB_NR:+.stress-$GIT_TEST_STRESS_JOB_NR}" TEST_NAME="$(basename "$0" .sh)" +TEST_NUMBER="${TEST_NAME%%-*}" +TEST_NUMBER="${TEST_NUMBER#t}" TEST_RESULTS_DIR="$TEST_OUTPUT_DIRECTORY/test-results" TEST_RESULTS_BASE="$TEST_RESULTS_DIR/$TEST_NAME$TEST_STRESS_JOB_SFX" TRASH_DIRECTORY="trash directory.$TEST_NAME$TEST_STRESS_JOB_SFX" @@ -386,7 +388,6 @@ unset VISUAL EMAIL LANGUAGE COLUMNS $("$PERL_PATH" -e ' my @env = keys %ENV; my $ok = join("|", qw( TRACE - TR2_ DEBUG TEST .*_TEST @@ -403,9 +404,13 @@ unset VISUAL EMAIL LANGUAGE COLUMNS $("$PERL_PATH" -e ' unset XDG_CACHE_HOME unset XDG_CONFIG_HOME unset GITPERLLIB -GIT_AUTHOR_EMAIL=author@example.com +TEST_AUTHOR_LOCALNAME=author +TEST_AUTHOR_DOMAIN=example.com +GIT_AUTHOR_EMAIL=${TEST_AUTHOR_LOCALNAME}@${TEST_AUTHOR_DOMAIN} GIT_AUTHOR_NAME='A U Thor' -GIT_COMMITTER_EMAIL=committer@example.com +TEST_COMMITTER_LOCALNAME=committer +TEST_COMMITTER_DOMAIN=example.com +GIT_COMMITTER_EMAIL=${TEST_COMMITTER_LOCALNAME}@${TEST_COMMITTER_DOMAIN} GIT_COMMITTER_NAME='C O Mitter' GIT_MERGE_VERBOSITY=5 GIT_MERGE_AUTOEDIT=no @@ -508,6 +513,9 @@ EMPTY_BLOB=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 LF=' ' +# Single quote +SQ=\' + # UTF-8 ZERO WIDTH NON-JOINER, which HFS+ ignores # when case-folding filenames u200c=$(printf '\342\200\214') @@ -568,6 +576,7 @@ export TERM error () { say_color error "error: $*" + finalize_junit_xml GIT_EXIT_OK=t exit 1 } @@ -696,7 +705,7 @@ test_failure_ () { say_color error "not ok $test_count - $1" shift printf '%s\n' "$*" | sed -e 's/^/# /' - test "$immediate" = "" || { GIT_EXIT_OK=t; exit 1; } + test "$immediate" = "" || { finalize_junit_xml; GIT_EXIT_OK=t; exit 1; } } test_known_broken_ok_ () { @@ -995,6 +1004,12 @@ test_skip () { to_skip=t skipped_reason="GIT_SKIP_TESTS" fi + if test -z "$to_skip" && test -n "$run_list" && + ! match_test_selector_list '--run' $test_count "$run_list" + then + to_skip=t + skipped_reason="--run" + fi if test -z "$to_skip" && test -n "$test_prereq" && ! test_have_prereq "$test_prereq" then @@ -1007,12 +1022,6 @@ test_skip () { fi skipped_reason="missing $missing_prereq${of_prereq}" fi - if test -z "$to_skip" && test -n "$run_list" && - ! match_test_selector_list '--run' $test_count "$run_list" - then - to_skip=t - skipped_reason="--run" - fi case "$to_skip" in t) @@ -1064,6 +1073,25 @@ write_junit_xml_testcase () { junit_have_testcase=t } +finalize_junit_xml () { + if test -n "$write_junit_xml" && test -n "$junit_xml_path" + then + test -n "$junit_have_testcase" || { + junit_start=$(test-tool date getnanos) + write_junit_xml_testcase "all tests skipped" + } + + # adjust the overall time + junit_time=$(test-tool date getnanos $junit_suite_start) + sed "s/<testsuite [^>]*/& time=\"$junit_time\"/" \ + <"$junit_xml_path" >"$junit_xml_path.new" + mv "$junit_xml_path.new" "$junit_xml_path" + + write_junit_xml " </testsuite>" "</testsuites>" + write_junit_xml= + fi +} + test_atexit_cleanup=: test_atexit_handler () { # In a succeeding test script 'test_atexit_handler' is invoked @@ -1086,21 +1114,7 @@ test_done () { # removed, so the commands can access pidfiles and socket files. test_atexit_handler - if test -n "$write_junit_xml" && test -n "$junit_xml_path" - then - test -n "$junit_have_testcase" || { - junit_start=$(test-tool date getnanos) - write_junit_xml_testcase "all tests skipped" - } - - # adjust the overall time - junit_time=$(test-tool date getnanos $junit_suite_start) - sed "s/<testsuite [^>]*/& time=\"$junit_time\"/" \ - <"$junit_xml_path" >"$junit_xml_path.new" - mv "$junit_xml_path.new" "$junit_xml_path" - - write_junit_xml " </testsuite>" "</testsuites>" - fi + finalize_junit_xml if test -z "$HARNESS_ACTIVE" then @@ -1389,6 +1403,25 @@ yes () { done } +# The GIT_TEST_FAIL_PREREQS code hooks into test_set_prereq(), and +# thus needs to be set up really early, and set an internal variable +# for convenience so the hot test_set_prereq() codepath doesn't need +# to call "git env--helper" (via test_bool_env). Only do that work +# if needed by seeing if GIT_TEST_FAIL_PREREQS is set at all. +GIT_TEST_FAIL_PREREQS_INTERNAL= +if test -n "$GIT_TEST_FAIL_PREREQS" +then + if test_bool_env GIT_TEST_FAIL_PREREQS false + then + GIT_TEST_FAIL_PREREQS_INTERNAL=true + test_set_prereq FAIL_PREREQS + fi +else + test_lazy_prereq FAIL_PREREQS ' + test_bool_env GIT_TEST_FAIL_PREREQS false + ' +fi + # Fix some commands on Windows uname_s=$(uname -s) case $uname_s in @@ -1443,11 +1476,9 @@ then unset GIT_TEST_GETTEXT_POISON_ORIG fi -# Can we rely on git's output in the C locale? -if test -z "$GIT_TEST_GETTEXT_POISON" -then - test_set_prereq C_LOCALE_OUTPUT -fi +test_lazy_prereq C_LOCALE_OUTPUT ' + ! test_bool_env GIT_TEST_GETTEXT_POISON false +' if test -z "$GIT_TEST_CHECK_CACHE_TREE" then |