diff options
Diffstat (limited to 't')
199 files changed, 5618 insertions, 1002 deletions
diff --git a/t/Makefile b/t/Makefile index 18e2b28b26..d613935f14 100644 --- a/t/Makefile +++ b/t/Makefile @@ -52,7 +52,8 @@ clean-except-prove-cache: clean: clean-except-prove-cache $(RM) .prove -test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax +test-lint: test-lint-duplicates test-lint-executable test-lint-shell-syntax \ + test-lint-filenames test-lint-duplicates: @dups=`echo $(T) | tr ' ' '\n' | sed 's/-.*//' | sort | uniq -d` && \ @@ -67,6 +68,14 @@ test-lint-executable: test-lint-shell-syntax: @'$(PERL_PATH_SQ)' check-non-portable-shell.pl $(T) $(THELPERS) +test-lint-filenames: + @# We do *not* pass a glob to ls-files but use grep instead, to catch + @# non-ASCII characters (which are quoted within double-quotes) + @bad="$$(git -c core.quotepath=true ls-files 2>/dev/null | \ + grep '["*:<>?\\|]')"; \ + test -z "$$bad" || { \ + echo >&2 "non-portable file name(s): $$bad"; exit 1; } + aggregate-results-and-cleanup: $(T) $(MAKE) aggregate-results $(MAKE) clean @@ -265,7 +265,7 @@ right, so this: $ sh ./t9200-git-cvsexport-commit.sh --run='1-4 !3' will run tests 1, 2, and 4. Items that comes later have higher -precendence. It means that this: +precedence. It means that this: $ sh ./t9200-git-cvsexport-commit.sh --run='!3 1-4' diff --git a/t/helper/test-chmtime.c b/t/helper/test-chmtime.c index dfe8a83261..e760256406 100644 --- a/t/helper/test-chmtime.c +++ b/t/helper/test-chmtime.c @@ -56,7 +56,7 @@ static int timespec_arg(const char *arg, long int *set_time, int *set_eq) return 1; } -int main(int argc, char *argv[]) +int cmd_main(int argc, const char **argv) { static int verbose; diff --git a/t/helper/test-config.c b/t/helper/test-config.c index 6a77552210..83a4f2ab86 100644 --- a/t/helper/test-config.c +++ b/t/helper/test-config.c @@ -25,6 +25,9 @@ * ascending order of priority from a config_set * constructed from files entered as arguments. * + * iterate -> iterate over all values using git_config(), and print some + * data for each + * * Examples: * * To print the value with highest priority for key "foo.bAr Baz.rock": @@ -32,13 +35,46 @@ * */ +static const char *scope_name(enum config_scope scope) +{ + switch (scope) { + case CONFIG_SCOPE_SYSTEM: + return "system"; + case CONFIG_SCOPE_GLOBAL: + return "global"; + case CONFIG_SCOPE_REPO: + return "repo"; + case CONFIG_SCOPE_CMDLINE: + return "cmdline"; + default: + return "unknown"; + } +} +static int iterate_cb(const char *var, const char *value, void *data) +{ + static int nr; + + if (nr++) + putchar('\n'); -int main(int argc, char **argv) + printf("key=%s\n", var); + printf("value=%s\n", value ? value : "(null)"); + printf("origin=%s\n", current_config_origin_type()); + printf("name=%s\n", current_config_name()); + printf("scope=%s\n", scope_name(current_config_scope())); + + return 0; +} + +int cmd_main(int argc, const char **argv) { int i, val; const char *v; const struct string_list *strptr; struct config_set cs; + + setup_git_directory(); + git_configset_init(&cs); if (argc < 2) { @@ -134,6 +170,9 @@ int main(int argc, char **argv) printf("Value not found for \"%s\"\n", argv[2]); goto exit1; } + } else if (!strcmp(argv[1], "iterate")) { + git_config(iterate_cb, NULL); + goto exit0; } die("%s: Please check the syntax and the function name", argv[0]); diff --git a/t/helper/test-ctype.c b/t/helper/test-ctype.c index 707a821f03..bb72c47df5 100644 --- a/t/helper/test-ctype.c +++ b/t/helper/test-ctype.c @@ -28,7 +28,7 @@ static int is_in(const char *s, int ch) #define LOWER "abcdefghijklmnopqrstuvwxyz" #define UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ" -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { TEST_CLASS(isdigit, DIGIT); TEST_CLASS(isspace, " \n\r\t"); diff --git a/t/helper/test-date.c b/t/helper/test-date.c index 63f373557e..506054bcd5 100644 --- a/t/helper/test-date.c +++ b/t/helper/test-date.c @@ -1,11 +1,12 @@ #include "cache.h" static const char *usage_msg = "\n" -" test-date show [time_t]...\n" +" test-date relative [time_t]...\n" +" test-date show:<format> [time_t]...\n" " test-date parse [date]...\n" " test-date approxidate [date]...\n"; -static void show_dates(char **argv, struct timeval *now) +static void show_relative_dates(const char **argv, struct timeval *now) { struct strbuf buf = STRBUF_INIT; @@ -17,7 +18,30 @@ static void show_dates(char **argv, struct timeval *now) strbuf_release(&buf); } -static void parse_dates(char **argv, struct timeval *now) +static void show_dates(const char **argv, const char *format) +{ + struct date_mode mode; + + parse_date_format(format, &mode); + for (; *argv; argv++) { + char *arg; + time_t t; + int tz; + + /* + * Do not use our normal timestamp parsing here, as the point + * is to test the formatting code in isolation. + */ + t = strtol(*argv, &arg, 10); + while (*arg == ' ') + arg++; + tz = atoi(arg); + + printf("%s -> %s\n", *argv, show_date(t, tz, &mode)); + } +} + +static void parse_dates(const char **argv, struct timeval *now) { struct strbuf result = STRBUF_INIT; @@ -36,7 +60,7 @@ static void parse_dates(char **argv, struct timeval *now) strbuf_release(&result); } -static void parse_approxidate(char **argv, struct timeval *now) +static void parse_approxidate(const char **argv, struct timeval *now) { for (; *argv; argv++) { time_t t; @@ -45,7 +69,7 @@ static void parse_approxidate(char **argv, struct timeval *now) } } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { struct timeval now; const char *x; @@ -61,8 +85,10 @@ int main(int argc, char **argv) argv++; if (!*argv) usage(usage_msg); - if (!strcmp(*argv, "show")) - show_dates(argv+1, &now); + if (!strcmp(*argv, "relative")) + show_relative_dates(argv+1, &now); + else if (skip_prefix(*argv, "show:", &x)) + show_dates(argv+1, x); else if (!strcmp(*argv, "parse")) parse_dates(argv+1, &now); else if (!strcmp(*argv, "approxidate")) diff --git a/t/helper/test-delta.c b/t/helper/test-delta.c index 4595cd6433..59937dc1be 100644 --- a/t/helper/test-delta.c +++ b/t/helper/test-delta.c @@ -15,7 +15,7 @@ static const char usage_str[] = "test-delta (-d|-p) <from_file> <data_file> <out_file>"; -int main(int argc, char *argv[]) +int cmd_main(int argc, const char **argv) { int fd; struct stat st; diff --git a/t/helper/test-dump-cache-tree.c b/t/helper/test-dump-cache-tree.c index bb53c0aa65..44f3290258 100644 --- a/t/helper/test-dump-cache-tree.c +++ b/t/helper/test-dump-cache-tree.c @@ -54,7 +54,7 @@ static int dump_cache_tree(struct cache_tree *it, return errs; } -int main(int ac, char **av) +int cmd_main(int ac, const char **av) { struct index_state istate; struct cache_tree *another = cache_tree(); diff --git a/t/helper/test-dump-split-index.c b/t/helper/test-dump-split-index.c index 861d28c9b6..e44430b699 100644 --- a/t/helper/test-dump-split-index.c +++ b/t/helper/test-dump-split-index.c @@ -7,7 +7,7 @@ static void show_bit(size_t pos, void *data) printf(" %d", (int)pos); } -int main(int ac, char **av) +int cmd_main(int ac, const char **av) { struct split_index *si; int i; @@ -23,7 +23,7 @@ int main(int ac, char **av) for (i = 0; i < the_index.cache_nr; i++) { struct cache_entry *ce = the_index.cache[i]; printf("%06o %s %d\t%s\n", ce->ce_mode, - sha1_to_hex(ce->sha1), ce_stage(ce), ce->name); + oid_to_hex(&ce->oid), ce_stage(ce), ce->name); } printf("replacements:"); if (si->replace_bitmap) diff --git a/t/helper/test-dump-untracked-cache.c b/t/helper/test-dump-untracked-cache.c index 0a1c285246..50112cc858 100644 --- a/t/helper/test-dump-untracked-cache.c +++ b/t/helper/test-dump-untracked-cache.c @@ -40,7 +40,7 @@ static void dump(struct untracked_cache_dir *ucd, struct strbuf *base) strbuf_setlen(base, len); } -int main(int ac, char **av) +int cmd_main(int ac, const char **av) { struct untracked_cache *uc; struct strbuf base = STRBUF_INIT; diff --git a/t/helper/test-fake-ssh.c b/t/helper/test-fake-ssh.c index 980de216e1..12beee99ad 100644 --- a/t/helper/test-fake-ssh.c +++ b/t/helper/test-fake-ssh.c @@ -2,7 +2,7 @@ #include "run-command.h" #include "strbuf.h" -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { const char *trash_directory = getenv("TRASH_DIRECTORY"); struct strbuf buf = STRBUF_INIT; diff --git a/t/helper/test-genrandom.c b/t/helper/test-genrandom.c index 54824d0754..8d11d22d98 100644 --- a/t/helper/test-genrandom.c +++ b/t/helper/test-genrandom.c @@ -6,7 +6,7 @@ #include "git-compat-util.h" -int main(int argc, char *argv[]) +int cmd_main(int argc, const char **argv) { unsigned long count, next = 0; unsigned char *c; diff --git a/t/helper/test-hashmap.c b/t/helper/test-hashmap.c index cc2891dd97..7aa9440e27 100644 --- a/t/helper/test-hashmap.c +++ b/t/helper/test-hashmap.c @@ -138,7 +138,7 @@ static void perf_hashmap(unsigned int method, unsigned int rounds) * * perfhashmap method rounds -> test hashmap.[ch] performance */ -int main(int argc, char *argv[]) +int cmd_main(int argc, const char **argv) { char line[1024]; struct hashmap map; diff --git a/t/helper/test-index-version.c b/t/helper/test-index-version.c index 05d4699c4a..f569f6b7ef 100644 --- a/t/helper/test-index-version.c +++ b/t/helper/test-index-version.c @@ -1,6 +1,6 @@ #include "cache.h" -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { struct cache_header hdr; int version; diff --git a/t/helper/test-line-buffer.c b/t/helper/test-line-buffer.c index 1e58f0476f..81575fe2ab 100644 --- a/t/helper/test-line-buffer.c +++ b/t/helper/test-line-buffer.c @@ -50,7 +50,7 @@ static void handle_line(const char *line, struct line_buffer *stdin_buf) handle_command(line, arg + 1, stdin_buf); } -int main(int argc, char *argv[]) +int cmd_main(int argc, const char **argv) { struct line_buffer stdin_buf = LINE_BUFFER_INIT; struct line_buffer file_buf = LINE_BUFFER_INIT; diff --git a/t/helper/test-match-trees.c b/t/helper/test-match-trees.c index d446b8eaca..e939502863 100644 --- a/t/helper/test-match-trees.c +++ b/t/helper/test-match-trees.c @@ -1,7 +1,7 @@ #include "cache.h" #include "tree.h" -int main(int ac, char **av) +int cmd_main(int ac, const char **av) { struct object_id hash1, hash2, shifted; struct tree *one, *two; diff --git a/t/helper/test-mergesort.c b/t/helper/test-mergesort.c index ea3b959e94..335cf6b626 100644 --- a/t/helper/test-mergesort.c +++ b/t/helper/test-mergesort.c @@ -22,7 +22,7 @@ static int compare_strings(const void *a, const void *b) return strcmp(x->text, y->text); } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { struct line *line, *p = NULL, *lines = NULL; struct strbuf sb = STRBUF_INIT; diff --git a/t/helper/test-mktemp.c b/t/helper/test-mktemp.c index c8c54213a3..89d9b2f7be 100644 --- a/t/helper/test-mktemp.c +++ b/t/helper/test-mktemp.c @@ -3,7 +3,7 @@ */ #include "git-compat-util.h" -int main(int argc, char *argv[]) +int cmd_main(int argc, const char **argv) { if (argc != 2) usage("Expected 1 parameter defining the temporary file template"); diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c index 2c63298fab..a01430c24b 100644 --- a/t/helper/test-parse-options.c +++ b/t/helper/test-parse-options.c @@ -94,7 +94,7 @@ static void show(struct string_list *expect, int *status, const char *fmt, ...) strbuf_release(&buf); } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { const char *prefix = "prefix/"; const char *usage[] = { diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c index ba805b374c..1ebe0f750c 100644 --- a/t/helper/test-path-utils.c +++ b/t/helper/test-path-utils.c @@ -156,7 +156,7 @@ static struct test_data dirname_data[] = { { NULL, NULL } }; -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { if (argc == 3 && !strcmp(argv[1], "normalize_path_copy")) { char *buf = xmallocz(strlen(argv[2])); @@ -213,7 +213,7 @@ int main(int argc, char **argv) } if (argc >= 4 && !strcmp(argv[1], "prefix_path")) { - char *prefix = argv[2]; + const char *prefix = argv[2]; int prefix_len = strlen(prefix); int nongit_ok; setup_git_directory_gently(&nongit_ok); diff --git a/t/helper/test-prio-queue.c b/t/helper/test-prio-queue.c index 7be72f0086..ae58fff359 100644 --- a/t/helper/test-prio-queue.c +++ b/t/helper/test-prio-queue.c @@ -16,7 +16,7 @@ static void show(int *v) free(v); } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { struct prio_queue pq = { intcmp }; diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c index b25bcf139b..2a7990efc3 100644 --- a/t/helper/test-read-cache.c +++ b/t/helper/test-read-cache.c @@ -1,6 +1,6 @@ #include "cache.h" -int main (int argc, char **argv) +int cmd_main(int argc, const char **argv) { int i, cnt = 1; if (argc == 2) diff --git a/t/helper/test-regex.c b/t/helper/test-regex.c index 0dc598ecdc..b5ea8a97c5 100644 --- a/t/helper/test-regex.c +++ b/t/helper/test-regex.c @@ -1,6 +1,23 @@ #include "git-compat-util.h" +#include "gettext.h" -int main(int argc, char **argv) +struct reg_flag { + const char *name; + int flag; +}; + +static struct reg_flag reg_flags[] = { + { "EXTENDED", REG_EXTENDED }, + { "NEWLINE", REG_NEWLINE }, + { "ICASE", REG_ICASE }, + { "NOTBOL", REG_NOTBOL }, +#ifdef REG_STARTEND + { "STARTEND", REG_STARTEND }, +#endif + { NULL, 0 } +}; + +static int test_regex_bug(void) { char *pat = "[^={} \t]+"; char *str = "={}\nfred"; @@ -16,5 +33,43 @@ int main(int argc, char **argv) if (m[0].rm_so == 3) /* matches '\n' when it should not */ die("regex bug confirmed: re-build git with NO_REGEX=1"); - exit(0); + return 0; +} + +int cmd_main(int argc, const char **argv) +{ + const char *pat; + const char *str; + int flags = 0; + regex_t r; + regmatch_t m[1]; + + if (argc == 2 && !strcmp(argv[1], "--bug")) + return test_regex_bug(); + else if (argc < 3) + usage("test-regex --bug\n" + "test-regex <pattern> <string> [<options>]"); + + argv++; + pat = *argv++; + str = *argv++; + while (*argv) { + struct reg_flag *rf; + for (rf = reg_flags; rf->name; rf++) + if (!strcmp(*argv, rf->name)) { + flags |= rf->flag; + break; + } + if (!rf->name) + die("do not recognize %s", *argv); + argv++; + } + git_setup_gettext(); + + if (regcomp(&r, pat, flags)) + die("failed regcomp() for pattern '%s'", pat); + if (regexec(&r, str, 1, m, 0)) + return 1; + + return 0; } diff --git a/t/helper/test-revision-walking.c b/t/helper/test-revision-walking.c index 3d0313354b..b8e6fe1d00 100644 --- a/t/helper/test-revision-walking.c +++ b/t/helper/test-revision-walking.c @@ -45,7 +45,7 @@ static int run_revision_walk(void) return got_revision; } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { if (argc < 2) return 1; diff --git a/t/helper/test-run-command.c b/t/helper/test-run-command.c index 30a64a98dc..d24d157379 100644 --- a/t/helper/test-run-command.c +++ b/t/helper/test-run-command.c @@ -26,7 +26,7 @@ static int parallel_next(struct child_process *cp, return 0; argv_array_pushv(&cp->args, d->argv); - strbuf_addf(err, "preloaded output of a child\n"); + strbuf_addstr(err, "preloaded output of a child\n"); number_callbacks++; return 1; } @@ -36,7 +36,7 @@ static int no_job(struct child_process *cp, void *cb, void **task_cb) { - strbuf_addf(err, "no further jobs available\n"); + strbuf_addstr(err, "no further jobs available\n"); return 0; } @@ -45,11 +45,11 @@ static int task_finished(int result, void *pp_cb, void *pp_task_cb) { - strbuf_addf(err, "asking for a quick stop\n"); + strbuf_addstr(err, "asking for a quick stop\n"); return 1; } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { struct child_process proc = CHILD_PROCESS_INIT; int jobs; diff --git a/t/helper/test-scrap-cache-tree.c b/t/helper/test-scrap-cache-tree.c index 6efee31a48..5b2fd09908 100644 --- a/t/helper/test-scrap-cache-tree.c +++ b/t/helper/test-scrap-cache-tree.c @@ -5,7 +5,7 @@ static struct lock_file index_lock; -int main(int ac, char **av) +int cmd_main(int ac, const char **av) { hold_locked_index(&index_lock, 1); if (read_cache() < 0) diff --git a/t/helper/test-sha1-array.c b/t/helper/test-sha1-array.c index 60ea1d5f14..09f7790971 100644 --- a/t/helper/test-sha1-array.c +++ b/t/helper/test-sha1-array.c @@ -6,7 +6,7 @@ static void print_sha1(const unsigned char sha1[20], void *data) puts(sha1_to_hex(sha1)); } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { struct sha1_array array = SHA1_ARRAY_INIT; struct strbuf line = STRBUF_INIT; diff --git a/t/helper/test-sha1.c b/t/helper/test-sha1.c index e57eae10bf..a1c13f54ec 100644 --- a/t/helper/test-sha1.c +++ b/t/helper/test-sha1.c @@ -1,6 +1,6 @@ #include "cache.h" -int main(int ac, char **av) +int cmd_main(int ac, const char **av) { git_SHA_CTX ctx; unsigned char sha1[20]; diff --git a/t/helper/test-sigchain.c b/t/helper/test-sigchain.c index e499fce60f..b71edbd442 100644 --- a/t/helper/test-sigchain.c +++ b/t/helper/test-sigchain.c @@ -13,7 +13,7 @@ X(two) X(three) #undef X -int main(int argc, char **argv) { +int cmd_main(int argc, const char **argv) { sigchain_push(SIGTERM, one); sigchain_push(SIGTERM, two); sigchain_push(SIGTERM, three); diff --git a/t/helper/test-string-list.c b/t/helper/test-string-list.c index 14bdf9d215..4a68967bd1 100644 --- a/t/helper/test-string-list.c +++ b/t/helper/test-string-list.c @@ -41,7 +41,7 @@ static int prefix_cb(struct string_list_item *item, void *cb_data) return starts_with(item->string, prefix); } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { if (argc == 5 && !strcmp(argv[1], "split")) { struct string_list list = STRING_LIST_INIT_DUP; diff --git a/t/helper/test-submodule-config.c b/t/helper/test-submodule-config.c index dab8c27768..2f144d539a 100644 --- a/t/helper/test-submodule-config.c +++ b/t/helper/test-submodule-config.c @@ -2,7 +2,7 @@ #include "submodule-config.h" #include "submodule.h" -static void die_usage(int argc, char **argv, const char *msg) +static void die_usage(int argc, const char **argv, const char *msg) { fprintf(stderr, "%s\n", msg); fprintf(stderr, "Usage: %s [<commit> <submodulepath>] ...\n", argv[0]); @@ -14,16 +14,16 @@ static int git_test_config(const char *var, const char *value, void *cb) return parse_submodule_config_option(var, value); } -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { - char **arg = argv; + const char **arg = argv; int my_argc = argc; int output_url = 0; int lookup_name = 0; arg++; my_argc--; - while (starts_with(arg[0], "--")) { + while (arg[0] && starts_with(arg[0], "--")) { if (!strcmp(arg[0], "--url")) output_url = 1; if (!strcmp(arg[0], "--name")) @@ -49,7 +49,7 @@ int main(int argc, char **argv) path_or_name = arg[1]; if (commit[0] == '\0') - hashcpy(commit_sha1, null_sha1); + hashclr(commit_sha1); else if (get_sha1(commit, commit_sha1) < 0) die_usage(argc, argv, "Commit not found."); diff --git a/t/helper/test-subprocess.c b/t/helper/test-subprocess.c index 56881a0324..30c5765bfc 100644 --- a/t/helper/test-subprocess.c +++ b/t/helper/test-subprocess.c @@ -1,7 +1,7 @@ #include "cache.h" #include "run-command.h" -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { struct child_process cp = CHILD_PROCESS_INIT; int nogit = 0; diff --git a/t/helper/test-svn-fe.c b/t/helper/test-svn-fe.c index 120ec96b0d..7667c0803f 100644 --- a/t/helper/test-svn-fe.c +++ b/t/helper/test-svn-fe.c @@ -11,7 +11,7 @@ static const char test_svnfe_usage[] = "test-svn-fe (<dumpfile> | [-d] <preimage> <delta> <len>)"; -static int apply_delta(int argc, char *argv[]) +static int apply_delta(int argc, const char **argv) { struct line_buffer preimage = LINE_BUFFER_INIT; struct line_buffer delta = LINE_BUFFER_INIT; @@ -35,7 +35,7 @@ static int apply_delta(int argc, char *argv[]) return 0; } -int main(int argc, char *argv[]) +int cmd_main(int argc, const char **argv) { if (argc == 2) { if (svndump_init(argv[1])) diff --git a/t/helper/test-urlmatch-normalization.c b/t/helper/test-urlmatch-normalization.c index 090bf219a7..49b6e836be 100644 --- a/t/helper/test-urlmatch-normalization.c +++ b/t/helper/test-urlmatch-normalization.c @@ -1,7 +1,7 @@ #include "git-compat-util.h" #include "urlmatch.h" -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { const char usage[] = "test-urlmatch-normalization [-p | -l] <url1> | <url1> <url2>"; char *url1, *url2; diff --git a/t/helper/test-wildmatch.c b/t/helper/test-wildmatch.c index 578b164fe6..52be876fed 100644 --- a/t/helper/test-wildmatch.c +++ b/t/helper/test-wildmatch.c @@ -1,6 +1,6 @@ #include "cache.h" -int main(int argc, char **argv) +int cmd_main(int argc, const char **argv) { int i; for (i = 2; i < argc; i++) { diff --git a/t/lib-git-daemon.sh b/t/lib-git-daemon.sh index 340534c064..f9cbd47931 100644 --- a/t/lib-git-daemon.sh +++ b/t/lib-git-daemon.sh @@ -82,8 +82,7 @@ stop_git_daemon() { kill "$GIT_DAEMON_PID" wait "$GIT_DAEMON_PID" >&3 2>&4 ret=$? - # expect exit with status 143 = 128+15 for signal TERM=15 - if test $ret -ne 143 + if test_match_signal 15 $? then error "git daemon exited with status: $ret" fi diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh index fb8823224e..688313ed5c 100644 --- a/t/lib-git-svn.sh +++ b/t/lib-git-svn.sh @@ -65,81 +65,22 @@ svn_cmd () { svn "$orig_svncmd" --config-dir "$svnconf" "$@" } -prepare_httpd () { - for d in \ - "$SVN_HTTPD_PATH" \ - /usr/sbin/apache2 \ - /usr/sbin/httpd \ - ; do - if test -f "$d" - then - SVN_HTTPD_PATH="$d" - break - fi - done - if test -z "$SVN_HTTPD_PATH" - then - echo >&2 '*** error: Apache not found' - return 1 - fi - for d in \ - "$SVN_HTTPD_MODULE_PATH" \ - /usr/lib/apache2/modules \ - /usr/libexec/apache2 \ - ; do - if test -d "$d" - then - SVN_HTTPD_MODULE_PATH="$d" - break - fi - done - if test -z "$SVN_HTTPD_MODULE_PATH" - then - echo >&2 '*** error: Apache module dir not found' - return 1 - fi - if test ! -f "$SVN_HTTPD_MODULE_PATH/mod_dav_svn.so" - then - echo >&2 '*** error: Apache module "mod_dav_svn" not found' - return 1 - fi - - repo_base_path="${1-svn}" - mkdir "$GIT_DIR"/logs - - cat > "$GIT_DIR/httpd.conf" <<EOF -ServerName "git svn test" -ServerRoot "$GIT_DIR" -DocumentRoot "$GIT_DIR" -PidFile "$GIT_DIR/httpd.pid" -LockFile logs/accept.lock -Listen 127.0.0.1:$SVN_HTTPD_PORT -LoadModule dav_module $SVN_HTTPD_MODULE_PATH/mod_dav.so -LoadModule dav_svn_module $SVN_HTTPD_MODULE_PATH/mod_dav_svn.so -<Location /$repo_base_path> - DAV svn - SVNPath "$rawsvnrepo" -</Location> -EOF -} - -start_httpd () { - if test -z "$SVN_HTTPD_PORT" - then - echo >&2 'SVN_HTTPD_PORT is not defined!' - return - fi - - prepare_httpd "$1" || return 1 - - "$SVN_HTTPD_PATH" -f "$GIT_DIR"/httpd.conf -k start - svnrepo="http://127.0.0.1:$SVN_HTTPD_PORT/$repo_base_path" -} - -stop_httpd () { - test -z "$SVN_HTTPD_PORT" && return - test ! -f "$GIT_DIR/httpd.conf" && return - "$SVN_HTTPD_PATH" -f "$GIT_DIR"/httpd.conf -k stop +maybe_start_httpd () { + loc=${1-svn} + + test_tristate GIT_SVN_TEST_HTTPD + case $GIT_SVN_TEST_HTTPD in + true) + . "$TEST_DIRECTORY"/lib-httpd.sh + LIB_HTTPD_SVN="$loc" + start_httpd + ;; + *) + stop_httpd () { + : noop + } + ;; + esac } convert_to_rev_db () { diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh index ac2cbee250..435a37465a 100644 --- a/t/lib-httpd.sh +++ b/t/lib-httpd.sh @@ -24,7 +24,7 @@ # LIB_HTTPD_MODULE_PATH web server modules path # LIB_HTTPD_PORT listening port # LIB_HTTPD_DAV enable DAV -# LIB_HTTPD_SVN enable SVN +# LIB_HTTPD_SVN enable SVN at given location (e.g. "svn") # LIB_HTTPD_SSL enable SSL # # Copyright (c) 2008 Clemens Buchacher <drizzd@aon.at> @@ -162,8 +162,10 @@ prepare_httpd() { if test -n "$LIB_HTTPD_SVN" then HTTPD_PARA="$HTTPD_PARA -DSVN" - rawsvnrepo="$HTTPD_ROOT_PATH/svnrepo" - svnrepo="http://127.0.0.1:$LIB_HTTPD_PORT/svn" + LIB_HTTPD_SVNPATH="$rawsvnrepo" + svnrepo="http://127.0.0.1:$LIB_HTTPD_PORT/" + svnrepo="$svnrepo$LIB_HTTPD_SVN" + export LIB_HTTPD_SVN LIB_HTTPD_SVNPATH fi fi } diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf index 018a83a5a1..c3e631394f 100644 --- a/t/lib-httpd/apache.conf +++ b/t/lib-httpd/apache.conf @@ -208,8 +208,8 @@ RewriteRule ^/half-auth-complete/ - [E=AUTHREQUIRED:yes] <IfDefine SVN> LoadModule dav_svn_module modules/mod_dav_svn.so - <Location /svn> + <Location /${LIB_HTTPD_SVN}> DAV svn - SVNPath svnrepo + SVNPath "${LIB_HTTPD_SVNPATH}" </Location> </IfDefine> diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh index 9a96e1566d..25a77ee5cb 100644 --- a/t/lib-rebase.sh +++ b/t/lib-rebase.sh @@ -29,6 +29,7 @@ set_fake_editor () { */COMMIT_EDITMSG) test -z "$EXPECT_HEADER_COUNT" || test "$EXPECT_HEADER_COUNT" = "$(sed -n '1s/^# This is a combination of \(.*\) commits\./\1/p' < "$1")" || + test "# # GETTEXT POISON #" = "$(sed -n '1p' < "$1")" || exit test -z "$FAKE_COMMIT_MESSAGE" || echo "$FAKE_COMMIT_MESSAGE" > "$1" test -z "$FAKE_COMMIT_AMEND" || echo "$FAKE_COMMIT_AMEND" >> "$1" diff --git a/t/perf/README b/t/perf/README index 8848c14619..49ea4349be 100644 --- a/t/perf/README +++ b/t/perf/README @@ -115,8 +115,16 @@ After that you will want to use some of the following: At least one of the first two is required! -You can use test_expect_success as usual. For actual performance -tests, use +You can use test_expect_success as usual. In both test_expect_success +and in test_perf, running "git" points to the version that is being +perf-tested. The $MODERN_GIT variable points to the git wrapper for the +currently checked-out version (i.e., the one that matches the t/perf +scripts you are running). This is useful if your setup uses commands +that only work with newer versions of git than what you might want to +test (but obviously your new commands must still create a state that can +be used by the older version of git you are testing). + +For actual performance tests, use test_perf 'descriptive string' ' command1 && diff --git a/t/perf/p0003-delta-base-cache.sh b/t/perf/p0003-delta-base-cache.sh new file mode 100755 index 0000000000..62369eaaf0 --- /dev/null +++ b/t/perf/p0003-delta-base-cache.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +test_description='Test operations that emphasize the delta base cache. + +We look at both "log --raw", which should put only trees into the delta cache, +and "log -Sfoo --raw", which should look at both trees and blobs. + +Any effects will be emphasized if the test repository is fully packed (loose +objects obviously do not use the delta base cache at all). It is also +emphasized if the pack has long delta chains (e.g., as produced by "gc +--aggressive"), though cache is still quite noticeable even with the default +depth of 50. + +The setting of core.deltaBaseCacheLimit in the source repository is also +relevant (depending on the size of your test repo), so be sure it is consistent +between runs. +' +. ./perf-lib.sh + +test_perf_large_repo + +# puts mostly trees into the delta base cache +test_perf 'log --raw' ' + git log --raw >/dev/null +' + +test_perf 'log -S' ' + git log --raw -Sfoo >/dev/null +' + +test_done diff --git a/t/perf/p3400-rebase.sh b/t/perf/p3400-rebase.sh new file mode 100755 index 0000000000..b3e7d525d2 --- /dev/null +++ b/t/perf/p3400-rebase.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +test_description='Tests rebase performance' +. ./perf-lib.sh + +test_perf_default_repo + +test_expect_success 'setup' ' + git checkout -f -b base && + git checkout -b to-rebase && + git checkout -b upstream && + for i in $(seq 100) + do + # simulate huge diffs + echo change$i >unrelated-file$i && + seq 1000 >>unrelated-file$i && + git add unrelated-file$i && + test_tick && + git commit -m commit$i unrelated-file$i && + echo change$i >unrelated-file$i && + seq 1000 | tac >>unrelated-file$i && + git add unrelated-file$i && + test_tick && + git commit -m commit$i-reverse unrelated-file$i || + break + done && + git checkout to-rebase && + test_commit our-patch interesting-file +' + +test_perf 'rebase on top of a lot of unrelated changes' ' + git rebase --onto upstream HEAD^ && + git rebase --onto base HEAD^ +' + +test_done diff --git a/t/perf/p4211-line-log.sh b/t/perf/p4211-line-log.sh index 3d074b0e41..b7ff68d4fa 100755 --- a/t/perf/p4211-line-log.sh +++ b/t/perf/p4211-line-log.sh @@ -23,11 +23,11 @@ test_perf 'git log --follow (baseline for -M)' ' git log --oneline --follow -- "$file" >/dev/null ' -test_perf 'git log -L' ' - git log -L 1:"$file" >/dev/null +test_perf 'git log -L (renames off)' ' + git log --no-renames -L 1:"$file" >/dev/null ' -test_perf 'git log -M -L' ' +test_perf 'git log -L (renames on)' ' git log -M -L 1:"$file" >/dev/null ' diff --git a/t/perf/p5303-many-packs.sh b/t/perf/p5303-many-packs.sh new file mode 100755 index 0000000000..3779851941 --- /dev/null +++ b/t/perf/p5303-many-packs.sh @@ -0,0 +1,87 @@ +#!/bin/sh + +test_description='performance with large numbers of packs' +. ./perf-lib.sh + +test_perf_large_repo + +# A real many-pack situation would probably come from having a lot of pushes +# over time. We don't know how big each push would be, but we can fake it by +# just walking the first-parent chain and having every 5 commits be their own +# "push". This isn't _entirely_ accurate, as real pushes would have some +# duplicate objects due to thin-pack fixing, but it's a reasonable +# approximation. +# +# And then all of the rest of the objects can go in a single packfile that +# represents the state before any of those pushes (actually, we'll generate +# that first because in such a setup it would be the oldest pack, and we sort +# the packs by reverse mtime inside git). +repack_into_n () { + rm -rf staging && + mkdir staging && + + git rev-list --first-parent HEAD | + sed -n '1~5p' | + head -n "$1" | + perl -e 'print reverse <>' \ + >pushes + + # create base packfile + head -n 1 pushes | + git pack-objects --delta-base-offset --revs staging/pack + + # and then incrementals between each pair of commits + last= && + while read rev + do + if test -n "$last"; then + { + echo "$rev" && + echo "^$last" + } | + git pack-objects --delta-base-offset --revs \ + staging/pack || return 1 + fi + last=$rev + done <pushes && + + # and install the whole thing + rm -f .git/objects/pack/* && + mv staging/* .git/objects/pack/ +} + +# Pretend we just have a single branch and no reflogs, and that everything is +# in objects/pack; that makes our fake pack-building via repack_into_n() +# much simpler. +test_expect_success 'simplify reachability' ' + tip=$(git rev-parse --verify HEAD) && + git for-each-ref --format="option no-deref%0adelete %(refname)" | + git update-ref --stdin && + rm -rf .git/logs && + git update-ref refs/heads/master $tip && + git symbolic-ref HEAD refs/heads/master && + git repack -ad +' + +for nr_packs in 1 50 1000 +do + test_expect_success "create $nr_packs-pack scenario" ' + repack_into_n $nr_packs + ' + + test_perf "rev-list ($nr_packs)" ' + git rev-list --objects --all >/dev/null + ' + + # This simulates the interesting part of the repack, which is the + # actual pack generation, without smudging the on-disk setup + # between trials. + test_perf "repack ($nr_packs)" ' + git pack-objects --keep-true-parents \ + --honor-pack-keep --non-empty --all \ + --reflog --indexed-objects --delta-base-offset \ + --stdout </dev/null >/dev/null + ' +done + +test_done diff --git a/t/perf/p5310-pack-bitmaps.sh b/t/perf/p5310-pack-bitmaps.sh index de2a224a36..bb91dbb173 100755 --- a/t/perf/p5310-pack-bitmaps.sh +++ b/t/perf/p5310-pack-bitmaps.sh @@ -32,6 +32,14 @@ test_perf 'simulated fetch' ' } | git pack-objects --revs --stdout >/dev/null ' +test_perf 'pack to file' ' + git pack-objects --all pack1 </dev/null >/dev/null +' + +test_perf 'pack to file (bitmap)' ' + git pack-objects --use-bitmap-index --all pack1b </dev/null >/dev/null +' + test_expect_success 'create partial bitmap state' ' # pick a commit to represent the repo tip in the past cutoff=$(git rev-list HEAD~100 -1) && @@ -53,8 +61,12 @@ test_expect_success 'create partial bitmap state' ' git update-ref HEAD $orig_tip ' -test_perf 'partial bitmap' ' +test_perf 'clone (partial bitmap)' ' git pack-objects --stdout --all </dev/null >/dev/null ' +test_perf 'pack to file (partial bitmap)' ' + git pack-objects --use-bitmap-index --all pack2b </dev/null >/dev/null +' + test_done diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh index 18c363ea7f..46f08ee087 100644 --- a/t/perf/perf-lib.sh +++ b/t/perf/perf-lib.sh @@ -52,6 +52,9 @@ TEST_NO_MALLOC_CHECK=t # need to export them for test_perf subshells export TEST_DIRECTORY TRASH_DIRECTORY GIT_BUILD_DIR GIT_TEST_CMP +MODERN_GIT=$GIT_BUILD_DIR/bin-wrappers/git +export MODERN_GIT + perf_results_dir=$TEST_OUTPUT_DIRECTORY/test-results mkdir -p "$perf_results_dir" rm -f "$perf_results_dir"/$(basename "$0" .sh).subtests @@ -81,7 +84,7 @@ test_perf_create_repo_from () { repo="$1" source="$2" source_git="$(git -C "$source" rev-parse --git-dir)" - objects_dir="$(git -C "$source" rev-parse --git-path objects)" + objects_dir="$("$MODERN_GIT" -C "$source" rev-parse --git-path objects)" mkdir -p "$repo/.git" ( cd "$source" && @@ -127,11 +130,15 @@ test_checkout_worktree () { # Performance tests should never fail. If they do, stop immediately immediate=t +# Perf tests require GNU time +case "$(uname -s)" in Darwin) GTIME="${GTIME:-gtime}";; esac +GTIME="${GTIME:-/usr/bin/time}" + test_run_perf_ () { test_cleanup=: test_export_="test_cleanup" export test_cleanup test_export_ - /usr/bin/time -f "%E %U %S" -o test_time.$i "$SHELL" -c ' + "$GTIME" -f "%E %U %S" -o test_time.$i "$SHELL" -c ' . '"$TEST_DIRECTORY"/test-lib-functions.sh' test_export () { [ $# != 0 ] || return 0 diff --git a/t/perf/run b/t/perf/run index cfd70129bb..e8adedadfd 100755 --- a/t/perf/run +++ b/t/perf/run @@ -30,7 +30,13 @@ unpack_git_rev () { } build_git_rev () { rev=$1 - cp ../../config.mak build/$rev/config.mak + for config in config.mak config.mak.autogen config.status + do + if test -e "../../$config" + then + cp "../../$config" "build/$rev/" + fi + done (cd build/$rev && make $GIT_PERF_MAKE_OPTS) || die "failed to build revision '$mydir'" } diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index 60811a3a7c..1aa5093f36 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -834,7 +834,7 @@ test_expect_success 'git write-tree should be able to write an empty tree' ' ' test_expect_success 'validate object ID of a known tree' ' - test "$tree" = 4b825dc642cb6eb9a060e54bf8d69288fbee4904 + test "$tree" = $EMPTY_TREE ' # Various types of objects diff --git a/t/t0001-init.sh b/t/t0001-init.sh index a6fdd5ef3a..8ffbbea4d6 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -384,4 +384,13 @@ test_expect_success MINGW 'bare git dir not hidden' ' ! is_hidden newdir ' +test_expect_success 'remote init from does not use config from cwd' ' + rm -rf newdir && + test_config core.logallrefupdates true && + git init newdir && + echo true >expect && + git -C newdir config --bool core.logallrefupdates >actual && + test_cmp expect actual +' + test_done diff --git a/t/t0005-signals.sh b/t/t0005-signals.sh index e7f27ebbc1..46042f1f13 100755 --- a/t/t0005-signals.sh +++ b/t/t0005-signals.sh @@ -11,12 +11,13 @@ EOF test_expect_success 'sigchain works' ' { test-sigchain >actual; ret=$?; } && - case "$ret" in - 143) true ;; # POSIX w/ SIGTERM=15 - 271) true ;; # ksh w/ SIGTERM=15 - 3) true ;; # Windows - *) false ;; - esac && + { + # Signal death by raise() on Windows acts like exit(3), + # regardless of the signal number. So we must allow that + # as well as the normal signal check. + test_match_signal 15 "$ret" || + test "$ret" = 3 + } && test_cmp expect actual ' @@ -41,12 +42,12 @@ test_expect_success 'create blob' ' test_expect_success !MINGW 'a constipated git dies with SIGPIPE' ' OUT=$( ((large_git; echo $? 1>&3) | :) 3>&1 ) && - test "$OUT" -eq 141 + test_match_signal 13 "$OUT" ' test_expect_success !MINGW 'a constipated git dies with SIGPIPE even if parent ignores it' ' OUT=$( ((trap "" PIPE; large_git; echo $? 1>&3) | :) 3>&1 ) && - test "$OUT" -eq 141 + test_match_signal 13 "$OUT" ' test_done diff --git a/t/t0006-date.sh b/t/t0006-date.sh index fac0986134..c0c910867d 100755 --- a/t/t0006-date.sh +++ b/t/t0006-date.sh @@ -6,26 +6,55 @@ test_description='test date parsing and printing' # arbitrary reference time: 2009-08-30 19:20:00 TEST_DATE_NOW=1251660000; export TEST_DATE_NOW -check_show() { +check_relative() { t=$(($TEST_DATE_NOW - $1)) echo "$t -> $2" >expect test_expect_${3:-success} "relative date ($2)" " - test-date show $t >actual && + test-date relative $t >actual && test_i18ncmp expect actual " } -check_show 5 '5 seconds ago' -check_show 300 '5 minutes ago' -check_show 18000 '5 hours ago' -check_show 432000 '5 days ago' -check_show 1728000 '3 weeks ago' -check_show 13000000 '5 months ago' -check_show 37500000 '1 year, 2 months ago' -check_show 55188000 '1 year, 9 months ago' -check_show 630000000 '20 years ago' -check_show 31449600 '12 months ago' -check_show 62985600 '2 years ago' +check_relative 5 '5 seconds ago' +check_relative 300 '5 minutes ago' +check_relative 18000 '5 hours ago' +check_relative 432000 '5 days ago' +check_relative 1728000 '3 weeks ago' +check_relative 13000000 '5 months ago' +check_relative 37500000 '1 year, 2 months ago' +check_relative 55188000 '1 year, 9 months ago' +check_relative 630000000 '20 years ago' +check_relative 31449600 '12 months ago' +check_relative 62985600 '2 years ago' + +check_show () { + format=$1 + time=$2 + expect=$3 + test_expect_success $4 "show date ($format:$time)" ' + echo "$time -> $expect" >expect && + test-date show:$format "$time" >actual && + test_cmp expect actual + ' +} + +# arbitrary but sensible time for examples +TIME='1466000000 +0200' +check_show iso8601 "$TIME" '2016-06-15 16:13:20 +0200' +check_show iso8601-strict "$TIME" '2016-06-15T16:13:20+02:00' +check_show rfc2822 "$TIME" 'Wed, 15 Jun 2016 16:13:20 +0200' +check_show short "$TIME" '2016-06-15' +check_show default "$TIME" 'Wed Jun 15 16:13:20 2016 +0200' +check_show raw "$TIME" '1466000000 +0200' +check_show unix "$TIME" '1466000000' +check_show iso-local "$TIME" '2016-06-15 14:13:20 +0000' +check_show raw-local "$TIME" '1466000000 +0000' +check_show unix-local "$TIME" '1466000000' + +# arbitrary time absurdly far in the future +FUTURE="5758122296 -0400" +check_show iso "$FUTURE" "2152-06-19 18:24:56 -0400" LONG_IS_64BIT +check_show iso-local "$FUTURE" "2152-06-19 22:24:56 +0000" LONG_IS_64BIT check_parse() { echo "$1 -> $2" >expect diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh index b425f3a0d2..d27f438bf4 100755 --- a/t/t0008-ignores.sh +++ b/t/t0008-ignores.sh @@ -34,7 +34,7 @@ expect_from_stdin () { test_stderr () { expected="$1" expect_in stderr "$1" && - test_cmp "$HOME/expected-stderr" "$HOME/stderr" + test_i18ncmp "$HOME/expected-stderr" "$HOME/stderr" } broken_c_unquote () { @@ -47,7 +47,7 @@ broken_c_unquote_verbose () { stderr_contains () { regexp="$1" - if grep "$regexp" "$HOME/stderr" + if test_i18ngrep "$regexp" "$HOME/stderr" then return 0 else diff --git a/t/t0012-help.sh b/t/t0012-help.sh new file mode 100755 index 0000000000..8faba2e8bc --- /dev/null +++ b/t/t0012-help.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +test_description='help' + +. ./test-lib.sh + +configure_help () { + test_config help.format html && + + # Unless the path has "://" in it, Git tries to make sure + # the documentation directory locally exists. Avoid it as + # we are only interested in seeing an attempt to correctly + # invoke a help browser in this test. + test_config help.htmlpath test://html && + + # Name a custom browser + test_config browser.test.cmd ./test-browser && + test_config help.browser test +} + +test_expect_success "setup" ' + # Just write out which page gets requested + write_script test-browser <<-\EOF + echo "$*" >test-browser.log + EOF +' + +test_expect_success "works for commands and guides by default" ' + configure_help && + git help status && + echo "test://html/git-status.html" >expect && + test_cmp expect test-browser.log && + git help revisions && + echo "test://html/gitrevisions.html" >expect && + test_cmp expect test-browser.log +' + +test_expect_success "--exclude-guides does not work for guides" ' + >test-browser.log && + test_must_fail git help --exclude-guides revisions && + test_must_be_empty test-browser.log +' + +test_expect_success "--help does not work for guides" " + cat <<-EOF >expect && + git: 'revisions' is not a git command. See 'git --help'. + EOF + test_must_fail git revisions --help 2>actual && + test_i18ncmp expect actual +" + +test_done diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh index 7bac2bcf26..e799e59544 100755 --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@ -268,4 +268,15 @@ test_expect_success 'disable filter with empty override' ' test_must_be_empty err ' +test_expect_success 'diff does not reuse worktree files that need cleaning' ' + test_config filter.counter.clean "echo . >>count; sed s/^/clean:/" && + echo "file filter=counter" >.gitattributes && + test_commit one file && + test_commit two file && + + >count && + git diff-tree -p HEAD && + test_line_count = 0 count +' + test_done diff --git a/t/t0025-crlf-auto.sh b/t/t0025-crlf-auto.sh index c164b4662a..d0bee08b2e 100755 --- a/t/t0025-crlf-auto.sh +++ b/t/t0025-crlf-auto.sh @@ -114,7 +114,7 @@ test_expect_success 'autocrlf=true does not normalize CRLF files' ' test -z "$LFonlydiff" -a -z "$CRLFonlydiff" -a -z "$LFwithNULdiff" ' -test_expect_success 'text=auto, autocrlf=true _does_ normalize CRLF files' ' +test_expect_success 'text=auto, autocrlf=true does not normalize CRLF files' ' rm -f .gitattributes tmp LFonly CRLFonly LFwithNUL && git config core.autocrlf true && @@ -126,7 +126,7 @@ test_expect_success 'text=auto, autocrlf=true _does_ normalize CRLF files' ' LFonlydiff=$(git diff LFonly) && CRLFonlydiff=$(git diff CRLFonly) && LFwithNULdiff=$(git diff LFwithNUL) && - test -z "$LFonlydiff" -a -n "$CRLFonlydiff" -a -z "$LFwithNULdiff" + test -z "$LFonlydiff" -a -z "$CRLFonlydiff" -a -z "$LFwithNULdiff" ' test_expect_success 'text=auto, autocrlf=true does not normalize binary files' ' diff --git a/t/t0027-auto-crlf.sh b/t/t0027-auto-crlf.sh index 93725895a4..90db54c9f9 100755 --- a/t/t0027-auto-crlf.sh +++ b/t/t0027-auto-crlf.sh @@ -119,8 +119,7 @@ commit_chk_wrnNNO () { fname=${pfx}_$f.txt && cp $f $fname && printf Z >>"$fname" && - git -c core.autocrlf=$crlf add $fname 2>/dev/null && - git -c core.autocrlf=$crlf commit -m "commit_$fname" $fname >"${pfx}_$f.err" 2>&1 + git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err" done test_expect_success "commit NNO files crlf=$crlf attr=$attr LF" ' @@ -175,8 +174,8 @@ attr_ascii () { text,lf) echo "text eol=lf" ;; text,crlf) echo "text eol=crlf" ;; auto,) echo "text=auto" ;; - auto,lf) echo "text eol=lf" ;; - auto,crlf) echo "text eol=crlf" ;; + auto,lf) echo "text=auto eol=lf" ;; + auto,crlf) echo "text=auto eol=crlf" ;; lf,) echo "text eol=lf" ;; crlf,) echo "text eol=crlf" ;; ,) echo "" ;; @@ -397,10 +396,9 @@ commit_chk_wrnNNO "" "" false "" "" "" "" commit_chk_wrnNNO "" "" true LF_CRLF "" "" "" "" commit_chk_wrnNNO "" "" input "" "" "" "" "" -commit_chk_wrnNNO "auto" "" false "$WILC" "$WICL" "$WAMIX" "" "" -commit_chk_wrnNNO "auto" "" true LF_CRLF "" LF_CRLF "" "" -commit_chk_wrnNNO "auto" "" input "" CRLF_LF CRLF_LF "" "" - +commit_chk_wrnNNO "auto" "" false "$WILC" "" "" "" "" +commit_chk_wrnNNO "auto" "" true LF_CRLF "" "" "" "" +commit_chk_wrnNNO "auto" "" input "" "" "" "" "" for crlf in true false input do commit_chk_wrnNNO -text "" $crlf "" "" "" "" "" @@ -408,8 +406,8 @@ do commit_chk_wrnNNO -text crlf $crlf "" "" "" "" "" commit_chk_wrnNNO "" lf $crlf "" CRLF_LF CRLF_LF "" CRLF_LF commit_chk_wrnNNO "" crlf $crlf LF_CRLF "" LF_CRLF LF_CRLF "" - commit_chk_wrnNNO auto lf $crlf "" CRLF_LF CRLF_LF "" CRLF_LF - commit_chk_wrnNNO auto crlf $crlf LF_CRLF "" LF_CRLF LF_CRLF "" + commit_chk_wrnNNO auto lf $crlf "" "" "" "" "" + commit_chk_wrnNNO auto crlf $crlf LF_CRLF "" "" "" "" commit_chk_wrnNNO text lf $crlf "" CRLF_LF CRLF_LF "" CRLF_LF commit_chk_wrnNNO text crlf $crlf LF_CRLF "" LF_CRLF LF_CRLF "" done @@ -418,7 +416,8 @@ commit_chk_wrnNNO "text" "" false "$WILC" "$WICL" "$WAMIX" "$WILC commit_chk_wrnNNO "text" "" true LF_CRLF "" LF_CRLF LF_CRLF "" commit_chk_wrnNNO "text" "" input "" CRLF_LF CRLF_LF "" CRLF_LF -test_expect_success 'create files cleanup' ' +test_expect_success 'commit NNO and cleanup' ' + git commit -m "commit files on top of NNO" && rm -f *.txt && git -c core.autocrlf=false reset --hard ' @@ -454,9 +453,9 @@ do check_in_repo_NNO -text "" $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul check_in_repo_NNO -text lf $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul check_in_repo_NNO -text crlf $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul - check_in_repo_NNO auto "" $crlf LF LF LF LF_mix_CR CRLF_nul - check_in_repo_NNO auto lf $crlf LF LF LF LF_mix_CR LF_nul - check_in_repo_NNO auto crlf $crlf LF LF LF LF_mix_CR LF_nul + check_in_repo_NNO auto "" $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul + check_in_repo_NNO auto lf $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul + check_in_repo_NNO auto crlf $crlf LF CRLF CRLF_mix_LF LF_mix_CR CRLF_nul check_in_repo_NNO text "" $crlf LF LF LF LF_mix_CR LF_nul check_in_repo_NNO text lf $crlf LF LF LF LF_mix_CR LF_nul check_in_repo_NNO text crlf $crlf LF LF LF LF_mix_CR LF_nul @@ -509,7 +508,7 @@ do checkout_files text "$id" "crlf" "$crlf" "$ceol" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul # currently the same as text, eol=XXX checkout_files auto "$id" "lf" "$crlf" "$ceol" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul - checkout_files auto "$id" "crlf" "$crlf" "$ceol" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul + checkout_files auto "$id" "crlf" "$crlf" "$ceol" CRLF CRLF CRLF_mix_LF LF_mix_CR LF_nul done # core.autocrlf false, different core.eol @@ -517,7 +516,7 @@ do # core.autocrlf true checkout_files "" "$id" "" true "$ceol" CRLF CRLF CRLF_mix_LF LF_mix_CR LF_nul # text: core.autocrlf = true overrides core.eol - checkout_files auto "$id" "" true "$ceol" CRLF CRLF CRLF LF_mix_CR LF_nul + checkout_files auto "$id" "" true "$ceol" CRLF CRLF CRLF_mix_LF LF_mix_CR LF_nul checkout_files text "$id" "" true "$ceol" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul # text: core.autocrlf = input overrides core.eol checkout_files text "$id" "" input "$ceol" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul @@ -531,8 +530,8 @@ do checkout_files text "$id" "" false "" $NL CRLF $MIX_CRLF_LF $MIX_LF_CR $LFNUL checkout_files text "$id" "" false native $NL CRLF $MIX_CRLF_LF $MIX_LF_CR $LFNUL # auto: core.autocrlf=false and core.eol unset(or native) uses native eol - checkout_files auto "$id" "" false "" $NL CRLF $MIX_CRLF_LF LF_mix_CR LF_nul - checkout_files auto "$id" "" false native $NL CRLF $MIX_CRLF_LF LF_mix_CR LF_nul + checkout_files auto "$id" "" false "" $NL CRLF CRLF_mix_LF LF_mix_CR LF_nul + checkout_files auto "$id" "" false native $NL CRLF CRLF_mix_LF LF_mix_CR LF_nul done # Should be the last test case: remove some files from the worktree diff --git a/t/t0070-fundamental.sh b/t/t0070-fundamental.sh index 5ed69a6f56..991ed2a48d 100755 --- a/t/t0070-fundamental.sh +++ b/t/t0070-fundamental.sh @@ -31,7 +31,7 @@ test_expect_success 'git_mkstemps_mode does not fail if fd 0 is not open' ' test_expect_success 'check for a bug in the regex routines' ' # if this test fails, re-build git with NO_REGEX=1 - test-regex + test-regex --bug ' test_done diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh index 4f38078ff3..b19f332694 100755 --- a/t/t1006-cat-file.sh +++ b/t/t1006-cat-file.sh @@ -231,7 +231,7 @@ $tag_content | git cat-file --batch)" ' -test_expect_success "--batch-check for an emtpy line" ' +test_expect_success "--batch-check for an empty line" ' test " missing" = "$(echo | git cat-file --batch-check)" ' diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh index 7d2baa15bb..acca9ac562 100755 --- a/t/t1007-hash-object.sh +++ b/t/t1007-hash-object.sh @@ -101,7 +101,7 @@ test_expect_success 'git hash-object --stdin file1 <file0 first operates on file test "$obname1" = "$obname1new" ' -test_expect_success 'check that appropriate filter is invoke when --path is used' ' +test_expect_success 'set up crlf tests' ' echo fooQ | tr Q "\\015" >file0 && cp file0 file1 && echo "file0 -crlf" >.gitattributes && @@ -109,7 +109,10 @@ test_expect_success 'check that appropriate filter is invoke when --path is used git config core.autocrlf true && file0_sha=$(git hash-object file0) && file1_sha=$(git hash-object file1) && - test "$file0_sha" != "$file1_sha" && + test "$file0_sha" != "$file1_sha" +' + +test_expect_success 'check that appropriate filter is invoke when --path is used' ' path1_sha=$(git hash-object --path=file1 file0) && path0_sha=$(git hash-object --path=file0 file1) && test "$file0_sha" = "$path0_sha" && @@ -117,38 +120,30 @@ test_expect_success 'check that appropriate filter is invoke when --path is used path1_sha=$(cat file0 | git hash-object --path=file1 --stdin) && path0_sha=$(cat file1 | git hash-object --path=file0 --stdin) && test "$file0_sha" = "$path0_sha" && - test "$file1_sha" = "$path1_sha" && - git config --unset core.autocrlf + test "$file1_sha" = "$path1_sha" +' + +test_expect_success 'gitattributes also work in a subdirectory' ' + mkdir subdir && + ( + cd subdir && + subdir_sha0=$(git hash-object ../file0) && + subdir_sha1=$(git hash-object ../file1) && + test "$file0_sha" = "$subdir_sha0" && + test "$file1_sha" = "$subdir_sha1" + ) ' test_expect_success 'check that --no-filters option works' ' - echo fooQ | tr Q "\\015" >file0 && - cp file0 file1 && - echo "file0 -crlf" >.gitattributes && - echo "file1 crlf" >>.gitattributes && - git config core.autocrlf true && - file0_sha=$(git hash-object file0) && - file1_sha=$(git hash-object file1) && - test "$file0_sha" != "$file1_sha" && nofilters_file1=$(git hash-object --no-filters file1) && test "$file0_sha" = "$nofilters_file1" && nofilters_file1=$(cat file1 | git hash-object --stdin) && - test "$file0_sha" = "$nofilters_file1" && - git config --unset core.autocrlf + test "$file0_sha" = "$nofilters_file1" ' test_expect_success 'check that --no-filters option works with --stdin-paths' ' - echo fooQ | tr Q "\\015" >file0 && - cp file0 file1 && - echo "file0 -crlf" >.gitattributes && - echo "file1 crlf" >>.gitattributes && - git config core.autocrlf true && - file0_sha=$(git hash-object file0) && - file1_sha=$(git hash-object file1) && - test "$file0_sha" != "$file1_sha" && nofilters_file1=$(echo "file1" | git hash-object --stdin-paths --no-filters) && - test "$file0_sha" = "$nofilters_file1" && - git config --unset core.autocrlf + test "$file0_sha" = "$nofilters_file1" ' pop_repo diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh index 0c74beedd2..c167f606ca 100755 --- a/t/t1011-read-tree-sparse-checkout.sh +++ b/t/t1011-read-tree-sparse-checkout.sh @@ -15,11 +15,11 @@ test_description='sparse checkout tests . "$TEST_DIRECTORY"/lib-read-tree.sh test_expect_success 'setup' ' - cat >expected <<-\EOF && + cat >expected <<-EOF && 100644 77f0ba1734ed79d12881f81b36ee134de6a3327b 0 init.t - 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 sub/added - 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 sub/addedtoo - 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 subsub/added + 100644 $EMPTY_BLOB 0 sub/added + 100644 $EMPTY_BLOB 0 sub/addedtoo + 100644 $EMPTY_BLOB 0 subsub/added EOF cat >expected.swt <<-\EOF && H init.t @@ -244,10 +244,10 @@ test_expect_success 'print errors when failed to update worktree' ' error: The following untracked working tree files would be overwritten by checkout: sub/added sub/addedtoo -Please move or remove them before you can switch branches. +Please move or remove them before you switch branches. Aborting EOF - test_cmp expected actual + test_i18ncmp expected actual ' test_expect_success 'checkout without --ignore-skip-worktree-bits' ' diff --git a/t/t1050-large.sh b/t/t1050-large.sh index f9f3d1391f..096dbffecc 100755 --- a/t/t1050-large.sh +++ b/t/t1050-large.sh @@ -177,10 +177,9 @@ test_expect_success 'zip achiving, deflate' ' git archive --format=zip HEAD >/dev/null ' -test_expect_success 'fsck' ' - test_must_fail git fsck 2>err && - n=$(grep "error: attempting to allocate .* over limit" err | wc -l) && - test "$n" -gt 1 +test_expect_success 'fsck large blobs' ' + git fsck 2>err && + test_must_be_empty err ' test_done diff --git a/t/t1100-commit-tree-options.sh b/t/t1100-commit-tree-options.sh index b7e9b4fc5b..ae66ba5bab 100755 --- a/t/t1100-commit-tree-options.sh +++ b/t/t1100-commit-tree-options.sh @@ -15,7 +15,7 @@ Also make sure that command line parser understands the normal . ./test-lib.sh cat >expected <<EOF -tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904 +tree $EMPTY_TREE author Author Name <author@email> 1117148400 +0000 committer Committer Name <committer@email> 1117150200 +0000 diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index d934a24417..923bfc5a26 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -886,7 +886,7 @@ test_expect_success !MINGW 'get --path copes with unset $HOME' ' git config --get --path path.normal >>result && git config --get --path path.trailingtilde >>result ) && - grep "[Ff]ailed to expand.*~/" msg && + test_i18ngrep "[Ff]ailed to expand.*~/" msg && test_cmp expect result ' @@ -1126,7 +1126,7 @@ test_expect_success 'barf on syntax error' ' key garbage EOF test_must_fail git config --get section.key >actual 2>error && - grep " line 3 " error + test_i18ngrep " line 3 " error ' test_expect_success 'barf on incomplete section header' ' @@ -1136,7 +1136,7 @@ test_expect_success 'barf on incomplete section header' ' key = value EOF test_must_fail git config --get section.key >actual 2>error && - grep " line 2 " error + test_i18ngrep " line 2 " error ' test_expect_success 'barf on incomplete string' ' @@ -1146,7 +1146,7 @@ test_expect_success 'barf on incomplete string' ' key = "value string EOF test_must_fail git config --get section.key >actual 2>error && - grep " line 3 " error + test_i18ngrep " line 3 " error ' test_expect_success 'urlmatch' ' diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh index ac10875408..1312004f8c 100755 --- a/t/t1301-shared-repo.sh +++ b/t/t1301-shared-repo.sh @@ -172,4 +172,45 @@ test_expect_success POSIXPERM 'forced modes' ' }" actual)" ' +test_expect_success POSIXPERM 'remote init does not use config from cwd' ' + git config core.sharedrepository 0666 && + umask 0022 && + git init --bare child.git && + echo "-rw-r--r--" >expect && + modebits child.git/config >actual && + test_cmp expect actual +' + +test_expect_success POSIXPERM 're-init respects core.sharedrepository (local)' ' + git config core.sharedrepository 0666 && + umask 0022 && + echo whatever >templates/foo && + git init --template=templates && + echo "-rw-rw-rw-" >expect && + modebits .git/foo >actual && + test_cmp expect actual +' + +test_expect_success POSIXPERM 're-init respects core.sharedrepository (remote)' ' + rm -rf child.git && + umask 0022 && + git init --bare --shared=0666 child.git && + test_path_is_missing child.git/foo && + git init --bare --template=../templates child.git && + echo "-rw-rw-rw-" >expect && + modebits child.git/foo >actual && + test_cmp expect actual +' + +test_expect_success POSIXPERM 'template can set core.sharedrepository' ' + rm -rf child.git && + umask 0022 && + git config core.sharedrepository 0666 && + cp .git/config templates/config && + git init --bare --template=../templates child.git && + echo "-rw-rw-rw-" >expect && + modebits child.git/HEAD >actual && + test_cmp expect actual +' + test_done diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh index 9bcd34969f..ce4cff13bb 100755 --- a/t/t1302-repo-version.sh +++ b/t/t1302-repo-version.sh @@ -25,46 +25,26 @@ test_expect_success 'setup' ' test_expect_success 'gitdir selection on normal repos' ' echo 0 >expect && git config core.repositoryformatversion >actual && - ( - cd test && - git config core.repositoryformatversion >../actual2 - ) && + git -C test config core.repositoryformatversion >actual2 && test_cmp expect actual && test_cmp expect actual2 ' test_expect_success 'gitdir selection on unsupported repo' ' # Make sure it would stop at test2, not trash - echo 99 >expect && - ( - cd test2 && - git config core.repositoryformatversion >../actual - ) && - test_cmp expect actual + test_expect_code 1 git -C test2 config core.repositoryformatversion >actual ' test_expect_success 'gitdir not required mode' ' git apply --stat test.patch && - ( - cd test && - git apply --stat ../test.patch - ) && - ( - cd test2 && - git apply --stat ../test.patch - ) + git -C test apply --stat ../test.patch && + git -C test2 apply --stat ../test.patch ' test_expect_success 'gitdir required mode' ' git apply --check --index test.patch && - ( - cd test && - git apply --check --index ../test.patch - ) && - ( - cd test2 && - test_must_fail git apply --check --index ../test.patch - ) + git -C test apply --check --index ../test.patch && + test_must_fail git -C test2 apply --check --index ../test.patch ' check_allow () { diff --git a/t/t1307-config-blob.sh b/t/t1307-config-blob.sh index 3c6791e6be..eed31ffa30 100755 --- a/t/t1307-config-blob.sh +++ b/t/t1307-config-blob.sh @@ -61,10 +61,7 @@ test_expect_success 'parse errors in blobs are properly attributed' ' git commit -m broken && test_must_fail git config --blob=HEAD:config some.value 2>err && - - # just grep for our token as the exact error message is likely to - # change or be internationalized - grep "HEAD:config" err + test_i18ngrep "HEAD:config" err ' test_expect_success 'can parse blob ending with CR' ' diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh index 005d66dbef..7655c94c28 100755 --- a/t/t1308-config-set.sh +++ b/t/t1308-config-set.sh @@ -197,14 +197,14 @@ test_expect_success 'proper error on error in default config files' ' echo "[" >>.git/config && echo "fatal: bad config line 34 in file .git/config" >expect && test_expect_code 128 test-config get_value foo.bar 2>actual && - test_cmp expect actual + test_i18ncmp expect actual ' test_expect_success 'proper error on error in custom config files' ' echo "[" >>syntax-error && echo "fatal: bad config line 1 in file syntax-error" >expect && test_expect_code 128 test-config configset_get_value foo.bar syntax-error 2>actual && - test_cmp expect actual + test_i18ncmp expect actual ' test_expect_success 'check line errors for malformed values' ' @@ -229,4 +229,39 @@ test_expect_success 'error on modifying repo config without repo' ' ) ' +cmdline_config="'foo.bar=from-cmdline'" +test_expect_success 'iteration shows correct origins' ' + echo "[foo]bar = from-repo" >.git/config && + echo "[foo]bar = from-home" >.gitconfig && + if test_have_prereq MINGW + then + # Use Windows path (i.e. *not* $HOME) + HOME_GITCONFIG=$(pwd)/.gitconfig + else + # Do not get fooled by symbolic links, i.e. $HOME != $(pwd) + HOME_GITCONFIG=$HOME/.gitconfig + fi && + cat >expect <<-EOF && + key=foo.bar + value=from-home + origin=file + name=$HOME_GITCONFIG + scope=global + + key=foo.bar + value=from-repo + origin=file + name=.git/config + scope=repo + + key=foo.bar + value=from-cmdline + origin=command line + name= + scope=cmdline + EOF + GIT_CONFIG_PARAMETERS=$cmdline_config test-config iterate >actual && + test_cmp expect actual +' + test_done diff --git a/t/t1350-config-hooks-path.sh b/t/t1350-config-hooks-path.sh index 5e3fb3a6af..f1f9aee9f5 100755 --- a/t/t1350-config-hooks-path.sh +++ b/t/t1350-config-hooks-path.sh @@ -34,4 +34,10 @@ test_expect_success 'Check that various forms of specifying core.hooksPath work' test_cmp expect actual ' +test_expect_success 'git rev-parse --git-path hooks' ' + git config core.hooksPath .git/custom-hooks && + git rev-parse --git-path hooks/abc >actual && + test .git/custom-hooks/abc = "$(cat actual)" +' + test_done diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index af1b20dd5c..d4fb977060 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -23,7 +23,7 @@ test_expect_success setup ' m=refs/heads/master n_dir=refs/heads/gu n=$n_dir/fixes -outside=foo +outside=refs/foo test_expect_success \ "create $m" \ @@ -361,7 +361,7 @@ test_expect_success 'stdin test setup' ' test_expect_success '-z fails without --stdin' ' test_must_fail git update-ref -z $m $m $m 2>err && - grep "usage: git update-ref" err + test_i18ngrep "usage: git update-ref" err ' test_expect_success 'stdin works with no input' ' @@ -479,7 +479,7 @@ test_expect_success 'stdin fails with duplicate refs' ' create $a $m EOF test_must_fail git update-ref --stdin <stdin 2>err && - grep "fatal: Multiple updates for ref '"'"'$a'"'"' not allowed." err + grep "fatal: multiple updates for ref '"'"'$a'"'"' not allowed." err ' test_expect_success 'stdin create ref works' ' @@ -880,7 +880,7 @@ test_expect_success 'stdin -z fails option with unknown name' ' test_expect_success 'stdin -z fails with duplicate refs' ' printf $F "create $a" "$m" "create $b" "$m" "create $a" "$m" >stdin && test_must_fail git update-ref -z --stdin <stdin 2>err && - grep "fatal: Multiple updates for ref '"'"'$a'"'"' not allowed." err + grep "fatal: multiple updates for ref '"'"'$a'"'"' not allowed." err ' test_expect_success 'stdin -z create ref works' ' @@ -1102,6 +1102,41 @@ test_expect_success 'stdin -z delete refs works with packed and loose refs' ' test_must_fail git rev-parse --verify -q $c ' +test_expect_success 'fails with duplicate HEAD update' ' + git branch target1 $A && + git checkout target1 && + cat >stdin <<-EOF && + update refs/heads/target1 $C + option no-deref + update HEAD $B + EOF + test_must_fail git update-ref --stdin <stdin 2>err && + grep "fatal: multiple updates for '\''HEAD'\'' (including one via its referent .refs/heads/target1.) are not allowed" err && + echo "refs/heads/target1" >expect && + git symbolic-ref HEAD >actual && + test_cmp expect actual && + echo "$A" >expect && + git rev-parse refs/heads/target1 >actual && + test_cmp expect actual +' + +test_expect_success 'fails with duplicate ref update via symref' ' + git branch target2 $A && + git symbolic-ref refs/heads/symref2 refs/heads/target2 && + cat >stdin <<-EOF && + update refs/heads/target2 $C + update refs/heads/symref2 $B + EOF + test_must_fail git update-ref --stdin <stdin 2>err && + grep "fatal: multiple updates for '\''refs/heads/target2'\'' (including one via symref .refs/heads/symref2.) are not allowed" err && + echo "refs/heads/target2" >expect && + git symbolic-ref refs/heads/symref2 >actual && + test_cmp expect actual && + echo "$A" >expect && + git rev-parse refs/heads/target2 >actual && + test_cmp expect actual +' + run_with_limited_open_files () { (ulimit -n 32 && "$@") } diff --git a/t/t1401-symbolic-ref.sh b/t/t1401-symbolic-ref.sh index ca3fa406c3..eec3e90f9c 100755 --- a/t/t1401-symbolic-ref.sh +++ b/t/t1401-symbolic-ref.sh @@ -33,18 +33,25 @@ test_expect_success 'symbolic-ref refuses bare sha1' ' ' reset_to_sane -test_expect_success 'symbolic-ref deletes HEAD' ' - git symbolic-ref -d HEAD && +test_expect_success 'HEAD cannot be removed' ' + test_must_fail git symbolic-ref -d HEAD +' + +reset_to_sane + +test_expect_success 'symbolic-ref can be deleted' ' + git symbolic-ref NOTHEAD refs/heads/foo && + git symbolic-ref -d NOTHEAD && test_path_is_file .git/refs/heads/foo && - test_path_is_missing .git/HEAD + test_path_is_missing .git/NOTHEAD ' reset_to_sane -test_expect_success 'symbolic-ref deletes dangling HEAD' ' - git symbolic-ref HEAD refs/heads/missing && - git symbolic-ref -d HEAD && +test_expect_success 'symbolic-ref can delete dangling symref' ' + git symbolic-ref NOTHEAD refs/heads/missing && + git symbolic-ref -d NOTHEAD && test_path_is_missing .git/refs/heads/missing && - test_path_is_missing .git/HEAD + test_path_is_missing .git/NOTHEAD ' reset_to_sane diff --git a/t/t1404-update-ref-df-conflicts.sh b/t/t1404-update-ref-df-conflicts.sh deleted file mode 100755 index 66bafb5cf4..0000000000 --- a/t/t1404-update-ref-df-conflicts.sh +++ /dev/null @@ -1,107 +0,0 @@ -#!/bin/sh - -test_description='Test git update-ref with D/F conflicts' -. ./test-lib.sh - -test_update_rejected () { - prefix="$1" && - before="$2" && - pack="$3" && - create="$4" && - error="$5" && - printf "create $prefix/%s $C\n" $before | - git update-ref --stdin && - git for-each-ref $prefix >unchanged && - if $pack - then - git pack-refs --all - fi && - printf "create $prefix/%s $C\n" $create >input && - test_must_fail git update-ref --stdin <input 2>output.err && - grep -F "$error" output.err && - git for-each-ref $prefix >actual && - test_cmp unchanged actual -} - -Q="'" - -test_expect_success 'setup' ' - - git commit --allow-empty -m Initial && - C=$(git rev-parse HEAD) - -' - -test_expect_success 'existing loose ref is a simple prefix of new' ' - - prefix=refs/1l && - test_update_rejected $prefix "a c e" false "b c/x d" \ - "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x$Q" - -' - -test_expect_success 'existing packed ref is a simple prefix of new' ' - - prefix=refs/1p && - test_update_rejected $prefix "a c e" true "b c/x d" \ - "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x$Q" - -' - -test_expect_success 'existing loose ref is a deeper prefix of new' ' - - prefix=refs/2l && - test_update_rejected $prefix "a c e" false "b c/x/y d" \ - "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x/y$Q" - -' - -test_expect_success 'existing packed ref is a deeper prefix of new' ' - - prefix=refs/2p && - test_update_rejected $prefix "a c e" true "b c/x/y d" \ - "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x/y$Q" - -' - -test_expect_success 'new ref is a simple prefix of existing loose' ' - - prefix=refs/3l && - test_update_rejected $prefix "a c/x e" false "b c d" \ - "$Q$prefix/c/x$Q exists; cannot create $Q$prefix/c$Q" - -' - -test_expect_success 'new ref is a simple prefix of existing packed' ' - - prefix=refs/3p && - test_update_rejected $prefix "a c/x e" true "b c d" \ - "$Q$prefix/c/x$Q exists; cannot create $Q$prefix/c$Q" - -' - -test_expect_success 'new ref is a deeper prefix of existing loose' ' - - prefix=refs/4l && - test_update_rejected $prefix "a c/x/y e" false "b c d" \ - "$Q$prefix/c/x/y$Q exists; cannot create $Q$prefix/c$Q" - -' - -test_expect_success 'new ref is a deeper prefix of existing packed' ' - - prefix=refs/4p && - test_update_rejected $prefix "a c/x/y e" true "b c d" \ - "$Q$prefix/c/x/y$Q exists; cannot create $Q$prefix/c$Q" - -' - -test_expect_success 'one new ref is a simple prefix of another' ' - - prefix=refs/5 && - test_update_rejected $prefix "a e" false "b c c/x d" \ - "cannot process $Q$prefix/c$Q and $Q$prefix/c/x$Q at the same time" - -' - -test_done diff --git a/t/t1404-update-ref-errors.sh b/t/t1404-update-ref-errors.sh new file mode 100755 index 0000000000..c34ece48f5 --- /dev/null +++ b/t/t1404-update-ref-errors.sh @@ -0,0 +1,407 @@ +#!/bin/sh + +test_description='Test git update-ref error handling' +. ./test-lib.sh + +# Create some references, perhaps run pack-refs --all, then try to +# create some more references. Ensure that the second creation fails +# with the correct error message. +# Usage: test_update_rejected <before> <pack> <create> <error> +# <before> is a ws-separated list of refs to create before the test +# <pack> (true or false) tells whether to pack the refs before the test +# <create> is a list of variables to attempt creating +# <error> is a string to look for in the stderr of update-ref. +# All references are created in the namespace specified by the current +# value of $prefix. +test_update_rejected () { + before="$1" && + pack="$2" && + create="$3" && + error="$4" && + printf "create $prefix/%s $C\n" $before | + git update-ref --stdin && + git for-each-ref $prefix >unchanged && + if $pack + then + git pack-refs --all + fi && + printf "create $prefix/%s $C\n" $create >input && + test_must_fail git update-ref --stdin <input 2>output.err && + grep -F "$error" output.err && + git for-each-ref $prefix >actual && + test_cmp unchanged actual +} + +Q="'" + +test_expect_success 'setup' ' + + git commit --allow-empty -m Initial && + C=$(git rev-parse HEAD) && + git commit --allow-empty -m Second && + D=$(git rev-parse HEAD) && + git commit --allow-empty -m Third && + E=$(git rev-parse HEAD) +' + +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" + +' + +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" + +' + +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" + +' + +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" + +' + +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" + +' + +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" + +' + +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" + +' + +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" + +' + +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" + +' + +test_expect_success 'empty directory should not fool rev-parse' ' + prefix=refs/e-rev-parse && + git update-ref $prefix/foo $C && + git pack-refs --all && + mkdir -p .git/$prefix/foo/bar/baz && + echo "$C" >expected && + git rev-parse $prefix/foo >actual && + test_cmp expected actual +' + +test_expect_success 'empty directory should not fool for-each-ref' ' + prefix=refs/e-for-each-ref && + git update-ref $prefix/foo $C && + git for-each-ref $prefix >expected && + git pack-refs --all && + mkdir -p .git/$prefix/foo/bar/baz && + git for-each-ref $prefix >actual && + test_cmp expected actual +' + +test_expect_success 'empty directory should not fool create' ' + prefix=refs/e-create && + mkdir -p .git/$prefix/foo/bar/baz && + printf "create %s $C\n" $prefix/foo | + git update-ref --stdin +' + +test_expect_success 'empty directory should not fool verify' ' + prefix=refs/e-verify && + git update-ref $prefix/foo $C && + git pack-refs --all && + mkdir -p .git/$prefix/foo/bar/baz && + printf "verify %s $C\n" $prefix/foo | + git update-ref --stdin +' + +test_expect_success 'empty directory should not fool 1-arg update' ' + prefix=refs/e-update-1 && + git update-ref $prefix/foo $C && + git pack-refs --all && + mkdir -p .git/$prefix/foo/bar/baz && + printf "update %s $D\n" $prefix/foo | + git update-ref --stdin +' + +test_expect_success 'empty directory should not fool 2-arg update' ' + prefix=refs/e-update-2 && + git update-ref $prefix/foo $C && + git pack-refs --all && + mkdir -p .git/$prefix/foo/bar/baz && + printf "update %s $D $C\n" $prefix/foo | + git update-ref --stdin +' + +test_expect_success 'empty directory should not fool 0-arg delete' ' + prefix=refs/e-delete-0 && + git update-ref $prefix/foo $C && + git pack-refs --all && + mkdir -p .git/$prefix/foo/bar/baz && + printf "delete %s\n" $prefix/foo | + git update-ref --stdin +' + +test_expect_success 'empty directory should not fool 1-arg delete' ' + prefix=refs/e-delete-1 && + git update-ref $prefix/foo $C && + git pack-refs --all && + mkdir -p .git/$prefix/foo/bar/baz && + printf "delete %s $C\n" $prefix/foo | + git update-ref --stdin +' + +# Test various errors when reading the old values of references... + +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 + EOF + printf "%s\n" "update $prefix/foo $E $D" | + test_must_fail git update-ref --stdin 2>output.err && + test_cmp expected output.err +' + +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 + EOF + printf "%s\n" "update $prefix/foo $E $D" | + test_must_fail git update-ref --stdin 2>output.err && + test_cmp expected output.err +' + +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 + EOF + printf "%s\n" "create $prefix/foo $E" | + test_must_fail git update-ref --stdin 2>output.err && + test_cmp expected output.err +' + +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 + EOF + printf "%s\n" "delete $prefix/foo $D" | + test_must_fail git update-ref --stdin 2>output.err && + test_cmp expected output.err +' + +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 + EOF + printf "%s\n" "update $prefix/symref $E $D" | + test_must_fail git update-ref --stdin 2>output.err && + test_cmp expected output.err +' + +test_expect_success 'incorrect old value blocks indirect update' ' + prefix=refs/incorrect-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 + EOF + printf "%s\n" "update $prefix/symref $E $D" | + test_must_fail git update-ref --stdin 2>output.err && + test_cmp expected output.err +' + +test_expect_success 'existing old value blocks indirect create' ' + prefix=refs/existing-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 + EOF + printf "%s\n" "create $prefix/symref $E" | + test_must_fail git update-ref --stdin 2>output.err && + test_cmp expected output.err +' + +test_expect_success 'incorrect old value blocks indirect delete' ' + prefix=refs/incorrect-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 + EOF + printf "%s\n" "delete $prefix/symref $D" | + test_must_fail git update-ref --stdin 2>output.err && + test_cmp expected output.err +' + +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 + EOF + printf "%s\n" "option no-deref" "update $prefix/symref $E $D" | + test_must_fail git update-ref --stdin 2>output.err && + test_cmp expected output.err +' + +test_expect_success 'incorrect old value blocks indirect no-deref update' ' + prefix=refs/incorrect-noderef-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 + EOF + printf "%s\n" "option no-deref" "update $prefix/symref $E $D" | + test_must_fail git update-ref --stdin 2>output.err && + test_cmp expected output.err +' + +test_expect_success 'existing old value blocks indirect no-deref create' ' + prefix=refs/existing-noderef-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 + EOF + printf "%s\n" "option no-deref" "create $prefix/symref $E" | + test_must_fail git update-ref --stdin 2>output.err && + test_cmp expected output.err +' + +test_expect_success 'incorrect old value blocks indirect no-deref delete' ' + prefix=refs/incorrect-noderef-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 + EOF + printf "%s\n" "option no-deref" "delete $prefix/symref $D" | + test_must_fail git update-ref --stdin 2>output.err && + test_cmp expected output.err +' + +test_expect_success 'non-empty directory blocks create' ' + prefix=refs/ne-create && + mkdir -p .git/$prefix/foo/bar && + : >.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 + 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 + EOF + printf "%s\n" "update $prefix/foo $D $C" | + test_must_fail git update-ref --stdin 2>output.err && + test_cmp expected output.err +' + +test_expect_success 'broken reference blocks create' ' + prefix=refs/broken-create && + mkdir -p .git/$prefix && + 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 + 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 + EOF + printf "%s\n" "update $prefix/foo $D $C" | + test_must_fail git update-ref --stdin 2>output.err && + test_cmp expected output.err +' + +test_expect_success 'non-empty directory blocks indirect create' ' + prefix=refs/ne-indirect-create && + git symbolic-ref $prefix/symref $prefix/foo && + mkdir -p .git/$prefix/foo/bar && + : >.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 + 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 + EOF + printf "%s\n" "update $prefix/symref $D $C" | + test_must_fail git update-ref --stdin 2>output.err && + test_cmp expected output.err +' + +test_expect_success 'broken reference blocks indirect create' ' + prefix=refs/broken-indirect-create && + git symbolic-ref $prefix/symref $prefix/foo && + 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 + 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 + EOF + printf "%s\n" "update $prefix/symref $D $C" | + test_must_fail git update-ref --stdin 2>output.err && + test_cmp expected output.err +' + +test_done diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh index dd2be049ec..553e26d9ce 100755 --- a/t/t1410-reflog.sh +++ b/t/t1410-reflog.sh @@ -359,7 +359,6 @@ test_expect_success 'continue walking past root commits' ' HEAD@{3} commit (initial): initial EOF test_commit initial && - git reflog && git checkout --orphan orphan1 && test_commit orphan1-1 && test_commit orphan1-2 && diff --git a/t/t1430-bad-ref-name.sh b/t/t1430-bad-ref-name.sh index 25ddab4e98..8937e25e49 100755 --- a/t/t1430-bad-ref-name.sh +++ b/t/t1430-bad-ref-name.sh @@ -285,7 +285,7 @@ test_expect_success 'update-ref -d cannot delete non-ref in .git dir' ' echo precious >expect && test_must_fail git update-ref -d my-private-file >output 2>error && test_must_be_empty output && - test_i18ngrep -e "cannot lock .*: unable to resolve reference" error && + test_i18ngrep -e "refusing to update ref with bad name" error && test_cmp expect .git/my-private-file ' diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index 7ee8ea004f..8f52da2771 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -523,4 +523,26 @@ test_expect_success 'fsck --connectivity-only' ' ) ' +remove_loose_object () { + sha1="$(git rev-parse "$1")" && + remainder=${sha1#??} && + firsttwo=${sha1%$remainder} && + rm .git/objects/$firsttwo/$remainder +} + +test_expect_success 'fsck --name-objects' ' + rm -rf name-objects && + git init name-objects && + ( + cd name-objects && + test_commit julius caesar.t && + test_commit augustus && + test_commit caesar && + remove_loose_object $(git rev-parse julius:caesar.t) && + test_must_fail git fsck --name-objects >out && + tree=$(git rev-parse --verify julius:) && + grep "$tree (\(refs/heads/master\|HEAD\)@{[0-9]*}:" out + ) +' + test_done diff --git a/t/t1506-rev-parse-diagnosis.sh b/t/t1506-rev-parse-diagnosis.sh index 86c2ff255d..79a0251efa 100755 --- a/t/t1506-rev-parse-diagnosis.sh +++ b/t/t1506-rev-parse-diagnosis.sh @@ -106,7 +106,7 @@ test_expect_success 'incorrect revision id' ' test_must_fail git rev-parse foobar:file.txt 2>error && grep "Invalid object name '"'"'foobar'"'"'." error && test_must_fail git rev-parse foobar 2> error && - grep "unknown revision or path not in the working tree." error + test_i18ngrep "unknown revision or path not in the working tree." error ' test_expect_success 'incorrect file in sha1:path' ' diff --git a/t/t1700-split-index.sh b/t/t1700-split-index.sh index 8aef49f236..292a0720fc 100755 --- a/t/t1700-split-index.sh +++ b/t/t1700-split-index.sh @@ -33,14 +33,14 @@ test_expect_success 'add one file' ' git update-index --add one && git ls-files --stage >ls-files.actual && cat >ls-files.expect <<EOF && -100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one +100644 $EMPTY_BLOB 0 one EOF test_cmp ls-files.expect ls-files.actual && test-dump-split-index .git/index | sed "/^own/d" >actual && cat >expect <<EOF && base $base -100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one +100644 $EMPTY_BLOB 0 one replacements: deletions: EOF @@ -51,7 +51,7 @@ test_expect_success 'disable split index' ' git update-index --no-split-index && git ls-files --stage >ls-files.actual && cat >ls-files.expect <<EOF && -100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one +100644 $EMPTY_BLOB 0 one EOF test_cmp ls-files.expect ls-files.actual && @@ -67,7 +67,7 @@ test_expect_success 'enable split index again, "one" now belongs to base index"' git update-index --split-index && git ls-files --stage >ls-files.actual && cat >ls-files.expect <<EOF && -100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one +100644 $EMPTY_BLOB 0 one EOF test_cmp ls-files.expect ls-files.actual && @@ -105,7 +105,7 @@ test_expect_success 'add another file, which stays index' ' git ls-files --stage >ls-files.actual && cat >ls-files.expect <<EOF && 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0 one -100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 two +100644 $EMPTY_BLOB 0 two EOF test_cmp ls-files.expect ls-files.actual && @@ -113,7 +113,7 @@ EOF q_to_tab >expect <<EOF && $BASE 100644 2e0996000b7e9019eabcad29391bf0f5c7702f0b 0Q -100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 two +100644 $EMPTY_BLOB 0 two replacements: 0 deletions: EOF @@ -159,14 +159,14 @@ test_expect_success 'add original file back' ' git update-index --add one && git ls-files --stage >ls-files.actual && cat >ls-files.expect <<EOF && -100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one +100644 $EMPTY_BLOB 0 one EOF test_cmp ls-files.expect ls-files.actual && test-dump-split-index .git/index | sed "/^own/d" >actual && cat >expect <<EOF && $BASE -100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one +100644 $EMPTY_BLOB 0 one replacements: deletions: 0 EOF @@ -178,8 +178,8 @@ test_expect_success 'add new file' ' git update-index --add two && git ls-files --stage >actual && cat >expect <<EOF && -100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one -100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 two +100644 $EMPTY_BLOB 0 one +100644 $EMPTY_BLOB 0 two EOF test_cmp expect actual ' @@ -188,8 +188,8 @@ test_expect_success 'unify index, two files remain' ' git update-index --no-split-index && 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 && diff --git a/t/t2010-checkout-ambiguous.sh b/t/t2010-checkout-ambiguous.sh index 87bdf9c96b..e76e84afbb 100755 --- a/t/t2010-checkout-ambiguous.sh +++ b/t/t2010-checkout-ambiguous.sh @@ -49,7 +49,7 @@ test_expect_success 'disambiguate checking out from a tree-ish' ' test_expect_success 'accurate error message with more than one ref' ' test_must_fail git checkout HEAD master -- 2>actual && - grep 2 actual && + test_i18ngrep 2 actual && test_i18ngrep "one reference expected, 2 given" actual ' diff --git a/t/t2018-checkout-branch.sh b/t/t2018-checkout-branch.sh index 2741262369..2131fb2a56 100755 --- a/t/t2018-checkout-branch.sh +++ b/t/t2018-checkout-branch.sh @@ -124,7 +124,7 @@ test_expect_success 'checkout -b to @{-1} fails with the right branch name' ' git checkout branch2 && echo >expect "fatal: A branch named '\''branch1'\'' already exists." && test_must_fail git checkout -b @{-1} 2>actual && - test_cmp expect actual + test_i18ncmp expect actual ' test_expect_success 'checkout -B to an existing branch resets branch to HEAD' ' diff --git a/t/t2020-checkout-detach.sh b/t/t2020-checkout-detach.sh index 5d68729d7a..fbb4ee9bb4 100755 --- a/t/t2020-checkout-detach.sh +++ b/t/t2020-checkout-detach.sh @@ -163,4 +163,27 @@ test_expect_success 'tracking count is accurate after orphan check' ' test_i18ncmp expect stdout ' +test_expect_success 'no advice given for explicit detached head state' ' + # baseline + test_config advice.detachedHead true && + git checkout child && git checkout HEAD^0 >expect.advice 2>&1 && + test_config advice.detachedHead false && + git checkout child && git checkout HEAD^0 >expect.no-advice 2>&1 && + test_unconfig advice.detachedHead && + # without configuration, the advice.* variables default to true + git checkout child && git checkout HEAD^0 >actual 2>&1 && + test_cmp expect.advice actual && + + # with explicit --detach + # no configuration + test_unconfig advice.detachedHead && + git checkout child && git checkout --detach HEAD^0 >actual 2>&1 && + test_cmp expect.no-advice actual && + + # explicitly decline advice + test_config advice.detachedHead false && + git checkout child && git checkout --detach HEAD^0 >actual 2>&1 && + test_cmp expect.no-advice actual +' + test_done diff --git a/t/t2028-worktree-move.sh b/t/t2028-worktree-move.sh new file mode 100755 index 0000000000..8298aaf97f --- /dev/null +++ b/t/t2028-worktree-move.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +test_description='test git worktree move, remove, lock and unlock' + +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit init && + git worktree add source && + git worktree list --porcelain | grep "^worktree" >actual && + cat <<-EOF >expected && + worktree $(pwd) + worktree $(pwd)/source + EOF + test_cmp expected actual +' + +test_expect_success 'lock main worktree' ' + test_must_fail git worktree lock . +' + +test_expect_success 'lock linked worktree' ' + git worktree lock --reason hahaha source && + echo hahaha >expected && + test_cmp expected .git/worktrees/source/locked +' + +test_expect_success 'lock linked worktree from another worktree' ' + rm .git/worktrees/source/locked && + git worktree add elsewhere && + git -C elsewhere worktree lock --reason hahaha ../source && + echo hahaha >expected && + test_cmp expected .git/worktrees/source/locked +' + +test_expect_success 'lock worktree twice' ' + test_must_fail git worktree lock source && + echo hahaha >expected && + test_cmp expected .git/worktrees/source/locked +' + +test_expect_success 'lock worktree twice (from the locked worktree)' ' + test_must_fail git -C source worktree lock . && + echo hahaha >expected && + test_cmp expected .git/worktrees/source/locked +' + +test_expect_success 'unlock main worktree' ' + test_must_fail git worktree unlock . +' + +test_expect_success 'unlock linked worktree' ' + git worktree unlock source && + test_path_is_missing .git/worktrees/source/locked +' + +test_expect_success 'unlock worktree twice' ' + test_must_fail git worktree unlock source && + test_path_is_missing .git/worktrees/source/locked +' + +test_done diff --git a/t/t2203-add-intent.sh b/t/t2203-add-intent.sh index 2a4a749b4f..8f22c43e24 100755 --- a/t/t2203-add-intent.sh +++ b/t/t2203-add-intent.sh @@ -82,5 +82,36 @@ test_expect_success 'cache-tree invalidates i-t-a paths' ' test_cmp expect actual ' +test_expect_success 'cache-tree does not ignore dir that has i-t-a entries' ' + git init ita-in-dir && + ( + cd ita-in-dir && + mkdir 2 && + for f in 1 2/1 2/2 3 + do + echo "$f" >"$f" + done && + git add 1 2/2 3 && + git add -N 2/1 && + git commit -m committed && + git ls-tree -r HEAD >actual && + grep 2/2 actual + ) +' + +test_expect_success 'cache-tree does skip dir that becomes empty' ' + rm -fr ita-in-dir && + git init ita-in-dir && + ( + cd ita-in-dir && + mkdir -p 1/2/3 && + echo 4 >1/2/3/4 && + git add -N 1/2/3/4 && + git write-tree >actual && + echo $EMPTY_TREE >expected && + test_cmp expected actual + ) +' + test_done diff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh index cccd7d923a..c8de6d8a19 100755 --- a/t/t2300-cd-to-toplevel.sh +++ b/t/t2300-cd-to-toplevel.sh @@ -4,11 +4,19 @@ test_description='cd_to_toplevel' . ./test-lib.sh +EXEC_PATH="$(git --exec-path)" +test_have_prereq !MINGW || +case "$EXEC_PATH" in +[A-Za-z]:/*) + EXEC_PATH="/${EXEC_PATH%%:*}${EXEC_PATH#?:}" + ;; +esac + test_cd_to_toplevel () { test_expect_success $3 "$2" ' ( cd '"'$1'"' && - PATH="$(git --exec-path):$PATH" && + PATH="$EXEC_PATH:$PATH" && . git-sh-setup && cd_to_toplevel && [ "$(pwd -P)" = "$TOPLEVEL" ] diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh index f7b0e599f1..470f33466c 100755 --- a/t/t3030-merge-recursive.sh +++ b/t/t3030-merge-recursive.sh @@ -660,4 +660,22 @@ test_expect_success 'merging with triple rename across D/F conflict' ' git merge other ' +test_expect_success 'merge-recursive remembers the names of all base trees' ' + git reset --hard HEAD && + + # 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 + test_must_fail git -c merge.verbosity=5 merge-recursive $(cat trees) -- $c1 $c3 >out && + + # merge-recursive prints in reverse order, but we do not care + sort <trees >expect && + sed -n "s/^virtual //p" out | sort >actual && + test_cmp expect actual +' + test_done diff --git a/t/t3101-ls-tree-dirname.sh b/t/t3101-ls-tree-dirname.sh index 425d858938..327ded4000 100755 --- a/t/t3101-ls-tree-dirname.sh +++ b/t/t3101-ls-tree-dirname.sh @@ -16,7 +16,7 @@ This test runs git ls-tree with the following in a tree. path3/1.txt - a file in a directory path3/2.txt - a file in a directory -Test the handling of mulitple directories which have matching file +Test the handling of multiple directories which have matching file entries. Also test odd filename and missing entries handling. ' . ./test-lib.sh diff --git a/t/t3102-ls-tree-wildcards.sh b/t/t3102-ls-tree-wildcards.sh index 4d4b02e760..e804377f1c 100755 --- a/t/t3102-ls-tree-wildcards.sh +++ b/t/t3102-ls-tree-wildcards.sh @@ -12,16 +12,16 @@ test_expect_success 'setup' ' ' test_expect_success 'ls-tree a[a] matches literally' ' - cat >expect <<-\EOF && - 100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 a[a]/three + cat >expect <<-EOF && + 100644 blob $EMPTY_BLOB a[a]/three EOF git ls-tree -r HEAD "a[a]" >actual && test_cmp expect actual ' test_expect_success 'ls-tree outside prefix' ' - cat >expect <<-\EOF && - 100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 ../a[a]/three + cat >expect <<-EOF && + 100644 blob $EMPTY_BLOB ../a[a]/three EOF ( cd aa && git ls-tree -r HEAD "../a[a]"; ) >actual && test_cmp expect actual diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index f3e3b6cf2e..8a833f354e 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -79,6 +79,15 @@ test_expect_success 'git branch -m dumps usage' ' test_i18ngrep "branch name required" err ' +test_expect_success 'git branch -m m broken_symref should work' ' + test_when_finished "git branch -D broken_symref" && + git branch -l m && + git symbolic-ref refs/heads/broken_symref refs/heads/i_am_broken && + git branch -m m broken_symref && + git reflog exists refs/heads/broken_symref && + test_must_fail git reflog exists refs/heads/i_am_broken +' + test_expect_success 'git branch -m m m/m should work' ' git branch -l m && git branch -m m m/m && @@ -550,7 +559,7 @@ If you wanted to make '"'master'"' track '"'origin/master'"', do this: git branch -d origin/master git branch --set-upstream-to origin/master EOF - test_cmp expected actual + test_i18ncmp expected actual ' test_expect_success '--set-upstream with two args only shows the deprecation message' ' @@ -559,7 +568,7 @@ test_expect_success '--set-upstream with two args only shows the deprecation mes cat >expected <<EOF && The --set-upstream flag is deprecated and will be removed. Consider using --track or --set-upstream-to EOF - test_cmp expected actual + test_i18ncmp expected actual ' test_expect_success '--set-upstream with one arg only shows the deprecation message if the branch existed' ' @@ -568,7 +577,7 @@ test_expect_success '--set-upstream with one arg only shows the deprecation mess cat >expected <<EOF && The --set-upstream flag is deprecated and will be removed. Consider using --track or --set-upstream-to EOF - test_cmp expected actual + test_i18ncmp expected actual ' test_expect_success '--set-upstream-to notices an error to set branch as own upstream' ' diff --git a/t/t3201-branch-contains.sh b/t/t3201-branch-contains.sh index 912a6635a8..7f3ec47241 100755 --- a/t/t3201-branch-contains.sh +++ b/t/t3201-branch-contains.sh @@ -156,7 +156,7 @@ test_expect_success 'branch --merged with --verbose' ' * topic 2c939f4 [ahead 1] foo zzz c77a0a9 second on master EOF - test_cmp expect actual + test_i18ncmp expect actual ' test_done diff --git a/t/t3310-notes-merge-manual-resolve.sh b/t/t3310-notes-merge-manual-resolve.sh index d5572121da..6967436327 100755 --- a/t/t3310-notes-merge-manual-resolve.sh +++ b/t/t3310-notes-merge-manual-resolve.sh @@ -178,7 +178,7 @@ test_expect_success 'merge z into m (== y) with default ("manual") resolver => C git config core.notesRef refs/notes/m && test_must_fail git notes merge z >output && # Output should point to where to resolve conflicts - grep -q "\\.git/NOTES_MERGE_WORKTREE" output && + test_i18ngrep "\\.git/NOTES_MERGE_WORKTREE" output && # Inspect merge conflicts ls .git/NOTES_MERGE_WORKTREE >output_conflicts && test_cmp expect_conflicts output_conflicts && @@ -381,7 +381,7 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol git config core.notesRef refs/notes/m && test_must_fail git notes merge z >output && # Output should point to where to resolve conflicts - grep -q "\\.git/NOTES_MERGE_WORKTREE" output && + test_i18ngrep "\\.git/NOTES_MERGE_WORKTREE" output && # Inspect merge conflicts ls .git/NOTES_MERGE_WORKTREE >output_conflicts && test_cmp expect_conflicts output_conflicts && @@ -415,7 +415,7 @@ git rev-parse refs/notes/z > pre_merge_z test_expect_success 'redo merge of z into m (== y) with default ("manual") resolver => Conflicting 3-way merge' ' test_must_fail git notes merge z >output && # Output should point to where to resolve conflicts - grep -q "\\.git/NOTES_MERGE_WORKTREE" output && + test_i18ngrep "\\.git/NOTES_MERGE_WORKTREE" output && # Inspect merge conflicts ls .git/NOTES_MERGE_WORKTREE >output_conflicts && test_cmp expect_conflicts output_conflicts && @@ -496,7 +496,7 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol git update-ref refs/notes/m refs/notes/y && test_must_fail git notes merge z >output && # Output should point to where to resolve conflicts - grep -q "\\.git/NOTES_MERGE_WORKTREE" output && + test_i18ngrep "\\.git/NOTES_MERGE_WORKTREE" output && # Inspect merge conflicts ls .git/NOTES_MERGE_WORKTREE >output_conflicts && test_cmp expect_conflicts output_conflicts && diff --git a/t/t3320-notes-merge-worktrees.sh b/t/t3320-notes-merge-worktrees.sh index 1f71d589f5..b9c3bc2487 100755 --- a/t/t3320-notes-merge-worktrees.sh +++ b/t/t3320-notes-merge-worktrees.sh @@ -52,7 +52,7 @@ test_expect_success 'merge z into y while mid-merge in another workdir fails' ' cd worktree && git config core.notesRef refs/notes/y && test_must_fail git notes merge z 2>err && - grep "A notes merge into refs/notes/y is already in-progress at" err + test_i18ngrep "a notes merge into refs/notes/y is already in-progress at" err ) && test_path_is_missing .git/worktrees/worktree/NOTES_MERGE_REF ' @@ -62,7 +62,7 @@ test_expect_success 'merge z into x while mid-merge on y succeeds' ' cd worktree2 && git config core.notesRef refs/notes/x && test_must_fail git notes merge z 2>&1 >out && - grep "Automatic notes merge failed" out && + test_i18ngrep "Automatic notes merge failed" out && grep -v "A notes merge into refs/notes/x is already in-progress in" out ) && echo "ref: refs/notes/x" >expect && diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh index 47b5682662..f5fd15e559 100755 --- a/t/t3400-rebase.sh +++ b/t/t3400-rebase.sh @@ -136,8 +136,8 @@ test_expect_success 'setup: recover' ' test_expect_success 'Show verbose error when HEAD could not be detached' ' >B && test_must_fail git rebase topic 2>output.err >output.out && - grep "The following untracked working tree files would be overwritten by checkout:" output.err && - grep B output.err + test_i18ngrep "The following untracked working tree files would be overwritten by checkout:" output.err && + test_i18ngrep B output.err ' rm -f B diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 66348f11d1..597e94e294 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -60,7 +60,7 @@ test_expect_success 'setup' ' test_commit P fileP ' -# "exec" commands are ran with the user shell by default, but this may +# "exec" commands are run with the user shell by default, but this may # be non-POSIX. For example, if SHELL=zsh then ">file" doesn't work # to create a file. Unsetting SHELL avoids such non-portable behavior # in tests. It must be exported for it to take effect where needed. @@ -219,9 +219,9 @@ test_expect_success 'abort with error when new base cannot be checked out' ' git commit -m "remove file in base" && set_fake_editor && test_must_fail git rebase -i master > output 2>&1 && - grep "The following untracked working tree files would be overwritten by checkout:" \ + test_i18ngrep "The following untracked working tree files would be overwritten by checkout:" \ output && - grep "file1" output && + test_i18ngrep "file1" output && test_path_is_missing .git/rebase-merge && git reset --hard HEAD^ ' @@ -540,7 +540,7 @@ test_expect_success 'clean error after failed "exec"' ' echo "edited again" > file7 && git add file7 && test_must_fail git rebase --continue 2>error && - grep "You have staged changes in your working tree." error + test_i18ngrep "You have staged changes in your working tree." error ' test_expect_success 'rebase a detached HEAD' ' @@ -1060,7 +1060,7 @@ test_expect_success 'todo count' ' EOF test_set_editor "$(pwd)/dump-raw.sh" && git rebase -i HEAD~4 >actual && - grep "^# Rebase ..* onto ..* ([0-9]" actual + test_i18ngrep "^# Rebase ..* onto ..* ([0-9]" actual ' test_expect_success 'rebase -i commits that overwrite untracked files (pick)' ' @@ -1160,7 +1160,7 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = ignore' ' FAKE_LINES="1 2 3 4" \ git rebase -i --root 2>actual && test D = $(git cat-file commit HEAD | sed -ne \$p) && - test_cmp expect actual + test_i18ncmp expect actual ' cat >expect <<EOF @@ -1181,7 +1181,7 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = warn' ' set_fake_editor && FAKE_LINES="1 2 3 4" \ git rebase -i --root 2>actual && - test_cmp expect actual && + test_i18ncmp expect actual && test D = $(git cat-file commit HEAD | sed -ne \$p) ' @@ -1205,7 +1205,7 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = error' ' set_fake_editor && test_must_fail env FAKE_LINES="1 2 4" \ git rebase -i --root 2>actual && - test_cmp expect 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" \ @@ -1228,7 +1228,7 @@ test_expect_success 'static check of bad command' ' set_fake_editor && test_must_fail env FAKE_LINES="1 2 3 bad 4 5" \ git rebase -i --root 2>actual && - test_cmp expect actual && + test_i18ncmp expect 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) && @@ -1263,7 +1263,7 @@ test_expect_success 'static check of bad SHA-1' ' set_fake_editor && test_must_fail env FAKE_LINES="1 2 edit fakesha 3 4 5 #" \ git rebase -i --root 2>actual && - test_cmp expect actual && + test_i18ncmp expect 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) @@ -1281,4 +1281,12 @@ test_expect_success 'editor saves as CR/LF' ' ) ' +SQ="'" +test_expect_success 'rebase -i --gpg-sign=<key-id>' ' + 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_done diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh index 8f53e54ce4..48346f1cc0 100755 --- a/t/t3415-rebase-autosquash.sh +++ b/t/t3415-rebase-autosquash.sh @@ -271,4 +271,37 @@ test_expect_success 'autosquash with custom inst format' ' test 2 = $(git cat-file commit HEAD^ | grep squash | wc -l) ' +set_backup_editor () { + write_script backup-editor.sh <<-\EOF + cp "$1" .git/backup-"$(basename "$1")" + EOF + test_set_editor "$PWD/backup-editor.sh" +} + +test_expect_failure 'autosquash with multiple empty patches' ' + test_tick && + git commit --allow-empty -m "empty" && + test_tick && + git commit --allow-empty -m "empty2" && + test_tick && + >fixup && + git add fixup && + git commit --fixup HEAD^^ && + ( + set_backup_editor && + GIT_USE_REBASE_HELPER=false \ + git rebase -i --force-rebase --autosquash HEAD~4 && + grep empty2 .git/backup-git-rebase-todo + ) +' + +test_expect_success 'extra spaces after fixup!' ' + base=$(git rev-parse HEAD) && + test_commit to-fixup && + git commit --allow-empty -m "fixup! to-fixup" && + git rebase -i --autosquash --keep-empty HEAD~2 && + parent=$(git rev-parse HEAD^) && + test $base = $parent +' + test_done diff --git a/t/t3420-rebase-autostash.sh b/t/t3420-rebase-autostash.sh index 944154b2e0..ab8a63e8d6 100755 --- a/t/t3420-rebase-autostash.sh +++ b/t/t3420-rebase-autostash.sh @@ -179,7 +179,7 @@ testrebase " --interactive" .git/rebase-merge test_expect_success 'abort rebase -i with --autostash' ' test_when_finished "git reset --hard" && - echo uncommited-content >file0 && + echo uncommitted-content >file0 && ( write_script abort-editor.sh <<-\EOF && echo >"$1" @@ -188,7 +188,38 @@ test_expect_success 'abort rebase -i with --autostash' ' test_must_fail git rebase -i --autostash HEAD^ && rm -f abort-editor.sh ) && - echo uncommited-content >expected && + echo uncommitted-content >expected && + test_cmp expected file0 +' + +test_expect_success 'restore autostash on editor failure' ' + test_when_finished "git reset --hard" && + echo uncommitted-content >file0 && + ( + test_set_editor "false" && + test_must_fail git rebase -i --autostash HEAD^ + ) && + echo uncommitted-content >expected && + test_cmp expected file0 +' + +test_expect_success 'autostash is saved on editor failure with conflict' ' + test_when_finished "git reset --hard" && + echo uncommitted-content >file0 && + ( + write_script abort-editor.sh <<-\EOF && + echo conflicting-content >file0 + exit 1 + EOF + test_set_editor "$(pwd)/abort-editor.sh" && + test_must_fail git rebase -i --autostash HEAD^ && + rm -f abort-editor.sh + ) && + echo conflicting-content >expected && + test_cmp expected file0 && + git checkout file0 && + git stash pop && + echo uncommitted-content >expected && test_cmp expected file0 ' diff --git a/t/t3427-rebase-subtree.sh b/t/t3427-rebase-subtree.sh new file mode 100755 index 0000000000..3780877e4e --- /dev/null +++ b/t/t3427-rebase-subtree.sh @@ -0,0 +1,119 @@ +#!/bin/sh + +test_description='git rebase tests for -Xsubtree + +This test runs git rebase and tests the subtree strategy. +' +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-rebase.sh + +commit_message() { + git log --pretty=format:%s -1 "$1" +} + +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 -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" +' + +# FAILURE: Does not preserve master5. +test_expect_failure 'Rebase -Xsubtree --preserve-merges --onto commit 5' ' + 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 rebase -Xsubtree=files_subtree --preserve-merges --onto files-master master && + verbose test "$(commit_message HEAD)" = "files_subtree/master5" +' + +# FAILURE: Does not preserve master4. +test_expect_failure '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 -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 -Xsubtree --keep-empty --preserve-merges --onto empty 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 rebase -Xsubtree=files_subtree --keep-empty --preserve-merges --onto files-master master && + verbose test "$(commit_message HEAD)" = "Empty commit" +' + +# FAILURE: fatal: Could not parse object +test_expect_failure 'Rebase -Xsubtree --onto commit 4' ' + 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" +' + +# 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' ' + 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 && + verbose test "$(commit_message HEAD)" = "Empty commit" +' + +test_done diff --git a/t/t3700-add.sh b/t/t3700-add.sh index 4865304ebb..2978cb9d64 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -7,6 +7,20 @@ test_description='Test of git add, including the -- option.' . ./test-lib.sh +# Test the file mode "$1" of the file "$2" in the index. +test_mode_in_index () { + case "$(git ls-files -s "$2")" in + "$1 "*" $2") + echo pass + ;; + *) + echo fail + git ls-files -s "$2" + return 1 + ;; + esac +} + test_expect_success \ 'Test of git add' \ 'touch foo && git add foo' @@ -25,18 +39,12 @@ test_expect_success \ echo foo >xfoo1 && chmod 755 xfoo1 && git add xfoo1 && - case "$(git ls-files --stage xfoo1)" in - 100644" "*xfoo1) echo pass;; - *) echo fail; git ls-files --stage xfoo1; (exit 1);; - esac' + test_mode_in_index 100644 xfoo1' test_expect_success 'git add: filemode=0 should not get confused by symlink' ' rm -f xfoo1 && test_ln_s_add foo xfoo1 && - case "$(git ls-files --stage xfoo1)" in - 120000" "*xfoo1) echo pass;; - *) echo fail; git ls-files --stage xfoo1; (exit 1);; - esac + test_mode_in_index 120000 xfoo1 ' test_expect_success \ @@ -45,28 +53,19 @@ test_expect_success \ echo foo >xfoo2 && chmod 755 xfoo2 && git update-index --add xfoo2 && - case "$(git ls-files --stage xfoo2)" in - 100644" "*xfoo2) echo pass;; - *) echo fail; git ls-files --stage xfoo2; (exit 1);; - esac' + test_mode_in_index 100644 xfoo2' test_expect_success 'git add: filemode=0 should not get confused by symlink' ' rm -f xfoo2 && test_ln_s_add foo xfoo2 && - case "$(git ls-files --stage xfoo2)" in - 120000" "*xfoo2) echo pass;; - *) echo fail; git ls-files --stage xfoo2; (exit 1);; - esac + test_mode_in_index 120000 xfoo2 ' test_expect_success \ 'git update-index --add: Test that executable bit is not used...' \ 'git config core.filemode 0 && test_ln_s_add xfoo2 xfoo3 && # runs git update-index --add - case "$(git ls-files --stage xfoo3)" in - 120000" "*xfoo3) echo pass;; - *) echo fail; git ls-files --stage xfoo3; (exit 1);; - esac' + test_mode_in_index 120000 xfoo3' test_expect_success '.gitignore test setup' ' echo "*.ig" >.gitignore && @@ -332,34 +331,22 @@ test_expect_success 'git add --dry-run --ignore-missing of non-existing file out test_i18ncmp expect.err actual.err ' -test_expect_success 'git add --chmod=+x stages a non-executable file with +x' ' +test_expect_success 'git add --chmod=[+-]x stages correctly' ' + rm -f foo1 && echo foo >foo1 && git add --chmod=+x foo1 && - case "$(git ls-files --stage foo1)" in - 100755" "*foo1) echo pass;; - *) echo fail; git ls-files --stage foo1; (exit 1);; - esac -' - -test_expect_success 'git add --chmod=-x stages an executable file with -x' ' - echo foo >xfoo1 && - chmod 755 xfoo1 && - git add --chmod=-x xfoo1 && - case "$(git ls-files --stage xfoo1)" in - 100644" "*xfoo1) echo pass;; - *) echo fail; git ls-files --stage xfoo1; (exit 1);; - esac + test_mode_in_index 100755 foo1 && + git add --chmod=-x foo1 && + test_mode_in_index 100644 foo1 ' test_expect_success POSIXPERM,SYMLINKS 'git add --chmod=+x with symlinks' ' git config core.filemode 1 && git config core.symlinks 1 && + rm -f foo2 && echo foo >foo2 && git add --chmod=+x foo2 && - case "$(git ls-files --stage foo2)" in - 100755" "*foo2) echo pass;; - *) echo fail; git ls-files --stage foo2; (exit 1);; - esac + test_mode_in_index 100755 foo2 ' test_done diff --git a/t/t4010-diff-pathspec.sh b/t/t4010-diff-pathspec.sh index 43c488b545..35b35a81c8 100755 --- a/t/t4010-diff-pathspec.sh +++ b/t/t4010-diff-pathspec.sh @@ -78,8 +78,6 @@ test_expect_success 'diff-tree pathspec' ' test_cmp expected current ' -EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904 - test_expect_success 'diff-tree with wildcard shows dir also matches' ' git diff-tree --name-only $EMPTY_TREE $tree -- "f*" >result && echo file0 >expected && diff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh index 643d729157..0a8af76aab 100755 --- a/t/t4012-diff-binary.sh +++ b/t/t4012-diff-binary.sh @@ -68,7 +68,7 @@ test_expect_success C_LOCALE_OUTPUT 'apply detecting corrupt patch correctly' ' sed -e "s/-CIT/xCIT/" <output >broken && test_must_fail git apply --stat --summary broken 2>detected && detected=$(cat detected) && - detected=$(expr "$detected" : "fatal.*at line \\([0-9]*\\)\$") && + detected=$(expr "$detected" : "error.*at line \\([0-9]*\\)\$") && detected=$(sed -ne "${detected}p" broken) && test "$detected" = xCIT ' @@ -77,7 +77,7 @@ test_expect_success C_LOCALE_OUTPUT 'apply detecting corrupt patch correctly' ' git diff --binary | sed -e "s/-CIT/xCIT/" >broken && test_must_fail git apply --stat --summary broken 2>detected && detected=$(cat detected) && - detected=$(expr "$detected" : "fatal.*at line \\([0-9]*\\)\$") && + detected=$(expr "$detected" : "error.*at line \\([0-9]*\\)\$") && detected=$(sed -ne "${detected}p" broken) && test "$detected" = xCIT ' diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index 94ef5000e7..566817e2ef 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -306,6 +306,8 @@ diff --no-index --name-status dir2 dir diff --no-index --name-status -- dir2 dir diff --no-index dir dir3 diff master master^ side +# Can't use spaces... +diff --line-prefix=abc master master^ side diff --dirstat master~1 master~2 diff --dirstat initial rearrange diff --dirstat-by-file initial rearrange @@ -325,6 +327,10 @@ test_expect_success 'diff --cached -- file on unborn branch' ' git diff --cached -- file0 >result && test_cmp "$TEST_DIRECTORY/t4013/diff.diff_--cached_--_file0" result ' +test_expect_success 'diff --line-prefix with spaces' ' + git diff --line-prefix="| | | " --cached -- file0 >result && + test_cmp "$TEST_DIRECTORY/t4013/diff.diff_--line-prefix_--cached_--_file0" result +' test_expect_success 'diff-tree --stdin with log formatting' ' cat >expect <<-\EOF && diff --git a/t/t4013/diff.diff_--line-prefix=abc_master_master^_side b/t/t4013/diff.diff_--line-prefix=abc_master_master^_side new file mode 100644 index 0000000000..99f91e7f0e --- /dev/null +++ b/t/t4013/diff.diff_--line-prefix=abc_master_master^_side @@ -0,0 +1,29 @@ +$ git diff --line-prefix=abc master master^ side +abcdiff --cc dir/sub +abcindex cead32e,7289e35..992913c +abc--- a/dir/sub +abc+++ b/dir/sub +abc@@@ -1,6 -1,4 +1,8 @@@ +abc A +abc B +abc +C +abc +D +abc +E +abc +F +abc+ 1 +abc+ 2 +abcdiff --cc file0 +abcindex b414108,f4615da..10a8a9f +abc--- a/file0 +abc+++ b/file0 +abc@@@ -1,6 -1,6 +1,9 @@@ +abc 1 +abc 2 +abc 3 +abc +4 +abc +5 +abc +6 +abc+ A +abc+ B +abc+ C +$ diff --git a/t/t4013/diff.diff_--line-prefix_--cached_--_file0 b/t/t4013/diff.diff_--line-prefix_--cached_--_file0 new file mode 100644 index 0000000000..f41ba4d36a --- /dev/null +++ b/t/t4013/diff.diff_--line-prefix_--cached_--_file0 @@ -0,0 +1,15 @@ +| | | diff --git a/file0 b/file0 +| | | new file mode 100644 +| | | index 0000000..10a8a9f +| | | --- /dev/null +| | | +++ b/file0 +| | | @@ -0,0 +1,9 @@ +| | | +1 +| | | +2 +| | | +3 +| | | +4 +| | | +5 +| | | +6 +| | | +A +| | | +B +| | | +C diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index 805dc9012d..8d90a6e500 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -229,6 +229,46 @@ check_patch () { grep -e "^Subject:" "$1" } +test_expect_success 'format.from=false' ' + + git -c format.from=false format-patch --stdout master..side | + sed -e "/^\$/q" >patch && + check_patch patch && + ! grep "^From: C O Mitter <committer@example.com>\$" patch +' + +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 +' + +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 +' + +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 +' + +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 +' + test_expect_success '--no-to overrides config.to' ' git config --replace-all format.to \ @@ -714,9 +754,22 @@ test_expect_success 'format-patch --ignore-if-in-upstream HEAD' ' git format-patch --ignore-if-in-upstream HEAD ' +git_version="$(git --version | sed "s/.* //")" + +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 && + signature >expect && + test_cmp expect output +' + test_expect_success 'format-patch --signature' ' - git format-patch --stdout --signature="my sig" -1 >output && - grep "my sig" output + git format-patch --stdout --signature="my sig" -1 | tail -n 3 >output && + signature "my sig" >expect && + test_cmp expect output ' test_expect_success 'format-patch with format.signature config' ' @@ -1462,12 +1515,12 @@ 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 >patch && - grep "^base-commit:" patch >actual && - grep "^prerequisite-patch-id:" patch >>actual && - echo "base-commit: $(git rev-parse HEAD~3)" >expected && + git format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual && + 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 actual ' @@ -1565,4 +1618,53 @@ test_expect_success 'format-patch --base overrides format.useAutoBase' ' test_cmp expected actual ' +test_expect_success 'format-patch --base with --attach' ' + git format-patch --attach=mimemime --stdout --base=HEAD~ -1 >patch && + sed -n -e "/^base-commit:/s/.*/1/p" -e "/^---*mimemime--$/s/.*/2/p" \ + patch >actual && + test_write_lines 1 2 >expect && + test_cmp expect actual +' + +test_expect_success 'format-patch --pretty=mboxrd' ' + sp=" " && + cat >msg <<-INPUT_END && + mboxrd should escape the body + + From could trip up a loose mbox parser + >From extra escape for reversibility + >>From extra escape for reversibility 2 + from lower case not escaped + Fromm bad speling not escaped + From with leading space not escaped + + F + From + From$sp + From $sp + From $sp + INPUT_END + + cat >expect <<-INPUT_END && + >From could trip up a loose mbox parser + >>From extra escape for reversibility + >>>From extra escape for reversibility 2 + from lower case not escaped + Fromm bad speling not escaped + From with leading space not escaped + + F + From + From + From + From + INPUT_END + + C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) && + git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch && + git grep -h --no-index -A11 \ + "^>From could trip up a loose mbox parser" patch >actual && + test_cmp expect actual +' + test_done diff --git a/t/t4021-format-patch-numbered.sh b/t/t4021-format-patch-numbered.sh index 886494b58f..9be65fd444 100755 --- a/t/t4021-format-patch-numbered.sh +++ b/t/t4021-format-patch-numbered.sh @@ -36,6 +36,11 @@ test_no_numbered() { test_num_no_numbered $1 2 } +test_single_cover_letter_numbered() { + grep "^Subject: \[PATCH 0/1\]" $1 && + grep "^Subject: \[PATCH 1/1\]" $1 +} + test_single_numbered() { grep "^Subject: \[PATCH 1/1\]" $1 } @@ -121,4 +126,16 @@ test_expect_success '--start-number && --numbered' ' grep "^Subject: \[PATCH 3/3\]" patch8 ' +test_expect_success 'single patch with cover-letter defaults to numbers' ' + git format-patch --cover-letter --stdout HEAD~1 >patch9.single && + test_single_cover_letter_numbered patch9.single +' + +test_expect_success 'Use --no-numbered and --cover-letter single patch' ' + git format-patch --no-numbered --stdout --cover-letter HEAD~1 >patch10 && + test_no_numbered patch10 +' + + + test_done diff --git a/t/t4026-color.sh b/t/t4026-color.sh index 2b32c4fbe6..ec78c5e3ac 100755 --- a/t/t4026-color.sh +++ b/t/t4026-color.sh @@ -50,14 +50,19 @@ test_expect_success 'attr negation' ' color "nobold nodim noul noblink noreverse" "[22;24;25;27m" ' +test_expect_success '"no-" variant of negation' ' + color "no-bold no-blink" "[22;25m" +' + test_expect_success 'long color specification' ' color "254 255 bold dim ul blink reverse" "[1;2;4;5;7;38;5;254;48;5;255m" ' test_expect_success 'absurdly long color specification' ' color \ - "#ffffff #ffffff bold nobold dim nodim ul noul blink noblink reverse noreverse" \ - "[1;2;4;5;7;22;24;25;27;38;2;255;255;255;48;2;255;255;255m" + "#ffffff #ffffff bold nobold dim nodim italic noitalic + ul noul blink noblink reverse noreverse strike nostrike" \ + "[1;2;3;4;5;7;9;22;23;24;25;27;29;38;2;255;255;255;48;2;255;255;255m" ' test_expect_success '0-7 are aliases for basic ANSI color names' ' diff --git a/t/t4033-diff-patience.sh b/t/t4033-diff-patience.sh index 3c9932edf3..113304dc59 100755 --- a/t/t4033-diff-patience.sh +++ b/t/t4033-diff-patience.sh @@ -5,6 +5,14 @@ test_description='patience diff algorithm' . ./test-lib.sh . "$TEST_DIRECTORY"/lib-diff-alternative.sh +test_expect_success '--ignore-space-at-eol with a single appended character' ' + printf "a\nb\nc\n" >pre && + printf "a\nbX\nc\n" >post && + test_must_fail git diff --no-index \ + --patience --ignore-space-at-eol pre post >diff && + grep "^+.*X" diff +' + test_diff_frobnitz "patience" test_diff_unique "patience" diff --git a/t/t4051-diff-function-context.sh b/t/t4051-diff-function-context.sh index b79b87790b..6154acb456 100755 --- a/t/t4051-diff-function-context.sh +++ b/t/t4051-diff-function-context.sh @@ -67,6 +67,15 @@ test_expect_success 'setup' ' commit_and_tag long_common_tail file.c && git checkout initial && + cat "$dir/hello.c" "$dir/dummy.c" >file.c && + commit_and_tag hello_dummy file.c && + + # overlap function context of 1st change and -u context of 2nd change + grep -v "delete me from hello" <"$dir/hello.c" >file.c && + sed 2p <"$dir/dummy.c" >>file.c && + commit_and_tag changed_hello_dummy file.c && + + git checkout initial && grep -v "delete me from hello" <file.c >file.c.new && mv file.c.new file.c && cat "$dir/appended1.c" >>file.c && @@ -179,4 +188,20 @@ test_expect_success ' context does not include other functions' ' test $(grep -c "^[ +-].*Begin" changed_hello_appended.diff) -le 2 ' +check_diff changed_hello_dummy 'changed two consecutive functions' + +test_expect_success ' context includes begin' ' + grep "^ .*Begin of hello" changed_hello_dummy.diff && + grep "^ .*Begin of dummy" changed_hello_dummy.diff +' + +test_expect_success ' context includes end' ' + grep "^ .*End of hello" changed_hello_dummy.diff && + grep "^ .*End of dummy" changed_hello_dummy.diff +' + +test_expect_success ' overlapping hunks are merged' ' + test $(grep -c "^@@" changed_hello_dummy.diff) -eq 1 +' + test_done diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh index 6eb83211b5..453e6c35eb 100755 --- a/t/t4053-diff-no-index.sh +++ b/t/t4053-diff-no-index.sh @@ -89,4 +89,42 @@ test_expect_success 'turning a file into a directory' ' ) ' +test_expect_success 'diff from repo subdir shows real paths (explicit)' ' + echo "diff --git a/../../non/git/a b/../../non/git/b" >expect && + test_expect_code 1 \ + git -C repo/sub \ + diff --no-index ../../non/git/a ../../non/git/b >actual && + head -n 1 <actual >actual.head && + test_cmp expect actual.head +' + +test_expect_success 'diff from repo subdir shows real paths (implicit)' ' + echo "diff --git a/../../non/git/a b/../../non/git/b" >expect && + test_expect_code 1 \ + git -C repo/sub \ + diff ../../non/git/a ../../non/git/b >actual && + head -n 1 <actual >actual.head && + test_cmp expect actual.head +' + +test_expect_success 'diff --no-index from repo subdir respects config (explicit)' ' + echo "diff --git ../../non/git/a ../../non/git/b" >expect && + test_config -C repo diff.noprefix true && + test_expect_code 1 \ + git -C repo/sub \ + diff --no-index ../../non/git/a ../../non/git/b >actual && + head -n 1 <actual >actual.head && + test_cmp expect actual.head +' + +test_expect_success 'diff --no-index from repo subdir respects config (implicit)' ' + echo "diff --git ../../non/git/a ../../non/git/b" >expect && + test_config -C repo diff.noprefix true && + test_expect_code 1 \ + git -C repo/sub \ + diff ../../non/git/a ../../non/git/b >actual && + head -n 1 <actual >actual.head && + test_cmp expect actual.head +' + test_done diff --git a/t/t4054-diff-bogus-tree.sh b/t/t4054-diff-bogus-tree.sh index 1d6efab3c5..18f42c5fff 100755 --- a/t/t4054-diff-bogus-tree.sh +++ b/t/t4054-diff-bogus-tree.sh @@ -3,8 +3,6 @@ test_description='test diff with a bogus tree containing the null sha1' . ./test-lib.sh -empty_tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904 - test_expect_success 'create bogus tree' ' bogus_tree=$( printf "100644 fooQQQQQQQQQQQQQQQQQQQQQ" | @@ -22,13 +20,13 @@ test_expect_success 'create tree with matching file' ' test_expect_success 'raw diff shows null sha1 (addition)' ' echo ":000000 100644 $_z40 $_z40 A foo" >expect && - git diff-tree $empty_tree $bogus_tree >actual && + git diff-tree $EMPTY_TREE $bogus_tree >actual && test_cmp expect actual ' test_expect_success 'raw diff shows null sha1 (removal)' ' echo ":100644 000000 $_z40 $_z40 D foo" >expect && - git diff-tree $bogus_tree $empty_tree >actual && + git diff-tree $bogus_tree $EMPTY_TREE >actual && test_cmp expect actual ' @@ -57,11 +55,11 @@ test_expect_success 'raw diff shows null sha1 (index)' ' ' test_expect_success 'patch fails due to bogus sha1 (addition)' ' - test_must_fail git diff-tree -p $empty_tree $bogus_tree + test_must_fail git diff-tree -p $EMPTY_TREE $bogus_tree ' test_expect_success 'patch fails due to bogus sha1 (removal)' ' - test_must_fail git diff-tree -p $bogus_tree $empty_tree + test_must_fail git diff-tree -p $bogus_tree $EMPTY_TREE ' test_expect_success 'patch fails due to bogus sha1 (modification)' ' diff --git a/t/t4059-diff-submodule-not-initialized.sh b/t/t4059-diff-submodule-not-initialized.sh new file mode 100755 index 0000000000..cd70fd5192 --- /dev/null +++ b/t/t4059-diff-submodule-not-initialized.sh @@ -0,0 +1,127 @@ +#!/bin/sh +# +# Copyright (c) 2016 Jacob Keller, based on t4041 by Jens Lehmann +# + +test_description='Test for submodule diff on non-checked out submodule + +This test tries to verify that add_submodule_odb works when the submodule was +initialized previously but the checkout has since been removed. +' + +. ./test-lib.sh + +# Tested non-UTF-8 encoding +test_encoding="ISO8859-1" + +# String "added" in German (translated with Google Translate), encoded in UTF-8, +# used in sample commit log messages in add_file() function below. +added=$(printf "hinzugef\303\274gt") + +add_file () { + ( + cd "$1" && + shift && + for name + do + echo "$name" >"$name" && + git add "$name" && + test_tick && + # "git commit -m" would break MinGW, as Windows refuse to pass + # $test_encoding encoded parameter to git. + echo "Add $name ($added $name)" | iconv -f utf-8 -t $test_encoding | + git -c "i18n.commitEncoding=$test_encoding" commit -F - + done >/dev/null && + git rev-parse --short --verify HEAD + ) +} + +commit_file () { + test_tick && + git commit "$@" -m "Commit $*" >/dev/null +} + +test_expect_success 'setup - submodules' ' + test_create_repo sm2 && + add_file . foo && + add_file sm2 foo1 foo2 && + smhead1=$(git -C sm2 rev-parse --short --verify HEAD) +' + +test_expect_success 'setup - git submodule add' ' + git submodule add ./sm2 sm1 && + commit_file sm1 .gitmodules && + git diff-tree -p --no-commit-id --submodule=log HEAD -- sm1 >actual && + cat >expected <<-EOF && + Submodule sm1 0000000...$smhead1 (new submodule) + EOF + test_cmp expected actual +' + +test_expect_success 'submodule directory removed' ' + rm -rf sm1 && + git diff-tree -p --no-commit-id --submodule=log HEAD -- sm1 >actual && + cat >expected <<-EOF && + Submodule sm1 0000000...$smhead1 (new submodule) + EOF + test_cmp expected actual +' + +test_expect_success 'setup - submodule multiple commits' ' + git submodule update --checkout sm1 && + smhead2=$(add_file sm1 foo3 foo4) && + commit_file sm1 && + git diff-tree -p --no-commit-id --submodule=log HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 $smhead1..$smhead2: + > Add foo4 ($added foo4) + > Add foo3 ($added foo3) + EOF + test_cmp expected actual +' + +test_expect_success 'submodule removed multiple commits' ' + rm -rf sm1 && + git diff-tree -p --no-commit-id --submodule=log HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 $smhead1..$smhead2: + > Add foo4 ($added foo4) + > Add foo3 ($added foo3) + EOF + test_cmp expected actual +' + +test_expect_success 'submodule not initialized in new clone' ' + git clone . sm3 && + git -C sm3 diff-tree -p --no-commit-id --submodule=log HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 $smhead1...$smhead2 (not initialized) + EOF + test_cmp expected actual +' + +test_expect_success 'setup submodule moved' ' + git submodule update --checkout sm1 && + git mv sm1 sm4 && + commit_file sm4 && + git diff-tree -p --no-commit-id --submodule=log HEAD >actual && + cat >expected <<-EOF && + Submodule sm4 0000000...$smhead2 (new submodule) + EOF + test_cmp expected actual +' + +test_expect_success 'submodule moved then removed' ' + smhead3=$(add_file sm4 foo6 foo7) && + commit_file sm4 && + rm -rf sm4 && + git diff-tree -p --no-commit-id --submodule=log HEAD >actual && + cat >expected <<-EOF && + Submodule sm4 $smhead2..$smhead3: + > Add foo7 ($added foo7) + > Add foo6 ($added foo6) + EOF + test_cmp expected actual +' + +test_done diff --git a/t/t4060-diff-submodule-option-diff-format.sh b/t/t4060-diff-submodule-option-diff-format.sh new file mode 100755 index 0000000000..7e23b55ea4 --- /dev/null +++ b/t/t4060-diff-submodule-option-diff-format.sh @@ -0,0 +1,749 @@ +#!/bin/sh +# +# Copyright (c) 2009 Jens Lehmann, based on t7401 by Ping Yin +# Copyright (c) 2011 Alexey Shumkin (+ non-UTF-8 commit encoding tests) +# Copyright (c) 2016 Jacob Keller (copy + convert to --submodule=diff) +# + +test_description='Support for diff format verbose submodule difference in git diff + +This test tries to verify the sanity of --submodule=diff option of git diff. +' + +. ./test-lib.sh + +# Tested non-UTF-8 encoding +test_encoding="ISO8859-1" + +# String "added" in German (translated with Google Translate), encoded in UTF-8, +# used in sample commit log messages in add_file() function below. +added=$(printf "hinzugef\303\274gt") + +add_file () { + ( + cd "$1" && + shift && + for name + do + echo "$name" >"$name" && + git add "$name" && + test_tick && + # "git commit -m" would break MinGW, as Windows refuse to pass + # $test_encoding encoded parameter to git. + echo "Add $name ($added $name)" | iconv -f utf-8 -t $test_encoding | + git -c "i18n.commitEncoding=$test_encoding" commit -F - + done >/dev/null && + git rev-parse --short --verify HEAD + ) +} + +commit_file () { + test_tick && + git commit "$@" -m "Commit $*" >/dev/null +} + +test_expect_success 'setup repository' ' + test_create_repo sm1 && + add_file . foo && + head1=$(add_file sm1 foo1 foo2) && + fullhead1=$(git -C sm1 rev-parse --verify HEAD) +' + +test_expect_success 'added submodule' ' + git add sm1 && + git diff-index -p --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 0000000...$head1 (new submodule) + diff --git a/sm1/foo1 b/sm1/foo1 + new file mode 100644 + index 0000000..1715acd + --- /dev/null + +++ b/sm1/foo1 + @@ -0,0 +1 @@ + +foo1 + diff --git a/sm1/foo2 b/sm1/foo2 + new file mode 100644 + index 0000000..54b060e + --- /dev/null + +++ b/sm1/foo2 + @@ -0,0 +1 @@ + +foo2 + EOF + test_cmp expected actual +' + +test_expect_success 'added submodule, set diff.submodule' ' + test_config diff.submodule log && + git add sm1 && + git diff-index -p --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 0000000...$head1 (new submodule) + diff --git a/sm1/foo1 b/sm1/foo1 + new file mode 100644 + index 0000000..1715acd + --- /dev/null + +++ b/sm1/foo1 + @@ -0,0 +1 @@ + +foo1 + diff --git a/sm1/foo2 b/sm1/foo2 + new file mode 100644 + index 0000000..54b060e + --- /dev/null + +++ b/sm1/foo2 + @@ -0,0 +1 @@ + +foo2 + EOF + test_cmp expected actual +' + +test_expect_success '--submodule=short overrides diff.submodule' ' + test_config diff.submodule log && + git add sm1 && + git diff --submodule=short --cached >actual && + cat >expected <<-EOF && + diff --git a/sm1 b/sm1 + new file mode 160000 + index 0000000..$head1 + --- /dev/null + +++ b/sm1 + @@ -0,0 +1 @@ + +Subproject commit $fullhead1 + EOF + test_cmp expected actual +' + +test_expect_success 'diff.submodule does not affect plumbing' ' + test_config diff.submodule log && + git diff-index -p HEAD >actual && + cat >expected <<-EOF && + diff --git a/sm1 b/sm1 + new file mode 160000 + index 0000000..$head1 + --- /dev/null + +++ b/sm1 + @@ -0,0 +1 @@ + +Subproject commit $fullhead1 + EOF + test_cmp expected actual +' + +commit_file sm1 && +head2=$(add_file sm1 foo3) + +test_expect_success 'modified submodule(forward)' ' + git diff-index -p --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 $head1..$head2: + diff --git a/sm1/foo3 b/sm1/foo3 + new file mode 100644 + index 0000000..c1ec6c6 + --- /dev/null + +++ b/sm1/foo3 + @@ -0,0 +1 @@ + +foo3 + EOF + test_cmp expected actual +' + +test_expect_success 'modified submodule(forward)' ' + git diff --submodule=diff >actual && + cat >expected <<-EOF && + Submodule sm1 $head1..$head2: + diff --git a/sm1/foo3 b/sm1/foo3 + new file mode 100644 + index 0000000..c1ec6c6 + --- /dev/null + +++ b/sm1/foo3 + @@ -0,0 +1 @@ + +foo3 + EOF + test_cmp expected actual +' + +test_expect_success 'modified submodule(forward) --submodule' ' + git diff --submodule >actual && + cat >expected <<-EOF && + Submodule sm1 $head1..$head2: + > Add foo3 ($added foo3) + EOF + test_cmp expected actual +' + +fullhead2=$(cd sm1; git rev-parse --verify HEAD) +test_expect_success 'modified submodule(forward) --submodule=short' ' + git diff --submodule=short >actual && + cat >expected <<-EOF && + diff --git a/sm1 b/sm1 + index $head1..$head2 160000 + --- a/sm1 + +++ b/sm1 + @@ -1 +1 @@ + -Subproject commit $fullhead1 + +Subproject commit $fullhead2 + EOF + test_cmp expected actual +' + +commit_file sm1 && +head3=$( + cd sm1 && + git reset --hard HEAD~2 >/dev/null && + git rev-parse --short --verify HEAD +) + +test_expect_success 'modified submodule(backward)' ' + git diff-index -p --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 $head2..$head3 (rewind): + diff --git a/sm1/foo2 b/sm1/foo2 + deleted file mode 100644 + index 54b060e..0000000 + --- a/sm1/foo2 + +++ /dev/null + @@ -1 +0,0 @@ + -foo2 + diff --git a/sm1/foo3 b/sm1/foo3 + deleted file mode 100644 + index c1ec6c6..0000000 + --- a/sm1/foo3 + +++ /dev/null + @@ -1 +0,0 @@ + -foo3 + EOF + test_cmp expected actual +' + +head4=$(add_file sm1 foo4 foo5) +test_expect_success 'modified submodule(backward and forward)' ' + git diff-index -p --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 $head2...$head4: + diff --git a/sm1/foo2 b/sm1/foo2 + deleted file mode 100644 + index 54b060e..0000000 + --- a/sm1/foo2 + +++ /dev/null + @@ -1 +0,0 @@ + -foo2 + diff --git a/sm1/foo3 b/sm1/foo3 + deleted file mode 100644 + index c1ec6c6..0000000 + --- a/sm1/foo3 + +++ /dev/null + @@ -1 +0,0 @@ + -foo3 + diff --git a/sm1/foo4 b/sm1/foo4 + new file mode 100644 + index 0000000..a0016db + --- /dev/null + +++ b/sm1/foo4 + @@ -0,0 +1 @@ + +foo4 + diff --git a/sm1/foo5 b/sm1/foo5 + new file mode 100644 + index 0000000..d6f2413 + --- /dev/null + +++ b/sm1/foo5 + @@ -0,0 +1 @@ + +foo5 + EOF + test_cmp expected actual +' + +commit_file sm1 && +mv sm1 sm1-bak && +echo sm1 >sm1 && +head5=$(git hash-object sm1 | cut -c1-7) && +git add sm1 && +rm -f sm1 && +mv sm1-bak sm1 + +test_expect_success 'typechanged submodule(submodule->blob), --cached' ' + git diff --submodule=diff --cached >actual && + cat >expected <<-EOF && + Submodule sm1 $head4...0000000 (submodule deleted) + diff --git a/sm1/foo1 b/sm1/foo1 + deleted file mode 100644 + index 1715acd..0000000 + --- a/sm1/foo1 + +++ /dev/null + @@ -1 +0,0 @@ + -foo1 + diff --git a/sm1/foo4 b/sm1/foo4 + deleted file mode 100644 + index a0016db..0000000 + --- a/sm1/foo4 + +++ /dev/null + @@ -1 +0,0 @@ + -foo4 + diff --git a/sm1/foo5 b/sm1/foo5 + deleted file mode 100644 + index d6f2413..0000000 + --- a/sm1/foo5 + +++ /dev/null + @@ -1 +0,0 @@ + -foo5 + diff --git a/sm1 b/sm1 + new file mode 100644 + index 0000000..9da5fb8 + --- /dev/null + +++ b/sm1 + @@ -0,0 +1 @@ + +sm1 + EOF + test_cmp expected actual +' + +test_expect_success 'typechanged submodule(submodule->blob)' ' + git diff --submodule=diff >actual && + cat >expected <<-EOF && + diff --git a/sm1 b/sm1 + deleted file mode 100644 + index 9da5fb8..0000000 + --- a/sm1 + +++ /dev/null + @@ -1 +0,0 @@ + -sm1 + Submodule sm1 0000000...$head4 (new submodule) + diff --git a/sm1/foo1 b/sm1/foo1 + new file mode 100644 + index 0000000..1715acd + --- /dev/null + +++ b/sm1/foo1 + @@ -0,0 +1 @@ + +foo1 + diff --git a/sm1/foo4 b/sm1/foo4 + new file mode 100644 + index 0000000..a0016db + --- /dev/null + +++ b/sm1/foo4 + @@ -0,0 +1 @@ + +foo4 + diff --git a/sm1/foo5 b/sm1/foo5 + new file mode 100644 + index 0000000..d6f2413 + --- /dev/null + +++ b/sm1/foo5 + @@ -0,0 +1 @@ + +foo5 + EOF + test_cmp expected actual +' + +rm -rf sm1 && +git checkout-index sm1 +test_expect_success 'typechanged submodule(submodule->blob)' ' + git diff-index -p --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 $head4...0000000 (submodule deleted) + diff --git a/sm1 b/sm1 + new file mode 100644 + index 0000000..9da5fb8 + --- /dev/null + +++ b/sm1 + @@ -0,0 +1 @@ + +sm1 + EOF + test_cmp expected actual +' + +rm -f sm1 && +test_create_repo sm1 && +head6=$(add_file sm1 foo6 foo7) +fullhead6=$(cd sm1; git rev-parse --verify HEAD) +test_expect_success 'nonexistent commit' ' + git diff-index -p --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 $head4...$head6 (commits not present) + EOF + test_cmp expected actual +' + +commit_file +test_expect_success 'typechanged submodule(blob->submodule)' ' + git diff-index -p --submodule=diff HEAD >actual && + cat >expected <<-EOF && + diff --git a/sm1 b/sm1 + deleted file mode 100644 + index 9da5fb8..0000000 + --- a/sm1 + +++ /dev/null + @@ -1 +0,0 @@ + -sm1 + Submodule sm1 0000000...$head6 (new submodule) + diff --git a/sm1/foo6 b/sm1/foo6 + new file mode 100644 + index 0000000..462398b + --- /dev/null + +++ b/sm1/foo6 + @@ -0,0 +1 @@ + +foo6 + diff --git a/sm1/foo7 b/sm1/foo7 + new file mode 100644 + index 0000000..6e9262c + --- /dev/null + +++ b/sm1/foo7 + @@ -0,0 +1 @@ + +foo7 + EOF + test_cmp expected actual +' + +commit_file sm1 && +test_expect_success 'submodule is up to date' ' + git diff-index -p --submodule=diff HEAD >actual && + cat >expected <<-EOF && + EOF + test_cmp expected actual +' + +test_expect_success 'submodule contains untracked content' ' + echo new > sm1/new-file && + git diff-index -p --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 contains untracked content + EOF + test_cmp expected actual +' + +test_expect_success 'submodule contains untracked content (untracked ignored)' ' + git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual && + ! test -s actual +' + +test_expect_success 'submodule contains untracked content (dirty ignored)' ' + git diff-index -p --ignore-submodules=dirty --submodule=diff HEAD >actual && + ! test -s actual +' + +test_expect_success 'submodule contains untracked content (all ignored)' ' + git diff-index -p --ignore-submodules=all --submodule=diff HEAD >actual && + ! test -s actual +' + +test_expect_success 'submodule contains untracked and modified content' ' + echo new > sm1/foo6 && + git diff-index -p --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 contains untracked content + Submodule sm1 contains modified content + diff --git a/sm1/foo6 b/sm1/foo6 + index 462398b..3e75765 100644 + --- a/sm1/foo6 + +++ b/sm1/foo6 + @@ -1 +1 @@ + -foo6 + +new + EOF + test_cmp expected actual +' + +# NOT OK +test_expect_success 'submodule contains untracked and modified content (untracked ignored)' ' + echo new > sm1/foo6 && + git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 contains modified content + diff --git a/sm1/foo6 b/sm1/foo6 + index 462398b..3e75765 100644 + --- a/sm1/foo6 + +++ b/sm1/foo6 + @@ -1 +1 @@ + -foo6 + +new + EOF + test_cmp expected actual +' + +test_expect_success 'submodule contains untracked and modified content (dirty ignored)' ' + echo new > sm1/foo6 && + git diff-index -p --ignore-submodules=dirty --submodule=diff HEAD >actual && + ! test -s actual +' + +test_expect_success 'submodule contains untracked and modified content (all ignored)' ' + echo new > sm1/foo6 && + git diff-index -p --ignore-submodules --submodule=diff HEAD >actual && + ! test -s actual +' + +test_expect_success 'submodule contains modified content' ' + rm -f sm1/new-file && + git diff-index -p --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 contains modified content + diff --git a/sm1/foo6 b/sm1/foo6 + index 462398b..3e75765 100644 + --- a/sm1/foo6 + +++ b/sm1/foo6 + @@ -1 +1 @@ + -foo6 + +new + EOF + test_cmp expected actual +' + +(cd sm1; git commit -mchange foo6 >/dev/null) && +head8=$(cd sm1; git rev-parse --short --verify HEAD) && +test_expect_success 'submodule is modified' ' + git diff-index -p --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 17243c9..$head8: + diff --git a/sm1/foo6 b/sm1/foo6 + index 462398b..3e75765 100644 + --- a/sm1/foo6 + +++ b/sm1/foo6 + @@ -1 +1 @@ + -foo6 + +new + EOF + test_cmp expected actual +' + +test_expect_success 'modified submodule contains untracked content' ' + echo new > sm1/new-file && + git diff-index -p --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 contains untracked content + Submodule sm1 17243c9..$head8: + diff --git a/sm1/foo6 b/sm1/foo6 + index 462398b..3e75765 100644 + --- a/sm1/foo6 + +++ b/sm1/foo6 + @@ -1 +1 @@ + -foo6 + +new + EOF + test_cmp expected actual +' + +test_expect_success 'modified submodule contains untracked content (untracked ignored)' ' + git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 17243c9..$head8: + diff --git a/sm1/foo6 b/sm1/foo6 + index 462398b..3e75765 100644 + --- a/sm1/foo6 + +++ b/sm1/foo6 + @@ -1 +1 @@ + -foo6 + +new + EOF + test_cmp expected actual +' + +test_expect_success 'modified submodule contains untracked content (dirty ignored)' ' + git diff-index -p --ignore-submodules=dirty --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 17243c9..cfce562: + diff --git a/sm1/foo6 b/sm1/foo6 + index 462398b..3e75765 100644 + --- a/sm1/foo6 + +++ b/sm1/foo6 + @@ -1 +1 @@ + -foo6 + +new + EOF + test_cmp expected actual +' + +test_expect_success 'modified submodule contains untracked content (all ignored)' ' + git diff-index -p --ignore-submodules=all --submodule=diff HEAD >actual && + ! test -s actual +' + +test_expect_success 'modified submodule contains untracked and modified content' ' + echo modification >> sm1/foo6 && + git diff-index -p --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 contains untracked content + Submodule sm1 contains modified content + Submodule sm1 17243c9..cfce562: + diff --git a/sm1/foo6 b/sm1/foo6 + index 462398b..dfda541 100644 + --- a/sm1/foo6 + +++ b/sm1/foo6 + @@ -1 +1,2 @@ + -foo6 + +new + +modification + EOF + test_cmp expected actual +' + +test_expect_success 'modified submodule contains untracked and modified content (untracked ignored)' ' + echo modification >> sm1/foo6 && + git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 contains modified content + Submodule sm1 17243c9..cfce562: + diff --git a/sm1/foo6 b/sm1/foo6 + index 462398b..e20e2d9 100644 + --- a/sm1/foo6 + +++ b/sm1/foo6 + @@ -1 +1,3 @@ + -foo6 + +new + +modification + +modification + EOF + test_cmp expected actual +' + +test_expect_success 'modified submodule contains untracked and modified content (dirty ignored)' ' + echo modification >> sm1/foo6 && + git diff-index -p --ignore-submodules=dirty --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 17243c9..cfce562: + diff --git a/sm1/foo6 b/sm1/foo6 + index 462398b..3e75765 100644 + --- a/sm1/foo6 + +++ b/sm1/foo6 + @@ -1 +1 @@ + -foo6 + +new + EOF + test_cmp expected actual +' + +test_expect_success 'modified submodule contains untracked and modified content (all ignored)' ' + echo modification >> sm1/foo6 && + git diff-index -p --ignore-submodules --submodule=diff HEAD >actual && + ! test -s actual +' + +# NOT OK +test_expect_success 'modified submodule contains modified content' ' + rm -f sm1/new-file && + git diff-index -p --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 contains modified content + Submodule sm1 17243c9..cfce562: + diff --git a/sm1/foo6 b/sm1/foo6 + index 462398b..ac466ca 100644 + --- a/sm1/foo6 + +++ b/sm1/foo6 + @@ -1 +1,5 @@ + -foo6 + +new + +modification + +modification + +modification + +modification + EOF + test_cmp expected actual +' + +rm -rf sm1 +test_expect_success 'deleted submodule' ' + git diff-index -p --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 17243c9...0000000 (submodule deleted) + EOF + test_cmp expected actual +' + +test_create_repo sm2 && +head7=$(add_file sm2 foo8 foo9) && +git add sm2 + +test_expect_success 'multiple submodules' ' + git diff-index -p --submodule=diff HEAD >actual && + cat >expected <<-EOF && + Submodule sm1 17243c9...0000000 (submodule deleted) + Submodule sm2 0000000...a5a65c9 (new submodule) + diff --git a/sm2/foo8 b/sm2/foo8 + new file mode 100644 + index 0000000..db9916b + --- /dev/null + +++ b/sm2/foo8 + @@ -0,0 +1 @@ + +foo8 + diff --git a/sm2/foo9 b/sm2/foo9 + new file mode 100644 + index 0000000..9c3b4f6 + --- /dev/null + +++ b/sm2/foo9 + @@ -0,0 +1 @@ + +foo9 + EOF + test_cmp expected actual +' + +test_expect_success 'path filter' ' + git diff-index -p --submodule=diff HEAD sm2 >actual && + cat >expected <<-EOF && + Submodule sm2 0000000...a5a65c9 (new submodule) + diff --git a/sm2/foo8 b/sm2/foo8 + new file mode 100644 + index 0000000..db9916b + --- /dev/null + +++ b/sm2/foo8 + @@ -0,0 +1 @@ + +foo8 + diff --git a/sm2/foo9 b/sm2/foo9 + new file mode 100644 + index 0000000..9c3b4f6 + --- /dev/null + +++ b/sm2/foo9 + @@ -0,0 +1 @@ + +foo9 + EOF + test_cmp expected actual +' + +commit_file sm2 +test_expect_success 'given commit' ' + git diff-index -p --submodule=diff HEAD^ >actual && + cat >expected <<-EOF && + Submodule sm1 17243c9...0000000 (submodule deleted) + Submodule sm2 0000000...a5a65c9 (new submodule) + diff --git a/sm2/foo8 b/sm2/foo8 + new file mode 100644 + index 0000000..db9916b + --- /dev/null + +++ b/sm2/foo8 + @@ -0,0 +1 @@ + +foo8 + diff --git a/sm2/foo9 b/sm2/foo9 + new file mode 100644 + index 0000000..9c3b4f6 + --- /dev/null + +++ b/sm2/foo9 + @@ -0,0 +1 @@ + +foo9 + EOF + test_cmp expected actual +' + +test_expect_success 'setup .git file for sm2' ' + (cd sm2 && + REAL="$(pwd)/../.real" && + mv .git "$REAL" + echo "gitdir: $REAL" >.git) +' + +test_expect_success 'diff --submodule=diff with .git file' ' + git diff --submodule=diff HEAD^ >actual && + cat >expected <<-EOF && + Submodule sm1 17243c9...0000000 (submodule deleted) + Submodule sm2 0000000...a5a65c9 (new submodule) + diff --git a/sm2/foo8 b/sm2/foo8 + new file mode 100644 + index 0000000..db9916b + --- /dev/null + +++ b/sm2/foo8 + @@ -0,0 +1 @@ + +foo8 + diff --git a/sm2/foo9 b/sm2/foo9 + new file mode 100644 + index 0000000..9c3b4f6 + --- /dev/null + +++ b/sm2/foo9 + @@ -0,0 +1 @@ + +foo9 + EOF + test_cmp expected actual +' + +test_done diff --git a/t/t4130-apply-criss-cross-rename.sh b/t/t4130-apply-criss-cross-rename.sh index d173acde0f..f8a313bcb9 100755 --- a/t/t4130-apply-criss-cross-rename.sh +++ b/t/t4130-apply-criss-cross-rename.sh @@ -13,9 +13,13 @@ create_file() { } test_expect_success 'setup' ' - create_file file1 "File1 contents" && - create_file file2 "File2 contents" && - create_file file3 "File3 contents" && + # Ensure that file sizes are different, because on Windows + # lstat() does not discover inode numbers, and we need + # other properties to discover swapped files + # (mtime is not always different, either). + create_file file1 "some content" && + create_file file2 "some other content" && + create_file file3 "again something else" && git add file1 file2 file3 && git commit -m 1 ' diff --git a/t/t4150-am.sh b/t/t4150-am.sh index b41bd17264..9ce9424d15 100755 --- a/t/t4150-am.sh +++ b/t/t4150-am.sh @@ -957,4 +957,24 @@ test_expect_success 'am -s unexpected trailer block' ' test_cmp expect actual ' +test_expect_success 'am --patch-format=mboxrd handles mboxrd' ' + rm -fr .git/rebase-apply && + git checkout -f first && + echo mboxrd >>file && + git add file && + cat >msg <<-\INPUT_END && + mboxrd should escape the body + + From could trip up a loose mbox parser + >From extra escape for reversibility + INPUT_END + git commit -F msg && + git format-patch --pretty=mboxrd --stdout -1 >mboxrd1 && + grep "^>From could trip up a loose mbox parser" mboxrd1 && + git checkout -f first && + git am --patch-format=mboxrd mboxrd1 && + git cat-file commit HEAD | tail -n4 >out && + test_cmp msg out +' + test_done diff --git a/t/t4153-am-resume-override-opts.sh b/t/t4153-am-resume-override-opts.sh index 7c013d84d5..8ea22d1bcb 100755 --- a/t/t4153-am-resume-override-opts.sh +++ b/t/t4153-am-resume-override-opts.sh @@ -53,7 +53,7 @@ test_expect_success '--no-quiet overrides --quiet' ' # Applying side1 will be quiet. test_must_fail git am --quiet side[123].eml >out && test_path_is_dir .git/rebase-apply && - ! test_i18ngrep "^Applying: " out && + test_i18ngrep ! "^Applying: " out && echo side1 >file && git add file && diff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh index a9773658f0..ae08b57712 100755 --- a/t/t4201-shortlog.sh +++ b/t/t4201-shortlog.sh @@ -184,4 +184,10 @@ test_expect_success 'shortlog with revision pseudo options' ' git shortlog --exclude=refs/heads/m* --all ' +test_expect_success 'shortlog with --output=<file>' ' + git shortlog --output=shortlog -1 master >output && + test ! -s output && + test_line_count = 3 shortlog +' + test_done diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 128ba93537..1ccbd5948a 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -188,6 +188,16 @@ test_expect_success 'git log --no-walk=sorted <commits> sorts by commit time' ' ' cat > expect << EOF +=== 804a787 sixth +=== 394ef78 fifth +=== 5d31159 fourth +EOF +test_expect_success 'git log --line-prefix="=== " --no-walk <commits> sorts by commit time' ' + git log --line-prefix="=== " --no-walk --oneline 5d31159 804a787 394ef78 > actual && + test_cmp expect actual +' + +cat > expect << EOF 5d31159 fourth 804a787 sixth 394ef78 fifth @@ -255,6 +265,20 @@ test_expect_success 'log -F -E --grep=<ere> uses ere' ' test_cmp expect actual ' +test_expect_success 'log with grep.patternType configuration' ' + >expect && + git -c grep.patterntype=fixed \ + log -1 --pretty=tformat:%s --grep=s.c.nd >actual && + test_cmp expect actual +' + +test_expect_success 'log with grep.patternType configuration and command line' ' + echo second >expect && + git -c grep.patterntype=fixed \ + log -1 --pretty=tformat:%s --basic-regexp --grep=s.c.nd >actual && + test_cmp expect actual +' + cat > expect <<EOF * Second * sixth @@ -270,6 +294,21 @@ test_expect_success 'simple log --graph' ' test_cmp expect actual ' +cat > expect <<EOF +123 * Second +123 * sixth +123 * fifth +123 * fourth +123 * third +123 * second +123 * initial +EOF + +test_expect_success 'simple log --graph --line-prefix="123 "' ' + git log --graph --line-prefix="123 " --pretty=tformat:%s >actual && + test_cmp expect actual +' + test_expect_success 'set up merge history' ' git checkout -b side HEAD~4 && test_commit side-1 1 1 && @@ -299,6 +338,27 @@ test_expect_success 'log --graph with merge' ' test_cmp expect actual ' +cat > expect <<\EOF +| | | * Merge branch 'side' +| | | |\ +| | | | * side-2 +| | | | * side-1 +| | | * | Second +| | | * | sixth +| | | * | fifth +| | | * | fourth +| | | |/ +| | | * third +| | | * second +| | | * initial +EOF + +test_expect_success 'log --graph --line-prefix="| | | " with merge' ' + git log --line-prefix="| | | " --graph --date-order --pretty=tformat:%s | + sed "s/ *\$//" >actual && + test_cmp expect actual +' + test_expect_success 'log --raw --graph -m with merge' ' git log --raw --graph --oneline -m master | head -n 500 >actual && grep "initial" actual @@ -853,6 +913,283 @@ test_expect_success 'log --graph with diff and stats' ' test_i18ncmp expect actual.sanitized ' +cat >expect <<\EOF +*** * commit COMMIT_OBJECT_NAME +*** |\ Merge: MERGE_PARENTS +*** | | Author: A U Thor <author@example.com> +*** | | +*** | | Merge HEADS DESCRIPTION +*** | | +*** | * commit COMMIT_OBJECT_NAME +*** | | Author: A U Thor <author@example.com> +*** | | +*** | | reach +*** | | --- +*** | | reach.t | 1 + +*** | | 1 file changed, 1 insertion(+) +*** | | +*** | | diff --git a/reach.t b/reach.t +*** | | new file mode 100644 +*** | | index 0000000..10c9591 +*** | | --- /dev/null +*** | | +++ b/reach.t +*** | | @@ -0,0 +1 @@ +*** | | +reach +*** | | +*** | \ +*** *-. \ commit COMMIT_OBJECT_NAME +*** |\ \ \ Merge: MERGE_PARENTS +*** | | | | Author: A U Thor <author@example.com> +*** | | | | +*** | | | | Merge HEADS DESCRIPTION +*** | | | | +*** | | * | commit COMMIT_OBJECT_NAME +*** | | |/ Author: A U Thor <author@example.com> +*** | | | +*** | | | octopus-b +*** | | | --- +*** | | | octopus-b.t | 1 + +*** | | | 1 file changed, 1 insertion(+) +*** | | | +*** | | | diff --git a/octopus-b.t b/octopus-b.t +*** | | | new file mode 100644 +*** | | | index 0000000..d5fcad0 +*** | | | --- /dev/null +*** | | | +++ b/octopus-b.t +*** | | | @@ -0,0 +1 @@ +*** | | | +octopus-b +*** | | | +*** | * | commit COMMIT_OBJECT_NAME +*** | |/ Author: A U Thor <author@example.com> +*** | | +*** | | octopus-a +*** | | --- +*** | | octopus-a.t | 1 + +*** | | 1 file changed, 1 insertion(+) +*** | | +*** | | diff --git a/octopus-a.t b/octopus-a.t +*** | | new file mode 100644 +*** | | index 0000000..11ee015 +*** | | --- /dev/null +*** | | +++ b/octopus-a.t +*** | | @@ -0,0 +1 @@ +*** | | +octopus-a +*** | | +*** * | commit COMMIT_OBJECT_NAME +*** |/ Author: A U Thor <author@example.com> +*** | +*** | seventh +*** | --- +*** | seventh.t | 1 + +*** | 1 file changed, 1 insertion(+) +*** | +*** | diff --git a/seventh.t b/seventh.t +*** | new file mode 100644 +*** | index 0000000..9744ffc +*** | --- /dev/null +*** | +++ b/seventh.t +*** | @@ -0,0 +1 @@ +*** | +seventh +*** | +*** * commit COMMIT_OBJECT_NAME +*** |\ Merge: MERGE_PARENTS +*** | | Author: A U Thor <author@example.com> +*** | | +*** | | Merge branch 'tangle' +*** | | +*** | * commit COMMIT_OBJECT_NAME +*** | |\ Merge: MERGE_PARENTS +*** | | | Author: A U Thor <author@example.com> +*** | | | +*** | | | Merge branch 'side' (early part) into tangle +*** | | | +*** | * | commit COMMIT_OBJECT_NAME +*** | |\ \ Merge: MERGE_PARENTS +*** | | | | Author: A U Thor <author@example.com> +*** | | | | +*** | | | | Merge branch 'master' (early part) into tangle +*** | | | | +*** | * | | commit COMMIT_OBJECT_NAME +*** | | | | Author: A U Thor <author@example.com> +*** | | | | +*** | | | | tangle-a +*** | | | | --- +*** | | | | tangle-a | 1 + +*** | | | | 1 file changed, 1 insertion(+) +*** | | | | +*** | | | | diff --git a/tangle-a b/tangle-a +*** | | | | new file mode 100644 +*** | | | | index 0000000..7898192 +*** | | | | --- /dev/null +*** | | | | +++ b/tangle-a +*** | | | | @@ -0,0 +1 @@ +*** | | | | +a +*** | | | | +*** * | | | commit COMMIT_OBJECT_NAME +*** |\ \ \ \ Merge: MERGE_PARENTS +*** | | | | | Author: A U Thor <author@example.com> +*** | | | | | +*** | | | | | Merge branch 'side' +*** | | | | | +*** | * | | | commit COMMIT_OBJECT_NAME +*** | | |_|/ Author: A U Thor <author@example.com> +*** | |/| | +*** | | | | side-2 +*** | | | | --- +*** | | | | 2 | 1 + +*** | | | | 1 file changed, 1 insertion(+) +*** | | | | +*** | | | | diff --git a/2 b/2 +*** | | | | new file mode 100644 +*** | | | | index 0000000..0cfbf08 +*** | | | | --- /dev/null +*** | | | | +++ b/2 +*** | | | | @@ -0,0 +1 @@ +*** | | | | +2 +*** | | | | +*** | * | | commit COMMIT_OBJECT_NAME +*** | | | | Author: A U Thor <author@example.com> +*** | | | | +*** | | | | side-1 +*** | | | | --- +*** | | | | 1 | 1 + +*** | | | | 1 file changed, 1 insertion(+) +*** | | | | +*** | | | | diff --git a/1 b/1 +*** | | | | new file mode 100644 +*** | | | | index 0000000..d00491f +*** | | | | --- /dev/null +*** | | | | +++ b/1 +*** | | | | @@ -0,0 +1 @@ +*** | | | | +1 +*** | | | | +*** * | | | commit COMMIT_OBJECT_NAME +*** | | | | Author: A U Thor <author@example.com> +*** | | | | +*** | | | | Second +*** | | | | --- +*** | | | | one | 1 + +*** | | | | 1 file changed, 1 insertion(+) +*** | | | | +*** | | | | diff --git a/one b/one +*** | | | | new file mode 100644 +*** | | | | index 0000000..9a33383 +*** | | | | --- /dev/null +*** | | | | +++ b/one +*** | | | | @@ -0,0 +1 @@ +*** | | | | +case +*** | | | | +*** * | | | commit COMMIT_OBJECT_NAME +*** | |_|/ Author: A U Thor <author@example.com> +*** |/| | +*** | | | sixth +*** | | | --- +*** | | | a/two | 1 - +*** | | | 1 file changed, 1 deletion(-) +*** | | | +*** | | | diff --git a/a/two b/a/two +*** | | | deleted file mode 100644 +*** | | | index 9245af5..0000000 +*** | | | --- a/a/two +*** | | | +++ /dev/null +*** | | | @@ -1 +0,0 @@ +*** | | | -ni +*** | | | +*** * | | commit COMMIT_OBJECT_NAME +*** | | | Author: A U Thor <author@example.com> +*** | | | +*** | | | fifth +*** | | | --- +*** | | | a/two | 1 + +*** | | | 1 file changed, 1 insertion(+) +*** | | | +*** | | | diff --git a/a/two b/a/two +*** | | | new file mode 100644 +*** | | | index 0000000..9245af5 +*** | | | --- /dev/null +*** | | | +++ b/a/two +*** | | | @@ -0,0 +1 @@ +*** | | | +ni +*** | | | +*** * | | commit COMMIT_OBJECT_NAME +*** |/ / Author: A U Thor <author@example.com> +*** | | +*** | | fourth +*** | | --- +*** | | ein | 1 + +*** | | 1 file changed, 1 insertion(+) +*** | | +*** | | diff --git a/ein b/ein +*** | | new file mode 100644 +*** | | index 0000000..9d7e69f +*** | | --- /dev/null +*** | | +++ b/ein +*** | | @@ -0,0 +1 @@ +*** | | +ichi +*** | | +*** * | commit COMMIT_OBJECT_NAME +*** |/ Author: A U Thor <author@example.com> +*** | +*** | third +*** | --- +*** | ichi | 1 + +*** | one | 1 - +*** | 2 files changed, 1 insertion(+), 1 deletion(-) +*** | +*** | diff --git a/ichi b/ichi +*** | new file mode 100644 +*** | index 0000000..9d7e69f +*** | --- /dev/null +*** | +++ b/ichi +*** | @@ -0,0 +1 @@ +*** | +ichi +*** | diff --git a/one b/one +*** | deleted file mode 100644 +*** | index 9d7e69f..0000000 +*** | --- a/one +*** | +++ /dev/null +*** | @@ -1 +0,0 @@ +*** | -ichi +*** | +*** * commit COMMIT_OBJECT_NAME +*** | Author: A U Thor <author@example.com> +*** | +*** | second +*** | --- +*** | one | 2 +- +*** | 1 file changed, 1 insertion(+), 1 deletion(-) +*** | +*** | diff --git a/one b/one +*** | index 5626abf..9d7e69f 100644 +*** | --- a/one +*** | +++ b/one +*** | @@ -1 +1 @@ +*** | -one +*** | +ichi +*** | +*** * commit COMMIT_OBJECT_NAME +*** Author: A U Thor <author@example.com> +*** +*** initial +*** --- +*** one | 1 + +*** 1 file changed, 1 insertion(+) +*** +*** diff --git a/one b/one +*** new file mode 100644 +*** index 0000000..5626abf +*** --- /dev/null +*** +++ b/one +*** @@ -0,0 +1 @@ +*** +one +EOF + +test_expect_success 'log --line-prefix="*** " --graph with diff and stats' ' + git log --line-prefix="*** " --no-renames --graph --pretty=short --stat -p >actual && + sanitize_output >actual.sanitized <actual && + test_i18ncmp expect actual.sanitized +' + test_expect_success 'dotdot is a parent directory' ' mkdir -p a/b && ( echo sixth && echo fifth ) >expect && @@ -860,12 +1197,15 @@ test_expect_success 'dotdot is a parent directory' ' test_cmp expect actual ' -test_expect_success GPG 'log --graph --show-signature' ' +test_expect_success GPG 'setup signed branch' ' test_when_finished "git reset --hard && git checkout master" && git checkout -b signed master && echo foo >foo && git add foo && - git commit -S -m signed_commit && + git commit -S -m signed_commit +' + +test_expect_success GPG 'log --graph --show-signature' ' git log --graph --show-signature -n1 signed >actual && grep "^| gpg: Signature made" actual && grep "^| gpg: Good signature" actual @@ -890,6 +1230,31 @@ test_expect_success GPG 'log --graph --show-signature for merged tag' ' grep "^| | gpg: Good signature" actual ' +test_expect_success GPG '--no-show-signature overrides --show-signature' ' + git log -1 --show-signature --no-show-signature signed >actual && + ! grep "^gpg:" actual +' + +test_expect_success GPG 'log.showsignature=true behaves like --show-signature' ' + test_config log.showsignature true && + git log -1 signed >actual && + grep "gpg: Signature made" actual && + grep "gpg: Good signature" actual +' + +test_expect_success GPG '--no-show-signature overrides log.showsignature=true' ' + test_config log.showsignature true && + git log -1 --no-show-signature signed >actual && + ! grep "^gpg:" actual +' + +test_expect_success GPG '--show-signature overrides log.showsignature=false' ' + test_config log.showsignature false && + git log -1 --show-signature signed >actual && + grep "gpg: Signature made" actual && + grep "gpg: Good signature" actual +' + test_expect_success 'log --graph --no-walk is forbidden' ' test_must_fail git log --graph --no-walk ' diff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh index 84a809690e..0288c17ec6 100755 --- a/t/t4204-patch-id.sh +++ b/t/t4204-patch-id.sh @@ -143,6 +143,20 @@ test_expect_success 'patch-id supports git-format-patch MIME output' ' test_cmp patch-id_master patch-id_same ' +test_expect_success 'patch-id respects config from subdir' ' + test_config patchid.stable true && + mkdir subdir && + + # copy these because test_patch_id() looks for them in + # the current directory + cp bar-then-foo foo-then-bar subdir && + + ( + cd subdir && + test_patch_id irrelevant patchid.stable=true + ) +' + cat >nonl <<\EOF diff --git i/a w/a index e69de29..2e65efe 100644 diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh index 7398605e7b..f5435fd250 100755 --- a/t/t4205-log-pretty-formats.sh +++ b/t/t4205-log-pretty-formats.sh @@ -145,253 +145,310 @@ test_expect_success 'setup more commits' ' test_expect_success 'left alignment formatting' ' git log --pretty="tformat:%<(40)%s" >actual && - qz_to_tab_space <<EOF >expected && -message two Z -message one Z -add bar Z -$(commit_msg) Z -EOF + qz_to_tab_space <<-EOF >expected && + message two Z + message one Z + add bar Z + $(commit_msg) Z + EOF test_cmp expected actual ' test_expect_success 'left alignment formatting. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%<(40)%s" >actual && - qz_to_tab_space <<EOF | iconv -f utf-8 -t $test_encoding >expected && -message two Z -message one Z -add bar Z -$(commit_msg) Z -EOF + qz_to_tab_space <<-EOF | iconv -f utf-8 -t $test_encoding >expected && + message two Z + message one Z + add bar Z + $(commit_msg) Z + EOF test_cmp expected actual ' test_expect_success 'left alignment formatting at the nth column' ' git log --pretty="tformat:%h %<|(40)%s" >actual && - qz_to_tab_space <<EOF >expected && -$head1 message two Z -$head2 message one Z -$head3 add bar Z -$head4 $(commit_msg) Z -EOF + qz_to_tab_space <<-EOF >expected && + $head1 message two Z + $head2 message one Z + $head3 add bar Z + $head4 $(commit_msg) Z + EOF + test_cmp expected actual +' + +test_expect_success 'left alignment formatting at the nth column' ' + COLUMNS=50 git log --pretty="tformat:%h %<|(-10)%s" >actual && + qz_to_tab_space <<-EOF >expected && + $head1 message two Z + $head2 message one Z + $head3 add bar Z + $head4 $(commit_msg) Z + EOF test_cmp expected actual ' test_expect_success 'left alignment formatting at the nth column. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%h %<|(40)%s" >actual && - qz_to_tab_space <<EOF | iconv -f utf-8 -t $test_encoding >expected && -$head1 message two Z -$head2 message one Z -$head3 add bar Z -$head4 $(commit_msg) Z -EOF + qz_to_tab_space <<-EOF | iconv -f utf-8 -t $test_encoding >expected && + $head1 message two Z + $head2 message one Z + $head3 add bar Z + $head4 $(commit_msg) Z + EOF test_cmp expected actual ' test_expect_success 'left alignment formatting with no padding' ' git log --pretty="tformat:%<(1)%s" >actual && - cat <<EOF >expected && -message two -message one -add bar -$(commit_msg) -EOF + cat <<-EOF >expected && + message two + message one + add bar + $(commit_msg) + EOF test_cmp expected actual ' test_expect_success 'left alignment formatting with no padding. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%<(1)%s" >actual && - cat <<EOF | iconv -f utf-8 -t $test_encoding >expected && -message two -message one -add bar -$(commit_msg) -EOF + cat <<-EOF | iconv -f utf-8 -t $test_encoding >expected && + message two + message one + add bar + $(commit_msg) + EOF test_cmp expected actual ' test_expect_success 'left alignment formatting with trunc' ' git log --pretty="tformat:%<(10,trunc)%s" >actual && - qz_to_tab_space <<EOF >expected && -message .. -message .. -add bar Z -initial... -EOF + qz_to_tab_space <<-\EOF >expected && + message .. + message .. + add bar Z + initial... + EOF test_cmp expected actual ' test_expect_success 'left alignment formatting with trunc. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%<(10,trunc)%s" >actual && - qz_to_tab_space <<EOF | iconv -f utf-8 -t $test_encoding >expected && -message .. -message .. -add bar Z -initial... -EOF + qz_to_tab_space <<-\EOF | iconv -f utf-8 -t $test_encoding >expected && + message .. + message .. + add bar Z + initial... + EOF test_cmp expected actual ' test_expect_success 'left alignment formatting with ltrunc' ' git log --pretty="tformat:%<(10,ltrunc)%s" >actual && - qz_to_tab_space <<EOF >expected && -..sage two -..sage one -add bar Z -..${sample_utf8_part}lich -EOF + qz_to_tab_space <<-EOF >expected && + ..sage two + ..sage one + add bar Z + ..${sample_utf8_part}lich + EOF test_cmp expected actual ' test_expect_success 'left alignment formatting with ltrunc. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%<(10,ltrunc)%s" >actual && - qz_to_tab_space <<EOF | iconv -f utf-8 -t $test_encoding >expected && -..sage two -..sage one -add bar Z -..${sample_utf8_part}lich -EOF + qz_to_tab_space <<-EOF | iconv -f utf-8 -t $test_encoding >expected && + ..sage two + ..sage one + add bar Z + ..${sample_utf8_part}lich + EOF test_cmp expected actual ' test_expect_success 'left alignment formatting with mtrunc' ' git log --pretty="tformat:%<(10,mtrunc)%s" >actual && - qz_to_tab_space <<EOF >expected && -mess.. two -mess.. one -add bar Z -init..lich -EOF + qz_to_tab_space <<-\EOF >expected && + mess.. two + mess.. one + add bar Z + init..lich + EOF test_cmp expected actual ' test_expect_success 'left alignment formatting with mtrunc. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%<(10,mtrunc)%s" >actual && - qz_to_tab_space <<EOF | iconv -f utf-8 -t $test_encoding >expected && -mess.. two -mess.. one -add bar Z -init..lich -EOF + qz_to_tab_space <<-\EOF | iconv -f utf-8 -t $test_encoding >expected && + mess.. two + mess.. one + add bar Z + init..lich + EOF test_cmp expected actual ' test_expect_success 'right alignment formatting' ' git log --pretty="tformat:%>(40)%s" >actual && - qz_to_tab_space <<EOF >expected && -Z message two -Z message one -Z add bar -Z $(commit_msg) -EOF + qz_to_tab_space <<-EOF >expected && + Z message two + Z message one + Z add bar + Z $(commit_msg) + EOF test_cmp expected actual ' test_expect_success 'right alignment formatting. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%>(40)%s" >actual && - qz_to_tab_space <<EOF | iconv -f utf-8 -t $test_encoding >expected && -Z message two -Z message one -Z add bar -Z $(commit_msg) -EOF + qz_to_tab_space <<-EOF | iconv -f utf-8 -t $test_encoding >expected && + Z message two + Z message one + Z add bar + Z $(commit_msg) + EOF test_cmp expected actual ' test_expect_success 'right alignment formatting at the nth column' ' git log --pretty="tformat:%h %>|(40)%s" >actual && - qz_to_tab_space <<EOF >expected && -$head1 message two -$head2 message one -$head3 add bar -$head4 $(commit_msg) -EOF + qz_to_tab_space <<-EOF >expected && + $head1 message two + $head2 message one + $head3 add bar + $head4 $(commit_msg) + EOF + test_cmp expected actual +' + +test_expect_success 'right alignment formatting at the nth column' ' + COLUMNS=50 git log --pretty="tformat:%h %>|(-10)%s" >actual && + qz_to_tab_space <<-EOF >expected && + $head1 message two + $head2 message one + $head3 add bar + $head4 $(commit_msg) + EOF test_cmp expected actual ' test_expect_success 'right alignment formatting at the nth column. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%h %>|(40)%s" >actual && - qz_to_tab_space <<EOF | iconv -f utf-8 -t $test_encoding >expected && -$head1 message two -$head2 message one -$head3 add bar -$head4 $(commit_msg) -EOF + qz_to_tab_space <<-EOF | iconv -f utf-8 -t $test_encoding >expected && + $head1 message two + $head2 message one + $head3 add bar + $head4 $(commit_msg) + EOF + test_cmp expected actual +' + +# Note: Space between 'message' and 'two' should be in the same column +# as in previous test. +test_expect_success 'right alignment formatting at the nth column with --graph. i18n.logOutputEncoding' ' + git -c i18n.logOutputEncoding=$test_encoding log --graph --pretty="tformat:%h %>|(40)%s" >actual && + iconv -f utf-8 -t $test_encoding >expected <<-EOF && + * $head1 message two + * $head2 message one + * $head3 add bar + * $head4 $(commit_msg) + EOF test_cmp expected actual ' test_expect_success 'right alignment formatting with no padding' ' git log --pretty="tformat:%>(1)%s" >actual && - cat <<EOF >expected && -message two -message one -add bar -$(commit_msg) -EOF + cat <<-EOF >expected && + message two + message one + add bar + $(commit_msg) + EOF + test_cmp expected actual +' + +test_expect_success 'right alignment formatting with no padding and with --graph' ' + git log --graph --pretty="tformat:%>(1)%s" >actual && + cat <<-EOF >expected && + * message two + * message one + * add bar + * $(commit_msg) + EOF test_cmp expected actual ' test_expect_success 'right alignment formatting with no padding. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%>(1)%s" >actual && - cat <<EOF | iconv -f utf-8 -t $test_encoding >expected && -message two -message one -add bar -$(commit_msg) -EOF + cat <<-EOF | iconv -f utf-8 -t $test_encoding >expected && + message two + message one + add bar + $(commit_msg) + EOF test_cmp expected actual ' test_expect_success 'center alignment formatting' ' git log --pretty="tformat:%><(40)%s" >actual && - qz_to_tab_space <<EOF >expected && -Z message two Z -Z message one Z -Z add bar Z -Z $(commit_msg) Z -EOF + qz_to_tab_space <<-EOF >expected && + Z message two Z + Z message one Z + Z add bar Z + Z $(commit_msg) Z + EOF test_cmp expected actual ' test_expect_success 'center alignment formatting. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%><(40)%s" >actual && - qz_to_tab_space <<EOF | iconv -f utf-8 -t $test_encoding >expected && -Z message two Z -Z message one Z -Z add bar Z -Z $(commit_msg) Z -EOF + qz_to_tab_space <<-EOF | iconv -f utf-8 -t $test_encoding >expected && + Z message two Z + Z message one Z + Z add bar Z + Z $(commit_msg) Z + EOF test_cmp expected actual ' test_expect_success 'center alignment formatting at the nth column' ' git log --pretty="tformat:%h %><|(40)%s" >actual && - qz_to_tab_space <<EOF >expected && -$head1 message two Z -$head2 message one Z -$head3 add bar Z -$head4 $(commit_msg) Z -EOF + qz_to_tab_space <<-EOF >expected && + $head1 message two Z + $head2 message one Z + $head3 add bar Z + $head4 $(commit_msg) Z + EOF + test_cmp expected actual +' + +test_expect_success 'center alignment formatting at the nth column' ' + COLUMNS=70 git log --pretty="tformat:%h %><|(-30)%s" >actual && + qz_to_tab_space <<-EOF >expected && + $head1 message two Z + $head2 message one Z + $head3 add bar Z + $head4 $(commit_msg) Z + EOF test_cmp expected actual ' test_expect_success 'center alignment formatting at the nth column. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%h %><|(40)%s" >actual && - qz_to_tab_space <<EOF | iconv -f utf-8 -t $test_encoding >expected && -$head1 message two Z -$head2 message one Z -$head3 add bar Z -$head4 $(commit_msg) Z -EOF + qz_to_tab_space <<-EOF | iconv -f utf-8 -t $test_encoding >expected && + $head1 message two Z + $head2 message one Z + $head3 add bar Z + $head4 $(commit_msg) Z + EOF test_cmp expected actual ' test_expect_success 'center alignment formatting with no padding' ' git log --pretty="tformat:%><(1)%s" >actual && - cat <<EOF >expected && -message two -message one -add bar -$(commit_msg) -EOF + cat <<-EOF >expected && + message two + message one + add bar + $(commit_msg) + EOF test_cmp expected actual ' @@ -400,34 +457,34 @@ EOF old_head1=$(git rev-parse --verify HEAD~0) test_expect_success 'center alignment formatting with no padding. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%><(1)%s" >actual && - cat <<EOF | iconv -f utf-8 -t $test_encoding >expected && -message two -message one -add bar -$(commit_msg) -EOF + cat <<-EOF | iconv -f utf-8 -t $test_encoding >expected && + message two + message one + add bar + $(commit_msg) + EOF test_cmp expected actual ' test_expect_success 'left/right alignment formatting with stealing' ' git commit --amend -m short --author "long long long <long@me.com>" && git log --pretty="tformat:%<(10,trunc)%s%>>(10,ltrunc)% an" >actual && - cat <<EOF >expected && -short long long long -message .. A U Thor -add bar A U Thor -initial... A U Thor -EOF + cat <<-\EOF >expected && + short long long long + message .. A U Thor + add bar A U Thor + initial... A U Thor + EOF test_cmp expected actual ' test_expect_success 'left/right alignment formatting with stealing. i18n.logOutputEncoding' ' git -c i18n.logOutputEncoding=$test_encoding log --pretty="tformat:%<(10,trunc)%s%>>(10,ltrunc)% an" >actual && - cat <<EOF | iconv -f utf-8 -t $test_encoding >expected && -short long long long -message .. A U Thor -add bar A U Thor -initial... A U Thor -EOF + cat <<-\EOF | iconv -f utf-8 -t $test_encoding >expected && + short long long long + message .. A U Thor + add bar A U Thor + initial... A U Thor + EOF test_cmp expected actual ' @@ -447,8 +504,10 @@ test_expect_success 'ISO and ISO-strict date formats display the same values' ' ' # get new digests (with no abbreviations) -head1=$(git rev-parse --verify HEAD~0) && -head2=$(git rev-parse --verify HEAD~1) && +test_expect_success 'set up log decoration tests' ' + head1=$(git rev-parse --verify HEAD~0) && + head2=$(git rev-parse --verify HEAD~1) +' test_expect_success 'log decoration properly follows tag chain' ' git tag -a tag1 -m tag1 && @@ -456,22 +515,22 @@ test_expect_success 'log decoration properly follows tag chain' ' git tag -d tag1 && git commit --amend -m shorter && git log --no-walk --tags --pretty="%H %d" --decorate=full >actual && - cat <<EOF >expected && -$head1 (tag: refs/tags/tag2) -$head2 (tag: refs/tags/message-one) -$old_head1 (tag: refs/tags/message-two) -EOF + cat <<-EOF >expected && + $head1 (tag: refs/tags/tag2) + $head2 (tag: refs/tags/message-one) + $old_head1 (tag: refs/tags/message-two) + EOF sort actual >actual1 && test_cmp expected actual1 ' test_expect_success 'clean log decoration' ' git log --no-walk --tags --pretty="%H %D" --decorate=full >actual && - cat >expected <<EOF && -$head1 tag: refs/tags/tag2 -$head2 tag: refs/tags/message-one -$old_head1 tag: refs/tags/message-two -EOF + cat >expected <<-EOF && + $head1 tag: refs/tags/tag2 + $head2 tag: refs/tags/message-one + $old_head1 tag: refs/tags/message-two + EOF sort actual >actual1 && test_cmp expected actual1 ' diff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh index f8008b6a3d..b972296f06 100755 --- a/t/t4207-log-decoration-colors.sh +++ b/t/t4207-log-decoration-colors.sh @@ -44,7 +44,7 @@ test_expect_success setup ' ' cat >expected <<EOF -${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD${c_reset}${c_commit} ->\ +${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD ->\ ${c_reset}${c_branch}master${c_reset}${c_commit},\ ${c_reset}${c_tag}tag: v1.0${c_reset}${c_commit},\ ${c_reset}${c_tag}tag: B${c_reset}${c_commit})${c_reset} B diff --git a/t/t4208-log-magic-pathspec.sh b/t/t4208-log-magic-pathspec.sh index d8f23f488e..001343e2fc 100755 --- a/t/t4208-log-magic-pathspec.sh +++ b/t/t4208-log-magic-pathspec.sh @@ -18,7 +18,7 @@ test_expect_success '"git log :/" should not be ambiguous' ' test_expect_success '"git log :/a" should be ambiguous (applied both rev and worktree)' ' : >a && test_must_fail git log :/a 2>error && - grep ambiguous error + test_i18ngrep ambiguous error ' test_expect_success '"git log :/a -- " should not be ambiguous' ' @@ -31,7 +31,7 @@ test_expect_success '"git log -- :/a" should not be ambiguous' ' test_expect_success '"git log :" should be ambiguous' ' test_must_fail git log : 2>error && - grep ambiguous error + test_i18ngrep ambiguous error ' test_expect_success 'git log -- :' ' diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh index 4451127eb2..9d87777b59 100755 --- a/t/t4211-line-log.sh +++ b/t/t4211-line-log.sh @@ -99,4 +99,11 @@ test_expect_success '-L with --first-parent and a merge' ' git log --first-parent -L 1,1:b.c ' +test_expect_success '-L with --output' ' + git checkout parallel-change && + git log --output=log -L :main:b.c >output && + test ! -s output && + test_line_count = 70 log +' + test_done diff --git a/t/t4254-am-corrupt.sh b/t/t4254-am-corrupt.sh index 85716dd6ec..9bd7dd2ba1 100755 --- a/t/t4254-am-corrupt.sh +++ b/t/t4254-am-corrupt.sh @@ -29,7 +29,7 @@ test_expect_success 'try to apply corrupted patch' ' ' test_expect_success 'compare diagnostic; ensure file is still here' ' - echo "fatal: git diff header lacks filename information (line 4)" >expected && + echo "error: git diff header lacks filename information (line 4)" >expected && test_path_is_file f && test_cmp expected actual ' diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh index 4b68bbafbe..80b2387341 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -319,4 +319,78 @@ test_expect_success 'catch non-matching pathspec' ' test_must_fail git archive -v HEAD -- "*.abc" >/dev/null ' +# Pull the size and date of each entry in a tarfile using the system tar. +# +# We'll pull out only the year from the date; that avoids any question of +# timezones impacting the result (as long as we keep our test times away from a +# year boundary; our reference times are all in August). +# +# The output of tar_info is expected to be "<size> <year>", both in decimal. It +# ignores the return value of tar. We have to do this, because some of our test +# input is only partial (the real data is 64GB in some cases). +tar_info () { + "$TAR" tvf "$1" | + awk '{ + split($4, date, "-") + print $3 " " date[1] + }' +} + +# See if our system tar can handle a tar file with huge sizes and dates far in +# the future, and that we can actually parse its output. +# +# The reference file was generated by GNU tar, and the magic time and size are +# both octal 01000000000001, which overflows normal ustar fields. +test_lazy_prereq TAR_HUGE ' + echo "68719476737 4147" >expect && + tar_info "$TEST_DIRECTORY"/t5000/huge-and-future.tar >actual && + test_cmp expect actual +' + +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 && + rm -f .git/index && + git update-index --add --cacheinfo 100644,$obj,huge && + git commit -m huge +' + +# We expect git to die with SIGPIPE here (otherwise we +# would generate the whole 64GB). +test_expect_success LONG_IS_64BIT 'generate tar with huge size' ' + { + git archive HEAD + echo $? >exit-code + } | test_copy_bytes 4096 >huge.tar && + echo 141 >expect && + test_cmp expect exit-code +' + +test_expect_success TAR_HUGE,LONG_IS_64BIT 'system tar can read our huge size' ' + echo 68719476737 >expect && + tar_info huge.tar | cut -d" " -f1 >actual && + test_cmp expect actual +' + +test_expect_success LONG_IS_64BIT 'set up repository with far-future commit' ' + rm -f .git/index && + echo content >file && + git add file && + GIT_COMMITTER_DATE="@68719476737 +0000" \ + git commit -m "tempori parendum" +' + +test_expect_success LONG_IS_64BIT 'generate tar with future mtime' ' + git archive HEAD >future.tar +' + +test_expect_success TAR_HUGE,LONG_IS_64BIT 'system tar can read our future mtime' ' + echo 4147 >expect && + tar_info future.tar | cut -d" " -f2 >actual && + test_cmp expect actual +' + test_done diff --git a/t/t5000/19f9c8273ec45a8938e6999cb59b3ff66739902a b/t/t5000/19f9c8273ec45a8938e6999cb59b3ff66739902a Binary files differnew file mode 100644 index 0000000000..5cbe9ec312 --- /dev/null +++ b/t/t5000/19f9c8273ec45a8938e6999cb59b3ff66739902a diff --git a/t/t5000/huge-and-future.tar b/t/t5000/huge-and-future.tar Binary files differnew file mode 100644 index 0000000000..63155e1855 --- /dev/null +++ b/t/t5000/huge-and-future.tar diff --git a/t/t5100-mailinfo.sh b/t/t5100-mailinfo.sh index 85b3df5e33..1a5a546230 100755 --- a/t/t5100-mailinfo.sh +++ b/t/t5100-mailinfo.sh @@ -111,4 +111,35 @@ test_expect_success 'mailinfo on message with quoted >From' ' test_cmp "$TEST_DIRECTORY"/t5100/quoted-from.expect quoted-from/msg ' +test_expect_success 'mailinfo unescapes with --mboxrd' ' + mkdir mboxrd && + git mailsplit -omboxrd --mboxrd \ + "$TEST_DIRECTORY"/t5100/sample.mboxrd >last && + test x"$(cat last)" = x2 && + for i in 0001 0002 + do + git mailinfo mboxrd/msg mboxrd/patch \ + <mboxrd/$i >mboxrd/out && + test_cmp "$TEST_DIRECTORY"/t5100/${i}mboxrd mboxrd/msg + done && + sp=" " && + echo "From " >expect && + echo "From " >>expect && + echo >> expect && + cat >sp <<-INPUT_END && + From mboxrd Mon Sep 17 00:00:00 2001 + From: trailing spacer <sp@example.com> + Subject: [PATCH] a commit with trailing space + + From$sp + >From$sp + + INPUT_END + + git mailsplit -f2 -omboxrd --mboxrd <sp >last && + test x"$(cat last)" = x1 && + git mailinfo mboxrd/msg mboxrd/patch <mboxrd/0003 && + test_cmp expect mboxrd/msg +' + test_done diff --git a/t/t5100/0001mboxrd b/t/t5100/0001mboxrd new file mode 100644 index 0000000000..494ec554b9 --- /dev/null +++ b/t/t5100/0001mboxrd @@ -0,0 +1,4 @@ +From the beginning, mbox should have been mboxrd +>From escaped +From not mangled but this line should have been escaped + diff --git a/t/t5100/0002mboxrd b/t/t5100/0002mboxrd new file mode 100644 index 0000000000..71343d41f2 --- /dev/null +++ b/t/t5100/0002mboxrd @@ -0,0 +1,5 @@ + >From unchanged + From also unchanged +no trailing space, no escaping necessary and '>' was intended: +>From + diff --git a/t/t5100/sample.mboxrd b/t/t5100/sample.mboxrd new file mode 100644 index 0000000000..79ad5ae0e7 --- /dev/null +++ b/t/t5100/sample.mboxrd @@ -0,0 +1,19 @@ +From mboxrd Mon Sep 17 00:00:00 2001 +From: mboxrd writer <mboxrd@example.com> +Date: Fri, 9 Jun 2006 00:44:16 -0700 +Subject: [PATCH] a commit with escaped From lines + +>From the beginning, mbox should have been mboxrd +>>From escaped +From not mangled but this line should have been escaped + +From mboxrd Mon Sep 17 00:00:00 2001 +From: mboxrd writer <mboxrd@example.com> +Date: Fri, 9 Jun 2006 00:44:16 -0700 +Subject: [PATCH 2/2] another with fake From lines + + >From unchanged + From also unchanged +no trailing space, no escaping necessary and '>' was intended: +>From + diff --git a/t/t5305-include-tag.sh b/t/t5305-include-tag.sh index f314ad5079..a5eca210b8 100755 --- a/t/t5305-include-tag.sh +++ b/t/t5305-include-tag.sh @@ -25,58 +25,94 @@ test_expect_success setup ' } >obj-list ' -rm -rf clone.git test_expect_success 'pack without --include-tag' ' - packname_1=$(git pack-objects \ + packname=$(git pack-objects \ --window=0 \ - test-1 <obj-list) + test-no-include <obj-list) ' test_expect_success 'unpack objects' ' - ( - GIT_DIR=clone.git && - export GIT_DIR && - git init && - git unpack-objects -n <test-1-${packname_1}.pack && - git unpack-objects <test-1-${packname_1}.pack - ) + rm -rf clone.git && + git init clone.git && + git -C clone.git unpack-objects <test-no-include-${packname}.pack ' test_expect_success 'check unpacked result (have commit, no tag)' ' git rev-list --objects $commit >list.expect && - ( - test_must_fail env GIT_DIR=clone.git git cat-file -e $tag && - git rev-list --objects $commit - ) >list.actual && + test_must_fail git -C clone.git cat-file -e $tag && + git -C clone.git rev-list --objects $commit >list.actual && test_cmp list.expect list.actual ' -rm -rf clone.git test_expect_success 'pack with --include-tag' ' - packname_1=$(git pack-objects \ + packname=$(git pack-objects \ --window=0 \ --include-tag \ - test-2 <obj-list) + test-include <obj-list) ' test_expect_success 'unpack objects' ' - ( - GIT_DIR=clone.git && - export GIT_DIR && - git init && - git unpack-objects -n <test-2-${packname_1}.pack && - git unpack-objects <test-2-${packname_1}.pack - ) + rm -rf clone.git && + git init clone.git && + git -C clone.git unpack-objects <test-include-${packname}.pack ' test_expect_success 'check unpacked result (have commit, have tag)' ' git rev-list --objects mytag >list.expect && - ( - GIT_DIR=clone.git && - export GIT_DIR && - git rev-list --objects $tag - ) >list.actual && + git -C clone.git rev-list --objects $tag >list.actual && test_cmp list.expect list.actual ' +# A tag of a tag, where the "inner" tag is not otherwise +# reachable, and a full peel points to a commit reachable from HEAD. +test_expect_success 'create hidden inner tag' ' + test_commit commit && + git tag -m inner inner HEAD && + git tag -m outer outer inner && + git tag -d inner +' + +test_expect_success 'pack explicit outer tag' ' + packname=$( + { + echo HEAD && + echo outer + } | + git pack-objects --revs test-hidden-explicit + ) +' + +test_expect_success 'unpack objects' ' + rm -rf clone.git && + git init clone.git && + git -C clone.git unpack-objects <test-hidden-explicit-${packname}.pack +' + +test_expect_success 'check unpacked result (have all objects)' ' + git -C clone.git rev-list --objects $(git rev-parse outer HEAD) +' + +test_expect_success 'pack implied outer tag' ' + packname=$( + echo HEAD | + git pack-objects --revs --include-tag test-hidden-implied + ) +' + +test_expect_success 'unpack objects' ' + rm -rf clone.git && + git init clone.git && + git -C clone.git unpack-objects <test-hidden-implied-${packname}.pack +' + +test_expect_success 'check unpacked result (have all objects)' ' + git -C clone.git rev-list --objects $(git rev-parse outer HEAD) +' + +test_expect_success 'single-branch clone can transfer tag' ' + rm -rf clone.git && + git clone --no-local --single-branch -b master . clone.git && + git -C clone.git fsck +' + test_done diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh index 3893afd687..b4c7a6ff6b 100755 --- a/t/t5310-pack-bitmaps.sh +++ b/t/t5310-pack-bitmaps.sh @@ -7,6 +7,18 @@ objpath () { echo ".git/objects/$(echo "$1" | sed -e 's|\(..\)|\1/|')" } +# show objects present in pack ($1 should be associated *.idx) +list_packed_objects () { + git show-index <"$1" | cut -d' ' -f2 +} + +# has_any pattern-file content-file +# tests whether content-file has any entry from pattern-file with entries being +# whole lines. +has_any () { + grep -Ff "$1" "$2" +} + test_expect_success 'setup repo with moderate-sized history' ' for i in $(test_seq 1 10); do test_commit $i @@ -16,6 +28,7 @@ test_expect_success 'setup repo with moderate-sized history' ' test_commit side-$i done && git checkout master && + bitmaptip=$(git rev-parse master) && blob=$(echo tagged-blob | git hash-object -w --stdin) && git tag tagged-blob $blob && git config repack.writebitmaps true && @@ -118,6 +131,83 @@ test_expect_success 'incremental repack can disable bitmaps' ' git repack -d --no-write-bitmap-index ' +test_expect_success 'pack-objects respects --local (non-local loose)' ' + git init --bare alt.git && + echo $(pwd)/alt.git/objects >.git/objects/info/alternates && + echo content1 >file1 && + # non-local loose object which is not present in bitmapped pack + altblob=$(GIT_DIR=alt.git git hash-object -w file1) && + # non-local loose object which is also present in bitmapped pack + git cat-file blob $blob | GIT_DIR=alt.git git hash-object -w --stdin && + git add file1 && + test_tick && + git commit -m commit_file1 && + echo HEAD | git pack-objects --local --stdout --revs >1.pack && + git index-pack 1.pack && + list_packed_objects 1.idx >1.objects && + printf "%s\n" "$altblob" "$blob" >nonlocal-loose && + ! has_any nonlocal-loose 1.objects +' + +test_expect_success 'pack-objects respects --honor-pack-keep (local non-bitmapped pack)' ' + echo content2 >file2 && + blob2=$(git hash-object -w file2) && + git add file2 && + test_tick && + git commit -m commit_file2 && + printf "%s\n" "$blob2" "$bitmaptip" >keepobjects && + pack2=$(git pack-objects pack2 <keepobjects) && + mv pack2-$pack2.* .git/objects/pack/ && + >.git/objects/pack/pack2-$pack2.keep && + rm $(objpath $blob2) && + echo HEAD | git pack-objects --honor-pack-keep --stdout --revs >2a.pack && + git index-pack 2a.pack && + list_packed_objects 2a.idx >2a.objects && + ! has_any keepobjects 2a.objects +' + +test_expect_success 'pack-objects respects --local (non-local pack)' ' + mv .git/objects/pack/pack2-$pack2.* alt.git/objects/pack/ && + echo HEAD | git pack-objects --local --stdout --revs >2b.pack && + git index-pack 2b.pack && + list_packed_objects 2b.idx >2b.objects && + ! has_any keepobjects 2b.objects +' + +test_expect_success 'pack-objects respects --honor-pack-keep (local bitmapped pack)' ' + ls .git/objects/pack/ | grep bitmap >output && + test_line_count = 1 output && + packbitmap=$(basename $(cat output) .bitmap) && + list_packed_objects .git/objects/pack/$packbitmap.idx >packbitmap.objects && + test_when_finished "rm -f .git/objects/pack/$packbitmap.keep" && + >.git/objects/pack/$packbitmap.keep && + echo HEAD | git pack-objects --honor-pack-keep --stdout --revs >3a.pack && + git index-pack 3a.pack && + list_packed_objects 3a.idx >3a.objects && + ! has_any packbitmap.objects 3a.objects +' + +test_expect_success 'pack-objects respects --local (non-local bitmapped pack)' ' + mv .git/objects/pack/$packbitmap.* alt.git/objects/pack/ && + test_when_finished "mv alt.git/objects/pack/$packbitmap.* .git/objects/pack/" && + echo HEAD | git pack-objects --local --stdout --revs >3b.pack && + git index-pack 3b.pack && + list_packed_objects 3b.idx >3b.objects && + ! has_any packbitmap.objects 3b.objects +' + +test_expect_success 'pack-objects to file can use bitmap' ' + # make sure we still have 1 bitmap index from previous tests + ls .git/objects/pack/ | grep bitmap >output && + test_line_count = 1 output && + # verify equivalent packs are generated with/without using bitmap index + packasha1=$(git pack-objects --no-use-bitmap-index --all packa </dev/null) && + packbsha1=$(git pack-objects --use-bitmap-index --all packb </dev/null) && + list_packed_objects <packa-$packasha1.idx >packa.objects && + list_packed_objects <packb-$packbsha1.idx >packb.objects && + test_cmp packa.objects packb.objects +' + test_expect_success 'full repack, reusing previous bitmaps' ' git repack -ad && ls .git/objects/pack/ | grep bitmap >output && @@ -143,6 +233,20 @@ test_expect_success 'create objects for missing-HAVE tests' ' EOF ' +test_expect_success 'pack-objects respects --incremental' ' + cat >revs2 <<-EOF && + HEAD + $commit + EOF + git pack-objects --incremental --stdout --revs <revs2 >4.pack && + git index-pack 4.pack && + list_packed_objects 4.idx >4.objects && + test_line_count = 4 4.objects && + git rev-list --objects $commit >revlist && + cut -d" " -f1 revlist |sort >objects && + test_cmp 4.objects objects +' + test_expect_success 'pack with missing blob' ' rm $(objpath $blob) && git pack-objects --stdout --revs <revs >/dev/null @@ -158,10 +262,6 @@ test_expect_success 'pack with missing parent' ' git pack-objects --stdout --revs <revs >/dev/null ' -test_lazy_prereq JGIT ' - type jgit -' - test_expect_success JGIT 'we can read jgit bitmaps' ' git clone . compat-jgit && ( diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh index 44f3d5fb28..9b19cff729 100755 --- a/t/t5504-fetch-receive-strict.sh +++ b/t/t5504-fetch-receive-strict.sh @@ -115,8 +115,8 @@ test_expect_success 'push with transfer.fsckobjects' ' test_cmp exp act ' -cat >bogus-commit <<\EOF -tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904 +cat >bogus-commit <<EOF +tree $EMPTY_TREE author Bugs Bunny 1234567890 +0000 committer Bugs Bunny <bugs@bun.ni> 1234567890 +0000 diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index dd2e6ce34e..8198d8eb05 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -1182,7 +1182,7 @@ test_expect_success 'extra args: setup' ' test_extra_arg () { test_expect_success "extra args: $*" " test_must_fail git remote $* bogus_extra_arg 2>actual && - grep '^usage:' actual + test_i18ngrep '^usage:' actual " } diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 454d896390..668c54be41 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -644,7 +644,7 @@ test_expect_success 'fetch --prune prints the remotes url' ' git fetch --prune origin 2>&1 | head -n1 >../actual ) && echo "From ${D}/." >expect && - test_cmp expect actual + test_i18ncmp expect actual ' test_expect_success 'branchname D/F conflict resolved by --prune' ' @@ -688,4 +688,34 @@ test_expect_success 'fetching with auto-gc does not lock up' ' ) ' +test_expect_success C_LOCALE_OUTPUT 'fetch aligned output' ' + git clone . full-output && + test_commit looooooooooooong-tag && + ( + cd full-output && + git -c fetch.output=full fetch origin 2>&1 | \ + grep -e "->" | cut -c 22- >../actual + ) && + cat >expect <<-\EOF && + master -> origin/master + looooooooooooong-tag -> looooooooooooong-tag + EOF + test_cmp expect actual +' + +test_expect_success C_LOCALE_OUTPUT 'fetch compact output' ' + git clone . compact && + test_commit extraaa && + ( + cd compact && + git -c fetch.output=compact fetch origin 2>&1 | \ + grep -e "->" | cut -c 22- >../actual + ) && + cat >expect <<-\EOF && + master -> origin/* + extraaa -> * + EOF + test_cmp expect actual +' + test_done diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh index 819b9ddd0f..befdfeefc6 100755 --- a/t/t5512-ls-remote.sh +++ b/t/t5512-ls-remote.sh @@ -207,5 +207,45 @@ test_expect_success 'ls-remote --symref omits filtered-out matches' ' test_cmp expect actual ' +test_lazy_prereq GIT_DAEMON ' + test_tristate GIT_TEST_GIT_DAEMON && + test "$GIT_TEST_GIT_DAEMON" != false +' + +# This test spawns a daemon, so run it only if the user would be OK with +# testing with git-daemon. +test_expect_success PIPE,JGIT,GIT_DAEMON 'indicate no refs in standards-compliant empty remote' ' + JGIT_DAEMON_PORT=${JGIT_DAEMON_PORT-${this_test#t}} && + JGIT_DAEMON_PID= && + git init --bare empty.git && + >empty.git/git-daemon-export-ok && + mkfifo jgit_daemon_output && + { + jgit daemon --port="$JGIT_DAEMON_PORT" . >jgit_daemon_output & + JGIT_DAEMON_PID=$! + } && + test_when_finished kill "$JGIT_DAEMON_PID" && + { + read line && + case $line in + Exporting*) + ;; + *) + echo "Expected: Exporting" && + false;; + esac && + read line && + case $line in + "Listening on"*) + ;; + *) + echo "Expected: Listening on" && + false;; + esac + } <jgit_daemon_output && + # --exit-code asks the command to exit with 2 when no + # matching refs are found. + test_expect_code 2 git ls-remote --exit-code git://localhost:$JGIT_DAEMON_PORT/empty.git +' test_done diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index 3159956fde..551844584f 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -211,7 +211,7 @@ test_expect_success 'fail if the index has unresolved entries' ' test -n "$(git ls-files -u)" && cp file expected && test_must_fail git pull . second 2>err && - test_i18ngrep "Pull is not possible because you have unmerged files" 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)" && @@ -255,6 +255,38 @@ test_expect_success '--rebase' ' test new = "$(git show HEAD:file2)" ' +test_expect_success '--rebase with conflicts shows advice' ' + test_when_finished "git rebase --abort; git checkout -f to-rebase" && + git checkout -b seq && + test_seq 5 >seq.txt && + git add seq.txt && + test_tick && + git commit -m "Add seq.txt" && + echo 6 >>seq.txt && + test_tick && + git commit -m "Append to seq.txt" seq.txt && + git checkout -b with-conflicts HEAD^ && + echo conflicting >>seq.txt && + test_tick && + git commit -m "Create conflict" seq.txt && + test_must_fail git pull --rebase . seq 2>err >out && + test_i18ngrep "When you have resolved this problem" out +' + +test_expect_success 'failed --rebase shows advice' ' + test_when_finished "git rebase --abort; git checkout -f to-rebase" && + git checkout -b diverging && + test_commit attributes .gitattributes "* text=auto" attrs && + sha1="$(printf "1\\r\\n" | git hash-object -w --stdin)" && + git update-index --cacheinfo 0644 $sha1 file && + git commit -m v1-with-cr && + # force checkout because `git reset --hard` will not leave clean `file` + git checkout -f -b fails-to-rebase HEAD^ && + test_commit v2-without-cr file "2" file2-lf && + test_must_fail git pull --rebase . diverging 2>err >out && + test_i18ngrep "When you have resolved this problem" out +' + test_expect_success '--rebase fails with multiple branches' ' git reset --hard before-rebase && test_must_fail git pull --rebase . copy master 2>err && diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh index 3683df13a6..d6981ba304 100755 --- a/t/t5523-push-upstream.sh +++ b/t/t5523-push-upstream.sh @@ -75,7 +75,7 @@ test_expect_success TTY 'progress messages go to tty' ' ensure_fresh_upstream && test_terminal git push -u upstream master >out 2>err && - grep "Writing objects" err + test_i18ngrep "Writing objects" err ' test_expect_success 'progress messages do not go to non-tty' ' @@ -83,7 +83,7 @@ test_expect_success 'progress messages do not go to non-tty' ' # skip progress messages, since stderr is non-tty git push -u upstream master >out 2>err && - ! grep "Writing objects" err + test_i18ngrep ! "Writing objects" err ' test_expect_success 'progress messages go to non-tty (forced)' ' @@ -91,22 +91,22 @@ test_expect_success 'progress messages go to non-tty (forced)' ' # force progress messages to stderr, even though it is non-tty git push -u --progress upstream master >out 2>err && - grep "Writing objects" err + test_i18ngrep "Writing objects" err ' test_expect_success TTY 'push -q suppresses progress' ' ensure_fresh_upstream && test_terminal git push -u -q upstream master >out 2>err && - ! grep "Writing objects" err + test_i18ngrep ! "Writing objects" err ' test_expect_success TTY 'push --no-progress suppresses progress' ' ensure_fresh_upstream && test_terminal git push -u --no-progress upstream master >out 2>err && - ! grep "Unpacking objects" err && - ! grep "Writing objects" err + test_i18ngrep ! "Unpacking objects" err && + test_i18ngrep ! "Writing objects" err ' test_expect_success TTY 'quiet push' ' diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh index 954d0e43f5..f3b0a8d30a 100755 --- a/t/t5526-fetch-submodules.sh +++ b/t/t5526-fetch-submodules.sh @@ -485,4 +485,39 @@ test_expect_success 'fetching submodules respects parallel settings' ' ) ' +test_expect_success 'fetching submodule into a broken repository' ' + # Prepare src and src/sub nested in it + git init src && + ( + cd src && + git init sub && + git -C sub commit --allow-empty -m "initial in sub" && + git submodule add -- ./sub sub && + git commit -m "initial in top" + ) && + + # Clone the old-fashoned way + git clone src dst && + git -C dst clone ../src/sub sub && + + # Make sure that old-fashoned layout is still supported + git -C dst status && + + # "diff" would find no change + git -C dst diff --exit-code && + + # Recursive-fetch works fine + git -C dst fetch --recurse-submodules && + + # Break the receiving submodule + rm -f dst/sub/.git/HEAD && + + # NOTE: without the fix the following tests will recurse forever! + # They should terminate with an error. + + test_must_fail git -C dst status && + test_must_fail git -C dst diff && + test_must_fail git -C dst fetch --recurse-submodules +' + test_done diff --git a/t/t5533-push-cas.sh b/t/t5533-push-cas.sh index c7320121ec..a2c9e7439f 100755 --- a/t/t5533-push-cas.sh +++ b/t/t5533-push-cas.sh @@ -191,4 +191,42 @@ test_expect_success 'cover everything with default force-with-lease (allowed)' ' test_cmp expect actual ' +test_expect_success 'new branch covered by force-with-lease' ' + setup_srcdst_basic && + ( + cd dst && + git branch branch master && + git push --force-with-lease=branch origin branch + ) && + git ls-remote dst refs/heads/branch >expect && + git ls-remote src refs/heads/branch >actual && + test_cmp expect actual +' + +test_expect_success 'new branch covered by force-with-lease (explicit)' ' + setup_srcdst_basic && + ( + cd dst && + git branch branch master && + git push --force-with-lease=branch: origin branch + ) && + git ls-remote dst refs/heads/branch >expect && + git ls-remote src refs/heads/branch >actual && + test_cmp expect actual +' + +test_expect_success 'new branch already exists' ' + setup_srcdst_basic && + ( + cd src && + git checkout -b branch master && + test_commit F + ) && + ( + cd dst && + git branch branch master && + test_must_fail git push --force-with-lease=branch: origin branch + ) +' + test_done diff --git a/t/t5536-fetch-conflicts.sh b/t/t5536-fetch-conflicts.sh index 6c5d3a4ce0..2e42cf3316 100755 --- a/t/t5536-fetch-conflicts.sh +++ b/t/t5536-fetch-conflicts.sh @@ -22,8 +22,8 @@ verify_stderr () { cat >expected && # We're not interested in the error # "fatal: The remote end hung up unexpectedly": - grep -E '^(fatal|warning):' <error | grep -v 'hung up' >actual | sort && - test_cmp expected actual + test_i18ngrep -E '^(fatal|warning):' <error | grep -v 'hung up' >actual | sort && + test_i18ncmp expected actual } test_expect_success 'setup' ' diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh index fd7d06b9a2..d38bf32470 100755 --- a/t/t5541-http-push-smart.sh +++ b/t/t5541-http-push-smart.sh @@ -74,7 +74,7 @@ test_expect_success 'push to remote repository (standard)' ' test_tick && git commit -m path2 && HEAD=$(git rev-parse --verify HEAD) && - GIT_CURL_VERBOSE=1 git push -v -v 2>err && + GIT_TRACE_CURL=true git push -v -v 2>err && ! grep "Expect: 100-continue" err && grep "POST git-receive-pack ([0-9]* bytes)" err && (cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git && @@ -119,7 +119,7 @@ test_expect_success 'rejected update prints status' ' git commit -m dev2 && test_must_fail git push origin dev2 2>act && sed -e "/^remote: /s/ *$//" <act >cmp && - test_cmp exp cmp + test_i18ncmp exp cmp ' rm -f "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update" @@ -219,7 +219,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 && - grep "^Writing objects" output + test_i18ngrep "^Writing objects" output ' test_expect_success TTY 'push --quiet silences status and progress' ' @@ -233,16 +233,16 @@ test_expect_success TTY 'push --no-progress silences progress but not status' ' cd "$ROOT_PATH"/test_repo_clone && test_commit no-progress && test_terminal git push --no-progress >output 2>&1 && - grep "^To http" output && - ! grep "^Writing objects" + test_i18ngrep "^To http" output && + test_i18ngrep ! "^Writing objects" ' test_expect_success 'push --progress shows progress to non-tty' ' cd "$ROOT_PATH"/test_repo_clone && test_commit progress && git push --progress >output 2>&1 && - grep "^To http" output && - grep "^Writing objects" output + test_i18ngrep "^To http" output && + test_i18ngrep "^Writing objects" output ' test_expect_success 'http push gives sane defaults to reflog' ' @@ -368,5 +368,14 @@ test_expect_success GPG 'push with post-receive to inspect certificate' ' test_cmp expect "$HTTPD_DOCUMENT_ROOT_PATH/push-cert-status" ' +test_expect_success 'push status output scrubs password' ' + cd "$ROOT_PATH/test_repo_clone" && + git push --porcelain \ + "$HTTPD_URL_USER_PASS/smart/test_repo.git" \ + +HEAD:scrub >status && + # should have been scrubbed down to vanilla URL + grep "^To $HTTPD_URL/smart/test_repo.git" status +' + stop_httpd test_done diff --git a/t/t5544-pack-objects-hook.sh b/t/t5544-pack-objects-hook.sh new file mode 100755 index 0000000000..4357af1525 --- /dev/null +++ b/t/t5544-pack-objects-hook.sh @@ -0,0 +1,62 @@ +#!/bin/sh + +test_description='test custom script in place of pack-objects' +. ./test-lib.sh + +test_expect_success 'create some history to fetch' ' + test_commit one && + test_commit two +' + +test_expect_success 'create debugging hook script' ' + write_script .git/hook <<-\EOF + echo >&2 "hook running" + echo "$*" >hook.args + cat >hook.stdin + "$@" <hook.stdin >hook.stdout + cat hook.stdout + EOF +' + +clear_hook_results () { + rm -rf .git/hook.* dst.git +} + +test_expect_success 'hook runs via global config' ' + clear_hook_results && + test_config_global uploadpack.packObjectsHook ./hook && + git clone --no-local . dst.git 2>stderr && + grep "hook running" stderr +' + +test_expect_success 'hook outputs are sane' ' + # check that we recorded a usable pack + git index-pack --stdin <.git/hook.stdout && + + # check that we recorded args and stdin. We do not check + # the full argument list or the exact pack contents, as it would make + # the test brittle. So just sanity check that we could replay + # the packing procedure. + grep "^git" .git/hook.args && + $(cat .git/hook.args) <.git/hook.stdin >replay +' + +test_expect_success 'hook runs from -c config' ' + clear_hook_results && + git clone --no-local \ + -u "git -c uploadpack.packObjectsHook=./hook upload-pack" \ + . dst.git 2>stderr && + grep "hook running" stderr +' + +test_expect_success 'hook does not run from repo config' ' + clear_hook_results && + test_config uploadpack.packObjectsHook "./hook" && + git clone --no-local . dst.git 2>stderr && + ! grep "hook running" stderr && + test_path_is_missing .git/hook.args && + test_path_is_missing .git/hook.stdin && + test_path_is_missing .git/hook.stdout +' + +test_done diff --git a/t/t5545-push-options.sh b/t/t5545-push-options.sh new file mode 100755 index 0000000000..ea813b9383 --- /dev/null +++ b/t/t5545-push-options.sh @@ -0,0 +1,103 @@ +#!/bin/sh + +test_description='pushing to a repository using push options' + +. ./test-lib.sh + +mk_repo_pair () { + rm -rf workbench upstream && + test_create_repo upstream && + test_create_repo workbench && + ( + cd upstream && + git config receive.denyCurrentBranch warn && + mkdir -p .git/hooks && + cat >.git/hooks/pre-receive <<-'EOF' && + #!/bin/sh + if test -n "$GIT_PUSH_OPTION_COUNT"; then + i=0 + >hooks/pre-receive.push_options + while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"; do + eval "value=\$GIT_PUSH_OPTION_$i" + echo $value >>hooks/pre-receive.push_options + i=$((i + 1)) + done + fi + EOF + chmod u+x .git/hooks/pre-receive + + cat >.git/hooks/post-receive <<-'EOF' && + #!/bin/sh + if test -n "$GIT_PUSH_OPTION_COUNT"; then + i=0 + >hooks/post-receive.push_options + while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"; do + eval "value=\$GIT_PUSH_OPTION_$i" + echo $value >>hooks/post-receive.push_options + i=$((i + 1)) + done + fi + EOF + chmod u+x .git/hooks/post-receive + ) && + ( + cd workbench && + git remote add up ../upstream + ) +} + +# Compare the ref ($1) in upstream with a ref value from workbench ($2) +# i.e. test_refs second HEAD@{2} +test_refs () { + test $# = 2 && + git -C upstream rev-parse --verify "$1" >expect && + git -C workbench rev-parse --verify "$2" >actual && + test_cmp expect actual +} + +test_expect_success 'one push option works for a single branch' ' + mk_repo_pair && + git -C upstream config receive.advertisePushOptions true && + ( + cd workbench && + test_commit one && + git push --mirror up && + test_commit two && + git push --push-option=asdf up master + ) && + test_refs master master && + echo "asdf" >expect && + test_cmp expect upstream/.git/hooks/pre-receive.push_options && + test_cmp expect upstream/.git/hooks/post-receive.push_options +' + +test_expect_success 'push option denied by remote' ' + mk_repo_pair && + git -C upstream config receive.advertisePushOptions false && + ( + cd workbench && + test_commit one && + git push --mirror up && + test_commit two && + test_must_fail git push --push-option=asdf up master + ) && + test_refs master HEAD@{1} +' + +test_expect_success 'two push options work' ' + mk_repo_pair && + git -C upstream config receive.advertisePushOptions true && + ( + cd workbench && + test_commit one && + git push --mirror up && + test_commit two && + git push --push-option=asdf --push-option="more structured text" up master + ) && + test_refs master master && + printf "asdf\nmore structured text\n" >expect && + test_cmp expect upstream/.git/hooks/pre-receive.push_options && + test_cmp expect upstream/.git/hooks/post-receive.push_options +' + +test_done diff --git a/t/t5546-receive-limits.sh b/t/t5546-receive-limits.sh new file mode 100755 index 0000000000..10cb0be2b7 --- /dev/null +++ b/t/t5546-receive-limits.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +test_description='check receive input limits' +. ./test-lib.sh + +# Let's run tests with different unpack limits: 1 and 10000 +# When the limit is 1, `git receive-pack` will call `git index-pack`. +# When the limit is 10000, `git receive-pack` will call `git unpack-objects`. + +test_pack_input_limit () { + case "$1" in + index) unpack_limit=1 ;; + unpack) unpack_limit=10000 ;; + esac + + test_expect_success 'prepare destination repository' ' + rm -fr dest && + git --bare init dest + ' + + test_expect_success "set unpacklimit to $unpack_limit" ' + git --git-dir=dest config receive.unpacklimit "$unpack_limit" + ' + + test_expect_success 'setting receive.maxInputSize to 512 rejects push' ' + git --git-dir=dest config receive.maxInputSize 512 && + test_must_fail git push dest HEAD + ' + + test_expect_success 'bumping limit to 4k allows push' ' + git --git-dir=dest config receive.maxInputSize 4k && + git push dest HEAD + ' + + test_expect_success 'prepare destination repository (again)' ' + rm -fr dest && + git --bare init dest + ' + + test_expect_success 'lifting the limit allows push' ' + git --git-dir=dest config receive.maxInputSize 0 && + git push dest HEAD + ' +} + +test_expect_success "create known-size (1024 bytes) commit" ' + test-genrandom foo 1024 >one-k && + git add one-k && + test_commit one-k +' + +test_pack_input_limit index +test_pack_input_limit unpack + +test_done diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh index 3484b6f0f3..7641417b4a 100755 --- a/t/t5550-http-fetch-dumb.sh +++ b/t/t5550-http-fetch-dumb.sh @@ -263,15 +263,15 @@ check_language () { >expect ;; ?*) - echo "Accept-Language: $1" >expect + echo "=> Send header: Accept-Language: $1" >expect ;; esac && - GIT_CURL_VERBOSE=1 \ + GIT_TRACE_CURL=true \ LANGUAGE=$2 \ git ls-remote "$HTTPD_URL/dumb/repo.git" >output 2>&1 && tr -d '\015' <output | sort -u | - sed -ne '/^Accept-Language:/ p' >actual && + sed -ne '/^=> Send header: Accept-Language:/ p' >actual && test_cmp expect actual } @@ -295,8 +295,16 @@ ja;q=0.95, zh;q=0.94, sv;q=0.93, pt;q=0.92, nb;q=0.91, *;q=0.90" \ ' test_expect_success 'git client does not send an empty Accept-Language' ' - GIT_CURL_VERBOSE=1 LANGUAGE= git ls-remote "$HTTPD_URL/dumb/repo.git" 2>stderr && - ! grep "^Accept-Language:" stderr + GIT_TRACE_CURL=true LANGUAGE= git ls-remote "$HTTPD_URL/dumb/repo.git" 2>stderr && + ! grep "^=> Send header: Accept-Language:" stderr +' + +test_expect_success 'remote-http complains cleanly about malformed urls' ' + # do not actually issue "list" or other commands, as we do not + # want to rely on what curl would actually do with such a broken + # URL. This is just about making sure we do not segfault during + # initialization. + test_must_fail git remote-http http::/example.com/repo.git ' stop_httpd diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh index 2f375eb94d..1ec5b2747a 100755 --- a/t/t5551-http-fetch-smart.sh +++ b/t/t5551-http-fetch-smart.sh @@ -43,12 +43,21 @@ cat >exp <<EOF < Content-Type: application/x-git-upload-pack-result EOF test_expect_success 'clone http repository' ' - GIT_CURL_VERBOSE=1 git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err && + GIT_TRACE_CURL=true git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err && test_cmp file clone/file && tr '\''\015'\'' Q <err | sed -e " s/Q\$// /^[*] /d + /^== Info:/d + /^=> Send header, /d + /^=> Send header:$/d + /^<= Recv header, /d + /^<= Recv header:$/d + s/=> Send header: // + s/= Recv header:// + /^<= Recv data/d + /^=> Send data/d /^$/d /^< $/d @@ -261,9 +270,9 @@ test_expect_success CMDLINE_LIMIT \ ' test_expect_success 'large fetch-pack requests can be split across POSTs' ' - GIT_CURL_VERBOSE=1 git -c http.postbuffer=65536 \ + GIT_TRACE_CURL=true git -c http.postbuffer=65536 \ clone --bare "$HTTPD_URL/smart/repo.git" split.git 2>err && - grep "^> POST" err >posts && + grep "^=> Send header: POST" err >posts && test_line_count = 2 posts ' diff --git a/t/t5614-clone-submodules.sh b/t/t5614-clone-submodules.sh index 32d83e2694..a87d329656 100755 --- a/t/t5614-clone-submodules.sh +++ b/t/t5614-clone-submodules.sh @@ -25,61 +25,46 @@ test_expect_success 'setup' ' test_expect_success 'nonshallow clone implies nonshallow submodule' ' test_when_finished "rm -rf super_clone" && git clone --recurse-submodules "file://$pwd/." super_clone && - ( - cd super_clone && - git log --oneline >lines && - test_line_count = 3 lines - ) && - ( - cd super_clone/sub && - git log --oneline >lines && - test_line_count = 3 lines - ) + git -C super_clone log --oneline >lines && + test_line_count = 3 lines && + git -C super_clone/sub log --oneline >lines && + test_line_count = 3 lines ' -test_expect_success 'shallow clone implies shallow submodule' ' +test_expect_success 'shallow clone with shallow submodule' ' + test_when_finished "rm -rf super_clone" && + git clone --recurse-submodules --depth 2 --shallow-submodules "file://$pwd/." super_clone && + git -C super_clone log --oneline >lines && + test_line_count = 2 lines && + git -C super_clone/sub log --oneline >lines && + test_line_count = 1 lines +' + +test_expect_success 'shallow clone does not imply shallow submodule' ' test_when_finished "rm -rf super_clone" && git clone --recurse-submodules --depth 2 "file://$pwd/." super_clone && - ( - cd super_clone && - git log --oneline >lines && - test_line_count = 2 lines - ) && - ( - cd super_clone/sub && - git log --oneline >lines && - test_line_count = 1 lines - ) + git -C super_clone log --oneline >lines && + test_line_count = 2 lines && + git -C super_clone/sub log --oneline >lines && + test_line_count = 3 lines ' test_expect_success 'shallow clone with non shallow submodule' ' test_when_finished "rm -rf super_clone" && git clone --recurse-submodules --depth 2 --no-shallow-submodules "file://$pwd/." super_clone && - ( - cd super_clone && - git log --oneline >lines && - test_line_count = 2 lines - ) && - ( - cd super_clone/sub && - git log --oneline >lines && - test_line_count = 3 lines - ) + git -C super_clone log --oneline >lines && + test_line_count = 2 lines && + git -C super_clone/sub log --oneline >lines && + test_line_count = 3 lines ' test_expect_success 'non shallow clone with shallow submodule' ' test_when_finished "rm -rf super_clone" && git clone --recurse-submodules --no-local --shallow-submodules "file://$pwd/." super_clone && - ( - cd super_clone && - git log --oneline >lines && - test_line_count = 3 lines - ) && - ( - cd super_clone/sub && - git log --oneline >lines && - test_line_count = 1 lines - ) + git -C super_clone log --oneline >lines && + test_line_count = 3 lines && + git -C super_clone/sub log --oneline >lines && + test_line_count = 1 lines ' test_expect_success 'clone follows shallow recommendation' ' diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh index a1dcdb81d7..f6020cd2aa 100755 --- a/t/t6006-rev-list-format.sh +++ b/t/t6006-rev-list-format.sh @@ -225,7 +225,7 @@ test_expect_success '%C(auto,...) respects --color=auto (stdout not tty)' ' test_expect_success '%C(auto) respects --color' ' git log --color --format="%C(auto)%H" -1 >actual && - printf "\\033[33m%s\\033[m\\n" $(git rev-parse HEAD) >expect && + printf "\\033[m\\033[33m%s\\033[m\\n" $(git rev-parse HEAD) >expect && test_cmp expect actual ' diff --git a/t/t6007-rev-list-cherry-pick-file.sh b/t/t6007-rev-list-cherry-pick-file.sh index 28d4f6b259..1408b608eb 100755 --- a/t/t6007-rev-list-cherry-pick-file.sh +++ b/t/t6007-rev-list-cherry-pick-file.sh @@ -207,4 +207,25 @@ test_expect_success '--count --left-right' ' test_cmp expect actual ' +# Corrupt the object store deliberately to make sure +# the object is not even checked for its existence. +remove_loose_object () { + sha1="$(git rev-parse "$1")" && + remainder=${sha1#??} && + firsttwo=${sha1%$remainder} && + rm .git/objects/$firsttwo/$remainder +} + +test_expect_success '--cherry-pick avoids looking at full diffs' ' + git checkout -b shy-diff && + test_commit dont-look-at-me && + echo Hello >dont-look-at-me.t && + test_tick && + git commit -m tip dont-look-at-me.t && + git checkout -b mainline HEAD^ && + test_commit to-cherry-pick && + remove_loose_object shy-diff^:dont-look-at-me.t && + git rev-list --cherry-pick ...shy-diff +' + test_done diff --git a/t/t6018-rev-list-glob.sh b/t/t6018-rev-list-glob.sh index d00f7db868..381f35ed16 100755 --- a/t/t6018-rev-list-glob.sh +++ b/t/t6018-rev-list-glob.sh @@ -257,7 +257,7 @@ test_expect_success 'rev-list accumulates multiple --exclude' ' # "git rev-list<ENTER>" is likely to be a bug in the calling script and may -# deserve an error message, but do cases where set of refs programatically +# deserve an error message, but do cases where set of refs programmatically # given using globbing and/or --stdin need to fail with the same error, or # are we better off reporting a success with no output? The following few # tests document the current behaviour to remind us that we might want to diff --git a/t/t6026-merge-attr.sh b/t/t6026-merge-attr.sh index ef0cbceafe..7a6e33e673 100755 --- a/t/t6026-merge-attr.sh +++ b/t/t6026-merge-attr.sh @@ -181,4 +181,19 @@ test_expect_success 'up-to-date merge without common ancestor' ' ) ' +test_expect_success 'custom merge does not lock index' ' + git reset --hard anchor && + write_script sleep-one-second.sh <<-\EOF && + sleep 1 & + echo $! >sleep.pid + EOF + test_when_finished "kill \$(cat sleep.pid)" && + + test_write_lines >.gitattributes \ + "* merge=ours" "text merge=sleep-one-second" && + test_config merge.ours.driver true && + test_config merge.sleep-one-second.driver ./sleep-one-second.sh && + git merge master +' + test_done diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index e74662ba5c..5e5370feb4 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -362,7 +362,7 @@ test_expect_success 'bisect starting with a detached HEAD' ' test_expect_success 'bisect errors out if bad and good are mistaken' ' git bisect reset && test_must_fail git bisect start $HASH2 $HASH4 2> rev_list_error && - grep "mistook good and bad" rev_list_error && + test_i18ngrep "mistook good and bad" rev_list_error && git bisect reset ' @@ -404,7 +404,7 @@ test_expect_success 'side branch creation' ' test_expect_success 'good merge base when good and bad are siblings' ' git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt && - grep "merge base must be tested" my_bisect_log.txt && + test_i18ngrep "merge base must be tested" my_bisect_log.txt && grep $HASH4 my_bisect_log.txt && git bisect good > my_bisect_log.txt && test_must_fail grep "merge base must be tested" my_bisect_log.txt && @@ -413,7 +413,7 @@ test_expect_success 'good merge base when good and bad are siblings' ' ' test_expect_success 'skipped merge base when good and bad are siblings' ' git bisect start "$SIDE_HASH7" "$HASH7" > my_bisect_log.txt && - grep "merge base must be tested" my_bisect_log.txt && + test_i18ngrep "merge base must be tested" my_bisect_log.txt && grep $HASH4 my_bisect_log.txt && git bisect skip > my_bisect_log.txt 2>&1 && grep "warning" my_bisect_log.txt && @@ -423,11 +423,11 @@ test_expect_success 'skipped merge base when good and bad are siblings' ' test_expect_success 'bad merge base when good and bad are siblings' ' git bisect start "$HASH7" HEAD > my_bisect_log.txt && - grep "merge base must be tested" my_bisect_log.txt && + test_i18ngrep "merge base must be tested" my_bisect_log.txt && grep $HASH4 my_bisect_log.txt && test_must_fail git bisect bad > my_bisect_log.txt 2>&1 && - grep "merge base $HASH4 is bad" my_bisect_log.txt && - grep "fixed between $HASH4 and \[$SIDE_HASH7\]" my_bisect_log.txt && + test_i18ngrep "merge base $HASH4 is bad" my_bisect_log.txt && + test_i18ngrep "fixed between $HASH4 and \[$SIDE_HASH7\]" my_bisect_log.txt && git bisect reset ' @@ -460,9 +460,9 @@ test_expect_success 'many merge bases creation' ' test_expect_success 'good merge bases when good and bad are siblings' ' git bisect start "$B_HASH" "$A_HASH" > my_bisect_log.txt && - grep "merge base must be tested" my_bisect_log.txt && + test_i18ngrep "merge base must be tested" my_bisect_log.txt && git bisect good > my_bisect_log2.txt && - grep "merge base must be tested" my_bisect_log2.txt && + test_i18ngrep "merge base must be tested" my_bisect_log2.txt && { { grep "$SIDE_HASH5" my_bisect_log.txt && @@ -477,14 +477,14 @@ test_expect_success 'good merge bases when good and bad are siblings' ' test_expect_success 'optimized merge base checks' ' git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt && - grep "merge base must be tested" my_bisect_log.txt && + test_i18ngrep "merge base must be tested" my_bisect_log.txt && grep "$HASH4" my_bisect_log.txt && git bisect good > my_bisect_log2.txt && test -f ".git/BISECT_ANCESTORS_OK" && test "$HASH6" = $(git rev-parse --verify HEAD) && git bisect bad > my_bisect_log3.txt && git bisect good "$A_HASH" > my_bisect_log4.txt && - grep "merge base must be tested" my_bisect_log4.txt && + test_i18ngrep "merge base must be tested" my_bisect_log4.txt && test_must_fail test -f ".git/BISECT_ANCESTORS_OK" ' @@ -562,7 +562,7 @@ test_expect_success 'skipping away from skipped commit' ' test_expect_success 'erroring out when using bad path parameters' ' test_must_fail git bisect start $PARA_HASH7 $HASH1 -- foobar 2> error.txt && - grep "bad path parameters" error.txt + test_i18ngrep "bad path parameters" error.txt ' test_expect_success 'test bisection on bare repo - --no-checkout specified' ' @@ -721,7 +721,7 @@ git bisect good 3de952f2416b6084f557ec417709eac740c6818c # first bad commit: [32a594a3fdac2d57cf6d02987e30eec68511498c] Add <4: Ciao for now> into <hello>. EOF -test_expect_success 'bisect log: successfull result' ' +test_expect_success 'bisect log: successful result' ' git bisect reset && git bisect start $HASH4 $HASH2 && git bisect good && @@ -803,7 +803,7 @@ test_expect_success 'bisect terms needs 0 or 1 argument' ' test_must_fail git bisect terms 1 2 && test_must_fail git bisect terms 2>actual && echo "no terms defined" >expected && - test_cmp expected actual + test_i18ncmp expected actual ' test_expect_success 'bisect terms shows good/bad after start' ' @@ -875,7 +875,7 @@ test_expect_success 'bisect start --term-* does store terms' ' Your current terms are two for the old state and one for the new state. EOF - test_cmp expected actual && + test_i18ncmp expected actual && git bisect terms --term-bad >actual && echo one >expected && test_cmp expected actual && diff --git a/t/t6038-merge-text-auto.sh b/t/t6038-merge-text-auto.sh index 85c10b0940..5e8d5fa50c 100755 --- a/t/t6038-merge-text-auto.sh +++ b/t/t6038-merge-text-auto.sh @@ -16,6 +16,13 @@ test_description='CRLF merge conflict across text=auto change test_have_prereq SED_STRIPS_CR && SED_OPTIONS=-b +compare_files () { + tr '\015\000' QN <"$1" >"$1".expect && + tr '\015\000' QN <"$2" >"$2".actual && + test_cmp "$1".expect "$2".actual && + rm "$1".expect "$2".actual +} + test_expect_success setup ' git config core.autocrlf false && @@ -30,7 +37,7 @@ test_expect_success setup ' git branch side && echo "* text=auto" >.gitattributes && - touch file && + echo first line >file && git add .gitattributes file && test_tick && git commit -m "normalize file" && @@ -81,38 +88,49 @@ test_expect_success 'Merge after setting text=auto' ' rm -f .gitattributes && git reset --hard a && git merge b && - test_cmp expected file + compare_files expected file ' -test_expect_success 'Merge addition of text=auto' ' +test_expect_success 'Merge addition of text=auto eol=LF' ' + git config core.eol lf && cat <<-\EOF >expected && first line same line EOF - if test_have_prereq NATIVE_CRLF; then - append_cr <expected >expected.temp && - mv expected.temp expected - fi && git config merge.renormalize true && git rm -fr . && rm -f .gitattributes && git reset --hard b && git merge a && - test_cmp expected file + compare_files expected file +' + +test_expect_success 'Merge addition of text=auto eol=CRLF' ' + git config core.eol crlf && + cat <<-\EOF >expected && + first line + same line + EOF + + append_cr <expected >expected.temp && + mv expected.temp expected && + git config merge.renormalize true && + git rm -fr . && + rm -f .gitattributes && + git reset --hard b && + echo >&2 "After git reset --hard b" && + git ls-files -s --eol >&2 && + git merge a && + compare_files expected file ' test_expect_success 'Detect CRLF/LF conflict after setting text=auto' ' + git config core.eol native && echo "<<<<<<<" >expected && - if test_have_prereq NATIVE_CRLF; then - echo first line | append_cr >>expected && - echo same line | append_cr >>expected && - echo ======= | append_cr >>expected - else - echo first line >>expected && - echo same line >>expected && - echo ======= >>expected - fi && + echo first line >>expected && + echo same line >>expected && + echo ======= >>expected && echo first line | append_cr >>expected && echo same line | append_cr >>expected && echo ">>>>>>>" >>expected && @@ -121,29 +139,23 @@ test_expect_success 'Detect CRLF/LF conflict after setting text=auto' ' git reset --hard a && test_must_fail git merge b && fuzz_conflict file >file.fuzzy && - test_cmp expected file.fuzzy + compare_files expected file.fuzzy ' test_expect_success 'Detect LF/CRLF conflict from addition of text=auto' ' echo "<<<<<<<" >expected && echo first line | append_cr >>expected && echo same line | append_cr >>expected && - if test_have_prereq NATIVE_CRLF; then - echo ======= | append_cr >>expected && - echo first line | append_cr >>expected && - echo same line | append_cr >>expected - else - echo ======= >>expected && - echo first line >>expected && - echo same line >>expected - fi && + echo ======= >>expected && + echo first line >>expected && + echo same line >>expected && echo ">>>>>>>" >>expected && git config merge.renormalize false && rm -f .gitattributes && git reset --hard b && test_must_fail git merge a && fuzz_conflict file >file.fuzzy && - test_cmp expected file.fuzzy + compare_files expected file.fuzzy ' test_expect_failure 'checkout -m after setting text=auto' ' @@ -158,7 +170,7 @@ test_expect_failure 'checkout -m after setting text=auto' ' git reset --hard initial && git checkout a -- . && git checkout -m b && - test_cmp expected file + compare_files expected file ' test_expect_failure 'checkout -m addition of text=auto' ' @@ -173,7 +185,7 @@ test_expect_failure 'checkout -m addition of text=auto' ' git reset --hard initial && git checkout b -- . && git checkout -m a && - test_cmp expected file + compare_files expected file ' test_expect_failure 'cherry-pick patch from after text=auto was added' ' @@ -187,7 +199,7 @@ test_expect_failure 'cherry-pick patch from after text=auto was added' ' git reset --hard b && test_must_fail git cherry-pick a >err 2>&1 && grep "[Nn]othing added" err && - test_cmp expected file + compare_files expected file ' test_expect_success 'Test delete/normalize conflict' ' diff --git a/t/t6301-for-each-ref-errors.sh b/t/t6301-for-each-ref-errors.sh index cdb67a03b7..c734ce2388 100755 --- a/t/t6301-for-each-ref-errors.sh +++ b/t/t6301-for-each-ref-errors.sh @@ -20,8 +20,8 @@ test_expect_success 'Broken refs are reported correctly' ' test_when_finished "rm -f .git/$r" && echo "warning: ignoring broken ref $r" >broken-err && git for-each-ref >out 2>err && - test_cmp full-list out && - test_cmp broken-err err + test_i18ncmp full-list out && + test_i18ncmp broken-err err ' test_expect_success 'NULL_SHA1 refs are reported correctly' ' @@ -31,10 +31,10 @@ test_expect_success 'NULL_SHA1 refs are reported correctly' ' echo "warning: ignoring broken ref $r" >zeros-err && git for-each-ref >out 2>err && test_cmp full-list out && - test_cmp zeros-err err && + test_i18ncmp zeros-err err && git for-each-ref --format="%(objectname) %(refname)" >brief-out 2>brief-err && test_cmp brief-list brief-out && - test_cmp zeros-err brief-err + test_i18ncmp zeros-err brief-err ' test_expect_success 'Missing objects are reported correctly' ' @@ -43,7 +43,7 @@ test_expect_success 'Missing objects are reported correctly' ' test_when_finished "rm -f .git/$r" && echo "fatal: missing object $MISSING for $r" >missing-err && test_must_fail git for-each-ref 2>err && - test_cmp missing-err err && + test_i18ncmp missing-err err && ( cat brief-list && echo "$MISSING $r" diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh index 4a2570ed95..e365d1ff77 100755 --- a/t/t7001-mv.sh +++ b/t/t7001-mv.sh @@ -292,8 +292,8 @@ test_expect_success 'setup submodule' ' echo content >file && git add file && git commit -m "added sub and file" && - mkdir -p deep/directory/hierachy && - git submodule add ./. deep/directory/hierachy/sub && + mkdir -p deep/directory/hierarchy && + git submodule add ./. deep/directory/hierarchy/sub && git commit -m "added another submodule" && git branch submodule ' @@ -485,8 +485,8 @@ test_expect_success 'moving a submodule in nested directories' ' # git status would fail if the update of linking git dir to # work dir of the submodule failed. git status && - git config -f ../.gitmodules submodule.deep/directory/hierachy/sub.path >../actual && - echo "directory/hierachy/sub" >../expect + git config -f ../.gitmodules submodule.deep/directory/hierarchy/sub.path >../actual && + echo "directory/hierarchy/sub" >../expect ) && test_cmp actual expect ' diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index f9b7d79af5..8b0f71a2ac 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -1202,10 +1202,17 @@ test_expect_success GPG,RFC1991 \ # try to sign with bad user.signingkey git config user.signingkey BobTheMouse test_expect_success GPG \ - 'git tag -s fails if gpg is misconfigured' \ + 'git tag -s fails if gpg is misconfigured (bad key)' \ 'test_must_fail git tag -s -m tail tag-gpg-failure' git config --unset user.signingkey +# try to produce invalid signature +test_expect_success GPG \ + 'git tag -s fails if gpg is misconfigured (bad signature format)' \ + 'test_config gpg.program echo && + test_must_fail git tag -s -m tail tag-gpg-failure' + + # try to verify without gpg: rm -rf gpghome diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh index e4fc5c826c..c8dc665f2f 100755 --- a/t/t7006-pager.sh +++ b/t/t7006-pager.sh @@ -49,6 +49,19 @@ test_expect_success TTY 'LESS and LV envvars are set for pagination' ' grep ^LV= pager-env.out ' +test_expect_success !MINGW,TTY 'LESS and LV envvars set by git-sh-setup' ' + ( + sane_unset LESS LV && + PAGER="env >pager-env.out; wc" && + export PAGER && + PATH="$(git --exec-path):$PATH" && + export PATH && + test_terminal sh -c ". git-sh-setup && git_pager" + ) && + grep ^LESS= pager-env.out && + grep ^LV= pager-env.out +' + test_expect_success TTY 'some commands do not use a pager' ' rm -f paginated.out && test_terminal git rev-list HEAD && diff --git a/t/t7011-skip-worktree-reading.sh b/t/t7011-skip-worktree-reading.sh index 88d60c1ce2..84f41451ec 100755 --- a/t/t7011-skip-worktree-reading.sh +++ b/t/t7011-skip-worktree-reading.sh @@ -23,17 +23,15 @@ S sub/1 H sub/2 EOF -NULL_SHA1=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 - setup_absent() { test -f 1 && rm 1 git update-index --remove 1 && - git update-index --add --cacheinfo 100644 $NULL_SHA1 1 && + git update-index --add --cacheinfo 100644 $EMPTY_BLOB 1 && git update-index --skip-worktree 1 } test_absent() { - echo "100644 $NULL_SHA1 0 1" > expected && + echo "100644 $EMPTY_BLOB 0 1" > expected && git ls-files --stage 1 > result && test_cmp expected result && test ! -f 1 @@ -42,12 +40,12 @@ test_absent() { setup_dirty() { git update-index --force-remove 1 && echo dirty > 1 && - git update-index --add --cacheinfo 100644 $NULL_SHA1 1 && + git update-index --add --cacheinfo 100644 $EMPTY_BLOB 1 && git update-index --skip-worktree 1 } test_dirty() { - echo "100644 $NULL_SHA1 0 1" > expected && + echo "100644 $EMPTY_BLOB 0 1" > expected && git ls-files --stage 1 > result && test_cmp expected result && echo dirty > expected @@ -120,7 +118,7 @@ test_expect_success 'grep with skip-worktree file' ' test "$(git grep --no-ext-grep test)" = "1:test" ' -echo ":000000 100644 $_z40 $NULL_SHA1 A 1" > expected +echo ":000000 100644 $_z40 $EMPTY_BLOB A 1" > expected test_expect_success 'diff-index does not examine skip-worktree absent entries' ' setup_absent && git diff-index HEAD -- 1 > result && diff --git a/t/t7012-skip-worktree-writing.sh b/t/t7012-skip-worktree-writing.sh index 9ceaa4049f..9d1abe50ef 100755 --- a/t/t7012-skip-worktree-writing.sh +++ b/t/t7012-skip-worktree-writing.sh @@ -53,17 +53,15 @@ test_expect_success 'read-tree removes worktree, dirty case' ' git update-index --no-skip-worktree added ' -NULL_SHA1=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 - setup_absent() { test -f 1 && rm 1 git update-index --remove 1 && - git update-index --add --cacheinfo 100644 $NULL_SHA1 1 && + git update-index --add --cacheinfo 100644 $EMPTY_BLOB 1 && git update-index --skip-worktree 1 } test_absent() { - echo "100644 $NULL_SHA1 0 1" > expected && + echo "100644 $EMPTY_BLOB 0 1" > expected && git ls-files --stage 1 > result && test_cmp expected result && test ! -f 1 @@ -72,12 +70,12 @@ test_absent() { setup_dirty() { git update-index --force-remove 1 && echo dirty > 1 && - git update-index --add --cacheinfo 100644 $NULL_SHA1 1 && + git update-index --add --cacheinfo 100644 $EMPTY_BLOB 1 && git update-index --skip-worktree 1 } test_dirty() { - echo "100644 $NULL_SHA1 0 1" > expected && + echo "100644 $EMPTY_BLOB 0 1" > expected && git ls-files --stage 1 > result && test_cmp expected result && echo dirty > expected diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh index 44bf1d84af..53cf42fac1 100755 --- a/t/t7060-wtstatus.sh +++ b/t/t7060-wtstatus.sh @@ -34,6 +34,7 @@ test_expect_success 'M/D conflict does not segfault' ' On branch side You have unmerged paths. (fix conflicts and run "git commit") + (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add/rm <file>..." as appropriate to mark resolution) @@ -138,6 +139,7 @@ test_expect_success 'status when conflicts with add and rm advice (deleted by th On branch master You have unmerged paths. (fix conflicts and run "git commit") + (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add/rm <file>..." as appropriate to mark resolution) @@ -171,6 +173,7 @@ test_expect_success 'status when conflicts with add and rm advice (both deleted) On branch conflict_second You have unmerged paths. (fix conflicts and run "git commit") + (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add/rm <file>..." as appropriate to mark resolution) @@ -195,6 +198,7 @@ test_expect_success 'status when conflicts with only rm advice (both deleted)' ' On branch conflict_second You have unmerged paths. (fix conflicts and run "git commit") + (use "git merge --abort" to abort the merge) Changes to be committed: @@ -228,4 +232,25 @@ test_expect_success 'status --branch with detached HEAD' ' test_i18ncmp expected actual ' +## Duplicate the above test and verify --porcelain=v1 arg parsing. +test_expect_success 'status --porcelain=v1 --branch with detached HEAD' ' + git reset --hard && + git checkout master^0 && + git status --branch --porcelain=v1 >actual && + cat >expected <<-EOF && + ## HEAD (no branch) + ?? .gitconfig + ?? actual + ?? expect + ?? expected + ?? mdconflict/ + EOF + test_i18ncmp expected actual +' + +## Verify parser error on invalid --porcelain argument. +test_expect_success 'status --porcelain=bogus' ' + test_must_fail git status --porcelain=bogus +' + test_done diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh index a971884cfd..0667bd9dd3 100755 --- a/t/t7063-status-untracked-cache.sh +++ b/t/t7063-status-untracked-cache.sh @@ -4,6 +4,20 @@ test_description='test untracked cache' . ./test-lib.sh +# On some filesystems (e.g. FreeBSD's ext2 and ufs) directory mtime +# is updated lazily after contents in the directory changes, which +# forces the untracked cache code to take the slow path. A test +# that wants to make sure that the fast path works correctly should +# call this helper to make mtime of the containing directory in sync +# with the reality before checking the fast path behaviour. +# +# See <20160803174522.5571-1-pclouds@gmail.com> if you want to know +# more. + +sync_mtime () { + find . -type d -ls >/dev/null +} + avoid_racy() { sleep 1 } @@ -53,7 +67,7 @@ A two EOF cat >../dump.expect <<EOF && -info/exclude e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 +info/exclude $EMPTY_BLOB core.excludesfile 0000000000000000000000000000000000000000 exclude_per_dir .gitignore flags 00000006 @@ -137,7 +151,7 @@ EOF test_expect_success 'verify untracked cache dump' ' test-dump-untracked-cache >../actual && cat >../expect <<EOF && -info/exclude e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 +info/exclude $EMPTY_BLOB core.excludesfile 0000000000000000000000000000000000000000 exclude_per_dir .gitignore flags 00000006 @@ -184,7 +198,7 @@ EOF test_expect_success 'verify untracked cache dump' ' test-dump-untracked-cache >../actual && cat >../expect <<EOF && -info/exclude e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 +info/exclude $EMPTY_BLOB core.excludesfile 0000000000000000000000000000000000000000 exclude_per_dir .gitignore flags 00000006 @@ -416,7 +430,8 @@ test_expect_success 'create/modify files, some of which are gitignored' ' echo four >done/four && # four is gitignored at a higher level echo five >done/five && # five is not gitignored echo test >base && #we need to ensure that the root dir is touched - rm base + rm base && + sync_mtime ' test_expect_success 'test sparse status with untracked cache' ' @@ -643,7 +658,7 @@ test_expect_success 'test ident field is working' ' cp -R done dthree dtwo four three ../other_worktree && GIT_WORK_TREE=../other_worktree git status 2>../err && echo "warning: Untracked cache is disabled on this system or location." >../expect && - test_cmp ../expect ../err + test_i18ncmp ../expect ../err ' test_done diff --git a/t/t7064-wtstatus-pv2.sh b/t/t7064-wtstatus-pv2.sh new file mode 100755 index 0000000000..3012a4d7c0 --- /dev/null +++ b/t/t7064-wtstatus-pv2.sh @@ -0,0 +1,593 @@ +#!/bin/sh + +test_description='git status --porcelain=v2 + +This test exercises porcelain V2 output for git status.' + + +. ./test-lib.sh + + +test_expect_success setup ' + test_tick && + git config core.autocrlf false && + echo x >file_x && + echo y >file_y && + echo z >file_z && + mkdir dir1 && + echo a >dir1/file_a && + echo b >dir1/file_b +' + +test_expect_success 'before initial commit, nothing added, only untracked' ' + cat >expect <<-EOF && + # branch.oid (initial) + # branch.head master + ? actual + ? dir1/ + ? expect + ? file_x + ? file_y + ? file_z + EOF + + git status --porcelain=v2 --branch --untracked-files=normal >actual && + test_cmp expect actual +' + +test_expect_success 'before initial commit, things added' ' + git add file_x file_y file_z dir1 && + OID_A=$(git hash-object -t blob -- dir1/file_a) && + OID_B=$(git hash-object -t blob -- dir1/file_b) && + OID_X=$(git hash-object -t blob -- file_x) && + OID_Y=$(git hash-object -t blob -- file_y) && + OID_Z=$(git hash-object -t blob -- file_z) && + + cat >expect <<-EOF && + # branch.oid (initial) + # branch.head master + 1 A. N... 000000 100644 100644 $_z40 $OID_A dir1/file_a + 1 A. N... 000000 100644 100644 $_z40 $OID_B dir1/file_b + 1 A. N... 000000 100644 100644 $_z40 $OID_X file_x + 1 A. N... 000000 100644 100644 $_z40 $OID_Y file_y + 1 A. N... 000000 100644 100644 $_z40 $OID_Z file_z + ? actual + ? expect + EOF + + git status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual +' + +test_expect_success 'before initial commit, things added (-z)' ' + lf_to_nul >expect <<-EOF && + # branch.oid (initial) + # branch.head master + 1 A. N... 000000 100644 100644 $_z40 $OID_A dir1/file_a + 1 A. N... 000000 100644 100644 $_z40 $OID_B dir1/file_b + 1 A. N... 000000 100644 100644 $_z40 $OID_X file_x + 1 A. N... 000000 100644 100644 $_z40 $OID_Y file_y + 1 A. N... 000000 100644 100644 $_z40 $OID_Z file_z + ? actual + ? expect + EOF + + git status -z --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual +' + +test_expect_success 'make first commit, comfirm HEAD oid and branch' ' + git commit -m initial && + H0=$(git rev-parse HEAD) && + cat >expect <<-EOF && + # branch.oid $H0 + # branch.head master + ? actual + ? expect + EOF + + git status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual +' + +test_expect_success 'after first commit, create unstaged changes' ' + echo x >>file_x && + OID_X1=$(git hash-object -t blob -- file_x) && + rm file_z && + H0=$(git rev-parse HEAD) && + + cat >expect <<-EOF && + # branch.oid $H0 + # branch.head master + 1 .M N... 100644 100644 100644 $OID_X $OID_X file_x + 1 .D N... 100644 100644 000000 $OID_Z $OID_Z file_z + ? actual + ? expect + EOF + + git status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual +' + +test_expect_success 'after first commit but omit untracked files and branch' ' + cat >expect <<-EOF && + 1 .M N... 100644 100644 100644 $OID_X $OID_X file_x + 1 .D N... 100644 100644 000000 $OID_Z $OID_Z file_z + EOF + + git status --porcelain=v2 --untracked-files=no >actual && + test_cmp expect actual +' + +test_expect_success 'after first commit, stage existing changes' ' + git add file_x && + git rm file_z && + H0=$(git rev-parse HEAD) && + + cat >expect <<-EOF && + # branch.oid $H0 + # branch.head master + 1 M. N... 100644 100644 100644 $OID_X $OID_X1 file_x + 1 D. N... 100644 000000 000000 $OID_Z $_z40 file_z + ? actual + ? expect + EOF + + git status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual +' + +test_expect_success 'rename causes 2 path lines' ' + git mv file_y renamed_y && + H0=$(git rev-parse HEAD) && + + q_to_tab >expect <<-EOF && + # branch.oid $H0 + # branch.head master + 1 M. N... 100644 100644 100644 $OID_X $OID_X1 file_x + 1 D. N... 100644 000000 000000 $OID_Z $_z40 file_z + 2 R. N... 100644 100644 100644 $OID_Y $OID_Y R100 renamed_yQfile_y + ? actual + ? expect + EOF + + git status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual +' + +test_expect_success 'rename causes 2 path lines (-z)' ' + H0=$(git rev-parse HEAD) && + + ## Lines use NUL path separator and line terminator, so double transform here. + q_to_nul <<-EOF | lf_to_nul >expect && + # branch.oid $H0 + # branch.head master + 1 M. N... 100644 100644 100644 $OID_X $OID_X1 file_x + 1 D. N... 100644 000000 000000 $OID_Z $_z40 file_z + 2 R. N... 100644 100644 100644 $OID_Y $OID_Y R100 renamed_yQfile_y + ? actual + ? expect + EOF + + git status --porcelain=v2 --branch --untracked-files=all -z >actual && + test_cmp expect actual +' + +test_expect_success 'make second commit, confirm clean and new HEAD oid' ' + git commit -m second && + H1=$(git rev-parse HEAD) && + + cat >expect <<-EOF && + # branch.oid $H1 + # branch.head master + ? actual + ? expect + EOF + + git status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual +' + +test_expect_success 'confirm ignored files are not printed' ' + test_when_finished "rm -f x.ign .gitignore" && + echo x.ign >.gitignore && + echo "ignore me" >x.ign && + + cat >expect <<-EOF && + ? .gitignore + ? actual + ? expect + EOF + + git status --porcelain=v2 --untracked-files=all >actual && + test_cmp expect actual +' + +test_expect_success 'ignored files are printed with --ignored' ' + test_when_finished "rm -f x.ign .gitignore" && + echo x.ign >.gitignore && + echo "ignore me" >x.ign && + + cat >expect <<-EOF && + ? .gitignore + ? actual + ? expect + ! x.ign + EOF + + git status --porcelain=v2 --ignored --untracked-files=all >actual && + test_cmp expect actual +' + +test_expect_success 'create and commit permanent ignore file' ' + cat >.gitignore <<-EOF && + actual* + expect* + EOF + + git add .gitignore && + git commit -m ignore_trash && + H1=$(git rev-parse HEAD) && + + cat >expect <<-EOF && + # branch.oid $H1 + # branch.head master + EOF + + git status --porcelain=v2 --branch >actual && + test_cmp expect actual +' + +test_expect_success 'verify --intent-to-add output' ' + test_when_finished "git rm -f intent1.add intent2.add" && + touch intent1.add && + echo test >intent2.add && + + git add --intent-to-add intent1.add intent2.add && + + cat >expect <<-EOF && + 1 AM N... 000000 100644 100644 $_z40 $EMPTY_BLOB intent1.add + 1 AM N... 000000 100644 100644 $_z40 $EMPTY_BLOB intent2.add + EOF + + git status --porcelain=v2 >actual && + test_cmp expect actual +' + +test_expect_success 'verify AA (add-add) conflict' ' + test_when_finished "git reset --hard" && + + git branch AA_A master && + git checkout AA_A && + echo "Branch AA_A" >conflict.txt && + OID_AA_A=$(git hash-object -t blob -- conflict.txt) && + git add conflict.txt && + git commit -m "branch aa_a" && + + git branch AA_B master && + git checkout AA_B && + echo "Branch AA_B" >conflict.txt && + OID_AA_B=$(git hash-object -t blob -- conflict.txt) && + git add conflict.txt && + git commit -m "branch aa_b" && + + git branch AA_M AA_B && + git checkout AA_M && + test_must_fail git merge AA_A && + + HM=$(git rev-parse HEAD) && + + cat >expect <<-EOF && + # branch.oid $HM + # branch.head AA_M + u AA N... 000000 100644 100644 100644 $_z40 $OID_AA_B $OID_AA_A conflict.txt + EOF + + git status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual +' + +test_expect_success 'verify UU (edit-edit) conflict' ' + test_when_finished "git reset --hard" && + + git branch UU_ANC master && + git checkout UU_ANC && + echo "Ancestor" >conflict.txt && + OID_UU_ANC=$(git hash-object -t blob -- conflict.txt) && + git add conflict.txt && + git commit -m "UU_ANC" && + + git branch UU_A UU_ANC && + git checkout UU_A && + echo "Branch UU_A" >conflict.txt && + OID_UU_A=$(git hash-object -t blob -- conflict.txt) && + git add conflict.txt && + git commit -m "branch uu_a" && + + git branch UU_B UU_ANC && + git checkout UU_B && + echo "Branch UU_B" >conflict.txt && + OID_UU_B=$(git hash-object -t blob -- conflict.txt) && + git add conflict.txt && + git commit -m "branch uu_b" && + + git branch UU_M UU_B && + git checkout UU_M && + test_must_fail git merge UU_A && + + HM=$(git rev-parse HEAD) && + + cat >expect <<-EOF && + # branch.oid $HM + # branch.head UU_M + u UU N... 100644 100644 100644 100644 $OID_UU_ANC $OID_UU_B $OID_UU_A conflict.txt + EOF + + git status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual +' + +test_expect_success 'verify upstream fields in branch header' ' + git checkout master && + test_when_finished "rm -rf sub_repo" && + git clone . sub_repo && + ( + ## Confirm local master tracks remote master. + cd sub_repo && + HUF=$(git rev-parse HEAD) && + + cat >expect <<-EOF && + # branch.oid $HUF + # branch.head master + # branch.upstream origin/master + # branch.ab +0 -0 + EOF + + git status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual && + + ## Test ahead/behind. + echo xyz >file_xyz && + git add file_xyz && + git commit -m xyz && + + HUF=$(git rev-parse HEAD) && + + cat >expect <<-EOF && + # branch.oid $HUF + # branch.head master + # branch.upstream origin/master + # branch.ab +1 -0 + EOF + + git status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual && + + ## Repeat the above but without --branch. + cat >expect <<-EOF && + EOF + + git status --porcelain=v2 --untracked-files=all >actual && + test_cmp expect actual && + + ## Test upstream-gone case. Fake this by pointing origin/master at + ## a non-existing commit. + OLD=$(git rev-parse origin/master) && + NEW=$_z40 && + mv .git/packed-refs .git/old-packed-refs && + sed "s/$OLD/$NEW/g" <.git/old-packed-refs >.git/packed-refs && + + HUF=$(git rev-parse HEAD) && + + cat >expect <<-EOF && + # branch.oid $HUF + # branch.head master + # branch.upstream origin/master + EOF + + git status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual + ) +' + +test_expect_success 'create and add submodule, submodule appears clean (A. S...)' ' + git checkout master && + git clone . sub_repo && + git clone . super_repo && + ( cd super_repo && + git submodule add ../sub_repo sub1 && + + ## Confirm stage/add of clean submodule. + HMOD=$(git hash-object -t blob -- .gitmodules) && + HSUP=$(git rev-parse HEAD) && + HSUB=$HSUP && + + cat >expect <<-EOF && + # branch.oid $HSUP + # branch.head master + # branch.upstream origin/master + # branch.ab +0 -0 + 1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules + 1 A. S... 000000 160000 160000 $_z40 $HSUB sub1 + EOF + + git status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual + ) +' + +test_expect_success 'untracked changes in added submodule (AM S..U)' ' + ( cd super_repo && + ## create untracked file in the submodule. + ( cd sub1 && + echo "xxxx" >file_in_sub + ) && + + HMOD=$(git hash-object -t blob -- .gitmodules) && + HSUP=$(git rev-parse HEAD) && + HSUB=$HSUP && + + cat >expect <<-EOF && + # branch.oid $HSUP + # branch.head master + # branch.upstream origin/master + # branch.ab +0 -0 + 1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules + 1 AM S..U 000000 160000 160000 $_z40 $HSUB sub1 + EOF + + git status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual + ) +' + +test_expect_success 'staged changes in added submodule (AM S.M.)' ' + ( cd super_repo && + ## stage the changes in the submodule. + ( cd sub1 && + git add file_in_sub + ) && + + HMOD=$(git hash-object -t blob -- .gitmodules) && + HSUP=$(git rev-parse HEAD) && + HSUB=$HSUP && + + cat >expect <<-EOF && + # branch.oid $HSUP + # branch.head master + # branch.upstream origin/master + # branch.ab +0 -0 + 1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules + 1 AM S.M. 000000 160000 160000 $_z40 $HSUB sub1 + EOF + + git status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual + ) +' + +test_expect_success 'staged and unstaged changes in added (AM S.M.)' ' + ( cd super_repo && + ( cd sub1 && + ## make additional unstaged changes (on the same file) in the submodule. + ## This does not cause us to get S.MU (because the submodule does not report + ## a "?" line for the unstaged changes). + echo "more changes" >>file_in_sub + ) && + + HMOD=$(git hash-object -t blob -- .gitmodules) && + HSUP=$(git rev-parse HEAD) && + HSUB=$HSUP && + + cat >expect <<-EOF && + # branch.oid $HSUP + # branch.head master + # branch.upstream origin/master + # branch.ab +0 -0 + 1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules + 1 AM S.M. 000000 160000 160000 $_z40 $HSUB sub1 + EOF + + git status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual + ) +' + +test_expect_success 'staged and untracked changes in added submodule (AM S.MU)' ' + ( cd super_repo && + ( cd sub1 && + ## stage new changes in tracked file. + git add file_in_sub && + ## create new untracked file. + echo "yyyy" >>another_file_in_sub + ) && + + HMOD=$(git hash-object -t blob -- .gitmodules) && + HSUP=$(git rev-parse HEAD) && + HSUB=$HSUP && + + cat >expect <<-EOF && + # branch.oid $HSUP + # branch.head master + # branch.upstream origin/master + # branch.ab +0 -0 + 1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules + 1 AM S.MU 000000 160000 160000 $_z40 $HSUB sub1 + EOF + + git status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual + ) +' + +test_expect_success 'commit within the submodule appears as new commit in super (AM SC..)' ' + ( cd super_repo && + ( cd sub1 && + ## Make a new commit in the submodule. + git add file_in_sub && + rm -f another_file_in_sub && + git commit -m "new commit" + ) && + + HMOD=$(git hash-object -t blob -- .gitmodules) && + HSUP=$(git rev-parse HEAD) && + HSUB=$HSUP && + + cat >expect <<-EOF && + # branch.oid $HSUP + # branch.head master + # branch.upstream origin/master + # branch.ab +0 -0 + 1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules + 1 AM SC.. 000000 160000 160000 $_z40 $HSUB sub1 + EOF + + git status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual + ) +' + +test_expect_success 'stage submodule in super and commit' ' + ( cd super_repo && + ## Stage the new submodule commit in the super. + git add sub1 && + ## Commit the super so that the sub no longer appears as added. + git commit -m "super commit" && + + HSUP=$(git rev-parse HEAD) && + + cat >expect <<-EOF && + # branch.oid $HSUP + # branch.head master + # branch.upstream origin/master + # branch.ab +1 -0 + EOF + + git status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual + ) +' + +test_expect_success 'make unstaged changes in existing submodule (.M S.M.)' ' + ( cd super_repo && + ( cd sub1 && + echo "zzzz" >>file_in_sub + ) && + + HSUP=$(git rev-parse HEAD) && + HSUB=$(cd sub1 && git rev-parse HEAD) && + + cat >expect <<-EOF && + # branch.oid $HSUP + # branch.head master + # branch.upstream origin/master + # branch.ab +1 -0 + 1 .M S.M. 160000 160000 160000 $HSUB $HSUB sub1 + EOF + + git status --porcelain=v2 --branch --untracked-files=all >actual && + test_cmp expect actual + ) +' + +test_done diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh index 98bcfe21aa..86f23be34a 100755 --- a/t/t7102-reset.sh +++ b/t/t7102-reset.sh @@ -66,14 +66,14 @@ test_expect_success 'reset --hard message' ' hex=$(git log -1 --format="%h") && git reset --hard > .actual && echo HEAD is now at $hex $(commit_msg) > .expected && - test_cmp .expected .actual + test_i18ncmp .expected .actual ' test_expect_success 'reset --hard message (ISO8859-1 logoutputencoding)' ' hex=$(git log -1 --format="%h") && git -c "i18n.logOutputEncoding=$test_encoding" reset --hard > .actual && echo HEAD is now at $hex $(commit_msg $test_encoding) > .expected && - test_cmp .expected .actual + test_i18ncmp .expected .actual ' >.diff_expect diff --git a/t/t7201-co.sh b/t/t7201-co.sh index 885923610a..d4b217b0ee 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -257,7 +257,7 @@ test_expect_success 'checkout to detach HEAD' ' git checkout -f renamer && git clean -f && git checkout renamer^ 2>messages && test_i18ngrep "HEAD is now at 7329388" messages && - test_line_count -gt 1 messages && + (test_line_count -gt 1 messages || test -n "$GETTEXT_POISON") && H=$(git rev-parse --verify HEAD) && M=$(git show-ref -s --verify refs/heads/master) && test "z$H" = "z$M" && diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index 3570f7bb8c..b77cce8e40 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -942,7 +942,7 @@ test_expect_success 'submodule deinit from subdirectory' ' cd sub && git submodule deinit ../init >../output ) && - grep "\\.\\./init" output && + test_i18ngrep "\\.\\./init" output && test -z "$(git config --get-regexp "submodule\.example\.")" && test -n "$(git config --get-regexp "submodule\.example2\.")" && test -f example2/.git && diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh index 5503ec067f..0726799e74 100755 --- a/t/t7403-submodule-sync.sh +++ b/t/t7403-submodule-sync.sh @@ -157,7 +157,7 @@ test_expect_success '"git submodule sync" should update submodule URLs - subdire cd sub && git submodule sync >../../output ) && - grep "\\.\\./submodule" output && + test_i18ngrep "\\.\\./submodule" output && test -d "$( cd super-clone/submodule && git config remote.origin.url @@ -188,7 +188,7 @@ test_expect_success '"git submodule sync --recursive" should update all submodul cd sub && git submodule sync --recursive >../../output ) && - grep "\\.\\./submodule/sub-submodule" output && + test_i18ngrep "\\.\\./submodule/sub-submodule" output && test -d "$( cd super-clone/submodule && git config remote.origin.url diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index 5f278799d5..64f322c4cc 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -136,8 +136,8 @@ test_expect_success 'submodule update --init --recursive from subdirectory' ' cd tmp && git submodule update --init --recursive ../super >../../actual 2>../../actual2 ) && - test_cmp expect actual && - test_cmp expect2 actual2 + test_i18ncmp expect actual && + test_i18ncmp expect2 actual2 ' apos="'"; @@ -209,9 +209,42 @@ test_expect_success 'submodule update --remote should fetch upstream changes' ' ) ' +test_expect_success 'submodule update --remote should fetch upstream changes with .' ' + ( + cd super && + git config -f .gitmodules submodule."submodule".branch "." && + git add .gitmodules && + git commit -m "submodules: update from the respective superproject branch" + ) && + ( + cd submodule && + echo line4a >> file && + git add file && + test_tick && + git commit -m "upstream line4a" && + git checkout -b test-branch && + test_commit on-test-branch + ) && + ( + cd super && + git submodule update --remote --force submodule && + git -C submodule log -1 --oneline >actual + git -C ../submodule log -1 --oneline master >expect + test_cmp expect actual && + git checkout -b test-branch && + git submodule update --remote --force submodule && + git -C submodule log -1 --oneline >actual + git -C ../submodule log -1 --oneline test-branch >expect + test_cmp expect actual && + git checkout master && + git branch -d test-branch && + git reset --hard HEAD^ + ) +' + test_expect_success 'local config should override .gitmodules branch' ' (cd submodule && - git checkout -b test-branch && + git checkout test-branch && echo line5 >> file && git add file && test_tick && @@ -370,7 +403,7 @@ test_expect_success 'submodule update - command in .git/config catches failure' (cd super && test_must_fail git submodule update submodule 2>../actual ) && - test_cmp actual expect + test_i18ncmp actual expect ' cat << EOF >expect @@ -388,7 +421,7 @@ test_expect_success 'submodule update - command in .git/config catches failure - mkdir tmp && cd tmp && test_must_fail git submodule update ../submodule 2>../../actual ) && - test_cmp actual expect + test_i18ncmp actual expect ' cat << EOF >expect @@ -408,7 +441,7 @@ test_expect_success 'recursive submodule update - command in .git/config catches mkdir -p tmp && cd tmp && test_must_fail git submodule update --recursive ../super 2>../../actual ) && - test_cmp actual expect + test_i18ncmp actual expect ' test_expect_success 'submodule init does not copy command into .git/config' ' @@ -841,16 +874,35 @@ test_expect_success SYMLINKS 'submodule update can handle symbolic links in pwd' ' test_expect_success 'submodule update clone shallow submodule' ' + test_when_finished "rm -rf super3" && + first=$(git -C cloned submodule status submodule |cut -c2-41) && + second=$(git -C submodule rev-parse HEAD) && + commit_count=$(git -C submodule rev-list --count $first^..$second) && git clone cloned super3 && pwd=$(pwd) && - (cd super3 && - sed -e "s#url = ../#url = file://$pwd/#" <.gitmodules >.gitmodules.tmp && - mv -f .gitmodules.tmp .gitmodules && - git submodule update --init --depth=3 - (cd submodule && - test 1 = $(git log --oneline | wc -l) - ) -) + ( + cd super3 && + sed -e "s#url = ../#url = file://$pwd/#" <.gitmodules >.gitmodules.tmp && + mv -f .gitmodules.tmp .gitmodules && + git submodule update --init --depth=$commit_count && + test 1 = $(git -C submodule log --oneline | wc -l) + ) +' + +test_expect_success 'submodule update clone shallow submodule outside of depth' ' + test_when_finished "rm -rf super3" && + git clone cloned super3 && + pwd=$(pwd) && + ( + cd super3 && + sed -e "s#url = ../#url = file://$pwd/#" <.gitmodules >.gitmodules.tmp && + mv -f .gitmodules.tmp .gitmodules && + test_must_fail git submodule update --init --depth=1 2>actual && + test_i18ngrep "Direct fetching of that commit failed." actual && + git -C ../submodule config uploadpack.allowReachableSHA1InWant true && + git submodule update --init --depth=1 >actual && + test 1 = $(git -C submodule log --oneline | wc -l) + ) ' test_expect_success 'submodule update --recursive drops module name before recursing' ' diff --git a/t/t7408-submodule-reference.sh b/t/t7408-submodule-reference.sh index eaea19b8f2..1c1e289ffd 100755 --- a/t/t7408-submodule-reference.sh +++ b/t/t7408-submodule-reference.sh @@ -8,74 +8,121 @@ test_description='test clone --reference' base_dir=$(pwd) -U=$base_dir/UPLOAD_LOG - -test_expect_success 'preparing first repository' \ -'test_create_repo A && cd A && -echo first > file1 && -git add file1 && -git commit -m A-initial' - -cd "$base_dir" - -test_expect_success 'preparing second repository' \ -'git clone A B && cd B && -echo second > file2 && -git add file2 && -git commit -m B-addition && -git repack -a -d && -git prune' - -cd "$base_dir" - -test_expect_success 'preparing superproject' \ -'test_create_repo super && cd super && -echo file > file && -git add file && -git commit -m B-super-initial' - -cd "$base_dir" - -test_expect_success 'submodule add --reference' \ -'cd super && git submodule add --reference ../B "file://$base_dir/A" sub && -git commit -m B-super-added' - -cd "$base_dir" - -test_expect_success 'after add: existence of info/alternates' \ -'test_line_count = 1 super/.git/modules/sub/objects/info/alternates' - -cd "$base_dir" - -test_expect_success 'that reference gets used with add' \ -'cd super/sub && -echo "0 objects, 0 kilobytes" > expected && -git count-objects > current && -diff expected current' - -cd "$base_dir" - -test_expect_success 'cloning superproject' \ -'git clone super super-clone' - -cd "$base_dir" - -test_expect_success 'update with reference' \ -'cd super-clone && git submodule update --init --reference ../B' - -cd "$base_dir" - -test_expect_success 'after update: existence of info/alternates' \ -'test_line_count = 1 super-clone/.git/modules/sub/objects/info/alternates' - -cd "$base_dir" - -test_expect_success 'that reference gets used with update' \ -'cd super-clone/sub && -echo "0 objects, 0 kilobytes" > expected && -git count-objects > current && -diff expected current' - -cd "$base_dir" +test_alternate_is_used () { + alternates_file="$1" && + working_dir="$2" && + test_line_count = 1 "$alternates_file" && + echo "0 objects, 0 kilobytes" >expect && + git -C "$working_dir" count-objects >actual && + test_cmp expect actual +} + +test_expect_success 'preparing first repository' ' + test_create_repo A && + ( + cd A && + echo first >file1 && + git add file1 && + git commit -m A-initial + ) +' + +test_expect_success 'preparing second repository' ' + git clone A B && + ( + cd B && + echo second >file2 && + git add file2 && + git commit -m B-addition && + git repack -a -d && + git prune + ) +' + +test_expect_success 'preparing superproject' ' + test_create_repo super && + ( + cd super && + echo file >file && + git add file && + git commit -m B-super-initial + ) +' + +test_expect_success 'submodule add --reference uses alternates' ' + ( + cd super && + git submodule add --reference ../B "file://$base_dir/A" sub && + git commit -m B-super-added && + git repack -ad + ) && + test_alternate_is_used super/.git/modules/sub/objects/info/alternates super/sub +' + +test_expect_success 'that reference gets used with add' ' + ( + cd super/sub && + echo "0 objects, 0 kilobytes" >expected && + git count-objects >current && + diff expected current + ) +' + +# The tests up to this point, and repositories created by them +# (A, B, super and super/sub), are about setting up the stage +# for subsequent tests and meant to be kept throughout the +# remainder of the test. +# Tests from here on, if they create their own test repository, +# are expected to clean after themselves. + +test_expect_success 'updating superproject keeps alternates' ' + test_when_finished "rm -rf super-clone" && + git clone super super-clone && + git -C super-clone submodule update --init --reference ../B && + test_alternate_is_used super-clone/.git/modules/sub/objects/info/alternates super-clone/sub +' + +test_expect_success 'submodules use alternates when cloning a superproject' ' + test_when_finished "rm -rf super-clone" && + git clone --reference super --recursive super super-clone && + ( + cd super-clone && + # test superproject has alternates setup correctly + test_alternate_is_used .git/objects/info/alternates . && + # test submodule has correct setup + test_alternate_is_used .git/modules/sub/objects/info/alternates sub + ) +' + +test_expect_success 'missing submodule alternate fails clone and submodule update' ' + test_when_finished "rm -rf super-clone" && + git clone super super2 && + test_must_fail git clone --recursive --reference super2 super2 super-clone && + ( + cd super-clone && + # test superproject has alternates setup correctly + test_alternate_is_used .git/objects/info/alternates . && + # update of the submodule succeeds + test_must_fail git submodule update --init && + # and we have no alternates: + test_must_fail test_alternate_is_used .git/modules/sub/objects/info/alternates sub && + test_must_fail test_path_is_file sub/file1 + ) +' + +test_expect_success 'ignoring missing submodule alternates passes clone and submodule update' ' + test_when_finished "rm -rf super-clone" && + git clone --reference-if-able super2 --recursive super2 super-clone && + ( + cd super-clone && + # test superproject has alternates setup correctly + test_alternate_is_used .git/objects/info/alternates . && + # update of the submodule succeeds + git submodule update --init && + # and we have no alternates: + test_must_fail test_alternate_is_used .git/modules/sub/objects/info/alternates sub && + test_path_is_file sub/file1 + ) +' test_done diff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh index fc97c3314e..47562ce465 100755 --- a/t/t7411-submodule-config.sh +++ b/t/t7411-submodule-config.sh @@ -82,6 +82,17 @@ test_expect_success 'error in one submodule config lets continue' ' ) ' +test_expect_success 'error message contains blob reference' ' + (cd super && + sha1=$(git rev-parse HEAD) && + test-submodule-config \ + HEAD b \ + HEAD submodule \ + 2>actual_err && + test_i18ngrep "submodule-blob $sha1:.gitmodules" actual_err >/dev/null + ) +' + cat >super/expect_url <<EOF Submodule url: 'git@somewhere.else.net:a.git' for path 'b' Submodule url: 'git@somewhere.else.net:submodule.git' for path 'submodule' diff --git a/t/t7508-status.sh b/t/t7508-status.sh index c3ed7cb51c..fb00e6d9b0 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -803,7 +803,7 @@ EOF ' cat >expect <<EOF -:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 M dir1/modified +:100644 100644 $EMPTY_BLOB 0000000000000000000000000000000000000000 M dir1/modified EOF test_expect_success 'status refreshes the index' ' touch dir2/added && @@ -1377,7 +1377,7 @@ EOF git config --add -f .gitmodules submodule.subname.ignore all && git config --add -f .gitmodules submodule.subname.path sm && git status > output && - test_cmp expect output && + test_i18ncmp expect output && git config -f .gitmodules --remove-section submodule.subname ' @@ -1387,7 +1387,7 @@ test_expect_success '.git/config ignore=all suppresses unstaged submodule summar git config --add submodule.subname.ignore all && git config --add submodule.subname.path sm && git status > output && - test_cmp expect output && + test_i18ncmp expect output && git config --remove-section submodule.subname && git config -f .gitmodules --remove-section submodule.subname ' diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh index 4177a8609a..6e839f5489 100755 --- a/t/t7510-signed-commit.sh +++ b/t/t7510-signed-commit.sh @@ -210,4 +210,11 @@ test_expect_success GPG 'show lack of signature with custom format' ' test_cmp expect actual ' +test_expect_success GPG 'log.showsignature behaves like --show-signature' ' + test_config log.showsignature true && + git show initial >actual && + grep "gpg: Signature made" actual && + grep "gpg: Good signature" actual +' + test_done diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh index 49d19a3b36..5c3db656df 100755 --- a/t/t7512-status-help.sh +++ b/t/t7512-status-help.sh @@ -29,6 +29,7 @@ test_expect_success 'status when conflicts unresolved' ' On branch conflicts You have unmerged paths. (fix conflicts and run "git commit") + (use "git merge --abort" to abort the merge) Unmerged paths: (use "git add <file>..." to mark resolution) diff --git a/t/t7517-per-repo-email.sh b/t/t7517-per-repo-email.sh index 337e6e30c3..2a22fa7588 100755 --- a/t/t7517-per-repo-email.sh +++ b/t/t7517-per-repo-email.sh @@ -36,4 +36,51 @@ test_expect_success 'succeeds cloning if global email is not set' ' git clone . clone ' +test_expect_success 'set up rebase scenarios' ' + # temporarily enable an actual ident for this setup + test_config user.email foo@example.com && + test_commit new && + git branch side-without-commit HEAD^ && + git checkout -b side-with-commit HEAD^ && + test_commit side +' + +test_expect_success 'fast-forward rebase does not care about ident' ' + git checkout -B tmp side-without-commit && + git rebase master +' + +test_expect_success 'non-fast-forward rebase refuses to write commits' ' + test_when_finished "git rebase --abort || true" && + git checkout -B tmp side-with-commit && + test_must_fail git rebase master +' + +test_expect_success 'fast-forward rebase does not care about ident (interactive)' ' + git checkout -B tmp side-without-commit && + git rebase -i master +' + +test_expect_success 'non-fast-forward rebase refuses to write commits (interactive)' ' + test_when_finished "git rebase --abort || true" && + git checkout -B tmp side-with-commit && + test_must_fail git rebase -i master +' + +test_expect_success 'noop interactive rebase does not care about ident' ' + git checkout -B tmp side-with-commit && + git rebase -i HEAD^ +' + +test_expect_success 'fast-forward rebase does not care about ident (preserve)' ' + git checkout -B tmp side-without-commit && + git rebase -p master +' + +test_expect_success 'non-fast-forward rebase refuses to write commits (preserve)' ' + test_when_finished "git rebase --abort || true" && + git checkout -B tmp side-with-commit && + test_must_fail git rebase -p master +' + test_done diff --git a/t/t7607-merge-overwrite.sh b/t/t7607-merge-overwrite.sh index 758a623cdb..9444d6a9b9 100755 --- a/t/t7607-merge-overwrite.sh +++ b/t/t7607-merge-overwrite.sh @@ -115,7 +115,7 @@ cat >expect <<\EOF error: The following untracked working tree files would be overwritten by merge: sub sub2 -Please move or remove them before you can merge. +Please move or remove them before you merge. Aborting EOF @@ -125,7 +125,7 @@ test_expect_success 'will not overwrite untracked file in leading path' ' cp important sub && cp important sub2 && test_must_fail git merge sub 2>out && - test_cmp out expect && + test_i18ncmp out expect && test_path_is_missing .git/MERGE_HEAD && test_cmp important sub && test_cmp important sub2 && diff --git a/t/t7609-merge-co-error-msgs.sh b/t/t7609-merge-co-error-msgs.sh index 6729cb379f..f80bdb81e1 100755 --- a/t/t7609-merge-co-error-msgs.sh +++ b/t/t7609-merge-co-error-msgs.sh @@ -31,7 +31,7 @@ error: The following untracked working tree files would be overwritten by merge: four three two -Please move or remove them before you can merge. +Please move or remove them before you merge. Aborting EOF @@ -53,10 +53,10 @@ error: Your local changes to the following files would be overwritten by merge: four three two -Please commit your changes or stash them before you can merge. +Please commit your changes or stash them before you merge. error: The following untracked working tree files would be overwritten by merge: five -Please move or remove them before you can merge. +Please move or remove them before you merge. Aborting EOF @@ -72,7 +72,7 @@ cat >expect <<\EOF error: Your local changes to the following files would be overwritten by checkout: rep/one rep/two -Please commit your changes or stash them before you can switch branches. +Please commit your changes or stash them before you switch branches. Aborting EOF @@ -94,7 +94,7 @@ cat >expect <<\EOF error: Your local changes to the following files would be overwritten by checkout: rep/one rep/two -Please commit your changes or stash them before you can switch branches. +Please commit your changes or stash them before you switch branches. Aborting EOF diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh index 76306cf268..7217f3968d 100755 --- a/t/t7610-mergetool.sh +++ b/t/t7610-mergetool.sh @@ -589,7 +589,12 @@ test_expect_success 'filenames seen by tools start with ./' ' git reset --hard master >/dev/null 2>&1 ' -test_expect_success 'temporary filenames are used with mergetool.writeToTemp' ' +test_lazy_prereq MKTEMP ' + tempdir=$(mktemp -d -t foo.XXXXXX) && + test -d "$tempdir" +' + +test_expect_success MKTEMP 'temporary filenames are used with mergetool.writeToTemp' ' git checkout -b test16 branch1 && test_config mergetool.writeToTemp true && test_config mergetool.myecho.cmd "echo \"\$LOCAL\"" && diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh index b66e383866..987573c41f 100755 --- a/t/t7701-repack-unpack-unreachable.sh +++ b/t/t7701-repack-unpack-unreachable.sh @@ -122,4 +122,32 @@ test_expect_success 'keep packed objects found only in index' ' git cat-file blob :file ' +test_expect_success 'repack -k keeps unreachable packed objects' ' + # create packed-but-unreachable object + sha1=$(echo unreachable-packed | git hash-object -w --stdin) && + pack=$(echo $sha1 | git pack-objects .git/objects/pack/pack) && + git prune-packed && + + # -k should keep it + git repack -adk && + git cat-file -p $sha1 && + + # and double check that without -k it would have been removed + git repack -ad && + test_must_fail git cat-file -p $sha1 +' + +test_expect_success 'repack -k packs unreachable loose objects' ' + # create loose unreachable object + sha1=$(echo would-be-deleted-loose | git hash-object -w --stdin) && + objpath=.git/objects/$(echo $sha1 | sed "s,..,&/,") && + test_path_is_file $objpath && + + # and confirm that the loose object goes away, but we can + # still access it (ergo, it is packed) + git repack -adk && + test_path_is_missing $objpath && + git cat-file -p $sha1 +' + test_done diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh index 7ce4cd753e..70a2de461a 100755 --- a/t/t7800-difftool.sh +++ b/t/t7800-difftool.sh @@ -124,6 +124,12 @@ test_expect_success PERL 'difftool stops on error with --trust-exit-code' ' test_cmp expect actual ' +test_expect_success PERL 'difftool honors exit status if command not found' ' + test_config difftool.nonexistent.cmd i-dont-exist && + test_config difftool.trustExitCode false && + test_must_fail git difftool -y -t nonexistent branch +' + test_expect_success PERL 'difftool honors --gui' ' difftool_test_setup && test_config merge.tool bogus-tool && @@ -412,6 +418,20 @@ run_dir_diff_test 'difftool --dir-diff from subdirectory' ' ) ' +run_dir_diff_test 'difftool --dir-diff from subdirectory with GIT_DIR set' ' + ( + GIT_DIR=$(pwd)/.git && + export GIT_DIR && + GIT_WORK_TREE=$(pwd) && + export GIT_WORK_TREE && + cd sub && + git difftool --dir-diff $symlinks --extcmd ls \ + branch -- sub >output && + grep sub output && + ! grep file output + ) +' + run_dir_diff_test 'difftool --dir-diff when worktree file is missing' ' test_when_finished git reset --hard && rm file2 && @@ -446,7 +466,7 @@ write_script .git/CHECK_SYMLINKS <<\EOF for f in file file2 sub/sub do echo "$f" - readlink "$2/$f" + ls -ld "$2/$f" | sed -e 's/.* -> //' done >actual EOF diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index 960425a4ec..de2405ccba 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -177,7 +177,7 @@ do test_expect_success "grep -c $L (no /dev/null)" ' ! git grep -c test $H | grep /dev/null - ' + ' test_expect_success "grep --max-depth -1 $L" ' { @@ -355,7 +355,7 @@ test_expect_success 'grep -l -C' ' cat >expected <<EOF file:5 EOF -test_expect_success 'grep -l -C' ' +test_expect_success 'grep -c -C' ' git grep -c -C1 foo >actual && test_cmp expected actual ' @@ -581,7 +581,7 @@ test_expect_success 'log grep (9)' ' ' test_expect_success 'log grep (9)' ' - git log -g --grep-reflog="commit: third" --author="non-existant" --pretty=tformat:%s >actual && + git log -g --grep-reflog="commit: third" --author="non-existent" --pretty=tformat:%s >actual && : >expect && test_cmp expect actual ' @@ -1377,4 +1377,62 @@ test_expect_success 'grep --color -e A --and -e B -p with context' ' test_cmp expected actual ' +test_expect_success 'grep can find things only in the work tree' ' + : >work-tree-only && + git add work-tree-only && + test_when_finished "git rm -f work-tree-only" && + echo "find in work tree" >work-tree-only && + git grep --quiet "find in work tree" && + test_must_fail git grep --quiet --cached "find in work tree" && + test_must_fail git grep --quiet "find in work tree" HEAD +' + +test_expect_success 'grep can find things only in the work tree (i-t-a)' ' + echo "intend to add this" >intend-to-add && + git add -N intend-to-add && + test_when_finished "git rm -f intend-to-add" && + git grep --quiet "intend to add this" && + test_must_fail git grep --quiet --cached "intend to add this" && + test_must_fail git grep --quiet "intend to add this" HEAD +' + +test_expect_success 'grep does not search work tree with assume unchanged' ' + echo "intend to add this" >intend-to-add && + git add -N intend-to-add && + git update-index --assume-unchanged intend-to-add && + test_when_finished "git rm -f intend-to-add" && + test_must_fail git grep --quiet "intend to add this" && + test_must_fail git grep --quiet --cached "intend to add this" && + test_must_fail git grep --quiet "intend to add this" HEAD +' + +test_expect_success 'grep can find things only in the index' ' + echo "only in the index" >cache-this && + git add cache-this && + rm cache-this && + test_when_finished "git rm --cached cache-this" && + test_must_fail git grep --quiet "only in the index" && + git grep --quiet --cached "only in the index" && + test_must_fail git grep --quiet "only in the index" HEAD +' + +test_expect_success 'grep does not report i-t-a with -L --cached' ' + echo "intend to add this" >intend-to-add && + git add -N intend-to-add && + test_when_finished "git rm -f intend-to-add" && + git ls-files | grep -v "^intend-to-add\$" >expected && + git grep -L --cached "nonexistent_string" >actual && + test_cmp expected actual +' + +test_expect_success 'grep does not report i-t-a and assume unchanged with -L' ' + echo "intend to add this" >intend-to-add-assume-unchanged && + git add -N intend-to-add-assume-unchanged && + test_when_finished "git rm -f intend-to-add-assume-unchanged" && + git update-index --assume-unchanged intend-to-add-assume-unchanged && + git ls-files | grep -v "^intend-to-add-assume-unchanged\$" >expected && + git grep -L "nonexistent_string" >actual && + test_cmp expected actual +' + test_done diff --git a/t/t7812-grep-icase-non-ascii.sh b/t/t7812-grep-icase-non-ascii.sh new file mode 100755 index 0000000000..169fd8d706 --- /dev/null +++ b/t/t7812-grep-icase-non-ascii.sh @@ -0,0 +1,71 @@ +#!/bin/sh + +test_description='grep icase on non-English locales' + +. ./lib-gettext.sh + +test_expect_success GETTEXT_LOCALE 'setup' ' + test_write_lines "TILRAUN: Halló Heimur!" >file && + git add file && + LC_ALL="$is_IS_locale" && + export LC_ALL +' + +test_have_prereq GETTEXT_LOCALE && +test-regex "HALLÓ" "Halló" ICASE && +test_set_prereq REGEX_LOCALE + +test_expect_success REGEX_LOCALE 'grep literal string, no -F' ' + git grep -i "TILRAUN: Halló Heimur!" && + git grep -i "TILRAUN: HALLÓ HEIMUR!" +' + +test_expect_success GETTEXT_LOCALE,LIBPCRE 'grep pcre utf-8 icase' ' + git grep --perl-regexp "TILRAUN: H.lló Heimur!" && + git grep --perl-regexp -i "TILRAUN: H.lló Heimur!" && + git grep --perl-regexp -i "TILRAUN: H.LLÓ HEIMUR!" +' + +test_expect_success GETTEXT_LOCALE,LIBPCRE 'grep pcre utf-8 string with "+"' ' + test_write_lines "TILRAUN: Hallóó Heimur!" >file2 && + git add file2 && + git grep -l --perl-regexp "TILRAUN: H.lló+ Heimur!" >actual && + echo file >expected && + echo file2 >>expected && + test_cmp expected actual +' + +test_expect_success REGEX_LOCALE 'grep literal string, with -F' ' + git grep --debug -i -F "TILRAUN: Halló Heimur!" 2>&1 >/dev/null | + grep fixed >debug1 && + test_write_lines "fixed TILRAUN: Halló Heimur!" >expect1 && + test_cmp expect1 debug1 && + + git grep --debug -i -F "TILRAUN: HALLÓ HEIMUR!" 2>&1 >/dev/null | + grep fixed >debug2 && + test_write_lines "fixed TILRAUN: HALLÓ HEIMUR!" >expect2 && + test_cmp expect2 debug2 +' + +test_expect_success REGEX_LOCALE 'grep string with regex, with -F' ' + test_write_lines "^*TILR^AUN:.* \\Halló \$He[]imur!\$" >file && + + git grep --debug -i -F "^*TILR^AUN:.* \\Halló \$He[]imur!\$" 2>&1 >/dev/null | + grep fixed >debug1 && + test_write_lines "fixed \\^*TILR^AUN:\\.\\* \\\\Halló \$He\\[]imur!\\\$" >expect1 && + test_cmp expect1 debug1 && + + git grep --debug -i -F "^*TILR^AUN:.* \\HALLÓ \$HE[]IMUR!\$" 2>&1 >/dev/null | + grep fixed >debug2 && + test_write_lines "fixed \\^*TILR^AUN:\\.\\* \\\\HALLÓ \$HE\\[]IMUR!\\\$" >expect2 && + test_cmp expect2 debug2 +' + +test_expect_success REGEX_LOCALE 'pickaxe -i on non-ascii' ' + git commit -m first && + git log --format=%f -i -S"TILRAUN: HALLÓ HEIMUR!" >actual && + echo first >expected && + test_cmp expected actual +' + +test_done diff --git a/t/t7813-grep-icase-iso.sh b/t/t7813-grep-icase-iso.sh new file mode 100755 index 0000000000..efef7fb81f --- /dev/null +++ b/t/t7813-grep-icase-iso.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +test_description='grep icase on non-English locales' + +. ./lib-gettext.sh + +test_expect_success GETTEXT_ISO_LOCALE 'setup' ' + printf "TILRAUN: Halló Heimur!" >file && + git add file && + LC_ALL="$is_IS_iso_locale" && + export LC_ALL +' + +test_expect_success GETTEXT_ISO_LOCALE,LIBPCRE 'grep pcre string' ' + git grep --perl-regexp -i "TILRAUN: H.lló Heimur!" && + git grep --perl-regexp -i "TILRAUN: H.LLÓ HEIMUR!" +' + +test_done diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh index ff09aced68..ab79de9544 100755 --- a/t/t8002-blame.sh +++ b/t/t8002-blame.sh @@ -6,6 +6,11 @@ test_description='git blame' PROG='git blame -c' . "$TEST_DIRECTORY"/annotate-tests.sh +test_expect_success 'blame untracked file in empty repo' ' + >untracked && + test_must_fail git blame untracked +' + PROG='git blame -c -e' test_expect_success 'blame --show-email' ' check_count \ diff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh index a9b266f0d3..661f9d430d 100755 --- a/t/t8003-blame-corner-cases.sh +++ b/t/t8003-blame-corner-cases.sh @@ -41,12 +41,12 @@ test_expect_success setup ' test_tick && GIT_AUTHOR_NAME=Fourth git commit -m Fourth && - { - echo ABC - echo DEF - echo XXXX - echo GHIJK - } >cow && + cat >cow <<-\EOF && + ABC + DEF + XXXX + GHIJK + EOF git add cow && test_tick && GIT_AUTHOR_NAME=Fifth git commit -m Fifth @@ -115,11 +115,11 @@ test_expect_success 'append with -C -C -C' ' test_expect_success 'blame wholesale copy' ' git blame -f -C -C1 HEAD^ -- cow | sed -e "$pick_fc" >current && - { - echo mouse-Initial - echo mouse-Second - echo mouse-Third - } >expected && + cat >expected <<-\EOF && + mouse-Initial + mouse-Second + mouse-Third + EOF test_cmp expected current ' @@ -127,16 +127,61 @@ test_expect_success 'blame wholesale copy' ' test_expect_success 'blame wholesale copy and more' ' git blame -f -C -C1 HEAD -- cow | sed -e "$pick_fc" >current && - { - echo mouse-Initial - echo mouse-Second - echo cow-Fifth - echo mouse-Third - } >expected && + cat >expected <<-\EOF && + mouse-Initial + mouse-Second + cow-Fifth + mouse-Third + EOF test_cmp expected current ' +test_expect_success 'blame wholesale copy and more in the index' ' + + cat >horse <<-\EOF && + ABC + DEF + XXXX + YYYY + GHIJK + EOF + git add horse && + test_when_finished "git rm -f horse" && + git blame -f -C -C1 -- horse | sed -e "$pick_fc" >current && + cat >expected <<-\EOF && + mouse-Initial + mouse-Second + cow-Fifth + horse-Not + mouse-Third + EOF + test_cmp expected current + +' + +test_expect_success 'blame during cherry-pick with file rename conflict' ' + + test_when_finished "git reset --hard && git checkout master" && + git checkout HEAD~3 && + echo MOUSE >> mouse && + git mv mouse rodent && + git add rodent && + GIT_AUTHOR_NAME=Rodent git commit -m "rodent" && + git checkout --detach master && + (git cherry-pick HEAD@{1} || test $? -eq 1) && + git show HEAD@{1}:rodent > rodent && + git add rodent && + git blame -f -C -C1 rodent | sed -e "$pick_fc" >current && + cat current && + cat >expected <<-\EOF && + mouse-Initial + mouse-Second + rodent-Not + EOF + test_cmp expected current +' + test_expect_success 'blame path that used to be a directory' ' mkdir path && echo A A A A A >path/file && @@ -167,12 +212,12 @@ EOF test_expect_success 'blame -L with invalid start' ' test_must_fail git blame -L5 tres 2>errors && - grep "has only 2 lines" errors + test_i18ngrep "has only 2 lines" errors ' test_expect_success 'blame -L with invalid end' ' test_must_fail git blame -L1,5 tres 2>errors && - grep "has only 2 lines" errors + test_i18ngrep "has only 2 lines" errors ' test_expect_success 'blame parses <end> part of -L' ' diff --git a/t/t8008-blame-formats.sh b/t/t8008-blame-formats.sh index 29f84a6dd1..92c8e792d1 100755 --- a/t/t8008-blame-formats.sh +++ b/t/t8008-blame-formats.sh @@ -87,4 +87,21 @@ test_expect_success 'blame --line-porcelain output' ' test_cmp expect actual ' +test_expect_success '--porcelain detects first non-blank line as subject' ' + ( + GIT_INDEX_FILE=.git/tmp-index && + export GIT_INDEX_FILE && + echo "This is it" >single-file && + git add single-file && + tree=$(git write-tree) && + commit=$(printf "%s\n%s\n%s\n\n\n \noneline\n\nbody\n" \ + "tree $tree" \ + "author A <a@b.c> 123456789 +0000" \ + "committer C <c@d.e> 123456789 +0000" | + git hash-object -w -t commit --stdin) && + git blame --porcelain $commit -- single-file >output && + grep "^summary oneline$" output + ) +' + test_done diff --git a/t/t8010-cat-file-filters.sh b/t/t8010-cat-file-filters.sh new file mode 100755 index 0000000000..d8242e467e --- /dev/null +++ b/t/t8010-cat-file-filters.sh @@ -0,0 +1,64 @@ +#!/bin/sh + +test_description='git cat-file filters support' +. ./test-lib.sh + +test_expect_success 'setup ' ' + echo "*.txt eol=crlf diff=txt" >.gitattributes && + echo "hello" | append_cr >world.txt && + git add .gitattributes world.txt && + test_tick && + git commit -m "Initial commit" +' + +has_cr () { + tr '\015' Q <"$1" | grep Q >/dev/null +} + +test_expect_success 'no filters with `git show`' ' + git show HEAD:world.txt >actual && + ! has_cr actual + +' + +test_expect_success 'no filters with cat-file' ' + git cat-file blob HEAD:world.txt >actual && + ! has_cr actual +' + +test_expect_success 'cat-file --filters converts to worktree version' ' + git cat-file --filters HEAD:world.txt >actual && + has_cr actual +' + +test_expect_success 'cat-file --filters --path=<path> works' ' + sha1=$(git rev-parse -q --verify HEAD:world.txt) && + git cat-file --filters --path=world.txt $sha1 >actual && + has_cr actual +' + +test_expect_success 'cat-file --textconv --path=<path> works' ' + sha1=$(git rev-parse -q --verify HEAD:world.txt) && + test_config diff.txt.textconv "tr A-Za-z N-ZA-Mn-za-m <" && + git cat-file --textconv --path=hello.txt $sha1 >rot13 && + test uryyb = "$(cat rot13 | remove_cr)" +' + +test_expect_success '--path=<path> complains without --textconv/--filters' ' + sha1=$(git rev-parse -q --verify HEAD:world.txt) && + test_must_fail git cat-file --path=hello.txt blob $sha1 >actual 2>err && + test ! -s actual && + grep "path.*needs.*filters" err +' + +test_expect_success 'cat-file --textconv --batch works' ' + sha1=$(git rev-parse -q --verify HEAD:world.txt) && + test_config diff.txt.textconv "tr A-Za-z N-ZA-Mn-za-m <" && + printf "%s hello.txt\n%s hello\n" $sha1 $sha1 | + git cat-file --textconv --batch >actual && + printf "%s blob 6\nuryyb\r\n\n%s blob 6\nhello\n\n" \ + $sha1 $sha1 >expect && + test_cmp expect actual +' + +test_done diff --git a/t/t9003-help-autocorrect.sh b/t/t9003-help-autocorrect.sh index dfe95c923b..b1c7919c4a 100755 --- a/t/t9003-help-autocorrect.sh +++ b/t/t9003-help-autocorrect.sh @@ -31,10 +31,10 @@ test_expect_success 'autocorrect showing candidates' ' git config help.autocorrect 0 && test_must_fail git lfg 2>actual && - sed -e "1,/^Did you mean this/d" actual | grep lgf && + grep "^ lgf" actual && test_must_fail git distimdist 2>actual && - sed -e "1,/^Did you mean this/d" actual | grep distimdistim + grep "^ distimdistim" actual ' test_expect_success 'autocorrect running commands' ' diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh index 28082b134f..92a3aa8063 100755 --- a/t/t9100-git-svn-basic.sh +++ b/t/t9100-git-svn-basic.sh @@ -8,8 +8,6 @@ GIT_SVN_LC_ALL=${LC_ALL:-$LANG} . ./lib-git-svn.sh -say 'define NO_SVN_TESTS to skip git svn tests' - case "$GIT_SVN_LC_ALL" in *.UTF-8) test_set_prereq UTF8 @@ -19,6 +17,27 @@ case "$GIT_SVN_LC_ALL" in ;; esac +deepdir=nothing-above +ceiling=$PWD + +test_expect_success 'git svn --version works anywhere' ' + mkdir -p "$deepdir" && ( + GIT_CEILING_DIRECTORIES="$ceiling" && + export GIT_CEILING_DIRECTORIES && + cd "$deepdir" && + git svn --version + ) +' + +test_expect_success 'git svn help works anywhere' ' + mkdir -p "$deepdir" && ( + GIT_CEILING_DIRECTORIES="$ceiling" && + export GIT_CEILING_DIRECTORIES && + cd "$deepdir" && + git svn help + ) +' + test_expect_success \ 'initialize git svn' ' mkdir import && diff --git a/t/t9115-git-svn-dcommit-funky-renames.sh b/t/t9115-git-svn-dcommit-funky-renames.sh index a87d3d3fc1..64bb495834 100755 --- a/t/t9115-git-svn-dcommit-funky-renames.sh +++ b/t/t9115-git-svn-dcommit-funky-renames.sh @@ -8,9 +8,10 @@ test_description='git svn dcommit can commit renames of files with ugly names' . ./lib-git-svn.sh test_expect_success 'load repository with strange names' ' - svnadmin load -q "$rawsvnrepo" < "$TEST_DIRECTORY"/t9115/funky-names.dump && - start_httpd gtk+ - ' + svnadmin load -q "$rawsvnrepo" <"$TEST_DIRECTORY"/t9115/funky-names.dump +' + +maybe_start_httpd gtk+ test_expect_success 'init and fetch repository' ' git svn init "$svnrepo" && diff --git a/t/t9118-git-svn-funky-branch-names.sh b/t/t9118-git-svn-funky-branch-names.sh index ecb1fed147..41a026637f 100755 --- a/t/t9118-git-svn-funky-branch-names.sh +++ b/t/t9118-git-svn-funky-branch-names.sh @@ -32,7 +32,7 @@ test_expect_success 'setup svnrepo' ' "$svnrepo/pr ject/branches/trailing_dotlock.lock" && svn_cmd cp -m "reflog" "$svnrepo/pr ject/trunk" \ "$svnrepo/pr ject/branches/not-a@{0}reflog@" && - start_httpd + maybe_start_httpd ' # SVN 1.7 will truncate "not-a%40{0]" to just "not-a". diff --git a/t/t9120-git-svn-clone-with-percent-escapes.sh b/t/t9120-git-svn-clone-with-percent-escapes.sh index 59465b147e..b28a1741e3 100755 --- a/t/t9120-git-svn-clone-with-percent-escapes.sh +++ b/t/t9120-git-svn-clone-with-percent-escapes.sh @@ -15,7 +15,7 @@ test_expect_success 'setup svnrepo' ' svn_cmd cp -m "tag" "$svnrepo/pr ject/trunk" \ "$svnrepo/pr ject/tags/v1" && rm -rf project && - start_httpd + maybe_start_httpd ' test_expect_success 'test clone with percent escapes' ' diff --git a/t/t9142-git-svn-shallow-clone.sh b/t/t9142-git-svn-shallow-clone.sh index e21ee5f663..9ee23be640 100755 --- a/t/t9142-git-svn-shallow-clone.sh +++ b/t/t9142-git-svn-shallow-clone.sh @@ -18,7 +18,7 @@ test_expect_success 'setup test repository' ' svn_cmd add foo && svn_cmd commit -m "add foo" ) && - start_httpd + maybe_start_httpd ' test_expect_success 'clone trunk with "-r HEAD"' ' diff --git a/t/t9158-git-svn-mergeinfo.sh b/t/t9158-git-svn-mergeinfo.sh index 13f78f2682..a875b45102 100755 --- a/t/t9158-git-svn-mergeinfo.sh +++ b/t/t9158-git-svn-mergeinfo.sh @@ -7,8 +7,6 @@ test_description='git svn mergeinfo propagation' . ./lib-git-svn.sh -say 'define NO_SVN_TESTS to skip git svn tests' - test_expect_success 'initialize source svn repo' ' svn_cmd mkdir -m x "$svnrepo"/trunk && svn_cmd co "$svnrepo"/trunk "$SVN_TREE" && diff --git a/t/t9160-git-svn-preserve-empty-dirs.sh b/t/t9160-git-svn-preserve-empty-dirs.sh index b4a4434604..0ede3cfedb 100755 --- a/t/t9160-git-svn-preserve-empty-dirs.sh +++ b/t/t9160-git-svn-preserve-empty-dirs.sh @@ -11,7 +11,6 @@ local Git repository with placeholder files.' . ./lib-git-svn.sh -say 'define NO_SVN_TESTS to skip git svn tests' GIT_REPO=git-svn-repo test_expect_success 'initialize source svn repo containing empty dirs' ' diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 74d740de41..2e0ba3ebd8 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -7,23 +7,6 @@ test_description='test git fast-import utility' . ./test-lib.sh . "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash -# Print $1 bytes from stdin to stdout. -# -# This could be written as "head -c $1", but IRIX "head" does not -# support the -c option. -head_c () { - perl -e ' - my $len = $ARGV[1]; - while ($len > 0) { - my $s; - my $nread = sysread(STDIN, $s, $len); - die "cannot read: $!" unless defined($nread); - print $s; - $len -= $nread; - } - ' - "$1" -} - verify_packs () { for p in .git/objects/pack/*.pack do @@ -2481,7 +2464,7 @@ test_expect_success PIPE 'R: copy using cat-file' ' read blob_id type size <&3 && echo "$blob_id $type $size" >response && - head_c $size >blob <&3 && + test_copy_bytes $size >blob <&3 && read newline <&3 && cat <<-EOF && @@ -2524,7 +2507,7 @@ test_expect_success PIPE 'R: print blob mid-commit' ' EOF read blob_id type size <&3 && - head_c $size >actual <&3 && + test_copy_bytes $size >actual <&3 && read newline <&3 && echo @@ -2559,7 +2542,7 @@ test_expect_success PIPE 'R: print staged blob within commit' ' echo "cat-blob $to_get" && read blob_id type size <&3 && - head_c $size >actual <&3 && + test_copy_bytes $size >actual <&3 && read newline <&3 && echo deleteall diff --git a/t/t9401-git-cvsserver-crlf.sh b/t/t9401-git-cvsserver-crlf.sh index f324b9f010..84787eee9a 100755 --- a/t/t9401-git-cvsserver-crlf.sh +++ b/t/t9401-git-cvsserver-crlf.sh @@ -154,7 +154,7 @@ test_expect_success 'adding files' ' echo "more text" > src.c && GIT_CONFIG="$git_config" cvs -Q add src.c >cvs.log 2>&1 && marked_as . src.c "" && - echo "psuedo-binary" > temp.bin + echo "pseudo-binary" > temp.bin ) && GIT_CONFIG="$git_config" cvs -Q add subdir/temp.bin >cvs.log 2>&1 && marked_as subdir temp.bin "-kb" && diff --git a/t/t9801-git-p4-branch.sh b/t/t9801-git-p4-branch.sh index 0aafd03334..6a86d6996b 100755 --- a/t/t9801-git-p4-branch.sh +++ b/t/t9801-git-p4-branch.sh @@ -300,7 +300,7 @@ test_expect_success 'git p4 clone complex branches' ' test_path_is_file file2 && test_path_is_file file3 && ! grep update file2 && - test_path_is_missing .git/git-p4-tmp + test_must_fail git show-ref --verify refs/git-p4-tmp ) ' @@ -352,7 +352,7 @@ test_expect_success 'git p4 sync changes to two branches in the same changelist' test_path_is_file file2 && test_path_is_file file3 && ! grep update file2 && - test_path_is_missing .git/git-p4-tmp + test_must_fail git show-ref --verify refs/git-p4-tmp ) ' diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh index 0db4469c89..97c9b32c2e 100755 --- a/t/t9903-bash-prompt.sh +++ b/t/t9903-bash-prompt.sh @@ -177,7 +177,7 @@ test_expect_success 'prompt - interactive rebase' ' git checkout b1 && test_when_finished "git checkout master" && git rebase -i HEAD^ && - test_when_finished "git rebase --abort" + test_when_finished "git rebase --abort" && __git_ps1 >"$actual" && test_cmp expected "$actual" ' diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index 48884d5208..fdaeb3a96b 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -81,6 +81,10 @@ test_decode_color () { ' } +lf_to_nul () { + perl -pe 'y/\012/\000/' +} + nul_to_q () { perl -pe 'y/\000/Q/' } @@ -612,7 +616,7 @@ test_must_fail () { then echo >&2 "test_must_fail: command succeeded: $*" return 1 - elif test $exit_code -eq 141 && list_contains "$_test_ok" sigpipe + elif test_match_signal 13 $exit_code && list_contains "$_test_ok" sigpipe then return 0 elif test $exit_code -gt 129 && test $exit_code -le 192 @@ -961,3 +965,32 @@ test_env () { done ) } + +# Returns true if the numeric exit code in "$2" represents the expected signal +# in "$1". Signals should be given numerically. +test_match_signal () { + if test "$2" = "$((128 + $1))" + then + # POSIX + return 0 + elif test "$2" = "$((256 + $1))" + then + # ksh + return 0 + fi + return 1 +} + +# Read up to "$1" bytes (or to EOF) from stdin and write them to stdout. +test_copy_bytes () { + perl -e ' + my $len = $ARGV[1]; + while ($len > 0) { + my $s; + my $nread = sysread(STDIN, $s, $len); + die "cannot read: $!" unless defined($nread); + print $s; + $len -= $nread; + } + ' - "$1" +} diff --git a/t/test-lib.sh b/t/test-lib.sh index 0055ebba46..11562bde10 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -89,6 +89,7 @@ unset VISUAL EMAIL LANGUAGE COLUMNS $("$PERL_PATH" -e ' UNZIP PERF_ CURL_VERBOSE + TRACE_CURL )); my @vars = grep(/^GIT_/ && !/^GIT_($ok)/o, @env); print join("\n", @vars); @@ -162,6 +163,9 @@ _x40="$_x05$_x05$_x05$_x05$_x05$_x05$_x05$_x05" # Zero SHA-1 _z40=0000000000000000000000000000000000000000 +EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904 +EMPTY_BLOB=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 + # Line feed LF=' ' @@ -170,7 +174,7 @@ LF=' # when case-folding filenames u200c=$(printf '\342\200\214') -export _x05 _x40 _z40 LF u200c +export _x05 _x40 _z40 LF u200c EMPTY_TREE EMPTY_BLOB # Each test should start with something like this, after copyright notices: # @@ -684,9 +688,9 @@ test_done () { test_results_dir="$TEST_OUTPUT_DIRECTORY/test-results" mkdir -p "$test_results_dir" base=${0##*/} - test_results_path="$test_results_dir/${base%.sh}-$$.counts" + test_results_path="$test_results_dir/${base%.sh}.counts" - cat >>"$test_results_path" <<-EOF + cat >"$test_results_path" <<-EOF total $test_count success $test_success fixed $test_fixed @@ -798,7 +802,7 @@ then # override all git executables in TEST_DIRECTORY/.. GIT_VALGRIND=$TEST_DIRECTORY/valgrind mkdir -p "$GIT_VALGRIND"/bin - for file in $GIT_BUILD_DIR/git* $GIT_BUILD_DIR/test-* + for file in $GIT_BUILD_DIR/git* $GIT_BUILD_DIR/t/helper/test-* do make_valgrind_symlink $file done @@ -1069,6 +1073,10 @@ test_lazy_prereq NOT_ROOT ' test "$uid" != 0 ' +test_lazy_prereq JGIT ' + type jgit +' + # SANITY is about "can you correctly predict what the filesystem would # do by only looking at the permission bits of the files and # directories?" A typical example of !SANITY is running the test @@ -1111,3 +1119,12 @@ run_with_limited_cmdline () { } test_lazy_prereq CMDLINE_LIMIT 'run_with_limited_cmdline true' + +build_option () { + git version --build-options | + sed -ne "s/^$1: //p" +} + +test_lazy_prereq LONG_IS_64BIT ' + test 8 -le "$(build_option sizeof-long)" +' |