diff options
Diffstat (limited to 't')
290 files changed, 10755 insertions, 2806 deletions
@@ -69,7 +69,8 @@ You can also run each test individually from command line, like this: You can pass --verbose (or -v), --debug (or -d), and --immediate (or -i) command line argument to the test, or by setting GIT_TEST_OPTS -appropriately before running "make". +appropriately before running "make". Short options can be bundled, i.e. +'-d -v' is the same as '-dv'. -v:: --verbose:: @@ -352,8 +353,8 @@ details. GIT_TEST_SPLIT_INDEX=<boolean> forces split-index mode on the whole test suite. Accept any boolean values that are accepted by git-config. -GIT_TEST_PROTOCOL_VERSION=<n>, when set, overrides the -'protocol.version' setting to n if it is less than n. +GIT_TEST_PROTOCOL_VERSION=<n>, when set, makes 'protocol.version' +default to n. GIT_TEST_FULL_IN_PACK_ARRAY=<boolean> exercises the uncommon pack-objects code path where there are more than 1024 packs even if @@ -378,6 +379,11 @@ GIT_TEST_COMMIT_GRAPH=<boolean>, when true, forces the commit-graph to be written after every 'git commit' command, and overrides the 'core.commitGraph' setting to true. +GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=<boolean>, when true, forces +commit-graph write to compute and write changed path Bloom filters for +every 'git commit-graph write', as if the `--changed-paths` option was +passed in. + GIT_TEST_FSMONITOR=$PWD/t7519/fsmonitor-all exercises the fsmonitor code path for utilizing a file system monitor to speed up detecting new or changed files. @@ -386,17 +392,13 @@ GIT_TEST_INDEX_VERSION=<n> exercises the index read/write code path for the index version specified. Can be set to any valid version (currently 2, 3, or 4). -GIT_TEST_PACK_SPARSE=<boolean> if enabled will default the pack-objects -builtin to use the sparse object walk. This can still be overridden by -the --no-sparse command-line argument. +GIT_TEST_PACK_SPARSE=<boolean> if disabled will default the pack-objects +builtin to use the non-sparse object walk. This can still be overridden by +the --sparse command-line argument. GIT_TEST_PRELOAD_INDEX=<boolean> exercises the preload-index code path by overriding the minimum number of cache entries required per thread. -GIT_TEST_STASH_USE_BUILTIN=<boolean>, when false, disables the -built-in version of git-stash. See 'stash.useBuiltin' in -git-config(1). - GIT_TEST_ADD_I_USE_BUILTIN=<boolean>, when true, enables the built-in version of git add -i. See 'add.interactive.useBuiltin' in git-config(1). @@ -550,6 +552,41 @@ Here are the "do's:" reports "ok" or "not ok" to the end user running the tests. Under --verbose, they are shown to help debug the tests. + - Be careful when you loop + + You may need to verify multiple things in a loop, but the + following does not work correctly: + + test_expect_success 'test three things' ' + for i in one two three + do + test_something "$i" + done && + test_something_else + ' + + Because the status of the loop itself is the exit status of the + test_something in the last round, the loop does not fail when + "test_something" for "one" or "two" fails. This is not what you + want. + + Instead, you can break out of the loop immediately when you see a + failure. Because all test_expect_* snippets are executed inside + a function, "return 1" can be used to fail the test immediately + upon a failure: + + test_expect_success 'test three things' ' + for i in one two three + do + test_something "$i" || return 1 + done && + test_something_else + ' + + Note that we still &&-chain the loop to propagate failures from + earlier commands. + + And here are the "don'ts:" - Don't exit() within a <script> part. diff --git a/t/check-non-portable-shell.pl b/t/check-non-portable-shell.pl index 38bfeebd88..fd3303552b 100755 --- a/t/check-non-portable-shell.pl +++ b/t/check-non-portable-shell.pl @@ -46,7 +46,7 @@ while (<>) { /(?:\$\(seq|^\s*seq\b)/ and err 'seq is not portable (use test_seq)'; /\bgrep\b.*--file\b/ and err 'grep --file FILE is not portable (use grep -f FILE)'; /\bexport\s+[A-Za-z0-9_]*=/ and err '"export FOO=bar" is not portable (use FOO=bar && export FOO)'; - /^\s*([A-Z0-9_]+=(\w+|(["']).*?\3)\s+)+(\w+)/ and exists($func{$4}) and + /^\s*([A-Z0-9_]+=(\w*|(["']).*?\3)\s+)+(\w+)/ and exists($func{$4}) and err '"FOO=bar shell_func" assignment extends beyond "shell_func"'; $line = ''; # this resets our $. for each file diff --git a/t/helper/test-advise.c b/t/helper/test-advise.c new file mode 100644 index 0000000000..38cdc2884e --- /dev/null +++ b/t/helper/test-advise.c @@ -0,0 +1,22 @@ +#include "test-tool.h" +#include "cache.h" +#include "advice.h" +#include "config.h" + +int cmd__advise_if_enabled(int argc, const char **argv) +{ + if (!argv[1]) + die("usage: %s <advice>", argv[0]); + + setup_git_directory(); + git_config(git_default_config, NULL); + + /* + * Any advice type can be used for testing, but NESTED_TAG was + * selected here and in t0018 where this command is being + * executed. + */ + advise_if_enabled(ADVICE_NESTED_TAG, argv[1]); + + return 0; +} diff --git a/t/helper/test-bloom.c b/t/helper/test-bloom.c new file mode 100644 index 0000000000..456f5ea7f9 --- /dev/null +++ b/t/helper/test-bloom.c @@ -0,0 +1,93 @@ +#include "git-compat-util.h" +#include "bloom.h" +#include "test-tool.h" +#include "commit.h" + +static struct bloom_filter_settings settings = DEFAULT_BLOOM_FILTER_SETTINGS; + +static void add_string_to_filter(const char *data, struct bloom_filter *filter) { + struct bloom_key key; + int i; + + fill_bloom_key(data, strlen(data), &key, &settings); + printf("Hashes:"); + for (i = 0; i < settings.num_hashes; i++){ + printf("0x%08x|", key.hashes[i]); + } + printf("\n"); + add_key_to_filter(&key, filter, &settings); +} + +static void print_bloom_filter(struct bloom_filter *filter) { + int i; + + if (!filter) { + printf("No filter.\n"); + return; + } + printf("Filter_Length:%d\n", (int)filter->len); + printf("Filter_Data:"); + for (i = 0; i < filter->len; i++) { + printf("%02x|", filter->data[i]); + } + printf("\n"); +} + +static void get_bloom_filter_for_commit(const struct object_id *commit_oid) +{ + struct commit *c; + struct bloom_filter *filter; + setup_git_directory(); + c = lookup_commit(the_repository, commit_oid); + filter = get_bloom_filter(the_repository, c, 1); + print_bloom_filter(filter); +} + +static const char *bloom_usage = "\n" +" test-tool bloom get_murmer3 <string>\n" +" test-tool bloom generate_filter <string> [<string>...]\n" +" test-tool get_filter_for_commit <commit-hex>\n"; + +int cmd__bloom(int argc, const char **argv) +{ + if (argc < 2) + usage(bloom_usage); + + if (!strcmp(argv[1], "get_murmur3")) { + uint32_t hashed; + if (argc < 3) + usage(bloom_usage); + hashed = murmur3_seeded(0, argv[2], strlen(argv[2])); + printf("Murmur3 Hash with seed=0:0x%08x\n", hashed); + } + + if (!strcmp(argv[1], "generate_filter")) { + struct bloom_filter filter; + int i = 2; + filter.len = (settings.bits_per_entry + BITS_PER_WORD - 1) / BITS_PER_WORD; + filter.data = xcalloc(filter.len, sizeof(unsigned char)); + + if (argc - 1 < i) + usage(bloom_usage); + + while (argv[i]) { + add_string_to_filter(argv[i], &filter); + i++; + } + + print_bloom_filter(&filter); + } + + if (!strcmp(argv[1], "get_filter_for_commit")) { + struct object_id oid; + const char *end; + if (argc < 3) + usage(bloom_usage); + if (parse_oid_hex(argv[2], &oid, &end)) + die("cannot parse oid '%s'", argv[2]); + init_bloom_filters(); + get_bloom_filter_for_commit(&oid); + } + + return 0; +} diff --git a/t/helper/test-config.c b/t/helper/test-config.c index 1e3bc7c8f4..234c722b48 100644 --- a/t/helper/test-config.c +++ b/t/helper/test-config.c @@ -48,6 +48,7 @@ static int iterate_cb(const char *var, const char *value, void *data) printf("value=%s\n", value ? value : "(null)"); printf("origin=%s\n", current_config_origin_type()); printf("name=%s\n", current_config_name()); + printf("lno=%d\n", current_config_line()); printf("scope=%s\n", config_scope_name(current_config_scope())); return 0; diff --git a/t/helper/test-dump-fsmonitor.c b/t/helper/test-dump-fsmonitor.c index 2786f47088..975f0ac890 100644 --- a/t/helper/test-dump-fsmonitor.c +++ b/t/helper/test-dump-fsmonitor.c @@ -13,7 +13,7 @@ int cmd__dump_fsmonitor(int ac, const char **av) printf("no fsmonitor\n"); return 0; } - printf("fsmonitor last update %"PRIuMAX"\n", (uintmax_t)istate->fsmonitor_last_update); + printf("fsmonitor last update %s\n", istate->fsmonitor_last_update); for (i = 0; i < istate->cache_nr; i++) printf((istate->cache[i]->ce_flags & CE_FSMONITOR_VALID) ? "+" : "-"); diff --git a/t/helper/test-dump-split-index.c b/t/helper/test-dump-split-index.c index 63c689d6ee..a209880eb3 100644 --- a/t/helper/test-dump-split-index.c +++ b/t/helper/test-dump-split-index.c @@ -13,6 +13,8 @@ int cmd__dump_split_index(int ac, const char **av) struct split_index *si; int i; + setup_git_directory(); + do_read_index(&the_index, av[1], 1); printf("own %s\n", oid_to_hex(&the_index.oid)); si = the_index.split_index; diff --git a/t/helper/test-sha1-array.c b/t/helper/test-oid-array.c index ad5e69f9d3..ce9fd5f091 100644 --- a/t/helper/test-sha1-array.c +++ b/t/helper/test-oid-array.c @@ -1,6 +1,6 @@ #include "test-tool.h" #include "cache.h" -#include "sha1-array.h" +#include "oid-array.h" static int print_oid(const struct object_id *oid, void *data) { @@ -8,7 +8,7 @@ static int print_oid(const struct object_id *oid, void *data) return 0; } -int cmd__sha1_array(int argc, const char **argv) +int cmd__oid_array(int argc, const char **argv) { struct oid_array array = OID_ARRAY_INIT; struct strbuf line = STRBUF_INIT; @@ -19,11 +19,11 @@ int cmd__sha1_array(int argc, const char **argv) if (skip_prefix(line.buf, "append ", &arg)) { if (get_oid_hex(arg, &oid)) - die("not a hexadecimal SHA1: %s", arg); + die("not a hexadecimal oid: %s", arg); oid_array_append(&array, &oid); } else if (skip_prefix(line.buf, "lookup ", &arg)) { if (get_oid_hex(arg, &oid)) - die("not a hexadecimal SHA1: %s", arg); + die("not a hexadecimal oid: %s", arg); printf("%d\n", oid_array_lookup(&array, &oid)); } else if (!strcmp(line.buf, "clear")) oid_array_clear(&array); diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c index af82db06ac..2051ce57db 100644 --- a/t/helper/test-parse-options.c +++ b/t/helper/test-parse-options.c @@ -121,6 +121,8 @@ int cmd__parse_options(int argc, const char **argv) OPT_INTEGER('j', NULL, &integer, "get a integer, too"), OPT_MAGNITUDE('m', "magnitude", &magnitude, "get a magnitude"), OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23), + OPT_CMDMODE(0, "mode1", &integer, "set integer to 1 (cmdmode option)", 1), + OPT_CMDMODE(0, "mode2", &integer, "set integer to 2 (cmdmode option)", 2), OPT_CALLBACK('L', "length", &integer, "str", "get length of <str>", length_callback), OPT_FILENAME('F', "file", &file, "set file to <file>"), diff --git a/t/helper/test-parse-pathspec-file.c b/t/helper/test-parse-pathspec-file.c new file mode 100644 index 0000000000..b3e08cef4b --- /dev/null +++ b/t/helper/test-parse-pathspec-file.c @@ -0,0 +1,33 @@ +#include "test-tool.h" +#include "parse-options.h" +#include "pathspec.h" +#include "gettext.h" + +int cmd__parse_pathspec_file(int argc, const char **argv) +{ + struct pathspec pathspec; + const char *pathspec_from_file = NULL; + int pathspec_file_nul = 0, i; + + static const char *const usage[] = { + "test-tool parse-pathspec-file --pathspec-from-file [--pathspec-file-nul]", + NULL + }; + + struct option options[] = { + OPT_PATHSPEC_FROM_FILE(&pathspec_from_file), + OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul), + OPT_END() + }; + + parse_options(argc, argv, NULL, options, usage, 0); + + parse_pathspec_file(&pathspec, 0, 0, NULL, pathspec_from_file, + pathspec_file_nul); + + for (i = 0; i < pathspec.nr; i++) + printf("%s\n", pathspec.items[i].original); + + clear_pathspec(&pathspec); + return 0; +} diff --git a/t/helper/test-path-utils.c b/t/helper/test-path-utils.c index 409034cf4e..313a153209 100644 --- a/t/helper/test-path-utils.c +++ b/t/helper/test-path-utils.c @@ -290,11 +290,14 @@ int cmd__path_utils(int argc, const char **argv) } if (argc >= 2 && !strcmp(argv[1], "real_path")) { + struct strbuf realpath = STRBUF_INIT; while (argc > 2) { - puts(real_path(argv[2])); + strbuf_realpath(&realpath, argv[2], 1); + puts(realpath.buf); argc--; argv++; } + strbuf_release(&realpath); return 0; } diff --git a/t/helper/test-pkt-line.c b/t/helper/test-pkt-line.c index 282d536384..12ca698e17 100644 --- a/t/helper/test-pkt-line.c +++ b/t/helper/test-pkt-line.c @@ -67,7 +67,7 @@ static void unpack_sideband(void) case PACKET_READ_NORMAL: band = reader.line[0] & 0xff; if (band < 1 || band > 2) - die("unexpected side band %d", band); + continue; /* skip non-sideband packets */ fd = band; write_or_die(fd, reader.line + 1, reader.pktlen - 1); diff --git a/t/helper/test-progress.c b/t/helper/test-progress.c index 42b96cb103..5d05cbe789 100644 --- a/t/helper/test-progress.c +++ b/t/helper/test-progress.c @@ -13,20 +13,13 @@ * * See 't0500-progress-display.sh' for examples. */ +#define GIT_TEST_PROGRESS_ONLY #include "test-tool.h" #include "gettext.h" #include "parse-options.h" #include "progress.h" #include "strbuf.h" -/* - * These are defined in 'progress.c', but are not exposed in 'progress.h', - * because they are exclusively for testing. - */ -extern int progress_testing; -extern uint64_t progress_test_ns; -void progress_test_force_update(void); - int cmd__progress(int argc, const char **argv) { int total = 0; diff --git a/t/helper/test-read-graph.c b/t/helper/test-read-graph.c index d2884efe0a..6d0c962438 100644 --- a/t/helper/test-read-graph.c +++ b/t/helper/test-read-graph.c @@ -7,26 +7,15 @@ int cmd__read_graph(int argc, const char **argv) { struct commit_graph *graph = NULL; - char *graph_name; - int open_ok; - int fd; - struct stat st; - const char *object_dir; + struct object_directory *odb; setup_git_directory(); - object_dir = get_object_directory(); + odb = the_repository->objects->odb; - graph_name = get_commit_graph_filename(object_dir); - - open_ok = open_commit_graph(graph_name, &fd, &st); - if (!open_ok) - die_errno(_("Could not open commit-graph '%s'"), graph_name); - - graph = load_commit_graph_one_fd_st(fd, &st); + graph = read_commit_graph_one(the_repository, odb); if (!graph) return 1; - FREE_AND_NULL(graph_name); printf("header: %08x %d %d %d %d\n", ntohl(*(uint32_t*)graph->data), @@ -45,6 +34,10 @@ int cmd__read_graph(int argc, const char **argv) printf(" commit_metadata"); if (graph->chunk_extra_edges) printf(" extra_edges"); + if (graph->chunk_bloom_indexes) + printf(" bloom_indexes"); + if (graph->chunk_bloom_data) + printf(" bloom_data"); printf("\n"); UNLEAK(graph); diff --git a/t/helper/test-repository.c b/t/helper/test-repository.c index f7f8618445..56f0e3c1be 100644 --- a/t/helper/test-repository.c +++ b/t/helper/test-repository.c @@ -19,12 +19,11 @@ static void test_parse_commit_in_graph(const char *gitdir, const char *worktree, memset(the_repository, 0, sizeof(*the_repository)); - /* TODO: Needed for temporary hack in hashcmp, see 183a638b7da. */ - repo_set_hash_algo(the_repository, GIT_HASH_SHA1); - if (repo_init(&r, gitdir, worktree)) die("Couldn't init repo"); + repo_set_hash_algo(the_repository, hash_algo_by_ptr(r.hash_algo)); + c = lookup_commit(&r, commit_oid); if (!parse_commit_in_graph(&r, c)) @@ -50,12 +49,11 @@ static void test_get_commit_tree_in_graph(const char *gitdir, memset(the_repository, 0, sizeof(*the_repository)); - /* TODO: Needed for temporary hack in hashcmp, see 183a638b7da. */ - repo_set_hash_algo(the_repository, GIT_HASH_SHA1); - if (repo_init(&r, gitdir, worktree)) die("Couldn't init repo"); + repo_set_hash_algo(the_repository, hash_algo_by_ptr(r.hash_algo)); + c = lookup_commit(&r, commit_oid); /* @@ -75,6 +73,10 @@ static void test_get_commit_tree_in_graph(const char *gitdir, int cmd__repository(int argc, const char **argv) { + int nongit_ok = 0; + + setup_git_directory_gently(&nongit_ok); + if (argc < 2) die("must have at least 2 arguments"); if (!strcmp(argv[1], "parse_commit_in_graph")) { diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c index f20989d449..590b2efca7 100644 --- a/t/helper/test-tool.c +++ b/t/helper/test-tool.c @@ -14,6 +14,8 @@ struct test_cmd { }; static struct test_cmd cmds[] = { + { "advise", cmd__advise_if_enabled }, + { "bloom", cmd__bloom }, { "chmtime", cmd__chmtime }, { "config", cmd__config }, { "ctype", cmd__ctype }, @@ -36,9 +38,11 @@ static struct test_cmd cmds[] = { { "match-trees", cmd__match_trees }, { "mergesort", cmd__mergesort }, { "mktemp", cmd__mktemp }, + { "oid-array", cmd__oid_array }, { "oidmap", cmd__oidmap }, { "online-cpus", cmd__online_cpus }, { "parse-options", cmd__parse_options }, + { "parse-pathspec-file", cmd__parse_pathspec_file }, { "path-utils", cmd__path_utils }, { "pkt-line", cmd__pkt_line }, { "prio-queue", cmd__prio_queue }, @@ -55,7 +59,6 @@ static struct test_cmd cmds[] = { { "scrap-cache-tree", cmd__scrap_cache_tree }, { "serve-v2", cmd__serve_v2 }, { "sha1", cmd__sha1 }, - { "sha1-array", cmd__sha1_array }, { "sha256", cmd__sha256 }, { "sigchain", cmd__sigchain }, { "strcmp-offset", cmd__strcmp_offset }, @@ -110,6 +113,7 @@ int cmd_main(int argc, const char **argv) argc--; trace2_cmd_name(cmds[i].name); trace2_cmd_list_config(); + trace2_cmd_list_env_vars(); return cmds[i].fn(argc, argv); } } diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h index 8ed2af71d1..ddc8e990e9 100644 --- a/t/helper/test-tool.h +++ b/t/helper/test-tool.h @@ -4,6 +4,8 @@ #define USE_THE_INDEX_COMPATIBILITY_MACROS #include "git-compat-util.h" +int cmd__advise_if_enabled(int argc, const char **argv); +int cmd__bloom(int argc, const char **argv); int cmd__chmtime(int argc, const char **argv); int cmd__config(int argc, const char **argv); int cmd__ctype(int argc, const char **argv); @@ -29,6 +31,7 @@ int cmd__mktemp(int argc, const char **argv); int cmd__oidmap(int argc, const char **argv); int cmd__online_cpus(int argc, const char **argv); int cmd__parse_options(int argc, const char **argv); +int cmd__parse_pathspec_file(int argc, const char** argv); int cmd__path_utils(int argc, const char **argv); int cmd__pkt_line(int argc, const char **argv); int cmd__prio_queue(int argc, const char **argv); @@ -45,7 +48,7 @@ int cmd__run_command(int argc, const char **argv); int cmd__scrap_cache_tree(int argc, const char **argv); int cmd__serve_v2(int argc, const char **argv); int cmd__sha1(int argc, const char **argv); -int cmd__sha1_array(int argc, const char **argv); +int cmd__oid_array(int argc, const char **argv); int cmd__sha256(int argc, const char **argv); int cmd__sigchain(int argc, const char **argv); int cmd__strcmp_offset(int argc, const char **argv); diff --git a/t/helper/test-windows-named-pipe.c b/t/helper/test-windows-named-pipe.c index b4b752b01a..ae52183e63 100644 --- a/t/helper/test-windows-named-pipe.c +++ b/t/helper/test-windows-named-pipe.c @@ -19,7 +19,7 @@ int cmd__windows_named_pipe(int argc, const char **argv) if (argc < 2) goto print_usage; filename = argv[1]; - if (strchr(filename, '/') || strchr(filename, '\\')) + if (strpbrk(filename, "/\\")) goto print_usage; strbuf_addf(&pathname, "//./pipe/%s", filename); diff --git a/t/lib-credential.sh b/t/lib-credential.sh index 937b831ea6..dea2cbef51 100755..100644 --- a/t/lib-credential.sh +++ b/t/lib-credential.sh @@ -1,4 +1,5 @@ -#!/bin/sh +# Shell library for testing credential handling including helpers. See t0302 +# for an example of testing a specific helper. # Try a set of credential helpers; the expected stdin, # stdout and stderr should be provided on stdin, @@ -19,7 +20,7 @@ check() { false fi && test_cmp expect-stdout stdout && - test_cmp expect-stderr stderr + test_i18ncmp expect-stderr stderr } read_chunk() { diff --git a/t/lib-git-p4.sh b/t/lib-git-p4.sh index 547b9f88e1..5aff2abe8b 100644 --- a/t/lib-git-p4.sh +++ b/t/lib-git-p4.sh @@ -175,7 +175,7 @@ stop_and_cleanup_p4d () { cleanup_git () { retry_until_success rm -r "$git" - test_must_fail test -d "$git" && + test_path_is_missing "$git" && retry_until_success mkdir "$git" } diff --git a/t/lib-gpg.sh b/t/lib-gpg.sh index 8d28652b72..9fc5241228 100755..100644 --- a/t/lib-gpg.sh +++ b/t/lib-gpg.sh @@ -1,14 +1,25 @@ -#!/bin/sh +# We always set GNUPGHOME, even if no usable GPG was found, as +# +# - It does not hurt, and +# +# - we cannot set global environment variables in lazy prereqs because they are +# executed in an eval'ed subshell that changes the working directory to a +# temporary one. + +GNUPGHOME="$PWD/gpghome" +export GNUPGHOME + +test_lazy_prereq GPG ' + gpg_version=$(gpg --version 2>&1) + test $? != 127 || exit 1 -gpg_version=$(gpg --version 2>&1) -if test $? != 127 -then # As said here: http://www.gnupg.org/documentation/faqs.html#q6.19 - # the gpg version 1.0.6 didn't parse trust packets correctly, so for + # the gpg version 1.0.6 did not parse trust packets correctly, so for # that version, creation of signed tags using the generated key fails. case "$gpg_version" in - 'gpg (GnuPG) 1.0.6'*) + "gpg (GnuPG) 1.0.6"*) say "Your version of gpg (1.0.6) is too buggy for testing" + exit 1 ;; *) # Available key info: @@ -27,55 +38,54 @@ then # To export ownertrust: # gpg --homedir /tmp/gpghome --export-ownertrust \ # > lib-gpg/ownertrust - mkdir ./gpghome && - chmod 0700 ./gpghome && - GNUPGHOME="$(pwd)/gpghome" && - export GNUPGHOME && - (gpgconf --kill gpg-agent >/dev/null 2>&1 || : ) && - gpg --homedir "${GNUPGHOME}" 2>/dev/null --import \ + mkdir "$GNUPGHOME" && + chmod 0700 "$GNUPGHOME" && + (gpgconf --kill gpg-agent || : ) && + gpg --homedir "${GNUPGHOME}" --import \ "$TEST_DIRECTORY"/lib-gpg/keyring.gpg && - gpg --homedir "${GNUPGHOME}" 2>/dev/null --import-ownertrust \ + gpg --homedir "${GNUPGHOME}" --import-ownertrust \ "$TEST_DIRECTORY"/lib-gpg/ownertrust && - gpg --homedir "${GNUPGHOME}" </dev/null >/dev/null 2>&1 \ - --sign -u committer@example.com && - test_set_prereq GPG && - # Available key info: - # * see t/lib-gpg/gpgsm-gen-key.in - # To generate new certificate: - # * no passphrase - # gpgsm --homedir /tmp/gpghome/ \ - # -o /tmp/gpgsm.crt.user \ - # --generate-key \ - # --batch t/lib-gpg/gpgsm-gen-key.in - # To import certificate: - # gpgsm --homedir /tmp/gpghome/ \ - # --import /tmp/gpgsm.crt.user - # To export into a .p12 we can later import: - # gpgsm --homedir /tmp/gpghome/ \ - # -o t/lib-gpg/gpgsm_cert.p12 \ - # --export-secret-key-p12 "committer@example.com" - echo | gpgsm --homedir "${GNUPGHOME}" 2>/dev/null \ - --passphrase-fd 0 --pinentry-mode loopback \ - --import "$TEST_DIRECTORY"/lib-gpg/gpgsm_cert.p12 && - - gpgsm --homedir "${GNUPGHOME}" 2>/dev/null -K | - grep fingerprint: | - cut -d" " -f4 | - tr -d '\n' >"${GNUPGHOME}/trustlist.txt" && - - echo " S relax" >>"${GNUPGHOME}/trustlist.txt" && - echo hello | gpgsm --homedir "${GNUPGHOME}" >/dev/null \ - -u committer@example.com -o /dev/null --sign - 2>&1 && - test_set_prereq GPGSM + gpg --homedir "${GNUPGHOME}" </dev/null >/dev/null \ + --sign -u committer@example.com ;; esac -fi +' + +test_lazy_prereq GPGSM ' + test_have_prereq GPG && + # Available key info: + # * see t/lib-gpg/gpgsm-gen-key.in + # To generate new certificate: + # * no passphrase + # gpgsm --homedir /tmp/gpghome/ \ + # -o /tmp/gpgsm.crt.user \ + # --generate-key \ + # --batch t/lib-gpg/gpgsm-gen-key.in + # To import certificate: + # gpgsm --homedir /tmp/gpghome/ \ + # --import /tmp/gpgsm.crt.user + # To export into a .p12 we can later import: + # gpgsm --homedir /tmp/gpghome/ \ + # -o t/lib-gpg/gpgsm_cert.p12 \ + # --export-secret-key-p12 "committer@example.com" + echo | gpgsm --homedir "${GNUPGHOME}" \ + --passphrase-fd 0 --pinentry-mode loopback \ + --import "$TEST_DIRECTORY"/lib-gpg/gpgsm_cert.p12 && + + gpgsm --homedir "${GNUPGHOME}" -K | + grep fingerprint: | + cut -d" " -f4 | + tr -d "\\n" >"${GNUPGHOME}/trustlist.txt" && + + echo " S relax" >>"${GNUPGHOME}/trustlist.txt" && + echo hello | gpgsm --homedir "${GNUPGHOME}" >/dev/null \ + -u committer@example.com -o /dev/null --sign - +' -if test_have_prereq GPG && - echo | gpg --homedir "${GNUPGHOME}" -b --rfc1991 >/dev/null 2>&1 -then - test_set_prereq RFC1991 -fi +test_lazy_prereq RFC1991 ' + test_have_prereq GPG && + echo | gpg --homedir "${GNUPGHOME}" -b --rfc1991 >/dev/null +' sanitize_pgp() { perl -ne ' diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh index 656997b4d6..1449ee95e9 100644 --- a/t/lib-httpd.sh +++ b/t/lib-httpd.sh @@ -132,7 +132,7 @@ prepare_httpd() { install_script broken-smart-http.sh install_script error-smart-http.sh install_script error.sh - install_script apply-one-time-sed.sh + install_script apply-one-time-perl.sh ln -s "$LIB_HTTPD_MODULE_PATH" "$HTTPD_ROOT_PATH/modules" diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf index 5c1c86c193..994e5290d6 100644 --- a/t/lib-httpd/apache.conf +++ b/t/lib-httpd/apache.conf @@ -113,7 +113,7 @@ Alias /auth/dumb/ www/auth/dumb/ SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH} SetEnv GIT_HTTP_EXPORT_ALL </LocationMatch> -<LocationMatch /one_time_sed/> +<LocationMatch /one_time_perl/> SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH} SetEnv GIT_HTTP_EXPORT_ALL </LocationMatch> @@ -122,7 +122,7 @@ ScriptAliasMatch /smart_*[^/]*/(.*) ${GIT_EXEC_PATH}/git-http-backend/$1 ScriptAlias /broken_smart/ broken-smart-http.sh/ ScriptAlias /error_smart/ error-smart-http.sh/ ScriptAlias /error/ error.sh/ -ScriptAliasMatch /one_time_sed/(.*) apply-one-time-sed.sh/$1 +ScriptAliasMatch /one_time_perl/(.*) apply-one-time-perl.sh/$1 <Directory ${GIT_EXEC_PATH}> Options FollowSymlinks </Directory> @@ -135,7 +135,7 @@ ScriptAliasMatch /one_time_sed/(.*) apply-one-time-sed.sh/$1 <Files error.sh> Options ExecCGI </Files> -<Files apply-one-time-sed.sh> +<Files apply-one-time-perl.sh> Options ExecCGI </Files> <Files ${GIT_EXEC_PATH}/git-http-backend> diff --git a/t/lib-httpd/apply-one-time-perl.sh b/t/lib-httpd/apply-one-time-perl.sh new file mode 100644 index 0000000000..09a0abdff7 --- /dev/null +++ b/t/lib-httpd/apply-one-time-perl.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +# If "one-time-perl" exists in $HTTPD_ROOT_PATH, run perl on the HTTP response, +# using the contents of "one-time-perl" as the perl command to be run. If the +# response was modified as a result, delete "one-time-perl" so that subsequent +# HTTP responses are no longer modified. +# +# This can be used to simulate the effects of the repository changing in +# between HTTP request-response pairs. +if test -f one-time-perl +then + LC_ALL=C + export LC_ALL + + "$GIT_EXEC_PATH/git-http-backend" >out + perl -pe "$(cat one-time-perl)" out >out_modified + + if cmp -s out out_modified + then + cat out + else + cat out_modified + rm one-time-perl + fi +else + "$GIT_EXEC_PATH/git-http-backend" +fi diff --git a/t/lib-httpd/apply-one-time-sed.sh b/t/lib-httpd/apply-one-time-sed.sh deleted file mode 100644 index bf7689d020..0000000000 --- a/t/lib-httpd/apply-one-time-sed.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh - -# If "one-time-sed" exists in $HTTPD_ROOT_PATH, run sed on the HTTP response, -# using the contents of "one-time-sed" as the sed command to be run. If the -# response was modified as a result, delete "one-time-sed" so that subsequent -# HTTP responses are no longer modified. -# -# This can be used to simulate the effects of the repository changing in -# between HTTP request-response pairs. -if test -f one-time-sed -then - "$GIT_EXEC_PATH/git-http-backend" >out - sed "$(cat one-time-sed)" out >out_modified - - if cmp -s out out_modified - then - cat out - else - cat out_modified - rm one-time-sed - fi -else - "$GIT_EXEC_PATH/git-http-backend" -fi diff --git a/t/lib-log-graph.sh b/t/lib-log-graph.sh new file mode 100644 index 0000000000..1184cceef2 --- /dev/null +++ b/t/lib-log-graph.sh @@ -0,0 +1,28 @@ +# Helps shared by the test scripts for comparing log graphs. + +sanitize_log_output () { + sed -e 's/ *$//' \ + -e 's/commit [0-9a-f]*$/commit COMMIT_OBJECT_NAME/' \ + -e 's/Merge: [ 0-9a-f]*$/Merge: MERGE_PARENTS/' \ + -e 's/Merge tag.*/Merge HEADS DESCRIPTION/' \ + -e 's/Merge commit.*/Merge HEADS DESCRIPTION/' \ + -e 's/index [0-9a-f]*\.\.[0-9a-f]*/index BEFORE..AFTER/' +} + +lib_test_cmp_graph () { + git log --graph "$@" >output && + sed 's/ *$//' >output.sanitized <output && + test_i18ncmp expect output.sanitized +} + +lib_test_cmp_short_graph () { + git log --graph --pretty=short "$@" >output && + sanitize_log_output >output.sanitized <output && + test_i18ncmp expect output.sanitized +} + +lib_test_cmp_colored_graph () { + git log --graph --color=always "$@" >output.colors.raw && + test_decode_color <output.colors.raw | sed "s/ *\$//" >output.colors && + test_cmp expect.colors output.colors +} diff --git a/t/lib-pack.sh b/t/lib-pack.sh index c4d907a450..f3463170b3 100644 --- a/t/lib-pack.sh +++ b/t/lib-pack.sh @@ -35,9 +35,11 @@ pack_header () { # have hardcoded some well-known objects. See the case statements below for the # complete list. pack_obj () { + test_oid_init + case "$1" in # empty blob - e69de29bb2d1d6434b8b29ae775ad8c2e48c5391) + $EMPTY_BLOB) case "$2" in '') printf '\060\170\234\003\0\0\0\0\1' @@ -47,7 +49,7 @@ pack_obj () { ;; # blob containing "\7\76" - e68fe8129b546b101aee9510c5328e7f21ca1d18) + $(test_oid packlib_7_76)) case "$2" in '') printf '\062\170\234\143\267\3\0\0\116\0\106' @@ -59,11 +61,18 @@ pack_obj () { printf '\234\143\142\142\142\267\003\0\0\151\0\114' return ;; + 37c8e2c15bb22b912e59b43fd51a4f7e9465ed0b5084c5a1411d991cbe630683) + printf '\165\67\310\342\301\133\262\53\221\56\131' && + printf '\264\77\325\32\117\176\224\145\355\13\120' && + printf '\204\305\241\101\35\231\34\276\143\6\203\170' && + printf '\234\143\142\142\142\267\003\0\0\151\0\114' + return + ;; esac ;; # blob containing "\7\0" - 01d7713666f4de822776c7622c10f1b07de280dc) + $(test_oid packlib_7_0)) case "$2" in '') printf '\062\170\234\143\147\0\0\0\20\0\10' @@ -75,6 +84,13 @@ pack_obj () { printf '\143\142\142\142\147\0\0\0\53\0\16' return ;; + 5d8e6fc40f2dab00e6983a48523fe57e621f46434cb58dbd4422fba03380d886) + printf '\165\135\216\157\304\17\55\253\0\346\230\72' && + printf '\110\122\77\345\176\142\37\106\103\114\265' && + printf '\215\275\104\42\373\240\63\200\330\206\170\234' && + printf '\143\142\142\142\147\0\0\0\53\0\16' + return + ;; esac ;; esac @@ -86,7 +102,7 @@ pack_obj () { then echo "$1" | git pack-objects --stdout >pack_obj.tmp && size=$(wc -c <pack_obj.tmp) && - dd if=pack_obj.tmp bs=1 count=$((size - 20 - 12)) skip=12 && + dd if=pack_obj.tmp bs=1 count=$((size - $(test_oid rawsz) - 12)) skip=12 && rm -f pack_obj.tmp return fi @@ -97,7 +113,8 @@ pack_obj () { # Compute and append pack trailer to "$1" pack_trailer () { - test-tool sha1 -b <"$1" >trailer.tmp && + test_oid_init && + test-tool $(test_oid algo) -b <"$1" >trailer.tmp && cat trailer.tmp >>"$1" && rm -f trailer.tmp } @@ -108,3 +125,11 @@ pack_trailer () { clear_packs () { rm -f .git/objects/pack/* } + +test_oid_cache <<-EOF +packlib_7_0 sha1:01d7713666f4de822776c7622c10f1b07de280dc +packlib_7_0 sha256:37c8e2c15bb22b912e59b43fd51a4f7e9465ed0b5084c5a1411d991cbe630683 + +packlib_7_76 sha1:e68fe8129b546b101aee9510c5328e7f21ca1d18 +packlib_7_76 sha256:5d8e6fc40f2dab00e6983a48523fe57e621f46434cb58dbd4422fba03380d886 +EOF diff --git a/t/lib-submodule-update.sh b/t/lib-submodule-update.sh index 1dd17fc03e..64fc6487dd 100755..100644 --- a/t/lib-submodule-update.sh +++ b/t/lib-submodule-update.sh @@ -297,7 +297,7 @@ test_submodule_content () { # - Directory containing tracked files replaced by submodule # - Submodule replaced by tracked files in directory # - Submodule replaced by tracked file with the same name -# - tracked file replaced by submodule +# - Tracked file replaced by submodule # # The default is that submodule contents aren't changed until "git submodule # update" is run. And even then that command doesn't delete the work tree of @@ -621,11 +621,13 @@ test_submodule_forced_switch () { # - Directory containing tracked files replaced by submodule # - Submodule replaced by tracked files in directory # - Submodule replaced by tracked file with the same name -# - tracked file replaced by submodule +# - Tracked file replaced by submodule # # New test cases # - Removing a submodule with a git directory absorbs the submodules # git directory first into the superproject. +# - Switching from no submodule to nested submodules +# - Switching from nested submodules to no submodule # Internal function; use test_submodule_switch_recursing_with_args() or # test_submodule_forced_switch_recursing_with_args() instead. @@ -658,22 +660,6 @@ test_submodule_recursing_with_args_common() { test_submodule_content sub1 origin/add_sub1 ) ' - test_expect_success "$command: submodule branch is not changed, detach HEAD instead" ' - prolog && - reset_work_tree_to_interested add_sub1 && - ( - cd submodule_update && - git -C sub1 checkout -b keep_branch && - git -C sub1 rev-parse HEAD >expect && - git branch -t modify_sub1 origin/modify_sub1 && - $command modify_sub1 && - test_superproject_content origin/modify_sub1 && - test_submodule_content sub1 origin/modify_sub1 && - git -C sub1 rev-parse keep_branch >actual && - test_cmp expect actual && - test_must_fail git -C sub1 symbolic-ref HEAD - ) - ' # Replacing a tracked file with a submodule produces a checked out submodule test_expect_success "$command: replace tracked file with submodule checks out submodule" ' @@ -699,6 +685,19 @@ test_submodule_recursing_with_args_common() { test_submodule_content sub1 origin/replace_directory_with_sub1 ) ' + # Switching to a commit with nested submodules recursively checks them out + test_expect_success "$command: nested submodules are checked out" ' + prolog && + reset_work_tree_to_interested no_submodule && + ( + cd submodule_update && + git branch -t modify_sub1_recursively origin/modify_sub1_recursively && + $command modify_sub1_recursively && + test_superproject_content origin/modify_sub1_recursively && + test_submodule_content sub1 origin/modify_sub1_recursively && + test_submodule_content -C sub1 sub2 origin/modify_sub1_recursively + ) + ' ######################## Disappearing submodule ####################### # Removing a submodule removes its work tree ... @@ -762,6 +761,21 @@ test_submodule_recursing_with_args_common() { ) ' + # Switching to a commit without nested submodules removes their worktrees + test_expect_success "$command: worktrees of nested submodules are removed" ' + prolog && + reset_work_tree_to_interested add_nested_sub && + ( + cd submodule_update && + git branch -t no_submodule origin/no_submodule && + $command no_submodule && + test_superproject_content origin/no_submodule && + ! test_path_is_dir sub1 && + test_must_fail git config -f .git/modules/sub1/config core.worktree && + test_must_fail git config -f .git/modules/sub1/modules/sub2/config core.worktree + ) + ' + ########################## Modified submodule ######################### # Updating a submodule sha1 updates the submodule's work tree test_expect_success "$command: modified submodule updates submodule work tree" ' @@ -789,6 +803,23 @@ test_submodule_recursing_with_args_common() { test_submodule_content sub1 origin/add_sub1 ) ' + # Updating a submodule does not touch the currently checked out branch in the submodule + test_expect_success "$command: submodule branch is not changed, detach HEAD instead" ' + prolog && + reset_work_tree_to_interested add_sub1 && + ( + cd submodule_update && + git -C sub1 checkout -b keep_branch && + git -C sub1 rev-parse HEAD >expect && + git branch -t modify_sub1 origin/modify_sub1 && + $command modify_sub1 && + test_superproject_content origin/modify_sub1 && + test_submodule_content sub1 origin/modify_sub1 && + git -C sub1 rev-parse keep_branch >actual && + test_cmp expect actual && + test_must_fail git -C sub1 symbolic-ref HEAD + ) + ' } # Declares and invokes several tests that, in various situations, checks that @@ -908,7 +939,6 @@ test_submodule_switch_recursing_with_args () { ) ' - # recursing deeper than one level doesn't work yet. test_expect_success "$command: modified submodule updates submodule recursively" ' prolog && reset_work_tree_to_interested add_nested_sub && diff --git a/t/perf/p5310-pack-bitmaps.sh b/t/perf/p5310-pack-bitmaps.sh index 6a3a42531b..b3e725f031 100755 --- a/t/perf/p5310-pack-bitmaps.sh +++ b/t/perf/p5310-pack-bitmaps.sh @@ -31,14 +31,37 @@ 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_perf 'rev-list (commits)' ' + git rev-list --all --use-bitmap-index >/dev/null +' + +test_perf 'rev-list (objects)' ' + git rev-list --all --use-bitmap-index --objects >/dev/null +' + +test_perf 'rev-list count with blob:none' ' + git rev-list --use-bitmap-index --count --objects --all \ + --filter=blob:none >/dev/null +' + +test_perf 'rev-list count with blob:limit=1k' ' + git rev-list --use-bitmap-index --count --objects --all \ + --filter=blob:limit=1k >/dev/null +' + +test_perf 'rev-list count with tree:0' ' + git rev-list --use-bitmap-index --count --objects --all \ + --filter=tree:0 >/dev/null +' + +test_perf 'simulated partial clone' ' + git pack-objects --stdout --all --filter=blob:none </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) && @@ -68,4 +91,9 @@ test_perf 'pack to file (partial bitmap)' ' git pack-objects --use-bitmap-index --all pack2b </dev/null >/dev/null ' +test_perf 'rev-list with tree filter (partial bitmap)' ' + git rev-list --use-bitmap-index --count --objects --all \ + --filter=tree:0 >/dev/null +' + test_done diff --git a/t/perf/p9300-fast-import-export.sh b/t/perf/p9300-fast-import-export.sh new file mode 100755 index 0000000000..586161e9ad --- /dev/null +++ b/t/perf/p9300-fast-import-export.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +test_description='test fast-import and fast-export performance' +. ./perf-lib.sh + +test_perf_default_repo + +# Use --no-data here to produce a vastly smaller export file. +# This is much cheaper to work with but should still exercise +# fast-import pretty well (we'll still process all commits and +# trees, which account for 60% or more of objects in most repos). +# +# Use --reencode to avoid the default of aborting on non-utf8 commits, +# which lets this test run against a wider variety of sample repos. +test_perf 'export (no-blobs)' ' + git fast-export --reencode=yes --no-data HEAD >export +' + +test_perf 'import (no-blobs)' ' + git fast-import --force <export +' + +test_done diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index 8a81a249d0..2ff176cd5d 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -77,9 +77,7 @@ _run_sub_test_lib_test_common () { # the sub-test. sane_unset HARNESS_ACTIVE && cd "$name" && - cat >"$name.sh" <<-EOF && - #!$SHELL_PATH - + write_script "$name.sh" "$TEST_SHELL_PATH" <<-EOF && test_description='$descr (run in sub test-lib) This is run in a sub test-lib so that we do not get incorrect @@ -94,15 +92,15 @@ _run_sub_test_lib_test_common () { . "\$TEST_DIRECTORY"/test-lib.sh EOF cat >>"$name.sh" && - chmod +x "$name.sh" && export TEST_DIRECTORY && TEST_OUTPUT_DIRECTORY=$(pwd) && export TEST_OUTPUT_DIRECTORY && + sane_unset GIT_TEST_FAIL_PREREQS && if test -z "$neg" then ./"$name.sh" "$@" >out 2>err else - ! ./"$name.sh" "$@" >out 2>err + ! ./"$name.sh" "$@" >out 2>err fi ) } @@ -155,7 +153,7 @@ test_expect_success 'pretend we have a fully passing test suite' " " test_expect_success 'pretend we have a partially passing test suite' " - test_must_fail run_sub_test_lib_test \ + run_sub_test_lib_test_err \ partial-pass '2/3 tests passing' <<-\\EOF && test_expect_success 'passing test #1' 'true' test_expect_success 'failing test #2' 'false' @@ -219,7 +217,7 @@ test_expect_success 'pretend we have fixed one of two known breakages (run in su " test_expect_success 'pretend we have a pass, fail, and known breakage' " - test_must_fail run_sub_test_lib_test \ + run_sub_test_lib_test_err \ mixed-results1 'mixed results #1' <<-\\EOF && test_expect_success 'passing test' 'true' test_expect_success 'failing test' 'false' @@ -238,7 +236,7 @@ test_expect_success 'pretend we have a pass, fail, and known breakage' " " test_expect_success 'pretend we have a mix of all possible results' " - test_must_fail run_sub_test_lib_test \ + run_sub_test_lib_test_err \ mixed-results2 'mixed results #2' <<-\\EOF && test_expect_success 'passing test' 'true' test_expect_success 'passing test' 'true' @@ -274,7 +272,7 @@ test_expect_success 'pretend we have a mix of all possible results' " " test_expect_success C_LOCALE_OUTPUT 'test --verbose' ' - test_must_fail run_sub_test_lib_test \ + run_sub_test_lib_test_err \ t1234-verbose "test verbose" --verbose <<-\EOF && test_expect_success "passing test" true test_expect_success "test with output" "echo foo" @@ -301,7 +299,7 @@ test_expect_success C_LOCALE_OUTPUT 'test --verbose' ' ' test_expect_success 'test --verbose-only' ' - test_must_fail run_sub_test_lib_test \ + run_sub_test_lib_test_err \ t2345-verbose-only-2 "test verbose-only=2" \ --verbose-only=2 <<-\EOF && test_expect_success "passing test" true @@ -833,8 +831,21 @@ then exit 1 fi +test_expect_success 'lazy prereqs do not turn off tracing' " + run_sub_test_lib_test lazy-prereq-and-tracing \ + 'lazy prereqs and -x' -v -x <<-\\EOF && + test_lazy_prereq LAZY true + + test_expect_success lazy 'test_have_prereq LAZY && echo trace' + + test_done + EOF + + grep 'echo trace' lazy-prereq-and-tracing/err +" + test_expect_success 'tests clean up even on failures' " - test_must_fail run_sub_test_lib_test \ + run_sub_test_lib_test_err \ failing-cleanup 'Failing tests with cleanup commands' <<-\\EOF && test_expect_success 'tests clean up even after a failure' ' touch clean-after-failure && @@ -863,7 +874,7 @@ test_expect_success 'tests clean up even on failures' " " test_expect_success 'test_atexit is run' " - test_must_fail run_sub_test_lib_test \ + run_sub_test_lib_test_err \ atexit-cleanup 'Run atexit commands' -i <<-\\EOF && test_expect_success 'tests clean up even after a failure' ' > ../../clean-atexit && diff --git a/t/t0001-init.sh b/t/t0001-init.sh index 26f8206326..1edd5aeb8f 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -392,13 +392,6 @@ test_expect_success SYMLINKS 're-init to move gitdir symlink' ' test_path_is_dir realgitdir/refs ' -# Tests for the hidden file attribute on windows -is_hidden () { - # Use the output of `attrib`, ignore the absolute path - case "$(attrib "$1")" in *H*?:*) return 0;; esac - return 1 -} - test_expect_success MINGW '.git hidden' ' rm -rf newdir && ( @@ -406,7 +399,7 @@ test_expect_success MINGW '.git hidden' ' mkdir newdir && cd newdir && git init && - is_hidden .git + test_path_is_hidden .git ) && check_config newdir/.git false unset ' diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh index 71e63d8b50..b660593c20 100755 --- a/t/t0003-attributes.sh +++ b/t/t0003-attributes.sh @@ -5,19 +5,16 @@ test_description=gitattributes . ./test-lib.sh attr_check () { - path="$1" expect="$2" + path="$1" expect="$2" git_opts="$3" && - git $3 check-attr test -- "$path" >actual 2>err && - echo "$path: test: $2" >expect && + git $git_opts check-attr test -- "$path" >actual 2>err && + echo "$path: test: $expect" >expect && test_cmp expect actual && - test_line_count = 0 err + test_must_be_empty err } attr_check_quote () { - - path="$1" - quoted_path="$2" - expect="$3" + path="$1" quoted_path="$2" expect="$3" && git check-attr test -- "$path" >actual && echo "\"$quoted_path\": test: $expect" >expect && @@ -27,7 +24,7 @@ attr_check_quote () { test_expect_success 'open-quoted pathname' ' echo "\"a test=a" >.gitattributes && - test_must_fail attr_check a a + attr_check a unspecified ' @@ -112,20 +109,20 @@ test_expect_success 'attribute test' ' test_expect_success 'attribute matching is case sensitive when core.ignorecase=0' ' - test_must_fail attr_check F f "-c core.ignorecase=0" && - test_must_fail attr_check a/F f "-c core.ignorecase=0" && - test_must_fail attr_check a/c/F f "-c core.ignorecase=0" && - test_must_fail attr_check a/G a/g "-c core.ignorecase=0" && - test_must_fail attr_check a/B/g a/b/g "-c core.ignorecase=0" && - test_must_fail attr_check a/b/G a/b/g "-c core.ignorecase=0" && - test_must_fail attr_check a/b/H a/b/h "-c core.ignorecase=0" && - test_must_fail attr_check a/b/D/g "a/b/d/*" "-c core.ignorecase=0" && - test_must_fail attr_check oNoFf unset "-c core.ignorecase=0" && - test_must_fail attr_check oFfOn set "-c core.ignorecase=0" && + attr_check F unspecified "-c core.ignorecase=0" && + attr_check a/F unspecified "-c core.ignorecase=0" && + attr_check a/c/F unspecified "-c core.ignorecase=0" && + attr_check a/G unspecified "-c core.ignorecase=0" && + attr_check a/B/g a/g "-c core.ignorecase=0" && + attr_check a/b/G unspecified "-c core.ignorecase=0" && + attr_check a/b/H unspecified "-c core.ignorecase=0" && + attr_check a/b/D/g a/g "-c core.ignorecase=0" && + attr_check oNoFf unspecified "-c core.ignorecase=0" && + attr_check oFfOn unspecified "-c core.ignorecase=0" && attr_check NO unspecified "-c core.ignorecase=0" && - test_must_fail attr_check a/b/D/NO "a/b/d/*" "-c core.ignorecase=0" && + attr_check a/b/D/NO unspecified "-c core.ignorecase=0" && attr_check a/b/d/YES a/b/d/* "-c core.ignorecase=0" && - test_must_fail attr_check a/E/f "A/e/F" "-c core.ignorecase=0" + attr_check a/E/f f "-c core.ignorecase=0" ' @@ -149,8 +146,8 @@ test_expect_success 'attribute matching is case insensitive when core.ignorecase ' test_expect_success CASE_INSENSITIVE_FS 'additional case insensitivity tests' ' - test_must_fail attr_check a/B/D/g "a/b/d/*" "-c core.ignorecase=0" && - test_must_fail attr_check A/B/D/NO "a/b/d/*" "-c core.ignorecase=0" && + attr_check a/B/D/g a/g "-c core.ignorecase=0" && + attr_check A/B/D/NO unspecified "-c core.ignorecase=0" && attr_check A/b/h a/b/h "-c core.ignorecase=1" && attr_check a/B/D/g "a/b/d/*" "-c core.ignorecase=1" && attr_check A/B/D/NO "a/b/d/*" "-c core.ignorecase=1" @@ -244,7 +241,7 @@ EOF git check-attr foo -- "a/b/f" >>actual 2>>err && git check-attr foo -- "a/b/c/f" >>actual 2>>err && test_cmp expect actual && - test_line_count = 0 err + test_must_be_empty err ' test_expect_success '"**" with no slashes test' ' @@ -265,7 +262,7 @@ EOF git check-attr foo -- "a/b/f" >>actual 2>>err && git check-attr foo -- "a/b/c/f" >>actual 2>>err && test_cmp expect actual && - test_line_count = 0 err + test_must_be_empty err ' test_expect_success 'using --git-dir and --work-tree' ' diff --git a/t/t0006-date.sh b/t/t0006-date.sh index d9fcc829a9..75ee9a96b8 100755 --- a/t/t0006-date.sh +++ b/t/t0006-date.sh @@ -81,6 +81,11 @@ check_parse 2008-02 bad check_parse 2008-02-14 bad check_parse '2008-02-14 20:30:45' '2008-02-14 20:30:45 +0000' check_parse '2008-02-14 20:30:45 -0500' '2008-02-14 20:30:45 -0500' +check_parse '2008.02.14 20:30:45 -0500' '2008-02-14 20:30:45 -0500' +check_parse '20080214T203045-04:00' '2008-02-14 20:30:45 -0400' +check_parse '20080214T203045 -04:00' '2008-02-14 20:30:45 -0400' +check_parse '20080214T203045.019-04:00' '2008-02-14 20:30:45 -0400' +check_parse '2008-02-14 20:30:45.019-04:00' '2008-02-14 20:30:45 -0400' check_parse '2008-02-14 20:30:45 -0015' '2008-02-14 20:30:45 -0015' check_parse '2008-02-14 20:30:45 -5' '2008-02-14 20:30:45 +0000' check_parse '2008-02-14 20:30:45 -5:' '2008-02-14 20:30:45 +0000' @@ -103,6 +108,7 @@ check_approxidate 5.seconds.ago '2009-08-30 19:19:55' check_approxidate 10.minutes.ago '2009-08-30 19:10:00' check_approxidate yesterday '2009-08-29 19:20:00' check_approxidate 3.days.ago '2009-08-27 19:20:00' +check_approxidate '12:34:56.3.days.ago' '2009-08-27 12:34:56' check_approxidate 3.weeks.ago '2009-08-09 19:20:00' check_approxidate 3.months.ago '2009-05-30 19:20:00' check_approxidate 2.years.3.months.ago '2007-05-30 19:20:00' diff --git a/t/t0007-git-var.sh b/t/t0007-git-var.sh index 1f600e2cae..88b9ae8158 100755 --- a/t/t0007-git-var.sh +++ b/t/t0007-git-var.sh @@ -17,7 +17,7 @@ test_expect_success 'get GIT_COMMITTER_IDENT' ' test_cmp expect actual ' -test_expect_success !FAIL_PREREQS,!AUTOIDENT 'requested identites are strict' ' +test_expect_success !FAIL_PREREQS,!AUTOIDENT 'requested identities are strict' ' ( sane_unset GIT_COMMITTER_NAME && sane_unset GIT_COMMITTER_EMAIL && diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh index 1744cee5e9..370a389e5c 100755 --- a/t/t0008-ignores.sh +++ b/t/t0008-ignores.sh @@ -424,9 +424,24 @@ test_expect_success 'local ignore inside a sub-directory with --verbose' ' ) ' -test_expect_success_multi 'nested include' \ - 'a/b/.gitignore:8:!on* a/b/one' ' - test_check_ignore "a/b/one" +test_expect_success 'nested include of negated pattern' ' + expect "" && + test_check_ignore "a/b/one" 1 +' + +test_expect_success 'nested include of negated pattern with -q' ' + expect "" && + test_check_ignore "-q a/b/one" 1 +' + +test_expect_success 'nested include of negated pattern with -v' ' + expect "a/b/.gitignore:8:!on* a/b/one" && + test_check_ignore "-v a/b/one" 0 +' + +test_expect_success 'nested include of negated pattern with -v -n' ' + expect "a/b/.gitignore:8:!on* a/b/one" && + test_check_ignore "-v -n a/b/one" 0 ' ############################################################################ @@ -460,7 +475,6 @@ test_expect_success 'cd to ignored sub-directory' ' expect_from_stdin <<-\EOF && foo twoooo - ../one seven ../../one EOF @@ -543,7 +557,6 @@ test_expect_success 'global ignore' ' globalthree a/globalthree a/per-repo - globaltwo EOF test_check_ignore "globalone per-repo globalthree a/globalthree a/per-repo not-ignored globaltwo" ' @@ -586,17 +599,7 @@ EOF cat <<-\EOF >expected-default one a/one - a/b/on - a/b/one - a/b/one one - a/b/one two - "a/b/one\"three" - a/b/two a/b/twooo - globaltwo - a/globaltwo - a/b/globaltwo - b/globaltwo EOF cat <<-EOF >expected-verbose .gitignore:1:one one @@ -696,8 +699,12 @@ cat <<-EOF >expected-all $global_excludes:2:!globaltwo ../b/globaltwo :: c/not-ignored EOF +cat <<-EOF >expected-default +../one +one +b/twooo +EOF grep -v '^:: ' expected-all >expected-verbose -sed -e 's/.* //' expected-verbose >expected-default broken_c_unquote stdin >stdin0 diff --git a/t/t0018-advice.sh b/t/t0018-advice.sh new file mode 100755 index 0000000000..e03554d2f3 --- /dev/null +++ b/t/t0018-advice.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +test_description='Test advise_if_enabled functionality' + +. ./test-lib.sh + +test_expect_success 'advice should be printed when config variable is unset' ' + cat >expect <<-\EOF && + hint: This is a piece of advice + hint: Disable this message with "git config advice.nestedTag false" + EOF + test-tool advise "This is a piece of advice" 2>actual && + test_i18ncmp expect actual +' + +test_expect_success 'advice should be printed when config variable is set to true' ' + cat >expect <<-\EOF && + hint: This is a piece of advice + hint: Disable this message with "git config advice.nestedTag false" + EOF + test_config advice.nestedTag true && + test-tool advise "This is a piece of advice" 2>actual && + test_i18ncmp expect actual +' + +test_expect_success 'advice should not be printed when config variable is set to false' ' + test_config advice.nestedTag false && + test-tool advise "This is a piece of advice" 2>actual && + test_must_be_empty actual +' + +test_done diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh index 854da0ae16..b63ba62e5d 100755 --- a/t/t0020-crlf.sh +++ b/t/t0020-crlf.sh @@ -159,8 +159,8 @@ test_expect_success 'checkout with autocrlf=input' ' rm -f tmp one dir/two three && git config core.autocrlf input && git read-tree --reset -u HEAD && - test_must_fail has_cr one && - test_must_fail has_cr dir/two && + ! has_cr one && + ! has_cr dir/two && git update-index -- one dir/two && test "$one" = $(git hash-object --stdin <one) && test "$two" = $(git hash-object --stdin <dir/two) && @@ -237,9 +237,9 @@ test_expect_success '.gitattributes says two is binary' ' git config core.autocrlf true && git read-tree --reset -u HEAD && - test_must_fail has_cr dir/two && + ! has_cr dir/two && verbose has_cr one && - test_must_fail has_cr three + ! has_cr three ' test_expect_success '.gitattributes says two is input' ' @@ -248,7 +248,7 @@ test_expect_success '.gitattributes says two is input' ' echo "two crlf=input" >.gitattributes && git read-tree --reset -u HEAD && - test_must_fail has_cr dir/two + ! has_cr dir/two ' test_expect_success '.gitattributes says two and three are text' ' @@ -270,7 +270,7 @@ test_expect_success 'in-tree .gitattributes (1)' ' rm -rf tmp one dir .gitattributes patch.file three && git read-tree --reset -u HEAD && - test_must_fail has_cr one && + ! has_cr one && verbose has_cr three ' @@ -280,7 +280,7 @@ test_expect_success 'in-tree .gitattributes (2)' ' git read-tree --reset HEAD && git checkout-index -f -q -u -a && - test_must_fail has_cr one && + ! has_cr one && verbose has_cr three ' @@ -291,7 +291,7 @@ test_expect_success 'in-tree .gitattributes (3)' ' git checkout-index -u .gitattributes && git checkout-index -u one dir/two three && - test_must_fail has_cr one && + ! has_cr one && verbose has_cr three ' @@ -302,7 +302,7 @@ test_expect_success 'in-tree .gitattributes (4)' ' git checkout-index -u one dir/two three && git checkout-index -u .gitattributes && - test_must_fail has_cr one && + ! has_cr one && verbose has_cr three ' diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh index 6c6d77b51a..4bfffa9c31 100755 --- a/t/t0021-conversion.sh +++ b/t/t0021-conversion.sh @@ -364,6 +364,10 @@ test_expect_success PERL 'required process filter should filter data' ' S=$(file_size test.r) && S2=$(file_size test2.r) && S3=$(file_size "testsubdir/test3 '\''sq'\'',\$x=.r") && + M=$(git hash-object test.r) && + M2=$(git hash-object test2.r) && + M3=$(git hash-object "testsubdir/test3 '\''sq'\'',\$x=.r") && + EMPTY=$(git hash-object /dev/null) && filter_git add . && cat >expected.log <<-EOF && @@ -378,14 +382,16 @@ test_expect_success PERL 'required process filter should filter data' ' test_cmp_count expected.log debug.log && git commit -m "test commit 2" && + MASTER=$(git rev-parse --verify master) && + META="ref=refs/heads/master treeish=$MASTER" && rm -f test2.r "testsubdir/test3 '\''sq'\'',\$x=.r" && filter_git checkout --quiet --no-progress . && cat >expected.log <<-EOF && START init handshake complete - IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK] - IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $S3 [OK] -- OUT: $S3 . [OK] + IN: smudge test2.r blob=$M2 $S2 [OK] -- OUT: $S2 . [OK] + IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r blob=$M3 $S3 [OK] -- OUT: $S3 . [OK] STOP EOF test_cmp_exclude_clean expected.log debug.log && @@ -406,10 +412,10 @@ test_expect_success PERL 'required process filter should filter data' ' cat >expected.log <<-EOF && START init handshake complete - IN: smudge test.r $S [OK] -- OUT: $S . [OK] - IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK] - IN: smudge test4-empty.r 0 [OK] -- OUT: 0 [OK] - IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $S3 [OK] -- OUT: $S3 . [OK] + IN: smudge test.r $META blob=$M $S [OK] -- OUT: $S . [OK] + IN: smudge test2.r $META blob=$M2 $S2 [OK] -- OUT: $S2 . [OK] + IN: smudge test4-empty.r $META blob=$EMPTY 0 [OK] -- OUT: 0 [OK] + IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $META blob=$M3 $S3 [OK] -- OUT: $S3 . [OK] STOP EOF test_cmp_exclude_clean expected.log debug.log && @@ -420,6 +426,117 @@ test_expect_success PERL 'required process filter should filter data' ' ) ' +test_expect_success PERL 'required process filter should filter data for various subcommands' ' + test_config_global filter.protocol.process "rot13-filter.pl debug.log clean smudge" && + test_config_global filter.protocol.required true && + ( + cd repo && + + S=$(file_size test.r) && + S2=$(file_size test2.r) && + S3=$(file_size "testsubdir/test3 '\''sq'\'',\$x=.r") && + M=$(git hash-object test.r) && + M2=$(git hash-object test2.r) && + M3=$(git hash-object "testsubdir/test3 '\''sq'\'',\$x=.r") && + EMPTY=$(git hash-object /dev/null) && + + MASTER=$(git rev-parse --verify master) && + + cp "$TEST_ROOT/test.o" test5.r && + git add test5.r && + git commit -m "test commit 3" && + git checkout empty-branch && + filter_git rebase --onto empty-branch master^^ master && + MASTER2=$(git rev-parse --verify master) && + META="ref=refs/heads/master treeish=$MASTER2" && + cat >expected.log <<-EOF && + START + init handshake complete + IN: smudge test.r $META blob=$M $S [OK] -- OUT: $S . [OK] + IN: smudge test2.r $META blob=$M2 $S2 [OK] -- OUT: $S2 . [OK] + IN: smudge test4-empty.r $META blob=$EMPTY 0 [OK] -- OUT: 0 [OK] + IN: smudge test5.r $META blob=$M $S [OK] -- OUT: $S . [OK] + IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $META blob=$M3 $S3 [OK] -- OUT: $S3 . [OK] + STOP + EOF + test_cmp_exclude_clean expected.log debug.log && + + git reset --hard empty-branch && + filter_git reset --hard $MASTER && + META="treeish=$MASTER" && + cat >expected.log <<-EOF && + START + init handshake complete + IN: smudge test.r $META blob=$M $S [OK] -- OUT: $S . [OK] + IN: smudge test2.r $META blob=$M2 $S2 [OK] -- OUT: $S2 . [OK] + IN: smudge test4-empty.r $META blob=$EMPTY 0 [OK] -- OUT: 0 [OK] + IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $META blob=$M3 $S3 [OK] -- OUT: $S3 . [OK] + STOP + EOF + test_cmp_exclude_clean expected.log debug.log && + + git branch old-master $MASTER && + git reset --hard empty-branch && + filter_git reset --hard old-master && + META="ref=refs/heads/old-master treeish=$MASTER" && + cat >expected.log <<-EOF && + START + init handshake complete + IN: smudge test.r $META blob=$M $S [OK] -- OUT: $S . [OK] + IN: smudge test2.r $META blob=$M2 $S2 [OK] -- OUT: $S2 . [OK] + IN: smudge test4-empty.r $META blob=$EMPTY 0 [OK] -- OUT: 0 [OK] + IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $META blob=$M3 $S3 [OK] -- OUT: $S3 . [OK] + STOP + EOF + test_cmp_exclude_clean expected.log debug.log && + + git checkout -b merge empty-branch && + git branch -f master $MASTER2 && + filter_git merge master && + META="treeish=$MASTER2" && + cat >expected.log <<-EOF && + START + init handshake complete + IN: smudge test.r $META blob=$M $S [OK] -- OUT: $S . [OK] + IN: smudge test2.r $META blob=$M2 $S2 [OK] -- OUT: $S2 . [OK] + IN: smudge test4-empty.r $META blob=$EMPTY 0 [OK] -- OUT: 0 [OK] + IN: smudge test5.r $META blob=$M $S [OK] -- OUT: $S . [OK] + IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $META blob=$M3 $S3 [OK] -- OUT: $S3 . [OK] + STOP + EOF + test_cmp_exclude_clean expected.log debug.log && + + filter_git archive master >/dev/null && + META="ref=refs/heads/master treeish=$MASTER2" && + cat >expected.log <<-EOF && + START + init handshake complete + IN: smudge test.r $META blob=$M $S [OK] -- OUT: $S . [OK] + IN: smudge test2.r $META blob=$M2 $S2 [OK] -- OUT: $S2 . [OK] + IN: smudge test4-empty.r $META blob=$EMPTY 0 [OK] -- OUT: 0 [OK] + IN: smudge test5.r $META blob=$M $S [OK] -- OUT: $S . [OK] + IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $META blob=$M3 $S3 [OK] -- OUT: $S3 . [OK] + STOP + EOF + test_cmp_exclude_clean expected.log debug.log && + + TREE="$(git rev-parse $MASTER2^{tree})" && + filter_git archive $TREE >/dev/null && + META="treeish=$TREE" && + cat >expected.log <<-EOF && + START + init handshake complete + IN: smudge test.r $META blob=$M $S [OK] -- OUT: $S . [OK] + IN: smudge test2.r $META blob=$M2 $S2 [OK] -- OUT: $S2 . [OK] + IN: smudge test4-empty.r $META blob=$EMPTY 0 [OK] -- OUT: 0 [OK] + IN: smudge test5.r $META blob=$M $S [OK] -- OUT: $S . [OK] + IN: smudge testsubdir/test3 '\''sq'\'',\$x=.r $META blob=$M3 $S3 [OK] -- OUT: $S3 . [OK] + STOP + EOF + test_cmp_exclude_clean expected.log debug.log + ) +' + test_expect_success PERL 'required process filter takes precedence' ' test_config_global filter.protocol.clean false && test_config_global filter.protocol.process "rot13-filter.pl debug.log clean" && @@ -519,17 +636,22 @@ test_expect_success PERL 'required process filter should process multiple packet EOF test_cmp_count expected.log debug.log && - rm -f *.file && + M1="blob=$(git hash-object 1pkt_1__.file)" && + M2="blob=$(git hash-object 2pkt_1+1.file)" && + M3="blob=$(git hash-object 2pkt_2-1.file)" && + M4="blob=$(git hash-object 2pkt_2__.file)" && + M5="blob=$(git hash-object 3pkt_2+1.file)" && + rm -f *.file debug.log && filter_git checkout --quiet --no-progress -- *.file && cat >expected.log <<-EOF && START init handshake complete - IN: smudge 1pkt_1__.file $(($S )) [OK] -- OUT: $(($S )) . [OK] - IN: smudge 2pkt_1+1.file $(($S +1)) [OK] -- OUT: $(($S +1)) .. [OK] - IN: smudge 2pkt_2-1.file $(($S*2-1)) [OK] -- OUT: $(($S*2-1)) .. [OK] - IN: smudge 2pkt_2__.file $(($S*2 )) [OK] -- OUT: $(($S*2 )) .. [OK] - IN: smudge 3pkt_2+1.file $(($S*2+1)) [OK] -- OUT: $(($S*2+1)) ... [OK] + IN: smudge 1pkt_1__.file $M1 $(($S )) [OK] -- OUT: $(($S )) . [OK] + IN: smudge 2pkt_1+1.file $M2 $(($S +1)) [OK] -- OUT: $(($S +1)) .. [OK] + IN: smudge 2pkt_2-1.file $M3 $(($S*2-1)) [OK] -- OUT: $(($S*2-1)) .. [OK] + IN: smudge 2pkt_2__.file $M4 $(($S*2 )) [OK] -- OUT: $(($S*2 )) .. [OK] + IN: smudge 3pkt_2+1.file $M5 $(($S*2+1)) [OK] -- OUT: $(($S*2+1)) ... [OK] STOP EOF test_cmp_exclude_clean expected.log debug.log && @@ -578,6 +700,10 @@ test_expect_success PERL 'process filter should restart after unexpected write f S=$(file_size test.r) && S2=$(file_size test2.r) && SF=$(file_size smudge-write-fail.r) && + M=$(git hash-object test.r) && + M2=$(git hash-object test2.r) && + MF=$(git hash-object smudge-write-fail.r) && + rm -f debug.log && git add . && rm -f *.r && @@ -591,11 +717,11 @@ test_expect_success PERL 'process filter should restart after unexpected write f cat >expected.log <<-EOF && START init handshake complete - IN: smudge smudge-write-fail.r $SF [OK] -- [WRITE FAIL] + IN: smudge smudge-write-fail.r blob=$MF $SF [OK] -- [WRITE FAIL] START init handshake complete - IN: smudge test.r $S [OK] -- OUT: $S . [OK] - IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK] + IN: smudge test.r blob=$M $S [OK] -- OUT: $S . [OK] + IN: smudge test2.r blob=$M2 $S2 [OK] -- OUT: $S2 . [OK] STOP EOF test_cmp_exclude_clean expected.log debug.log && @@ -629,6 +755,10 @@ test_expect_success PERL 'process filter should not be restarted if it signals a S=$(file_size test.r) && S2=$(file_size test2.r) && SE=$(file_size error.r) && + M=$(git hash-object test.r) && + M2=$(git hash-object test2.r) && + ME=$(git hash-object error.r) && + rm -f debug.log && git add . && rm -f *.r && @@ -637,9 +767,9 @@ test_expect_success PERL 'process filter should not be restarted if it signals a cat >expected.log <<-EOF && START init handshake complete - IN: smudge error.r $SE [OK] -- [ERROR] - IN: smudge test.r $S [OK] -- OUT: $S . [OK] - IN: smudge test2.r $S2 [OK] -- OUT: $S2 . [OK] + IN: smudge error.r blob=$ME $SE [OK] -- [ERROR] + IN: smudge test.r blob=$M $S [OK] -- OUT: $S . [OK] + IN: smudge test2.r blob=$M2 $S2 [OK] -- OUT: $S2 . [OK] STOP EOF test_cmp_exclude_clean expected.log debug.log && @@ -665,18 +795,21 @@ test_expect_success PERL 'process filter abort stops processing of all further f echo "error this blob and all future blobs" >abort.o && cp abort.o abort.r && + M="blob=$(git hash-object abort.r)" && + rm -f debug.log && SA=$(file_size abort.r) && git add . && rm -f *.r && + # Note: This test assumes that Git filters files in alphabetical # order ("abort.r" before "test.r"). filter_git checkout --quiet --no-progress . && cat >expected.log <<-EOF && START init handshake complete - IN: smudge abort.r $SA [OK] -- [ABORT] + IN: smudge abort.r $M $SA [OK] -- [ABORT] STOP EOF test_cmp_exclude_clean expected.log debug.log && @@ -727,27 +860,29 @@ test_expect_success PERL 'delayed checkout in process filter' ' ) && S=$(file_size "$TEST_ROOT/test.o") && + PM="ref=refs/heads/master treeish=$(git -C repo rev-parse --verify master) " && + M="${PM}blob=$(git -C repo rev-parse --verify master:test.a)" && cat >a.exp <<-EOF && START init handshake complete - IN: smudge test.a $S [OK] -- OUT: $S . [OK] - IN: smudge test-delay10.a $S [OK] -- [DELAYED] - IN: smudge test-delay11.a $S [OK] -- [DELAYED] - IN: smudge test-delay20.a $S [OK] -- [DELAYED] + IN: smudge test.a $M $S [OK] -- OUT: $S . [OK] + IN: smudge test-delay10.a $M $S [OK] -- [DELAYED] + IN: smudge test-delay11.a $M $S [OK] -- [DELAYED] + IN: smudge test-delay20.a $M $S [OK] -- [DELAYED] IN: list_available_blobs test-delay10.a test-delay11.a [OK] - IN: smudge test-delay10.a 0 [OK] -- OUT: $S . [OK] - IN: smudge test-delay11.a 0 [OK] -- OUT: $S . [OK] + IN: smudge test-delay10.a $M 0 [OK] -- OUT: $S . [OK] + IN: smudge test-delay11.a $M 0 [OK] -- OUT: $S . [OK] IN: list_available_blobs test-delay20.a [OK] - IN: smudge test-delay20.a 0 [OK] -- OUT: $S . [OK] + IN: smudge test-delay20.a $M 0 [OK] -- OUT: $S . [OK] IN: list_available_blobs [OK] STOP EOF cat >b.exp <<-EOF && START init handshake complete - IN: smudge test-delay10.b $S [OK] -- [DELAYED] + IN: smudge test-delay10.b $M $S [OK] -- [DELAYED] IN: list_available_blobs test-delay10.b [OK] - IN: smudge test-delay10.b 0 [OK] -- OUT: $S . [OK] + IN: smudge test-delay10.b $M 0 [OK] -- OUT: $S . [OK] IN: list_available_blobs [OK] STOP EOF @@ -767,8 +902,11 @@ test_expect_success PERL 'delayed checkout in process filter' ' rm *.a *.b && filter_git checkout . && - test_cmp_count ../a.exp a.log && - test_cmp_count ../b.exp b.log && + # We are not checking out a ref here, so filter out ref metadata. + sed -e "s!$PM!!" ../a.exp >a.exp.filtered && + sed -e "s!$PM!!" ../b.exp >b.exp.filtered && + test_cmp_count a.exp.filtered a.log && + test_cmp_count b.exp.filtered b.log && test_cmp_committed_rot13 "$TEST_ROOT/test.o" test.a && test_cmp_committed_rot13 "$TEST_ROOT/test.o" test-delay10.a && @@ -795,7 +933,6 @@ test_expect_success PERL 'missing file in delayed checkout' ' rm -rf repo-cloned && test_must_fail git clone repo repo-cloned 2>git-stderr.log && - cat git-stderr.log && grep "error: .missing-delay\.a. was not filtered properly" git-stderr.log ' diff --git a/t/t0021/rot13-filter.pl b/t/t0021/rot13-filter.pl index 470107248e..cd32a82da5 100644 --- a/t/t0021/rot13-filter.pl +++ b/t/t0021/rot13-filter.pl @@ -135,7 +135,13 @@ while (1) { if ( exists $DELAY{$pathname} and $DELAY{$pathname}{"requested"} == 0 ) { $DELAY{$pathname}{"requested"} = 1; } + } elsif ($buffer =~ /^(ref|treeish|blob)=/) { + print $debug " $buffer"; } else { + # In general, filters need to be graceful about + # new metadata, since it's documented that we + # can pass any key-value pairs, but for tests, + # let's be a little stricter. die "Unknown message '$buffer'"; } diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index 705a136ed9..f8178ee4e3 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -23,6 +23,8 @@ usage: test-tool parse-options <options> -j <n> get a integer, too -m, --magnitude <n> get a magnitude --set23 set integer to 23 + --mode1 set integer to 1 (cmdmode option) + --mode2 set integer to 2 (cmdmode option) -L, --length <str> get length of <str> -F, --file <file> set file to <file> @@ -52,7 +54,7 @@ Alias -A, --alias-source <string> get a string -Z, --alias-target <string> - get a string + alias of --alias-source EOF @@ -242,7 +244,7 @@ test_expect_success 'Alias options do not contribute to abbreviation' ' ' cat >typo.err <<\EOF -error: did you mean `--boolean` (with two dashes ?) +error: did you mean `--boolean` (with two dashes)? EOF test_expect_success 'detect possible typos' ' @@ -252,7 +254,7 @@ test_expect_success 'detect possible typos' ' ' cat >typo.err <<\EOF -error: did you mean `--ambiguous` (with two dashes ?) +error: did you mean `--ambiguous` (with two dashes)? EOF test_expect_success 'detect possible typos' ' @@ -324,6 +326,22 @@ test_expect_success 'OPT_NEGBIT() works' ' test-tool parse-options --expect="boolean: 6" -bb --no-neg-or4 ' +test_expect_success 'OPT_CMDMODE() works' ' + test-tool parse-options --expect="integer: 1" --mode1 +' + +test_expect_success 'OPT_CMDMODE() detects incompatibility' ' + test_must_fail test-tool parse-options --mode1 --mode2 >output 2>output.err && + test_must_be_empty output && + test_i18ngrep "incompatible with --mode" output.err +' + +test_expect_success 'OPT_CMDMODE() detects incompatibility with something else' ' + test_must_fail test-tool parse-options --set23 --mode2 >output 2>output.err && + test_must_be_empty output && + test_i18ngrep "incompatible with something else" output.err +' + test_expect_success 'OPT_COUNTUP() with PARSE_OPT_NODASH works' ' test-tool parse-options --expect="boolean: 6" + + + + + + ' diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh index 2ea2d00c39..56db5c8aba 100755 --- a/t/t0060-path-utils.sh +++ b/t/t0060-path-utils.sh @@ -476,6 +476,7 @@ test_expect_success MINGW 'is_valid_path() on Windows' ' C:\\git \ comm \ conout.c \ + com0.c \ lptN \ \ --not \ @@ -488,6 +489,7 @@ test_expect_success MINGW 'is_valid_path() on Windows' ' "AUX.c" \ "abc/conOut\$ .xyz/test" \ lpt8 \ + com9.c \ "lpt*" \ Nul \ "PRN./abc" diff --git a/t/t0064-sha1-array.sh b/t/t0064-sha1-array.sh index 5dda570b9a..45685af2fd 100755 --- a/t/t0064-sha1-array.sh +++ b/t/t0064-sha1-array.sh @@ -18,7 +18,7 @@ test_expect_success 'ordered enumeration' ' { echoid append 88 44 aa 55 && echo for_each_unique - } | test-tool sha1-array >actual && + } | test-tool oid-array >actual && test_cmp expect actual ' @@ -28,7 +28,7 @@ test_expect_success 'ordered enumeration with duplicate suppression' ' echoid append 88 44 aa 55 && echoid append 88 44 aa 55 && echo for_each_unique - } | test-tool sha1-array >actual && + } | test-tool oid-array >actual && test_cmp expect actual ' @@ -36,7 +36,7 @@ test_expect_success 'lookup' ' { echoid append 88 44 aa 55 && echoid lookup 55 - } | test-tool sha1-array >actual && + } | test-tool oid-array >actual && n=$(cat actual) && test "$n" -eq 1 ' @@ -45,7 +45,7 @@ test_expect_success 'lookup non-existing entry' ' { echoid append 88 44 aa 55 && echoid lookup 33 - } | test-tool sha1-array >actual && + } | test-tool oid-array >actual && n=$(cat actual) && test "$n" -lt 0 ' @@ -55,7 +55,7 @@ test_expect_success 'lookup with duplicates' ' echoid append 88 44 aa 55 && echoid append 88 44 aa 55 && echoid lookup 55 - } | test-tool sha1-array >actual && + } | test-tool oid-array >actual && n=$(cat actual) && test "$n" -ge 2 && test "$n" -le 3 @@ -66,7 +66,7 @@ test_expect_success 'lookup non-existing entry with duplicates' ' echoid append 88 44 aa 55 && echoid append 88 44 aa 55 && echoid lookup 66 - } | test-tool sha1-array >actual && + } | test-tool oid-array >actual && n=$(cat actual) && test "$n" -lt 0 ' @@ -81,7 +81,7 @@ test_expect_success 'lookup with almost duplicate values' ' echo "append $id1" && echo "append $id2" && echoid lookup 55 - } | test-tool sha1-array >actual && + } | test-tool oid-array >actual && n=$(cat actual) && test "$n" -eq 0 ' @@ -90,7 +90,7 @@ test_expect_success 'lookup with single duplicate value' ' { echoid append 55 55 && echoid lookup 55 - } | test-tool sha1-array >actual && + } | test-tool oid-array >actual && n=$(cat actual) && test "$n" -ge 0 && test "$n" -le 1 diff --git a/t/t0067-parse_pathspec_file.sh b/t/t0067-parse_pathspec_file.sh new file mode 100755 index 0000000000..7bab49f361 --- /dev/null +++ b/t/t0067-parse_pathspec_file.sh @@ -0,0 +1,108 @@ +#!/bin/sh + +test_description='Test parse_pathspec_file()' + +. ./test-lib.sh + +test_expect_success 'one item from stdin' ' + cat >expect <<-\EOF && + fileA.t + EOF + + echo fileA.t | + test-tool parse-pathspec-file --pathspec-from-file=- >actual && + + test_cmp expect actual +' + +test_expect_success 'one item from file' ' + cat >expect <<-\EOF && + fileA.t + EOF + + echo fileA.t >list && + test-tool parse-pathspec-file --pathspec-from-file=list >actual && + + test_cmp expect actual +' + +test_expect_success 'NUL delimiters' ' + cat >expect <<-\EOF && + fileA.t + fileB.t + EOF + + printf "fileA.t\0fileB.t\0" | + test-tool parse-pathspec-file --pathspec-from-file=- --pathspec-file-nul >actual && + + test_cmp expect actual +' + +test_expect_success 'LF delimiters' ' + cat >expect <<-\EOF && + fileA.t + fileB.t + EOF + + printf "fileA.t\nfileB.t\n" | + test-tool parse-pathspec-file --pathspec-from-file=- >actual && + + test_cmp expect actual +' + +test_expect_success 'no trailing delimiter' ' + cat >expect <<-\EOF && + fileA.t + fileB.t + EOF + + printf "fileA.t\nfileB.t" | + test-tool parse-pathspec-file --pathspec-from-file=- >actual && + + test_cmp expect actual +' + +test_expect_success 'CRLF delimiters' ' + cat >expect <<-\EOF && + fileA.t + fileB.t + EOF + + printf "fileA.t\r\nfileB.t\r\n" | + test-tool parse-pathspec-file --pathspec-from-file=- >actual && + + test_cmp expect actual +' + +test_expect_success 'quotes' ' + cat >expect <<-\EOF && + fileA.t + EOF + + cat >list <<-\EOF && + "file\101.t" + EOF + + test-tool parse-pathspec-file --pathspec-from-file=list >actual && + + test_cmp expect actual +' + +test_expect_success '--pathspec-file-nul takes quotes literally' ' + # Note: there is an extra newline because --pathspec-file-nul takes + # input \n literally, too + cat >expect <<-\EOF && + "file\101.t" + + EOF + + cat >list <<-\EOF && + "file\101.t" + EOF + + test-tool parse-pathspec-file --pathspec-from-file=list --pathspec-file-nul >actual && + + test_cmp expect actual +' + +test_done diff --git a/t/t0095-bloom.sh b/t/t0095-bloom.sh new file mode 100755 index 0000000000..809ec7b0b8 --- /dev/null +++ b/t/t0095-bloom.sh @@ -0,0 +1,117 @@ +#!/bin/sh + +test_description='Testing the various Bloom filter computations in bloom.c' +. ./test-lib.sh + +test_expect_success 'compute unseeded murmur3 hash for empty string' ' + cat >expect <<-\EOF && + Murmur3 Hash with seed=0:0x00000000 + EOF + test-tool bloom get_murmur3 "" >actual && + test_cmp expect actual +' + +test_expect_success 'compute unseeded murmur3 hash for test string 1' ' + cat >expect <<-\EOF && + Murmur3 Hash with seed=0:0x627b0c2c + EOF + test-tool bloom get_murmur3 "Hello world!" >actual && + test_cmp expect actual +' + +test_expect_success 'compute unseeded murmur3 hash for test string 2' ' + cat >expect <<-\EOF && + Murmur3 Hash with seed=0:0x2e4ff723 + EOF + test-tool bloom get_murmur3 "The quick brown fox jumps over the lazy dog" >actual && + test_cmp expect actual +' + +test_expect_success 'compute bloom key for empty string' ' + cat >expect <<-\EOF && + Hashes:0x5615800c|0x5b966560|0x61174ab4|0x66983008|0x6c19155c|0x7199fab0|0x771ae004| + Filter_Length:2 + Filter_Data:11|11| + EOF + test-tool bloom generate_filter "" >actual && + test_cmp expect actual +' + +test_expect_success 'compute bloom key for whitespace' ' + cat >expect <<-\EOF && + Hashes:0xf178874c|0x5f3d6eb6|0xcd025620|0x3ac73d8a|0xa88c24f4|0x16510c5e|0x8415f3c8| + Filter_Length:2 + Filter_Data:51|55| + EOF + test-tool bloom generate_filter " " >actual && + test_cmp expect actual +' + +test_expect_success 'compute bloom key for test string 1' ' + cat >expect <<-\EOF && + Hashes:0xb270de9b|0x1bb6f26e|0x84fd0641|0xee431a14|0x57892de7|0xc0cf41ba|0x2a15558d| + Filter_Length:2 + Filter_Data:92|6c| + EOF + test-tool bloom generate_filter "Hello world!" >actual && + test_cmp expect actual +' + +test_expect_success 'compute bloom key for test string 2' ' + cat >expect <<-\EOF && + Hashes:0x20ab385b|0xf5237fe2|0xc99bc769|0x9e140ef0|0x728c5677|0x47049dfe|0x1b7ce585| + Filter_Length:2 + Filter_Data:a5|4a| + EOF + test-tool bloom generate_filter "file.txt" >actual && + test_cmp expect actual +' + +test_expect_success 'get bloom filters for commit with no changes' ' + git init && + git commit --allow-empty -m "c0" && + cat >expect <<-\EOF && + Filter_Length:0 + Filter_Data: + EOF + test-tool bloom get_filter_for_commit "$(git rev-parse HEAD)" >actual && + test_cmp expect actual +' + +test_expect_success 'get bloom filter for commit with 10 changes' ' + rm actual && + rm expect && + mkdir smallDir && + for i in $(test_seq 0 9) + do + echo $i >smallDir/$i + done && + git add smallDir && + git commit -m "commit with 10 changes" && + cat >expect <<-\EOF && + Filter_Length:25 + Filter_Data:82|a0|65|47|0c|92|90|c0|a1|40|02|a0|e2|40|e0|04|0a|9a|66|cf|80|19|85|42|23| + EOF + test-tool bloom get_filter_for_commit "$(git rev-parse HEAD)" >actual && + test_cmp expect actual +' + +test_expect_success EXPENSIVE 'get bloom filter for commit with 513 changes' ' + rm actual && + rm expect && + mkdir bigDir && + for i in $(test_seq 0 512) + do + echo $i >bigDir/$i + done && + git add bigDir && + git commit -m "commit with 513 changes" && + cat >expect <<-\EOF && + Filter_Length:0 + Filter_Data: + EOF + test-tool bloom get_filter_for_commit "$(git rev-parse HEAD)" >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t0212-trace2-event.sh b/t/t0212-trace2-event.sh index 7065a1b937..1529155cf0 100755 --- a/t/t0212-trace2-event.sh +++ b/t/t0212-trace2-event.sh @@ -199,6 +199,43 @@ test_expect_success JSON_PP 'event stream, list config' ' test_cmp expect actual ' +# Test listing of all "interesting" environment variables. + +test_expect_success JSON_PP 'event stream, list env vars' ' + test_when_finished "rm trace.event actual expect" && + GIT_TRACE2_EVENT="$(pwd)/trace.event" \ + GIT_TRACE2_ENV_VARS="A_VAR,OTHER_VAR,MISSING" \ + A_VAR=1 OTHER_VAR="hello world" test-tool trace2 001return 0 && + perl "$TEST_DIRECTORY/t0212/parse_events.perl" <trace.event >actual && + sed -e "s/^|//" >expect <<-EOF && + |VAR1 = { + | "_SID0_":{ + | "argv":[ + | "_EXE_", + | "trace2", + | "001return", + | "0" + | ], + | "exit_code":0, + | "hierarchy":"trace2", + | "name":"trace2", + | "params":[ + | { + | "param":"A_VAR", + | "value":"1" + | }, + | { + | "param":"OTHER_VAR", + | "value":"hello world" + | } + | ], + | "version":"$V" + | } + |}; + EOF + test_cmp expect actual +' + test_expect_success JSON_PP 'basic trace2_data' ' test_when_finished "rm trace.event actual expect" && GIT_TRACE2_EVENT="$(pwd)/trace.event" test-tool trace2 006data test_category k1 v1 test_category k2 v2 && diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh index 82eaaea0f4..bc2d74098f 100755 --- a/t/t0300-credentials.sh +++ b/t/t0300-credentials.sh @@ -22,6 +22,11 @@ test_expect_success 'setup helper scripts' ' exit 0 EOF + write_script git-credential-quit <<-\EOF && + . ./dump + echo quit=1 + EOF + write_script git-credential-verbatim <<-\EOF && user=$1; shift pass=$1; shift @@ -35,43 +40,71 @@ test_expect_success 'setup helper scripts' ' test_expect_success 'credential_fill invokes helper' ' check fill "verbatim foo bar" <<-\EOF + protocol=http + host=example.com -- + protocol=http + host=example.com username=foo password=bar -- verbatim: get + verbatim: protocol=http + verbatim: host=example.com EOF ' test_expect_success 'credential_fill invokes multiple helpers' ' check fill useless "verbatim foo bar" <<-\EOF + protocol=http + host=example.com -- + protocol=http + host=example.com username=foo password=bar -- useless: get + useless: protocol=http + useless: host=example.com verbatim: get + verbatim: protocol=http + verbatim: host=example.com EOF ' test_expect_success 'credential_fill stops when we get a full response' ' check fill "verbatim one two" "verbatim three four" <<-\EOF + protocol=http + host=example.com -- + protocol=http + host=example.com username=one password=two -- verbatim: get + verbatim: protocol=http + verbatim: host=example.com EOF ' test_expect_success 'credential_fill continues through partial response' ' check fill "verbatim one \"\"" "verbatim two three" <<-\EOF + protocol=http + host=example.com -- + protocol=http + host=example.com username=two password=three -- verbatim: get + verbatim: protocol=http + verbatim: host=example.com verbatim: get + verbatim: protocol=http + verbatim: host=example.com verbatim: username=one EOF ' @@ -97,14 +130,20 @@ test_expect_success 'credential_fill passes along metadata' ' test_expect_success 'credential_approve calls all helpers' ' check approve useless "verbatim one two" <<-\EOF + protocol=http + host=example.com username=foo password=bar -- -- useless: store + useless: protocol=http + useless: host=example.com useless: username=foo useless: password=bar verbatim: store + verbatim: protocol=http + verbatim: host=example.com verbatim: username=foo verbatim: password=bar EOF @@ -112,6 +151,8 @@ test_expect_success 'credential_approve calls all helpers' ' test_expect_success 'do not bother storing password-less credential' ' check approve useless <<-\EOF + protocol=http + host=example.com username=foo -- -- @@ -121,14 +162,20 @@ test_expect_success 'do not bother storing password-less credential' ' test_expect_success 'credential_reject calls all helpers' ' check reject useless "verbatim one two" <<-\EOF + protocol=http + host=example.com username=foo password=bar -- -- useless: erase + useless: protocol=http + useless: host=example.com useless: username=foo useless: password=bar verbatim: erase + verbatim: protocol=http + verbatim: host=example.com verbatim: username=foo verbatim: password=bar EOF @@ -136,33 +183,49 @@ test_expect_success 'credential_reject calls all helpers' ' test_expect_success 'usernames can be preserved' ' check fill "verbatim \"\" three" <<-\EOF + protocol=http + host=example.com username=one -- + protocol=http + host=example.com username=one password=three -- verbatim: get + verbatim: protocol=http + verbatim: host=example.com verbatim: username=one EOF ' test_expect_success 'usernames can be overridden' ' check fill "verbatim two three" <<-\EOF + protocol=http + host=example.com username=one -- + protocol=http + host=example.com username=two password=three -- verbatim: get + verbatim: protocol=http + verbatim: host=example.com verbatim: username=one EOF ' test_expect_success 'do not bother completing already-full credential' ' check fill "verbatim three four" <<-\EOF + protocol=http + host=example.com username=one password=two -- + protocol=http + host=example.com username=one password=two -- @@ -174,23 +237,31 @@ test_expect_success 'do not bother completing already-full credential' ' # askpass helper is run, we know the internal getpass is working. test_expect_success 'empty helper list falls back to internal getpass' ' check fill <<-\EOF + protocol=http + host=example.com -- + protocol=http + host=example.com username=askpass-username password=askpass-password -- - askpass: Username: - askpass: Password: + askpass: Username for '\''http://example.com'\'': + askpass: Password for '\''http://askpass-username@example.com'\'': EOF ' test_expect_success 'internal getpass does not ask for known username' ' check fill <<-\EOF + protocol=http + host=example.com username=foo -- + protocol=http + host=example.com username=foo password=askpass-password -- - askpass: Password: + askpass: Password for '\''http://foo@example.com'\'': EOF ' @@ -202,7 +273,11 @@ HELPER="!f() { test_expect_success 'respect configured credentials' ' test_config credential.helper "$HELPER" && check fill <<-\EOF + protocol=http + host=example.com -- + protocol=http + host=example.com username=foo password=bar -- @@ -240,6 +315,102 @@ test_expect_success 'do not match configured credential' ' EOF ' +test_expect_success 'match multiple configured helpers' ' + test_config credential.helper "verbatim \"\" \"\"" && + test_config credential.https://example.com.helper "$HELPER" && + check fill <<-\EOF + protocol=https + host=example.com + path=repo.git + -- + protocol=https + host=example.com + username=foo + password=bar + -- + verbatim: get + verbatim: protocol=https + verbatim: host=example.com + EOF +' + +test_expect_success 'match multiple configured helpers with URLs' ' + test_config credential.https://example.com/repo.git.helper "verbatim \"\" \"\"" && + test_config credential.https://example.com.helper "$HELPER" && + check fill <<-\EOF + protocol=https + host=example.com + path=repo.git + -- + protocol=https + host=example.com + username=foo + password=bar + -- + verbatim: get + verbatim: protocol=https + verbatim: host=example.com + EOF +' + +test_expect_success 'match percent-encoded values' ' + test_config credential.https://example.com/%2566.git.helper "$HELPER" && + check fill <<-\EOF + url=https://example.com/%2566.git + -- + protocol=https + host=example.com + username=foo + password=bar + -- + EOF +' + +test_expect_success 'match percent-encoded UTF-8 values in path' ' + test_config credential.https://example.com.useHttpPath true && + test_config credential.https://example.com/perú.git.helper "$HELPER" && + check fill <<-\EOF + url=https://example.com/per%C3%BA.git + -- + protocol=https + host=example.com + path=perú.git + username=foo + password=bar + -- + EOF +' + +test_expect_success 'match percent-encoded values in username' ' + test_config credential.https://user%2fname@example.com/foo/bar.git.helper "$HELPER" && + check fill <<-\EOF + url=https://user%2fname@example.com/foo/bar.git + -- + protocol=https + host=example.com + username=foo + password=bar + -- + EOF +' + +test_expect_success 'fetch with multiple path components' ' + test_unconfig credential.helper && + test_config credential.https://example.com/foo/repo.git.helper "verbatim foo bar" && + check fill <<-\EOF + url=https://example.com/foo/repo.git + -- + protocol=https + host=example.com + username=foo + password=bar + -- + verbatim: get + verbatim: protocol=https + verbatim: host=example.com + EOF +' + test_expect_success 'pull username from config' ' test_config credential.https://example.com.username foo && check fill <<-\EOF @@ -255,6 +426,63 @@ test_expect_success 'pull username from config' ' EOF ' +test_expect_success 'honors username from URL over helper (URL)' ' + test_config credential.https://example.com.username bob && + test_config credential.https://example.com.helper "verbatim \"\" bar" && + check fill <<-\EOF + url=https://alice@example.com + -- + protocol=https + host=example.com + username=alice + password=bar + -- + verbatim: get + verbatim: protocol=https + verbatim: host=example.com + verbatim: username=alice + EOF +' + +test_expect_success 'honors username from URL over helper (components)' ' + test_config credential.https://example.com.username bob && + test_config credential.https://example.com.helper "verbatim \"\" bar" && + check fill <<-\EOF + protocol=https + host=example.com + username=alice + -- + protocol=https + host=example.com + username=alice + password=bar + -- + verbatim: get + verbatim: protocol=https + verbatim: host=example.com + verbatim: username=alice + EOF +' + +test_expect_success 'last matching username wins' ' + test_config credential.https://example.com/path.git.username bob && + test_config credential.https://example.com.username alice && + test_config credential.https://example.com.helper "verbatim \"\" bar" && + check fill <<-\EOF + url=https://example.com/path.git + -- + protocol=https + host=example.com + username=alice + password=bar + -- + verbatim: get + verbatim: protocol=https + verbatim: host=example.com + verbatim: username=alice + EOF +' + test_expect_success 'http paths can be part of context' ' check fill "verbatim foo bar" <<-\EOF && protocol=https @@ -289,23 +517,179 @@ test_expect_success 'http paths can be part of context' ' EOF ' +test_expect_success 'context uses urlmatch' ' + test_config "credential.https://*.org.useHttpPath" true && + check fill "verbatim foo bar" <<-\EOF + protocol=https + host=example.org + path=foo.git + -- + protocol=https + host=example.org + path=foo.git + username=foo + password=bar + -- + verbatim: get + verbatim: protocol=https + verbatim: host=example.org + verbatim: path=foo.git + EOF +' + test_expect_success 'helpers can abort the process' ' test_must_fail git \ - -c credential.helper="!f() { echo quit=1; }; f" \ + -c credential.helper=quit \ -c credential.helper="verbatim foo bar" \ - credential fill >stdout && - test_must_be_empty stdout + credential fill >stdout 2>stderr <<-\EOF && + protocol=http + host=example.com + EOF + test_must_be_empty stdout && + cat >expect <<-\EOF && + quit: get + quit: protocol=http + quit: host=example.com + fatal: credential helper '\''quit'\'' told us to quit + EOF + test_i18ncmp expect stderr ' test_expect_success 'empty helper spec resets helper list' ' test_config credential.helper "verbatim file file" && check fill "" "verbatim cmdline cmdline" <<-\EOF + protocol=http + host=example.com -- + protocol=http + host=example.com username=cmdline password=cmdline -- verbatim: get + verbatim: protocol=http + verbatim: host=example.com + EOF +' + +test_expect_success 'url parser rejects embedded newlines' ' + test_must_fail git credential fill 2>stderr <<-\EOF && + url=https://one.example.com?%0ahost=two.example.com/ + EOF + cat >expect <<-\EOF && + warning: url contains a newline in its path component: https://one.example.com?%0ahost=two.example.com/ + fatal: credential url cannot be parsed: https://one.example.com?%0ahost=two.example.com/ + EOF + test_i18ncmp expect stderr +' + +test_expect_success 'host-less URLs are parsed as empty host' ' + check fill "verbatim foo bar" <<-\EOF + url=cert:///path/to/cert.pem + -- + protocol=cert + host= + path=path/to/cert.pem + username=foo + password=bar + -- + verbatim: get + verbatim: protocol=cert + verbatim: host= + verbatim: path=path/to/cert.pem EOF ' +test_expect_success 'credential system refuses to work with missing host' ' + test_must_fail git credential fill 2>stderr <<-\EOF && + protocol=http + EOF + cat >expect <<-\EOF && + fatal: refusing to work with credential missing host field + EOF + test_i18ncmp expect stderr +' + +test_expect_success 'credential system refuses to work with missing protocol' ' + test_must_fail git credential fill 2>stderr <<-\EOF && + host=example.com + EOF + cat >expect <<-\EOF && + fatal: refusing to work with credential missing protocol field + EOF + test_i18ncmp expect stderr +' + +# usage: check_host_and_path <url> <expected-host> <expected-path> +check_host_and_path () { + # we always parse the path component, but we need this to make sure it + # is passed to the helper + test_config credential.useHTTPPath true && + check fill "verbatim user pass" <<-EOF + url=$1 + -- + protocol=https + host=$2 + path=$3 + username=user + password=pass + -- + verbatim: get + verbatim: protocol=https + verbatim: host=$2 + verbatim: path=$3 + EOF +} + +test_expect_success 'url parser handles bare query marker' ' + check_host_and_path https://example.com?foo.git example.com ?foo.git +' + +test_expect_success 'url parser handles bare fragment marker' ' + check_host_and_path https://example.com#foo.git example.com "#foo.git" +' + +test_expect_success 'url parser not confused by encoded markers' ' + check_host_and_path https://example.com%23%3f%2f/foo.git \ + "example.com#?/" foo.git +' + +test_expect_success 'credential config with partial URLs' ' + echo "echo password=yep" | write_script git-credential-yep && + test_write_lines url=https://user@example.com/repo.git >stdin && + for partial in \ + example.com \ + user@example.com \ + https:// \ + https://example.com \ + https://example.com/ \ + https://user@example.com \ + https://user@example.com/ \ + https://example.com/repo.git \ + https://user@example.com/repo.git \ + /repo.git + do + git -c credential.$partial.helper=yep \ + credential fill <stdin >stdout && + grep yep stdout || + return 1 + done && + + for partial in \ + dont.use.this \ + http:// \ + /repo + do + git -c credential.$partial.helper=yep \ + credential fill <stdin >stdout && + ! grep yep stdout || + return 1 + done && + + git -c credential.$partial.helper=yep \ + -c credential.with%0anewline.username=uh-oh \ + credential fill <stdin >stdout 2>stderr && + test_i18ngrep "skipping credential lookup for key" stderr +' + test_done diff --git a/t/t0302-credential-store.sh b/t/t0302-credential-store.sh index d6b54e8c65..716bf1af9f 100755 --- a/t/t0302-credential-store.sh +++ b/t/t0302-credential-store.sh @@ -107,7 +107,6 @@ test_expect_success 'store: if both xdg and home files exist, only store in home test_must_be_empty "$HOME/.config/git/credentials" ' - test_expect_success 'erase: erase matching credentials from both xdg and home files' ' echo "https://home-user:home-pass@example.com" >"$HOME/.git-credentials" && mkdir -p "$HOME/.config/git" && @@ -120,4 +119,94 @@ test_expect_success 'erase: erase matching credentials from both xdg and home fi test_must_be_empty "$HOME/.config/git/credentials" ' +invalid_credential_test() { + test_expect_success "get: ignore credentials without $1 as invalid" ' + echo "$2" >"$HOME/.git-credentials" && + check fill store <<-\EOF + protocol=https + host=example.com + -- + protocol=https + host=example.com + username=askpass-username + password=askpass-password + -- + askpass: Username for '\''https://example.com'\'': + askpass: Password for '\''https://askpass-username@example.com'\'': + -- + EOF + ' +} + +invalid_credential_test "scheme" ://user:pass@example.com +invalid_credential_test "valid host/path" https://user:pass@ +invalid_credential_test "username/password" https://pass@example.com + +test_expect_success 'get: credentials with DOS line endings are invalid' ' + printf "https://user:pass@example.com\r\n" >"$HOME/.git-credentials" && + check fill store <<-\EOF + protocol=https + host=example.com + -- + protocol=https + host=example.com + username=askpass-username + password=askpass-password + -- + askpass: Username for '\''https://example.com'\'': + askpass: Password for '\''https://askpass-username@example.com'\'': + -- + EOF +' + +test_expect_success 'get: credentials with path and DOS line endings are valid' ' + printf "https://user:pass@example.com/repo.git\r\n" >"$HOME/.git-credentials" && + check fill store <<-\EOF + url=https://example.com/repo.git + -- + protocol=https + host=example.com + username=user + password=pass + -- + EOF +' + +test_expect_success 'get: credentials with DOS line endings are invalid if path is relevant' ' + printf "https://user:pass@example.com/repo.git\r\n" >"$HOME/.git-credentials" && + test_config credential.useHttpPath true && + check fill store <<-\EOF + url=https://example.com/repo.git + -- + protocol=https + host=example.com + path=repo.git + username=askpass-username + password=askpass-password + -- + askpass: Username for '\''https://example.com/repo.git'\'': + askpass: Password for '\''https://askpass-username@example.com/repo.git'\'': + -- + EOF +' + +test_expect_success 'get: store file can contain empty/bogus lines' ' + echo "" >"$HOME/.git-credentials" && + q_to_tab <<-\CREDENTIAL >>"$HOME/.git-credentials" && + #comment + Q + https://user:pass@example.com + CREDENTIAL + check fill store <<-\EOF + protocol=https + host=example.com + -- + protocol=https + host=example.com + username=user + password=pass + -- + EOF +' + test_done diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh index eb44bafb59..140f459977 100755 --- a/t/t1011-read-tree-sparse-checkout.sh +++ b/t/t1011-read-tree-sparse-checkout.sh @@ -74,13 +74,19 @@ test_expect_success 'read-tree --no-sparse-checkout with empty .git/info/sparse- test_expect_success 'read-tree with empty .git/info/sparse-checkout' ' git config core.sparsecheckout true && echo >.git/info/sparse-checkout && - read_tree_u_must_fail -m -u HEAD && + read_tree_u_must_succeed -m -u HEAD && git ls-files --stage >result && test_cmp expected result && git ls-files -t >result && + cat >expected.swt <<-\EOF && + S init.t + S sub/added + S sub/addedtoo + S subsub/added + EOF test_cmp expected.swt result && - test -f init.t && - test -f sub/added + ! test -f init.t && + ! test -f sub/added ' test_expect_success 'match directories with trailing slash' ' @@ -233,18 +239,19 @@ test_expect_success 'read-tree --reset removes outside worktree' ' test_must_be_empty result ' -test_expect_success 'print errors when failed to update worktree' ' +test_expect_success 'print warnings when some worktree updates disabled' ' echo sub >.git/info/sparse-checkout && git checkout -f init && mkdir sub && touch sub/added sub/addedtoo && - test_must_fail git checkout top 2>actual && + # Use -q to suppress "Previous HEAD position" and "Head is now at" msgs + git checkout -q top 2>actual && cat >expected <<\EOF && -error: The following untracked working tree files would be overwritten by checkout: +warning: The following paths were already present and thus not updated despite sparse patterns: sub/added sub/addedtoo -Please move or remove them before you switch branches. -Aborting + +After fixing the above paths, you may want to run `git sparse-checkout reapply`. EOF test_i18ncmp expected actual ' diff --git a/t/t1050-large.sh b/t/t1050-large.sh index d3b2adb28b..184b479a21 100755 --- a/t/t1050-large.sh +++ b/t/t1050-large.sh @@ -53,7 +53,8 @@ test_expect_success 'add a large file or two' ' for p in .git/objects/pack/pack-*.pack do count=$(( $count + 1 )) - if test -f "$p" && idx=${p%.pack}.idx && test -f "$idx" + if test_path_is_file "$p" && + idx=${p%.pack}.idx && test_path_is_file "$idx" then continue fi @@ -65,7 +66,7 @@ test_expect_success 'add a large file or two' ' test $cnt = 2 && for l in .git/objects/??/?????????????????????????????????????? do - test -f "$l" || continue + test_path_is_file "$l" || continue bad=t done && test -z "$bad" && @@ -76,7 +77,8 @@ test_expect_success 'add a large file or two' ' for p in .git/objects/pack/pack-*.pack do count=$(( $count + 1 )) - if test -f "$p" && idx=${p%.pack}.idx && test -f "$idx" + if test_path_is_file "$p" && + idx=${p%.pack}.idx && test_path_is_file "$idx" then continue fi @@ -111,7 +113,7 @@ test_expect_success 'packsize limit' ' count=0 && for pi in .git/objects/pack/pack-*.idx do - test -f "$pi" && count=$(( $count + 1 )) + test_path_is_file "$pi" && count=$(( $count + 1 )) done && test $count = 2 && diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh index ff7f8f7a1f..88cdde255c 100755 --- a/t/t1091-sparse-checkout-builtin.sh +++ b/t/t1091-sparse-checkout-builtin.sh @@ -12,6 +12,13 @@ list_files() { (cd "$1" && printf '%s\n' *) } +check_files() { + list_files "$1" >actual && + shift && + printf "%s\n" $@ >expect && + test_cmp expect actual +} + test_expect_success 'setup' ' git init repo && ( @@ -39,11 +46,11 @@ test_expect_success 'git sparse-checkout list (empty)' ' test_expect_success 'git sparse-checkout list (populated)' ' test_when_finished rm -f repo/.git/info/sparse-checkout && - cat >repo/.git/info/sparse-checkout <<-EOF && - /folder1/* - /deep/ - **/a - !*bin* + cat >repo/.git/info/sparse-checkout <<-\EOF && + /folder1/* + /deep/ + **/a + !*bin* EOF cp repo/.git/info/sparse-checkout expect && git -C repo sparse-checkout list >list && @@ -52,22 +59,20 @@ test_expect_success 'git sparse-checkout list (populated)' ' test_expect_success 'git sparse-checkout init' ' git -C repo sparse-checkout init && - cat >expect <<-EOF && - /* - !/*/ + cat >expect <<-\EOF && + /* + !/*/ EOF test_cmp expect repo/.git/info/sparse-checkout && test_cmp_config -C repo true core.sparsecheckout && - list_files repo >dir && - echo a >expect && - test_cmp expect dir + check_files repo a ' test_expect_success 'git sparse-checkout list after init' ' git -C repo sparse-checkout list >actual && - cat >expect <<-EOF && - /* - !/*/ + cat >expect <<-\EOF && + /* + !/*/ EOF test_cmp expect actual ' @@ -75,32 +80,24 @@ test_expect_success 'git sparse-checkout list after init' ' test_expect_success 'init with existing sparse-checkout' ' echo "*folder*" >> repo/.git/info/sparse-checkout && git -C repo sparse-checkout init && - cat >expect <<-EOF && - /* - !/*/ - *folder* + cat >expect <<-\EOF && + /* + !/*/ + *folder* EOF test_cmp expect repo/.git/info/sparse-checkout && - list_files repo >dir && - cat >expect <<-EOF && - a - folder1 - folder2 - EOF - test_cmp expect dir + check_files repo a folder1 folder2 ' test_expect_success 'clone --sparse' ' - git clone --sparse repo clone && + git clone --sparse "file://$(pwd)/repo" clone && git -C clone sparse-checkout list >actual && - cat >expect <<-EOF && - /* - !/*/ + cat >expect <<-\EOF && + /* + !/*/ EOF test_cmp expect actual && - list_files clone >dir && - echo a >expect && - test_cmp expect dir + check_files clone a ' test_expect_success 'set enables config' ' @@ -109,51 +106,52 @@ test_expect_success 'set enables config' ' cd empty-config && test_commit test file && test_path_is_missing .git/config.worktree && - test_must_fail git sparse-checkout set nothing && + git sparse-checkout set nothing && test_path_is_file .git/config.worktree && - test_must_fail git config core.sparseCheckout && - git sparse-checkout set "/*" && test_cmp_config true core.sparseCheckout ) ' test_expect_success 'set sparse-checkout using builtin' ' git -C repo sparse-checkout set "/*" "!/*/" "*folder*" && - cat >expect <<-EOF && - /* - !/*/ - *folder* + cat >expect <<-\EOF && + /* + !/*/ + *folder* EOF git -C repo sparse-checkout list >actual && test_cmp expect actual && test_cmp expect repo/.git/info/sparse-checkout && - list_files repo >dir && - cat >expect <<-EOF && - a - folder1 - folder2 - EOF - test_cmp expect dir + check_files repo a folder1 folder2 ' test_expect_success 'set sparse-checkout using --stdin' ' - cat >expect <<-EOF && - /* - !/*/ - /folder1/ - /folder2/ + cat >expect <<-\EOF && + /* + !/*/ + /folder1/ + /folder2/ EOF git -C repo sparse-checkout set --stdin <expect && git -C repo sparse-checkout list >actual && test_cmp expect actual && test_cmp expect repo/.git/info/sparse-checkout && - list_files repo >dir && - cat >expect <<-EOF && - a - folder1 - folder2 + check_files repo "a folder1 folder2" +' + +test_expect_success 'add to sparse-checkout' ' + cat repo/.git/info/sparse-checkout >expect && + cat >add <<-\EOF && + pattern1 + /folder1/ + pattern2 EOF - test_cmp expect dir + cat add >>expect && + git -C repo sparse-checkout add --stdin <add && + git -C repo sparse-checkout list >actual && + test_cmp expect actual && + test_cmp expect repo/.git/info/sparse-checkout && + check_files repo "a folder1 folder2" ' test_expect_success 'cone mode: match patterns' ' @@ -162,13 +160,7 @@ test_expect_success 'cone mode: match patterns' ' git -C repo read-tree -mu HEAD 2>err && test_i18ngrep ! "disabling cone patterns" err && git -C repo reset --hard && - list_files repo >dir && - cat >expect <<-EOF && - a - folder1 - folder2 - EOF - test_cmp expect dir + check_files repo a folder1 folder2 ' test_expect_success 'cone mode: warn on bad pattern' ' @@ -185,14 +177,7 @@ test_expect_success 'sparse-checkout disable' ' test_path_is_file repo/.git/info/sparse-checkout && git -C repo config --list >config && test_must_fail git config core.sparseCheckout && - list_files repo >dir && - cat >expect <<-EOF && - a - deep - folder1 - folder2 - EOF - test_cmp expect dir + check_files repo a deep folder1 folder2 ' test_expect_success 'cone mode: init and set' ' @@ -204,52 +189,31 @@ test_expect_success 'cone mode: init and set' ' test_cmp expect dir && git -C repo sparse-checkout set deep/deeper1/deepest/ 2>err && test_must_be_empty err && - list_files repo >dir && - cat >expect <<-EOF && - a - deep - EOF - test_cmp expect dir && - list_files repo/deep >dir && - cat >expect <<-EOF && - a - deeper1 - EOF - test_cmp expect dir && - list_files repo/deep/deeper1 >dir && - cat >expect <<-EOF && - a - deepest - EOF - test_cmp expect dir && - cat >expect <<-EOF && - /* - !/*/ - /deep/ - !/deep/*/ - /deep/deeper1/ - !/deep/deeper1/*/ - /deep/deeper1/deepest/ + check_files repo a deep && + check_files repo/deep a deeper1 && + check_files repo/deep/deeper1 a deepest && + cat >expect <<-\EOF && + /* + !/*/ + /deep/ + !/deep/*/ + /deep/deeper1/ + !/deep/deeper1/*/ + /deep/deeper1/deepest/ EOF test_cmp expect repo/.git/info/sparse-checkout && - git -C repo sparse-checkout set --stdin 2>err <<-EOF && - folder1 - folder2 + git -C repo sparse-checkout set --stdin 2>err <<-\EOF && + folder1 + folder2 EOF test_must_be_empty err && - cat >expect <<-EOF && - a - folder1 - folder2 - EOF - list_files repo >dir && - test_cmp expect dir + check_files repo a folder1 folder2 ' test_expect_success 'cone mode: list' ' - cat >expect <<-EOF && - folder1 - folder2 + cat >expect <<-\EOF && + folder1 + folder2 EOF git -C repo sparse-checkout set --stdin <expect && git -C repo sparse-checkout list >actual 2>err && @@ -260,28 +224,74 @@ test_expect_success 'cone mode: list' ' test_expect_success 'cone mode: set with nested folders' ' git -C repo sparse-checkout set deep deep/deeper1/deepest 2>err && test_line_count = 0 err && - cat >expect <<-EOF && - /* - !/*/ - /deep/ + cat >expect <<-\EOF && + /* + !/*/ + /deep/ EOF test_cmp repo/.git/info/sparse-checkout expect ' -test_expect_success 'revert to old sparse-checkout on bad update' ' +test_expect_success 'cone mode: add independent path' ' + git -C repo sparse-checkout set deep/deeper1 && + git -C repo sparse-checkout add folder1 && + cat >expect <<-\EOF && + /* + !/*/ + /deep/ + !/deep/*/ + /deep/deeper1/ + /folder1/ + EOF + test_cmp expect repo/.git/info/sparse-checkout && + check_files repo a deep folder1 +' + +test_expect_success 'cone mode: add sibling path' ' + git -C repo sparse-checkout set deep/deeper1 && + git -C repo sparse-checkout add deep/deeper2 && + cat >expect <<-\EOF && + /* + !/*/ + /deep/ + !/deep/*/ + /deep/deeper1/ + /deep/deeper2/ + EOF + test_cmp expect repo/.git/info/sparse-checkout && + check_files repo a deep +' + +test_expect_success 'cone mode: add parent path' ' + git -C repo sparse-checkout set deep/deeper1 folder1 && + git -C repo sparse-checkout add deep && + cat >expect <<-\EOF && + /* + !/*/ + /deep/ + /folder1/ + EOF + test_cmp expect repo/.git/info/sparse-checkout && + check_files repo a deep folder1 +' + +test_expect_success 'not-up-to-date does not block rest of sparsification' ' + test_when_finished git -C repo sparse-checkout disable && test_when_finished git -C repo reset --hard && + git -C repo sparse-checkout set deep && + echo update >repo/deep/deeper2/a && cp repo/.git/info/sparse-checkout expect && - test_must_fail git -C repo sparse-checkout set deep/deeper1 2>err && - test_i18ngrep "cannot set sparse-checkout patterns" err && - test_cmp repo/.git/info/sparse-checkout expect && - list_files repo/deep >dir && - cat >expect <<-EOF && - a - deeper1 - deeper2 - EOF - test_cmp dir expect + test_write_lines "!/deep/*/" "/deep/deeper1/" >>expect && + + git -C repo sparse-checkout set deep/deeper1 2>err && + + test_i18ngrep "The following paths are not up to date" err && + test_cmp expect repo/.git/info/sparse-checkout && + check_files repo/deep a deeper1 deeper2 && + check_files repo/deep/deeper1 a deepest && + check_files repo/deep/deeper1/deepest a && + check_files repo/deep/deeper2 a ' test_expect_success 'revert to old sparse-checkout on empty update' ' @@ -290,8 +300,8 @@ test_expect_success 'revert to old sparse-checkout on empty update' ' echo >file && git add file && git commit -m "test" && - test_must_fail git sparse-checkout set nothing 2>err && - test_i18ngrep "Sparse checkout leaves no entry on working directory" err && + git sparse-checkout set nothing 2>err && + test_i18ngrep ! "Sparse checkout leaves no entry on working directory" err && test_i18ngrep ! ".git/index.lock" err && git sparse-checkout set file ) @@ -301,7 +311,7 @@ test_expect_success 'fail when lock is taken' ' test_when_finished rm -rf repo/.git/info/sparse-checkout.lock && touch repo/.git/info/sparse-checkout.lock && test_must_fail git -C repo sparse-checkout set deep 2>err && - test_i18ngrep "File exists" err + test_i18ngrep "Unable to create .*\.lock" err ' test_expect_success '.gitignore should not warn about cone mode' ' @@ -311,33 +321,105 @@ test_expect_success '.gitignore should not warn about cone mode' ' test_i18ngrep ! "disabling cone patterns" err ' -test_expect_success 'sparse-checkout (init|set|disable) fails with dirty status' ' +test_expect_success 'sparse-checkout (init|set|disable) warns with dirty status' ' git clone repo dirty && echo dirty >dirty/folder1/a && - test_must_fail git -C dirty sparse-checkout init && - test_must_fail git -C dirty sparse-checkout set /folder2/* /deep/deeper1/* && - test_must_fail git -C dirty sparse-checkout disable && + + git -C dirty sparse-checkout init 2>err && + test_i18ngrep "warning.*The following paths are not up to date" err && + + git -C dirty sparse-checkout set /folder2/* /deep/deeper1/* 2>err && + test_i18ngrep "warning.*The following paths are not up to date" err && + test_path_is_file dirty/folder1/a && + + git -C dirty sparse-checkout disable 2>err && + test_must_be_empty err && + git -C dirty reset --hard && git -C dirty sparse-checkout init && git -C dirty sparse-checkout set /folder2/* /deep/deeper1/* && - git -C dirty sparse-checkout disable + test_path_is_missing dirty/folder1/a && + git -C dirty sparse-checkout disable && + test_path_is_file dirty/folder1/a +' + +test_expect_success 'sparse-checkout (init|set|disable) warns with unmerged status' ' + git clone repo unmerged && + + cat >input <<-EOF && + 0 0000000000000000000000000000000000000000 folder1/a + 100644 $(git -C unmerged rev-parse HEAD:folder1/a) 1 folder1/a + EOF + git -C unmerged update-index --index-info <input && + + git -C unmerged sparse-checkout init 2>err && + test_i18ngrep "warning.*The following paths are unmerged" err && + + git -C unmerged sparse-checkout set /folder2/* /deep/deeper1/* 2>err && + test_i18ngrep "warning.*The following paths are unmerged" err && + test_path_is_file dirty/folder1/a && + + git -C unmerged sparse-checkout disable 2>err && + test_i18ngrep "warning.*The following paths are unmerged" err && + + git -C unmerged reset --hard && + git -C unmerged sparse-checkout init && + git -C unmerged sparse-checkout set /folder2/* /deep/deeper1/* && + git -C unmerged sparse-checkout disable +' + +test_expect_success 'sparse-checkout reapply' ' + git clone repo tweak && + + echo dirty >tweak/deep/deeper2/a && + + cat >input <<-EOF && + 0 0000000000000000000000000000000000000000 folder1/a + 100644 $(git -C tweak rev-parse HEAD:folder1/a) 1 folder1/a + EOF + git -C tweak update-index --index-info <input && + + git -C tweak sparse-checkout init --cone 2>err && + test_i18ngrep "warning.*The following paths are not up to date" err && + test_i18ngrep "warning.*The following paths are unmerged" err && + + git -C tweak sparse-checkout set folder2 deep/deeper1 2>err && + test_i18ngrep "warning.*The following paths are not up to date" err && + test_i18ngrep "warning.*The following paths are unmerged" err && + + git -C tweak sparse-checkout reapply 2>err && + test_i18ngrep "warning.*The following paths are not up to date" err && + test_path_is_file tweak/deep/deeper2/a && + test_i18ngrep "warning.*The following paths are unmerged" err && + test_path_is_file tweak/folder1/a && + + git -C tweak checkout HEAD deep/deeper2/a && + git -C tweak sparse-checkout reapply 2>err && + test_i18ngrep ! "warning.*The following paths are not up to date" err && + test_path_is_missing tweak/deep/deeper2/a && + test_i18ngrep "warning.*The following paths are unmerged" err && + test_path_is_file tweak/folder1/a && + + git -C tweak add folder1/a && + git -C tweak sparse-checkout reapply 2>err && + test_must_be_empty err && + test_path_is_missing tweak/deep/deeper2/a && + test_path_is_missing tweak/folder1/a && + + git -C tweak sparse-checkout disable ' test_expect_success 'cone mode: set with core.ignoreCase=true' ' + rm repo/.git/info/sparse-checkout && git -C repo sparse-checkout init --cone && git -C repo -c core.ignoreCase=true sparse-checkout set folder1 && - cat >expect <<-EOF && - /* - !/*/ - /folder1/ + cat >expect <<-\EOF && + /* + !/*/ + /folder1/ EOF test_cmp expect repo/.git/info/sparse-checkout && - list_files repo >dir && - cat >expect <<-EOF && - a - folder1 - EOF - test_cmp expect dir + check_files repo a folder1 ' test_expect_success 'interaction with submodules' ' @@ -351,21 +433,175 @@ test_expect_success 'interaction with submodules' ' git sparse-checkout init --cone && git sparse-checkout set folder1 ) && - list_files super >dir && + check_files super a folder1 modules && + check_files super/modules/child a deep folder1 folder2 +' + +test_expect_success 'different sparse-checkouts with worktrees' ' + git -C repo worktree add --detach ../worktree && + check_files worktree "a deep folder1 folder2" && + git -C worktree sparse-checkout init --cone && + git -C repo sparse-checkout set folder1 && + git -C worktree sparse-checkout set deep/deeper1 && + check_files repo a folder1 && + check_files worktree a deep +' + +test_expect_success 'set using filename keeps file on-disk' ' + git -C repo sparse-checkout set a deep && cat >expect <<-\EOF && - a - folder1 - modules + /* + !/*/ + /a/ + /deep/ EOF - test_cmp expect dir && - list_files super/modules/child >dir && + test_cmp expect repo/.git/info/sparse-checkout && + check_files repo a deep +' + +check_read_tree_errors () { + REPO=$1 + FILES=$2 + ERRORS=$3 + git -C $REPO -c core.sparseCheckoutCone=false read-tree -mu HEAD 2>err && + test_must_be_empty err && + check_files $REPO "$FILES" && + git -C $REPO read-tree -mu HEAD 2>err && + if test -z "$ERRORS" + then + test_must_be_empty err + else + test_i18ngrep "$ERRORS" err + fi && + check_files $REPO $FILES +} + +test_expect_success 'pattern-checks: /A/**' ' + cat >repo/.git/info/sparse-checkout <<-\EOF && + /* + !/*/ + /folder1/** + EOF + check_read_tree_errors repo "a folder1" "disabling cone pattern matching" +' + +test_expect_success 'pattern-checks: /A/**/B/' ' + cat >repo/.git/info/sparse-checkout <<-\EOF && + /* + !/*/ + /deep/**/deepest + EOF + check_read_tree_errors repo "a deep" "disabling cone pattern matching" && + check_files repo/deep "deeper1" && + check_files repo/deep/deeper1 "deepest" +' + +test_expect_success 'pattern-checks: too short' ' + cat >repo/.git/info/sparse-checkout <<-\EOF && + /* + !/*/ + / + EOF + check_read_tree_errors repo "a" "disabling cone pattern matching" +' +test_expect_success 'pattern-checks: not too short' ' + cat >repo/.git/info/sparse-checkout <<-\EOF && + /* + !/*/ + /b/ + EOF + git -C repo read-tree -mu HEAD 2>err && + test_must_be_empty err && + check_files repo a +' + +test_expect_success 'pattern-checks: trailing "*"' ' + cat >repo/.git/info/sparse-checkout <<-\EOF && + /* + !/*/ + /a* + EOF + check_read_tree_errors repo "a" "disabling cone pattern matching" +' + +test_expect_success 'pattern-checks: starting "*"' ' + cat >repo/.git/info/sparse-checkout <<-\EOF && + /* + !/*/ + *eep/ + EOF + check_read_tree_errors repo "a deep" "disabling cone pattern matching" +' + +test_expect_success 'pattern-checks: contained glob characters' ' + for c in "[a]" "\\" "?" "*" + do + cat >repo/.git/info/sparse-checkout <<-EOF && + /* + !/*/ + something$c-else/ + EOF + check_read_tree_errors repo "a" "disabling cone pattern matching" + done +' + +test_expect_success BSLASHPSPEC 'pattern-checks: escaped characters' ' + git clone repo escaped && + TREEOID=$(git -C escaped rev-parse HEAD:folder1) && + NEWTREE=$(git -C escaped mktree <<-EOF + $(git -C escaped ls-tree HEAD) + 040000 tree $TREEOID zbad\\dir + 040000 tree $TREEOID zdoes*exist + 040000 tree $TREEOID zglob[!a]? + EOF + ) && + COMMIT=$(git -C escaped commit-tree $NEWTREE -p HEAD) && + git -C escaped reset --hard $COMMIT && + check_files escaped "a deep folder1 folder2 zbad\\dir zdoes*exist" zglob[!a]? && + git -C escaped sparse-checkout init --cone && + git -C escaped sparse-checkout set zbad\\dir/bogus "zdoes*not*exist" "zdoes*exist" "zglob[!a]?" && cat >expect <<-\EOF && - a - deep - folder1 - folder2 + /* + !/*/ + /zbad\\dir/ + !/zbad\\dir/*/ + /zbad\\dir/bogus/ + /zdoes\*exist/ + /zdoes\*not\*exist/ + /zglob\[!a]\?/ EOF - test_cmp expect dir + test_cmp expect escaped/.git/info/sparse-checkout && + check_read_tree_errors escaped "a zbad\\dir zdoes*exist zglob[!a]?" && + git -C escaped ls-tree -d --name-only HEAD >list-expect && + git -C escaped sparse-checkout set --stdin <list-expect && + cat >expect <<-\EOF && + /* + !/*/ + /deep/ + /folder1/ + /folder2/ + /zbad\\dir/ + /zdoes\*exist/ + /zglob\[!a]\?/ + EOF + test_cmp expect escaped/.git/info/sparse-checkout && + check_files escaped "a deep folder1 folder2 zbad\\dir zdoes*exist" zglob[!a]? && + git -C escaped sparse-checkout list >list-actual && + test_cmp list-expect list-actual +' + +test_expect_success MINGW 'cone mode replaces backslashes with slashes' ' + git -C repo sparse-checkout set deep\\deeper1 && + cat >expect <<-\EOF && + /* + !/*/ + /deep/ + !/deep/*/ + /deep/deeper1/ + EOF + test_cmp expect repo/.git/info/sparse-checkout && + check_files repo a deep && + check_files repo/deep a deeper1 ' test_done diff --git a/t/t1300-config.sh b/t/t1300-config.sh index 5464c46c18..97ebfe1f9d 100755 --- a/t/t1300-config.sh +++ b/t/t1300-config.sh @@ -1408,6 +1408,8 @@ test_expect_success 'urlmatch favors more specific URLs' ' cookieFile = /tmp/wildcard.txt [http "https://*.example.com/wildcardwithsubdomain"] cookieFile = /tmp/wildcardwithsubdomain.txt + [http "https://*.example.*"] + cookieFile = /tmp/multiwildcard.txt [http "https://trailing.example.com"] cookieFile = /tmp/trailing.txt [http "https://user@*.example.com/"] @@ -1454,6 +1456,10 @@ test_expect_success 'urlmatch favors more specific URLs' ' echo http.cookiefile /tmp/sub.txt >expect && git config --get-urlmatch HTTP https://user@sub.example.com >actual && + test_cmp expect actual && + + echo http.cookiefile /tmp/multiwildcard.txt >expect && + git config --get-urlmatch HTTP https://wildcard.example.org >actual && test_cmp expect actual ' diff --git a/t/t1306-xdg-files.sh b/t/t1306-xdg-files.sh index 21e139a313..dd87b43be1 100755 --- a/t/t1306-xdg-files.sh +++ b/t/t1306-xdg-files.sh @@ -153,7 +153,7 @@ test_expect_success 'Checking attributes in both XDG and local attributes files' test_expect_success 'Checking attributes in a non-XDG global attributes file' ' - test_might_fail rm .gitattributes && + rm -f .gitattributes && echo "f attr_f=test" >"$HOME"/my_gitattributes && git config core.attributesfile "$HOME"/my_gitattributes && echo "f: attr_f: test" >expected && @@ -165,7 +165,7 @@ test_expect_success 'Checking attributes in a non-XDG global attributes file' ' test_expect_success 'write: xdg file exists and ~/.gitconfig doesn'\''t' ' mkdir -p "$HOME"/.config/git && >"$HOME"/.config/git/config && - test_might_fail rm "$HOME"/.gitconfig && + rm -f "$HOME"/.gitconfig && git config --global user.name "write_config" && echo "[user]" >expected && echo " name = write_config" >>expected && @@ -183,8 +183,8 @@ test_expect_success 'write: xdg file exists and ~/.gitconfig exists' ' test_expect_success 'write: ~/.config/git/ exists and config file doesn'\''t' ' - test_might_fail rm "$HOME"/.gitconfig && - test_might_fail rm "$HOME"/.config/git/config && + rm -f "$HOME"/.gitconfig && + rm -f "$HOME"/.config/git/config && git config --global user.name "write_gitconfig" && echo "[user]" >expected && echo " name = write_gitconfig" >>expected && diff --git a/t/t1307-config-blob.sh b/t/t1307-config-blob.sh index 37dc689d8c..002e6d3388 100755 --- a/t/t1307-config-blob.sh +++ b/t/t1307-config-blob.sh @@ -74,7 +74,7 @@ test_expect_success 'can parse blob ending with CR' ' ' test_expect_success 'config --blob outside of a repository is an error' ' - test_must_fail nongit git config --blob=foo --list + nongit test_must_fail git config --blob=foo --list ' test_done diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh index fba0abe429..3a527e3a84 100755 --- a/t/t1308-config-set.sh +++ b/t/t1308-config-set.sh @@ -238,8 +238,8 @@ 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 && + printf "[ignore]\n\tthis = please\n[foo]bar = from-repo\n" >.git/config && + printf "[foo]\n\tbar = from-home\n" >.gitconfig && if test_have_prereq MINGW then # Use Windows path (i.e. *not* $HOME) @@ -253,18 +253,28 @@ test_expect_success 'iteration shows correct origins' ' value=from-home origin=file name=$HOME_GITCONFIG + lno=2 scope=global + key=ignore.this + value=please + origin=file + name=.git/config + lno=2 + scope=local + key=foo.bar value=from-repo origin=file name=.git/config + lno=3 scope=local key=foo.bar value=from-cmdline origin=command line name= + lno=-1 scope=command EOF GIT_CONFIG_PARAMETERS=$cmdline_config test-tool config iterate >actual && diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh index b815cdd1b8..e1197ac818 100755 --- a/t/t1400-update-ref.sh +++ b/t/t1400-update-ref.sh @@ -361,55 +361,67 @@ ld="Thu, 26 May 2005 18:43:00 -0500" test_expect_success 'Query "master@{May 25 2005}" (before history)' ' test_when_finished "rm -f o e" && git rev-parse --verify "master@{May 25 2005}" >o 2>e && - test $C = $(cat o) && - test "warning: Log for '\''master'\'' only goes back to $ed." = "$(cat e)" + echo "$C" >expect && + test_cmp expect o && + echo "warning: log for '\''master'\'' only goes back to $ed" >expect && + test_i18ncmp expect e ' test_expect_success 'Query master@{2005-05-25} (before history)' ' test_when_finished "rm -f o e" && git rev-parse --verify master@{2005-05-25} >o 2>e && - test $C = $(cat o) && - test "warning: Log for '\''master'\'' only goes back to $ed." = "$(cat e)" + echo "$C" >expect && + test_cmp expect o && + echo "warning: log for '\''master'\'' only goes back to $ed" >expect && + test_i18ncmp expect e ' test_expect_success 'Query "master@{May 26 2005 23:31:59}" (1 second before history)' ' test_when_finished "rm -f o e" && git rev-parse --verify "master@{May 26 2005 23:31:59}" >o 2>e && - test $C = $(cat o) && - test "warning: Log for '\''master'\'' only goes back to $ed." = "$(cat e)" + echo "$C" >expect && + test_cmp expect o && + echo "warning: log for '\''master'\'' only goes back to $ed" >expect && + test_i18ncmp expect e ' test_expect_success 'Query "master@{May 26 2005 23:32:00}" (exactly history start)' ' test_when_finished "rm -f o e" && git rev-parse --verify "master@{May 26 2005 23:32:00}" >o 2>e && - test $C = $(cat o) && + echo "$C" >expect && + test_cmp expect o && test_must_be_empty e ' test_expect_success 'Query "master@{May 26 2005 23:32:30}" (first non-creation change)' ' test_when_finished "rm -f o e" && git rev-parse --verify "master@{May 26 2005 23:32:30}" >o 2>e && - test $A = $(cat o) && + echo "$A" >expect && + test_cmp expect o && test_must_be_empty e ' test_expect_success 'Query "master@{2005-05-26 23:33:01}" (middle of history with gap)' ' test_when_finished "rm -f o e" && git rev-parse --verify "master@{2005-05-26 23:33:01}" >o 2>e && - test $B = $(cat o) && + echo "$B" >expect && + test_cmp expect o && test_i18ngrep -F "warning: log for ref $m has gap after $gd" e ' test_expect_success 'Query "master@{2005-05-26 23:38:00}" (middle of history)' ' test_when_finished "rm -f o e" && git rev-parse --verify "master@{2005-05-26 23:38:00}" >o 2>e && - test $Z = $(cat o) && + echo "$Z" >expect && + test_cmp expect o && test_must_be_empty e ' test_expect_success 'Query "master@{2005-05-26 23:43:00}" (exact end of history)' ' test_when_finished "rm -f o e" && git rev-parse --verify "master@{2005-05-26 23:43:00}" >o 2>e && - test $E = $(cat o) && + echo "$E" >expect && + test_cmp expect o && test_must_be_empty e ' test_expect_success 'Query "master@{2005-05-28}" (past end of history)' ' test_when_finished "rm -f o e" && git rev-parse --verify "master@{2005-05-28}" >o 2>e && - test $D = $(cat o) && + echo "$D" >expect && + test_cmp expect o && test_i18ngrep -F "warning: log for ref $m unexpectedly ended on $ld" e ' @@ -1342,15 +1354,6 @@ test_expect_success 'fails with duplicate ref update via symref' ' test_cmp expect actual ' -run_with_limited_open_files () { - (ulimit -n 32 && "$@") -} - -test_lazy_prereq ULIMIT_FILE_DESCRIPTORS ' - test_have_prereq !MINGW,!CYGWIN && - run_with_limited_open_files true -' - test_expect_success ULIMIT_FILE_DESCRIPTORS 'large transaction creating branches does not burst open file limit' ' ( for i in $(test_seq 33) @@ -1392,4 +1395,135 @@ test_expect_success 'handle per-worktree refs in refs/bisect' ' ! test_cmp main-head worktree-head ' +test_expect_success 'transaction handles empty commit' ' + cat >stdin <<-EOF && + start + prepare + commit + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" start prepare commit >expect && + test_cmp expect actual +' + +test_expect_success 'transaction handles empty commit with missing prepare' ' + cat >stdin <<-EOF && + start + commit + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" start commit >expect && + test_cmp expect actual +' + +test_expect_success 'transaction handles sole commit' ' + cat >stdin <<-EOF && + commit + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" commit >expect && + test_cmp expect actual +' + +test_expect_success 'transaction handles empty abort' ' + cat >stdin <<-EOF && + start + prepare + abort + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" start prepare abort >expect && + test_cmp expect actual +' + +test_expect_success 'transaction exits on multiple aborts' ' + cat >stdin <<-EOF && + abort + abort + EOF + test_must_fail git update-ref --stdin <stdin >actual 2>err && + printf "%s: ok\n" abort >expect && + test_cmp expect actual && + grep "fatal: transaction is closed" err +' + +test_expect_success 'transaction exits on start after prepare' ' + cat >stdin <<-EOF && + prepare + start + EOF + test_must_fail git update-ref --stdin <stdin 2>err >actual && + printf "%s: ok\n" prepare >expect && + test_cmp expect actual && + grep "fatal: prepared transactions can only be closed" err +' + +test_expect_success 'transaction handles empty abort with missing prepare' ' + cat >stdin <<-EOF && + start + abort + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" start abort >expect && + test_cmp expect actual +' + +test_expect_success 'transaction handles sole abort' ' + cat >stdin <<-EOF && + abort + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" abort >expect && + test_cmp expect actual +' + +test_expect_success 'transaction can handle commit' ' + cat >stdin <<-EOF && + start + create $a HEAD + commit + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" start commit >expect && + test_cmp expect actual && + git rev-parse HEAD >expect && + git rev-parse $a >actual && + test_cmp expect actual +' + +test_expect_success 'transaction can handle abort' ' + cat >stdin <<-EOF && + start + create $b HEAD + abort + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" start abort >expect && + test_cmp expect actual && + test_path_is_missing .git/$b +' + +test_expect_success 'transaction aborts by default' ' + cat >stdin <<-EOF && + start + create $b HEAD + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" start >expect && + test_cmp expect actual && + test_path_is_missing .git/$b +' + +test_expect_success 'transaction with prepare aborts by default' ' + cat >stdin <<-EOF && + start + create $b HEAD + prepare + EOF + git update-ref --stdin <stdin >actual && + printf "%s: ok\n" start prepare >expect && + test_cmp expect actual && + test_path_is_missing .git/$b +' + test_done diff --git a/t/t1406-submodule-ref-store.sh b/t/t1406-submodule-ref-store.sh index d199d872fb..36b7ef5046 100755 --- a/t/t1406-submodule-ref-store.sh +++ b/t/t1406-submodule-ref-store.sh @@ -75,7 +75,7 @@ test_expect_success 'for_each_reflog()' ' ' test_expect_success 'for_each_reflog_ent()' ' - $RUN for-each-reflog-ent HEAD >actual && cat actual && + $RUN for-each-reflog-ent HEAD >actual && head -n1 actual | grep first && tail -n2 actual | head -n1 | grep master.to.new ' diff --git a/t/t1409-avoid-packing-refs.sh b/t/t1409-avoid-packing-refs.sh index e5cb8a252d..be12fb6350 100755 --- a/t/t1409-avoid-packing-refs.sh +++ b/t/t1409-avoid-packing-refs.sh @@ -8,7 +8,7 @@ test_description='avoid rewriting packed-refs unnecessarily' # shouldn't upset readers, and it should be omitted if the file is # ever rewritten. mark_packed_refs () { - sed -e "s/^\(#.*\)/\1 t1409 /" <.git/packed-refs >.git/packed-refs.new && + sed -e "s/^\(#.*\)/\1 t1409 /" .git/packed-refs >.git/packed-refs.new && mv .git/packed-refs.new .git/packed-refs } @@ -27,15 +27,15 @@ test_expect_success 'setup' ' ' test_expect_success 'do not create packed-refs file gratuitously' ' - test_must_fail test -f .git/packed-refs && + test_path_is_missing .git/packed-refs && git update-ref refs/heads/foo $A && - test_must_fail test -f .git/packed-refs && + test_path_is_missing .git/packed-refs && git update-ref refs/heads/foo $B && - test_must_fail test -f .git/packed-refs && + test_path_is_missing .git/packed-refs && git update-ref refs/heads/foo $C $B && - test_must_fail test -f .git/packed-refs && + test_path_is_missing .git/packed-refs && git update-ref -d refs/heads/foo && - test_must_fail test -f .git/packed-refs + test_path_is_missing .git/packed-refs ' test_expect_success 'check that marking the packed-refs file works' ' @@ -46,7 +46,7 @@ test_expect_success 'check that marking the packed-refs file works' ' git for-each-ref >actual && test_cmp expected actual && git pack-refs --all && - test_must_fail check_packed_refs_marked && + ! check_packed_refs_marked && git for-each-ref >actual2 && test_cmp expected actual2 ' @@ -80,7 +80,7 @@ test_expect_success 'touch packed-refs on delete of packed' ' git pack-refs --all && mark_packed_refs && git update-ref -d refs/heads/packed-delete && - test_must_fail check_packed_refs_marked + ! check_packed_refs_marked ' test_expect_success 'leave packed-refs untouched on update of loose' ' diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index 02478bc4ec..449ebc5657 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -133,6 +133,30 @@ test_expect_success 'other worktree HEAD link pointing at a funny place' ' test_i18ngrep "worktrees/other/HEAD points to something strange" out ' +test_expect_success 'commit with multiple signatures is okay' ' + git cat-file commit HEAD >basis && + cat >sigs <<-EOF && + gpgsig -----BEGIN PGP SIGNATURE----- + VGhpcyBpcyBub3QgcmVhbGx5IGEgc2lnbmF0dXJlLg== + -----END PGP SIGNATURE----- + gpgsig-sha256 -----BEGIN PGP SIGNATURE----- + VGhpcyBpcyBub3QgcmVhbGx5IGEgc2lnbmF0dXJlLg== + -----END PGP SIGNATURE----- + EOF + sed -e "/^committer/q" basis >okay && + cat sigs >>okay && + echo >>okay && + sed -e "1,/^$/d" basis >>okay && + cat okay && + new=$(git hash-object -t commit -w --stdin <okay) && + test_when_finished "remove_object $new" && + git update-ref refs/heads/bogus "$new" && + test_when_finished "git update-ref -d refs/heads/bogus" && + git fsck 2>out && + cat out && + ! grep "commit $new" out +' + test_expect_success 'email without @ is okay' ' git cat-file commit HEAD >basis && sed "s/@/AT/" basis >okay && @@ -141,7 +165,6 @@ test_expect_success 'email without @ is okay' ' git update-ref refs/heads/bogus "$new" && test_when_finished "git update-ref -d refs/heads/bogus" && git fsck 2>out && - cat out && ! grep "commit $new" out ' diff --git a/t/t1501-work-tree.sh b/t/t1501-work-tree.sh index 3498d3d55e..b75558040f 100755 --- a/t/t1501-work-tree.sh +++ b/t/t1501-work-tree.sh @@ -350,7 +350,7 @@ test_expect_success 'Multi-worktree setup' ' mkdir work && mkdir -p repo.git/repos/foo && cp repo.git/HEAD repo.git/index repo.git/repos/foo && - test_might_fail cp repo.git/sharedindex.* repo.git/repos/foo && + { cp repo.git/sharedindex.* repo.git/repos/foo || :; } && sane_unset GIT_DIR GIT_CONFIG GIT_WORK_TREE ' diff --git a/t/t1506-rev-parse-diagnosis.sh b/t/t1506-rev-parse-diagnosis.sh index 6d951ca015..52edcbdcc3 100755 --- a/t/t1506-rev-parse-diagnosis.sh +++ b/t/t1506-rev-parse-diagnosis.sh @@ -9,10 +9,10 @@ exec </dev/null test_did_you_mean () { cat >expected <<-EOF && - fatal: Path '$2$3' $4, but not ${5:-$SQ$3$SQ}. - Did you mean '$1:$2$3'${2:+ aka $SQ$1:./$3$SQ}? + fatal: path '$2$3' $4, but not ${5:-$SQ$3$SQ} + hint: Did you mean '$1:$2$3'${2:+ aka $SQ$1:./$3$SQ}? EOF - test_cmp expected error + test_i18ncmp expected error } HASH_file= @@ -103,53 +103,53 @@ test_expect_success 'correct relative file objects (6)' ' test_expect_success 'incorrect revision id' ' test_must_fail git rev-parse foobar:file.txt 2>error && - grep "Invalid object name '"'"'foobar'"'"'." error && - test_must_fail git rev-parse foobar 2> error && + test_i18ngrep "invalid object name .foobar." error && + test_must_fail git rev-parse foobar 2>error && test_i18ngrep "unknown revision or path not in the working tree." error ' test_expect_success 'incorrect file in sha1:path' ' - test_must_fail git rev-parse HEAD:nothing.txt 2> error && - grep "fatal: Path '"'"'nothing.txt'"'"' does not exist in '"'"'HEAD'"'"'" error && - test_must_fail git rev-parse HEAD:index-only.txt 2> error && - grep "fatal: Path '"'"'index-only.txt'"'"' exists on disk, but not in '"'"'HEAD'"'"'." error && + test_must_fail git rev-parse HEAD:nothing.txt 2>error && + test_i18ngrep "path .nothing.txt. does not exist in .HEAD." error && + test_must_fail git rev-parse HEAD:index-only.txt 2>error && + test_i18ngrep "path .index-only.txt. exists on disk, but not in .HEAD." error && (cd subdir && - test_must_fail git rev-parse HEAD:file2.txt 2> error && + test_must_fail git rev-parse HEAD:file2.txt 2>error && test_did_you_mean HEAD subdir/ file2.txt exists ) ' test_expect_success 'incorrect file in :path and :N:path' ' - test_must_fail git rev-parse :nothing.txt 2> error && - grep "fatal: Path '"'"'nothing.txt'"'"' does not exist (neither on disk nor in the index)." error && - test_must_fail git rev-parse :1:nothing.txt 2> error && - grep "Path '"'"'nothing.txt'"'"' does not exist (neither on disk nor in the index)." error && - test_must_fail git rev-parse :1:file.txt 2> error && + test_must_fail git rev-parse :nothing.txt 2>error && + test_i18ngrep "path .nothing.txt. does not exist (neither on disk nor in the index)" error && + test_must_fail git rev-parse :1:nothing.txt 2>error && + test_i18ngrep "path .nothing.txt. does not exist (neither on disk nor in the index)" error && + test_must_fail git rev-parse :1:file.txt 2>error && test_did_you_mean ":0" "" file.txt "is in the index" "at stage 1" && (cd subdir && - test_must_fail git rev-parse :1:file.txt 2> error && + test_must_fail git rev-parse :1:file.txt 2>error && test_did_you_mean ":0" "" file.txt "is in the index" "at stage 1" && - test_must_fail git rev-parse :file2.txt 2> error && + test_must_fail git rev-parse :file2.txt 2>error && test_did_you_mean ":0" subdir/ file2.txt "is in the index" && - test_must_fail git rev-parse :2:file2.txt 2> error && + test_must_fail git rev-parse :2:file2.txt 2>error && test_did_you_mean :0 subdir/ file2.txt "is in the index") && - test_must_fail git rev-parse :disk-only.txt 2> error && - grep "fatal: Path '"'"'disk-only.txt'"'"' exists on disk, but not in the index." error + test_must_fail git rev-parse :disk-only.txt 2>error && + test_i18ngrep "path .disk-only.txt. exists on disk, but not in the index" error ' test_expect_success 'invalid @{n} reference' ' test_must_fail git rev-parse master@{99999} >output 2>error && test_must_be_empty output && - grep "fatal: Log for [^ ]* only has [0-9][0-9]* entries." error && + test_i18ngrep "log for [^ ]* only has [0-9][0-9]* entries" error && test_must_fail git rev-parse --verify master@{99999} >output 2>error && test_must_be_empty output && - grep "fatal: Log for [^ ]* only has [0-9][0-9]* entries." error + test_i18ngrep "log for [^ ]* only has [0-9][0-9]* entries" error ' test_expect_success 'relative path not found' ' ( cd subdir && test_must_fail git rev-parse HEAD:./nonexistent.txt 2>error && - grep subdir/nonexistent.txt error + test_i18ngrep subdir/nonexistent.txt error ) ' @@ -162,7 +162,7 @@ test_expect_success 'relative path outside worktree' ' test_expect_success 'relative path when cwd is outside worktree' ' test_must_fail git --git-dir=.git --work-tree=subdir rev-parse HEAD:./file.txt >output 2>error && test_must_be_empty output && - grep "relative path syntax can.t be used outside working tree." error + test_i18ngrep "relative path syntax can.t be used outside working tree" error ' test_expect_success '<commit>:file correctly diagnosed after a pathname' ' @@ -222,4 +222,18 @@ test_expect_success 'reject Nth ancestor if N is too high' ' test_must_fail git rev-parse HEAD~100000000000000000000000000000000 ' +test_expect_success 'pathspecs with wildcards are not ambiguous' ' + echo "*.c" >expect && + git rev-parse "*.c" >actual && + test_cmp expect actual +' + +test_expect_success 'backslash does not trigger wildcard rule' ' + test_must_fail git rev-parse "foo\\bar" +' + +test_expect_success 'escaped char does not trigger wildcard rule' ' + test_must_fail git rev-parse "foo\\*bar" +' + test_done diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh index 8b4cf8a6e3..dfc0d96d8a 100755 --- a/t/t1507-rev-parse-upstream.sh +++ b/t/t1507-rev-parse-upstream.sh @@ -28,14 +28,9 @@ test_expect_success 'setup' ' ) ' -full_name () { - (cd clone && - git rev-parse --symbolic-full-name "$@") -} - commit_subject () { (cd clone && - git show -s --pretty=format:%s "$@") + git show -s --pretty=tformat:%s "$@") } error_message () { @@ -44,63 +39,78 @@ error_message () { } test_expect_success '@{upstream} resolves to correct full name' ' - test refs/remotes/origin/master = "$(full_name @{upstream})" && - test refs/remotes/origin/master = "$(full_name @{UPSTREAM})" && - test refs/remotes/origin/master = "$(full_name @{UpSTReam})" + echo refs/remotes/origin/master >expect && + git -C clone rev-parse --symbolic-full-name @{upstream} >actual && + test_cmp expect actual && + git -C clone rev-parse --symbolic-full-name @{UPSTREAM} >actual && + test_cmp expect actual && + git -C clone rev-parse --symbolic-full-name @{UpSTReam} >actual && + test_cmp expect actual ' test_expect_success '@{u} resolves to correct full name' ' - test refs/remotes/origin/master = "$(full_name @{u})" && - test refs/remotes/origin/master = "$(full_name @{U})" + echo refs/remotes/origin/master >expect && + git -C clone rev-parse --symbolic-full-name @{u} >actual && + test_cmp expect actual && + git -C clone rev-parse --symbolic-full-name @{U} >actual && + test_cmp expect actual ' test_expect_success 'my-side@{upstream} resolves to correct full name' ' - test refs/remotes/origin/side = "$(full_name my-side@{u})" + echo refs/remotes/origin/side >expect && + git -C clone rev-parse --symbolic-full-name my-side@{u} >actual && + test_cmp expect actual ' test_expect_success 'upstream of branch with @ in middle' ' - full_name fun@ny@{u} >actual && + git -C clone rev-parse --symbolic-full-name fun@ny@{u} >actual && echo refs/remotes/origin/side >expect && test_cmp expect actual && - full_name fun@ny@{U} >actual && + git -C clone rev-parse --symbolic-full-name fun@ny@{U} >actual && test_cmp expect actual ' test_expect_success 'upstream of branch with @ at start' ' - full_name @funny@{u} >actual && + git -C clone rev-parse --symbolic-full-name @funny@{u} >actual && echo refs/remotes/origin/side >expect && test_cmp expect actual ' test_expect_success 'upstream of branch with @ at end' ' - full_name funny@@{u} >actual && + git -C clone rev-parse --symbolic-full-name funny@@{u} >actual && echo refs/remotes/origin/side >expect && test_cmp expect actual ' test_expect_success 'refs/heads/my-side@{upstream} does not resolve to my-side{upstream}' ' - test_must_fail full_name refs/heads/my-side@{upstream} + test_must_fail git -C clone rev-parse --symbolic-full-name refs/heads/my-side@{upstream} ' test_expect_success 'my-side@{u} resolves to correct commit' ' git checkout side && test_commit 5 && (cd clone && git fetch) && - test 2 = "$(commit_subject my-side)" && - test 5 = "$(commit_subject my-side@{u})" + echo 2 >expect && + commit_subject my-side >actual && + test_cmp expect actual && + echo 5 >expect && + commit_subject my-side@{u} >actual ' test_expect_success 'not-tracking@{u} fails' ' - test_must_fail full_name non-tracking@{u} && + test_must_fail git -C clone rev-parse --symbolic-full-name non-tracking@{u} && (cd clone && git checkout --no-track -b non-tracking) && - test_must_fail full_name non-tracking@{u} + test_must_fail git -C clone rev-parse --symbolic-full-name non-tracking@{u} ' test_expect_success '<branch>@{u}@{1} resolves correctly' ' test_commit 6 && (cd clone && git fetch) && - test 5 = $(commit_subject my-side@{u}@{1}) && - test 5 = $(commit_subject my-side@{U}@{1}) + echo 5 >expect && + commit_subject my-side@{u}@{1} >actual && + test_cmp expect actual && + commit_subject my-side@{U}@{1} >actual && + test_cmp expect actual ' test_expect_success '@{u} without specifying branch fails on a detached HEAD' ' @@ -149,7 +159,9 @@ test_expect_success 'checkout other@{u}' ' ' test_expect_success 'branch@{u} works when tracking a local branch' ' - test refs/heads/master = "$(full_name local-master@{u})" + echo refs/heads/master >expect && + git -C clone rev-parse --symbolic-full-name local-master@{u} >actual && + test_cmp expect actual ' test_expect_success 'branch@{u} error message when no upstream' ' @@ -203,35 +215,37 @@ test_expect_success 'pull works when tracking a local branch' ' # makes sense if the previous one succeeded test_expect_success '@{u} works when tracking a local branch' ' - test refs/heads/master = "$(full_name @{u})" + echo refs/heads/master >expect && + git -C clone rev-parse --symbolic-full-name @{u} >actual && + test_cmp expect actual ' -commit=$(git rev-parse HEAD) -cat >expect <<EOF -commit $commit -Reflog: master@{0} (C O Mitter <committer@example.com>) -Reflog message: branch: Created from HEAD -Author: A U Thor <author@example.com> -Date: Thu Apr 7 15:15:13 2005 -0700 - - 3 -EOF test_expect_success 'log -g other@{u}' ' + commit=$(git rev-parse HEAD) && + cat >expect <<-EOF && + commit $commit + Reflog: master@{0} (C O Mitter <committer@example.com>) + Reflog message: branch: Created from HEAD + Author: A U Thor <author@example.com> + Date: Thu Apr 7 15:15:13 2005 -0700 + + 3 + EOF git log -1 -g other@{u} >actual && test_cmp expect actual ' -cat >expect <<EOF -commit $commit -Reflog: master@{Thu Apr 7 15:17:13 2005 -0700} (C O Mitter <committer@example.com>) -Reflog message: branch: Created from HEAD -Author: A U Thor <author@example.com> -Date: Thu Apr 7 15:15:13 2005 -0700 - - 3 -EOF - test_expect_success 'log -g other@{u}@{now}' ' + commit=$(git rev-parse HEAD) && + cat >expect <<-EOF && + commit $commit + Reflog: master@{Thu Apr 7 15:17:13 2005 -0700} (C O Mitter <committer@example.com>) + Reflog message: branch: Created from HEAD + Author: A U Thor <author@example.com> + Date: Thu Apr 7 15:15:13 2005 -0700 + + 3 + EOF git log -1 -g other@{u}@{now} >actual && test_cmp expect actual ' diff --git a/t/t2018-checkout-branch.sh b/t/t2018-checkout-branch.sh index 822381dd9d..21583154d8 100755 --- a/t/t2018-checkout-branch.sh +++ b/t/t2018-checkout-branch.sh @@ -1,50 +1,76 @@ #!/bin/sh -test_description='checkout ' +test_description='checkout' . ./test-lib.sh -# Arguments: <branch> <sha> [<checkout options>] +# Arguments: [!] <branch> <oid> [<checkout options>] # # Runs "git checkout" to switch to <branch>, testing that # # 1) we are on the specified branch, <branch>; -# 2) HEAD is <sha>; if <sha> is not specified, the old HEAD is used. +# 2) HEAD is <oid>; if <oid> is not specified, the old HEAD is used. # # If <checkout options> is not specified, "git checkout" is run with -b. -do_checkout() { +# +# If the first argument is `!`, "git checkout" is expected to fail when +# it is run. +do_checkout () { + should_fail= && + if test "x$1" = "x!" + then + should_fail=yes && + shift + fi && exp_branch=$1 && exp_ref="refs/heads/$exp_branch" && - # if <sha> is not specified, use HEAD. - exp_sha=${2:-$(git rev-parse --verify HEAD)} && + # if <oid> is not specified, use HEAD. + exp_oid=${2:-$(git rev-parse --verify HEAD)} && # default options for git checkout: -b - if [ -z "$3" ]; then + if test -z "$3" + then opts="-b" else opts="$3" fi - git checkout $opts $exp_branch $exp_sha && + if test -n "$should_fail" + then + test_must_fail git checkout $opts $exp_branch $exp_oid + else + git checkout $opts $exp_branch $exp_oid && + echo "$exp_ref" >ref.expect && + git rev-parse --symbolic-full-name HEAD >ref.actual && + test_cmp ref.expect ref.actual && + echo "$exp_oid" >oid.expect && + git rev-parse --verify HEAD >oid.actual && + test_cmp oid.expect oid.actual + fi +} - test $exp_ref = $(git rev-parse --symbolic-full-name HEAD) && - test $exp_sha = $(git rev-parse --verify HEAD) +test_dirty_unmergeable () { + test_expect_code 1 git diff --exit-code } -test_dirty_unmergeable() { - ! git diff --exit-code >/dev/null +test_dirty_unmergeable_discards_changes () { + git diff --exit-code } -setup_dirty_unmergeable() { +setup_dirty_unmergeable () { echo >>file1 change2 } -test_dirty_mergeable() { - ! git diff --cached --exit-code >/dev/null +test_dirty_mergeable () { + test_expect_code 1 git diff --cached --exit-code } -setup_dirty_mergeable() { +test_dirty_mergeable_discards_changes () { + git diff --cached --exit-code +} + +setup_dirty_mergeable () { echo >file2 file2 && git add file2 } @@ -82,7 +108,7 @@ test_expect_success 'checkout -b to a new branch, set to an explicit ref' ' test_expect_success 'checkout -b to a new branch with unmergeable changes fails' ' setup_dirty_unmergeable && - test_must_fail do_checkout branch2 $HEAD1 && + do_checkout ! branch2 $HEAD1 && test_dirty_unmergeable ' @@ -93,7 +119,7 @@ test_expect_success 'checkout -f -b to a new branch with unmergeable changes dis # still dirty and on branch1 do_checkout branch2 $HEAD1 "-f -b" && - test_must_fail test_dirty_unmergeable + test_dirty_unmergeable_discards_changes ' test_expect_success 'checkout -b to a new branch preserves mergeable changes' ' @@ -111,12 +137,12 @@ test_expect_success 'checkout -f -b to a new branch with mergeable changes disca test_when_finished git reset --hard HEAD && setup_dirty_mergeable && do_checkout branch2 $HEAD1 "-f -b" && - test_must_fail test_dirty_mergeable + test_dirty_mergeable_discards_changes ' test_expect_success 'checkout -b to an existing branch fails' ' test_when_finished git reset --hard HEAD && - test_must_fail do_checkout branch2 $HEAD2 + do_checkout ! branch2 $HEAD2 ' test_expect_success 'checkout -b to @{-1} fails with the right branch name' ' @@ -140,7 +166,8 @@ test_expect_success 'checkout -B to a merge base' ' ' test_expect_success 'checkout -B to an existing branch from detached HEAD resets branch to HEAD' ' - git checkout $(git rev-parse --verify HEAD) && + head=$(git rev-parse --verify HEAD) && + git checkout "$head" && do_checkout branch2 "" -B ' @@ -155,14 +182,14 @@ test_expect_success 'checkout -B to an existing branch with unmergeable changes git checkout branch1 && setup_dirty_unmergeable && - test_must_fail do_checkout branch2 $HEAD1 -B && + do_checkout ! branch2 $HEAD1 -B && test_dirty_unmergeable ' test_expect_success 'checkout -f -B to an existing branch with unmergeable changes discards changes' ' # still dirty and on branch1 do_checkout branch2 $HEAD1 "-f -B" && - test_must_fail test_dirty_unmergeable + test_dirty_unmergeable_discards_changes ' test_expect_success 'checkout -B to an existing branch preserves mergeable changes' ' @@ -179,7 +206,7 @@ test_expect_success 'checkout -f -B to an existing branch with mergeable changes setup_dirty_mergeable && do_checkout branch2 $HEAD1 "-f -B" && - test_must_fail test_dirty_mergeable + test_dirty_mergeable_discards_changes ' test_expect_success 'checkout -b <describe>' ' @@ -211,4 +238,26 @@ test_expect_success 'checkout -b after clone --no-checkout does a checkout of HE test_path_is_file dest/a.t ' +test_expect_success 'checkout -b to a new branch preserves mergeable changes despite sparse-checkout' ' + test_when_finished " + git reset --hard && + git checkout branch1-scratch && + test_might_fail git branch -D branch3 && + git config core.sparseCheckout false && + rm .git/info/sparse-checkout" && + + test_commit file2 && + + echo stuff >>file1 && + echo file2 >.git/info/sparse-checkout && + git config core.sparseCheckout true && + + CURHEAD=$(git rev-parse HEAD) && + do_checkout branch3 $CURHEAD && + + echo file1 >expect && + git diff --name-only >actual && + test_cmp expect actual +' + test_done diff --git a/t/t2024-checkout-dwim.sh b/t/t2024-checkout-dwim.sh index fa0718c730..accfa9aa4b 100755 --- a/t/t2024-checkout-dwim.sh +++ b/t/t2024-checkout-dwim.sh @@ -37,7 +37,9 @@ test_expect_success 'setup' ' git checkout -b foo && test_commit a_foo && git checkout -b bar && - test_commit a_bar + test_commit a_bar && + git checkout -b ambiguous_branch_and_file && + test_commit a_ambiguous_branch_and_file ) && git init repo_b && ( @@ -46,7 +48,9 @@ test_expect_success 'setup' ' git checkout -b foo && test_commit b_foo && git checkout -b baz && - test_commit b_baz + test_commit b_baz && + git checkout -b ambiguous_branch_and_file && + test_commit b_ambiguous_branch_and_file ) && git remote add repo_a repo_a && git remote add repo_b repo_b && @@ -75,6 +79,26 @@ test_expect_success 'checkout of branch from multiple remotes fails #1' ' test_branch master ' +test_expect_success 'when arg matches multiple remotes, do not fallback to interpreting as pathspec' ' + # create a file with name matching remote branch name + git checkout -b t_ambiguous_branch_and_file && + >ambiguous_branch_and_file && + git add ambiguous_branch_and_file && + git commit -m "ambiguous_branch_and_file" && + + # modify file to verify that it will not be touched by checkout + test_when_finished "git checkout -- ambiguous_branch_and_file" && + echo "file contents" >ambiguous_branch_and_file && + cp ambiguous_branch_and_file expect && + + test_must_fail git checkout ambiguous_branch_and_file 2>err && + + test_i18ngrep "matched multiple (2) remote tracking branches" err && + + # file must not be altered + test_cmp expect ambiguous_branch_and_file +' + test_expect_success 'checkout of branch from multiple remotes fails with advice' ' git checkout -B master && test_might_fail git branch -D foo && diff --git a/t/t2026-checkout-pathspec-file.sh b/t/t2026-checkout-pathspec-file.sh index f62fd27440..43d31d7948 100755 --- a/t/t2026-checkout-pathspec-file.sh +++ b/t/t2026-checkout-pathspec-file.sh @@ -109,7 +109,11 @@ test_expect_success 'CRLF delimiters' ' test_expect_success 'quotes' ' restore_checkpoint && - printf "\"file\\101.t\"" | git checkout --pathspec-from-file=- HEAD^1 && + cat >list <<-\EOF && + "file\101.t" + EOF + + git checkout --pathspec-from-file=list HEAD^1 && cat >expect <<-\EOF && M fileA.t @@ -120,7 +124,10 @@ test_expect_success 'quotes' ' test_expect_success 'quotes not compatible with --pathspec-file-nul' ' restore_checkpoint && - printf "\"file\\101.t\"" >list && + cat >list <<-\EOF && + "file\101.t" + EOF + test_must_fail git checkout --pathspec-from-file=list --pathspec-file-nul HEAD^1 ' @@ -136,4 +143,21 @@ test_expect_success 'only touches what was listed' ' verify_expect ' +test_expect_success 'error conditions' ' + restore_checkpoint && + echo fileA.t >list && + + test_must_fail git checkout --pathspec-from-file=list --detach 2>err && + test_i18ngrep -e "--pathspec-from-file is incompatible with --detach" err && + + test_must_fail git checkout --pathspec-from-file=list --patch 2>err && + test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err && + + test_must_fail git checkout --pathspec-from-file=list -- fileA.t 2>err && + test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err && + + test_must_fail git checkout --pathspec-file-nul 2>err && + test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err +' + test_done diff --git a/t/t2070-restore.sh b/t/t2070-restore.sh index 21c3f84459..89e5a142c9 100755 --- a/t/t2070-restore.sh +++ b/t/t2070-restore.sh @@ -69,6 +69,17 @@ test_expect_success 'restore --staged uses HEAD as source' ' test_cmp expected actual ' +test_expect_success 'restore --worktree --staged uses HEAD as source' ' + test_when_finished git reset --hard && + git show HEAD:./first.t >expected && + echo dirty >>first.t && + git add first.t && + git restore --worktree --staged first.t && + git show :./first.t >actual && + test_cmp expected actual && + test_cmp expected first.t +' + test_expect_success 'restore --ignore-unmerged ignores unmerged entries' ' git init unmerged && ( @@ -106,4 +117,21 @@ test_expect_success 'restore --staged adds deleted intent-to-add file back to in git diff --cached --exit-code ' +test_expect_success 'restore --staged invalidates cache tree for deletions' ' + test_when_finished git reset --hard && + >new1 && + >new2 && + git add new1 new2 && + + # It is important to commit and then reset here, so that the index + # contains a valid cache-tree for the "both" tree. + git commit -m both && + git reset --soft HEAD^ && + + git restore --staged new1 && + git commit -m "just new2" && + git rev-parse HEAD:new2 && + test_must_fail git rev-parse HEAD:new1 +' + test_done diff --git a/t/t2072-restore-pathspec-file.sh b/t/t2072-restore-pathspec-file.sh index db58e83735..0d47946e8a 100755 --- a/t/t2072-restore-pathspec-file.sh +++ b/t/t2072-restore-pathspec-file.sh @@ -109,7 +109,11 @@ test_expect_success 'CRLF delimiters' ' test_expect_success 'quotes' ' restore_checkpoint && - printf "\"file\\101.t\"" | git restore --pathspec-from-file=- --source=HEAD^1 && + cat >list <<-\EOF && + "file\101.t" + EOF + + git restore --pathspec-from-file=list --source=HEAD^1 && cat >expect <<-\EOF && M fileA.t @@ -120,7 +124,10 @@ test_expect_success 'quotes' ' test_expect_success 'quotes not compatible with --pathspec-file-nul' ' restore_checkpoint && - printf "\"file\\101.t\"" >list && + cat >list <<-\EOF && + "file\101.t" + EOF + test_must_fail git restore --pathspec-from-file=list --pathspec-file-nul --source=HEAD^1 ' @@ -136,4 +143,22 @@ test_expect_success 'only touches what was listed' ' verify_expect ' +test_expect_success 'error conditions' ' + restore_checkpoint && + echo fileA.t >list && + >empty_list && + + test_must_fail git restore --pathspec-from-file=list --patch --source=HEAD^1 2>err && + test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err && + + test_must_fail git restore --pathspec-from-file=list --source=HEAD^1 -- fileA.t 2>err && + test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err && + + test_must_fail git restore --pathspec-file-nul --source=HEAD^1 2>err && + test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err && + + test_must_fail git restore --pathspec-from-file=empty_list --source=HEAD^1 2>err && + test_i18ngrep -e "you must specify path(s) to restore" err +' + test_done diff --git a/t/t2107-update-index-basic.sh b/t/t2107-update-index-basic.sh index 2242cd098e..a30b7ca6bc 100755 --- a/t/t2107-update-index-basic.sh +++ b/t/t2107-update-index-basic.sh @@ -9,7 +9,6 @@ Tests for command-line parsing and basic operation. test_expect_success 'update-index --nonsense fails' ' test_must_fail git update-index --nonsense 2>msg && - cat msg && test -s msg ' diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh index b5ece19460..5a7495474a 100755 --- a/t/t2400-worktree-add.sh +++ b/t/t2400-worktree-add.sh @@ -570,6 +570,15 @@ test_expect_success '"add" an existing locked but missing worktree' ' git worktree add --force --force --detach gnoo ' +test_expect_success '"add" not tripped up by magic worktree matching"' ' + # if worktree "sub1/bar" exists, "git worktree add bar" in distinct + # directory `sub2` should not mistakenly complain that `bar` is an + # already-registered worktree + mkdir sub1 sub2 && + git -C sub1 --git-dir=../.git worktree add --detach bozo && + git -C sub2 --git-dir=../.git worktree add --detach bozo +' + test_expect_success FUNNYNAMES 'sanitize generated worktree name' ' git worktree add --detach ". weird*..?.lock.lock" && test -d .git/worktrees/---weird-.- diff --git a/t/t2402-worktree-list.sh b/t/t2402-worktree-list.sh index bb6fb9b12c..52585ec2aa 100755 --- a/t/t2402-worktree-list.sh +++ b/t/t2402-worktree-list.sh @@ -151,4 +151,10 @@ test_expect_success 'linked worktrees are sorted' ' test_cmp expected sorted/main/actual ' +test_expect_success 'worktree path when called in .git directory' ' + git worktree list >list1 && + git -C .git worktree list >list2 && + test_cmp list1 list2 +' + test_done diff --git a/t/t2405-worktree-submodule.sh b/t/t2405-worktree-submodule.sh new file mode 100755 index 0000000000..e1b2bfd87e --- /dev/null +++ b/t/t2405-worktree-submodule.sh @@ -0,0 +1,90 @@ +#!/bin/sh + +test_description='Combination of submodules and multiple worktrees' + +. ./test-lib.sh + +base_path=$(pwd -P) + +test_expect_success 'setup: create origin repos' ' + git init origin/sub && + test_commit -C origin/sub file1 && + git init origin/main && + test_commit -C origin/main first && + git -C origin/main submodule add ../sub && + git -C origin/main commit -m "add sub" && + test_commit -C origin/sub "file1 updated" file1 file1updated file1updated && + git -C origin/main/sub pull && + git -C origin/main add sub && + git -C origin/main commit -m "sub updated" +' + +test_expect_success 'setup: clone superproject to create main worktree' ' + git clone --recursive "$base_path/origin/main" main +' + +rev1_hash_main=$(git --git-dir=origin/main/.git show --pretty=format:%h -q "HEAD~1") +rev1_hash_sub=$(git --git-dir=origin/sub/.git show --pretty=format:%h -q "HEAD~1") + +test_expect_success 'add superproject worktree' ' + git -C main worktree add "$base_path/worktree" "$rev1_hash_main" +' + +test_expect_failure 'submodule is checked out just after worktree add' ' + git -C worktree diff --submodule master"^!" >out && + grep "file1 updated" out +' + +test_expect_success 'add superproject worktree and initialize submodules' ' + git -C main worktree add "$base_path/worktree-submodule-update" "$rev1_hash_main" && + git -C worktree-submodule-update submodule update +' + +test_expect_success 'submodule is checked out just after submodule update in linked worktree' ' + git -C worktree-submodule-update diff --submodule master"^!" >out && + grep "file1 updated" out +' + +test_expect_success 'add superproject worktree and manually add submodule worktree' ' + git -C main worktree add "$base_path/linked_submodule" "$rev1_hash_main" && + git -C main/sub worktree add "$base_path/linked_submodule/sub" "$rev1_hash_sub" +' + +test_expect_success 'submodule is checked out after manually adding submodule worktree' ' + git -C linked_submodule diff --submodule master"^!" >out && + grep "file1 updated" out +' + +test_expect_success 'checkout --recurse-submodules uses $GIT_DIR for submodules in a linked worktree' ' + git -C main worktree add "$base_path/checkout-recurse" --detach && + git -C checkout-recurse submodule update --init && + echo "gitdir: ../../main/.git/worktrees/checkout-recurse/modules/sub" >expect-gitfile && + cat checkout-recurse/sub/.git >actual-gitfile && + test_cmp expect-gitfile actual-gitfile && + git -C main/sub rev-parse HEAD >expect-head-main && + git -C checkout-recurse checkout --recurse-submodules HEAD~1 && + cat checkout-recurse/sub/.git >actual-gitfile && + git -C main/sub rev-parse HEAD >actual-head-main && + test_cmp expect-gitfile actual-gitfile && + test_cmp expect-head-main actual-head-main +' + +test_expect_success 'core.worktree is removed in $GIT_DIR/modules/<name>/config, not in $GIT_COMMON_DIR/modules/<name>/config' ' + echo "../../../sub" >expect-main && + git -C main/sub config --get core.worktree >actual-main && + test_cmp expect-main actual-main && + echo "../../../../../../checkout-recurse/sub" >expect-linked && + git -C checkout-recurse/sub config --get core.worktree >actual-linked && + test_cmp expect-linked actual-linked && + git -C checkout-recurse checkout --recurse-submodules first && + test_expect_code 1 git -C main/.git/worktrees/checkout-recurse/modules/sub config --get core.worktree >linked-config && + test_must_be_empty linked-config && + git -C main/sub config --get core.worktree >actual-main && + test_cmp expect-main actual-main +' + +test_expect_success 'unsetting core.worktree does not prevent running commands directly against the submodule repository' ' + git -C main/.git/worktrees/checkout-recurse/modules/sub log +' + +test_done diff --git a/t/t3000-ls-files-others.sh b/t/t3000-ls-files-others.sh index 0aefadacb0..ffdfb16f58 100755 --- a/t/t3000-ls-files-others.sh +++ b/t/t3000-ls-files-others.sh @@ -91,4 +91,125 @@ test_expect_success SYMLINKS 'ls-files --others with symlinked submodule' ' test_cmp expect actual ' +test_expect_success 'setup nested pathspec search' ' + test_create_repo nested && + ( + cd nested && + + mkdir -p partially_tracked/untracked_dir && + > partially_tracked/content && + > partially_tracked/untracked_dir/file && + + mkdir -p untracked/deep && + > untracked/deep/path && + > untracked/deep/foo.c && + + git add partially_tracked/content + ) +' + +test_expect_success 'ls-files -o --directory with single deep dir pathspec' ' + ( + cd nested && + + git ls-files -o --directory untracked/deep/ >actual && + + cat <<-EOF >expect && + untracked/deep/ + EOF + + test_cmp expect actual + ) +' + +test_expect_success 'ls-files -o --directory with multiple dir pathspecs' ' + ( + cd nested && + + git ls-files -o --directory partially_tracked/ untracked/ >actual && + + cat <<-EOF >expect && + partially_tracked/untracked_dir/ + untracked/ + EOF + + test_cmp expect actual + ) +' + +test_expect_success 'ls-files -o --directory with mix dir/file pathspecs' ' + ( + cd nested && + + git ls-files -o --directory partially_tracked/ untracked/deep/path >actual && + + cat <<-EOF >expect && + partially_tracked/untracked_dir/ + untracked/deep/path + EOF + + test_cmp expect actual + ) +' + +test_expect_success 'ls-files --o --directory with glob filetype match' ' + ( + cd nested && + + # globs kinda defeat --directory, but only for that pathspec + git ls-files --others --directory partially_tracked "untracked/*.c" >actual && + + cat <<-EOF >expect && + partially_tracked/untracked_dir/ + untracked/deep/foo.c + EOF + + test_cmp expect actual + ) +' + +test_expect_success 'ls-files --o --directory with mix of tracked states' ' + ( + cd nested && + + # globs kinda defeat --directory, but only for that pathspec + git ls-files --others --directory partially_tracked/ "untracked/?*" >actual && + + cat <<-EOF >expect && + partially_tracked/untracked_dir/ + untracked/deep/ + EOF + + test_cmp expect actual + ) +' + +test_expect_success 'ls-files --o --directory with glob filetype match only' ' + ( + cd nested && + + git ls-files --others --directory "untracked/*.c" >actual && + + cat <<-EOF >expect && + untracked/deep/foo.c + EOF + + test_cmp expect actual + ) +' + +test_expect_success 'ls-files --o --directory to get immediate paths under one dir only' ' + ( + cd nested && + + git ls-files --others --directory "untracked/?*" >actual && + + cat <<-EOF >expect && + untracked/deep/ + EOF + + test_cmp expect actual + ) +' + test_done diff --git a/t/t3007-ls-files-recurse-submodules.sh b/t/t3007-ls-files-recurse-submodules.sh index 318b5bce7e..4a08000713 100755 --- a/t/t3007-ls-files-recurse-submodules.sh +++ b/t/t3007-ls-files-recurse-submodules.sh @@ -130,7 +130,6 @@ test_expect_success '--recurse-submodules and pathspecs setup' ' git ls-files --recurse-submodules >actual && test_cmp expect actual && - cat actual && git ls-files --recurse-submodules "*" >actual && test_cmp expect actual ' diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh index 2170758e38..d48d211a95 100755 --- a/t/t3030-merge-recursive.sh +++ b/t/t3030-merge-recursive.sh @@ -604,7 +604,7 @@ test_expect_success 'merge removes empty directories' ' git commit -mremoved-d/e && git checkout master && git merge -s recursive rm && - test_must_fail test -d d + test_path_is_missing d ' test_expect_success 'merge-recursive simple w/submodule' ' diff --git a/t/t3033-merge-toplevel.sh b/t/t3033-merge-toplevel.sh index d314599428..e29c284b9b 100755 --- a/t/t3033-merge-toplevel.sh +++ b/t/t3033-merge-toplevel.sh @@ -142,6 +142,17 @@ test_expect_success 'refuse two-project merge by default' ' test_must_fail git merge five ' +test_expect_success 'refuse two-project merge by default, quit before --autostash happens' ' + t3033_reset && + git reset --hard four && + echo change >>one.t && + git diff >expect && + test_must_fail git merge --autostash five 2>err && + test_i18ngrep ! "stash" err && + git diff >actual && + test_cmp expect actual +' + test_expect_success 'two-project merge with --allow-unrelated-histories' ' t3033_reset && git reset --hard four && @@ -149,4 +160,15 @@ test_expect_success 'two-project merge with --allow-unrelated-histories' ' git diff --exit-code five ' +test_expect_success 'two-project merge with --allow-unrelated-histories with --autostash' ' + t3033_reset && + git reset --hard four && + echo change >>one.t && + git diff one.t >expect && + git merge --allow-unrelated-histories --autostash five 2>err && + test_i18ngrep "Applied autostash." err && + git diff one.t >actual && + test_cmp expect actual +' + test_done diff --git a/t/t3035-merge-sparse.sh b/t/t3035-merge-sparse.sh index c4b4a94324..74562e1235 100755 --- a/t/t3035-merge-sparse.sh +++ b/t/t3035-merge-sparse.sh @@ -28,7 +28,7 @@ test_expect_success 'setup' ' git config core.sparseCheckout true && echo "/checked-out" >.git/info/sparse-checkout && git reset --hard && - ! git merge theirs + test_must_fail git merge theirs ' test_expect_success 'reset --hard works after the conflict' ' @@ -42,7 +42,7 @@ test_expect_success 'is reset properly' ' ' test_expect_success 'setup: conflict back' ' - ! git merge theirs + test_must_fail git merge theirs ' test_expect_success 'Merge abort works after the conflict' ' diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh index 0575dd72b1..e024cff65c 100755 --- a/t/t3206-range-diff.sh +++ b/t/t3206-range-diff.sh @@ -102,6 +102,14 @@ test_expect_success 'setup' ' n3 sha256:3b0a644 n4 sha256:e461653 + # mode change + o1 sha1:4d39cb3 + o2 sha1:26c107f + o3 sha1:4c1e0f5 + o1 sha256:d0dd598 + o2 sha256:c4a279e + o3 sha256:78459d7 + # added and removed s1 sha1:096b1ba s2 sha1:d92e698 @@ -336,7 +344,7 @@ test_expect_success 'renamed file' ' test_expect_success 'file with mode only change' ' git range-diff --no-color --submodule=log topic...mode-only-change >actual && sed s/Z/\ /g >expect <<-EOF && - 1: fccce22 ! 1: 4d39cb3 s/4/A/ + 1: $(test_oid t2) ! 1: $(test_oid o1) s/4/A/ @@ Metadata ZAuthor: Thomas Rast <trast@inf.ethz.ch> Z @@ -352,7 +360,7 @@ test_expect_success 'file with mode only change' ' Z 7 + + ## other-file (new) ## - 2: 147e64e ! 2: 26c107f s/11/B/ + 2: $(test_oid t3) ! 2: $(test_oid o2) s/11/B/ @@ Metadata ZAuthor: Thomas Rast <trast@inf.ethz.ch> Z @@ -368,7 +376,7 @@ test_expect_success 'file with mode only change' ' Z 14 + + ## other-file (mode change 100644 => 100755) ## - 3: a63e992 = 3: 4c1e0f5 s/12/B/ + 3: $(test_oid t4) = 3: $(test_oid o3) s/12/B/ EOF test_cmp expect actual ' @@ -505,6 +513,16 @@ test_expect_success 'range-diff overrides diff.noprefix internally' ' git -c diff.noprefix=true range-diff HEAD^... ' +test_expect_success 'basic with modified format.pretty with suffix' ' + git -c format.pretty="format:commit %H%d%n" range-diff \ + master..topic master..unmodified +' + +test_expect_success 'basic with modified format.pretty without "commit "' ' + git -c format.pretty="format:%H%n" range-diff \ + master..topic master..unmodified +' + test_expect_success 'range-diff compares notes by default' ' git notes add -m "topic note" topic && git notes add -m "unmodified note" unmodified && diff --git a/t/t3305-notes-fanout.sh b/t/t3305-notes-fanout.sh index 831f83d211..3b4753e1b4 100755 --- a/t/t3305-notes-fanout.sh +++ b/t/t3305-notes-fanout.sh @@ -4,6 +4,38 @@ test_description='Test that adding/removing many notes triggers automatic fanout . ./test-lib.sh +path_has_fanout() { + path=$1 && + fanout=$2 && + after_last_slash=$((40 - $fanout * 2)) && + echo $path | grep -q "^\([0-9a-f]\{2\}/\)\{$fanout\}[0-9a-f]\{$after_last_slash\}$" +} + +touched_one_note_with_fanout() { + notes_commit=$1 && + modification=$2 && # 'A' for addition, 'D' for deletion + fanout=$3 && + diff=$(git diff-tree --no-commit-id --name-status --root -r $notes_commit) && + path=$(echo $diff | sed -e "s/^$modification[\t ]//") && + path_has_fanout "$path" $fanout; +} + +all_notes_have_fanout() { + notes_commit=$1 && + fanout=$2 && + git ls-tree -r --name-only $notes_commit 2>/dev/null | + while read path + do + path_has_fanout $path $fanout || return 1 + done +} + +test_expect_success 'tweak test environment' ' + git checkout -b nondeterminism && + test_commit A && + git checkout --orphan with_notes; +' + test_expect_success 'creating many notes with git-notes' ' num_notes=300 && i=0 && @@ -20,7 +52,7 @@ test_expect_success 'creating many notes with git-notes' ' test_expect_success 'many notes created correctly with git-notes' ' git log | grep "^ " > output && - i=300 && + i=$num_notes && while test $i -gt 0 do echo " commit #$i" && @@ -30,34 +62,46 @@ test_expect_success 'many notes created correctly with git-notes' ' test_cmp expect output ' -test_expect_success 'many notes created with git-notes triggers fanout' ' - # Expect entire notes tree to have a fanout == 1 - git ls-tree -r --name-only refs/notes/commits | - while read path +test_expect_success 'stable fanout 0 is followed by stable fanout 1' ' + i=$num_notes && + fanout=0 && + while test $i -gt 0 do - echo $path | grep "^../[0-9a-f]*$" || { - echo "Invalid path \"$path\"" && - return 1; - } - done + i=$(($i - 1)) && + if touched_one_note_with_fanout refs/notes/commits~$i A $fanout + then + continue + elif test $fanout -eq 0 + then + fanout=1 && + if all_notes_have_fanout refs/notes/commits~$i $fanout + then + echo "Fanout 0 -> 1 at refs/notes/commits~$i" && + continue + fi + fi && + echo "Failed fanout=$fanout check at refs/notes/commits~$i" && + git ls-tree -r --name-only refs/notes/commits~$i && + return 1 + done && + all_notes_have_fanout refs/notes/commits 1 ' test_expect_success 'deleting most notes with git-notes' ' - num_notes=250 && + remove_notes=285 && i=0 && git rev-list HEAD | - while test $i -lt $num_notes && read sha1 + while test $i -lt $remove_notes && read sha1 do i=$(($i + 1)) && test_tick && - git notes remove "$sha1" || - exit 1 + git notes remove "$sha1" 2>/dev/null || return 1 done ' test_expect_success 'most notes deleted correctly with git-notes' ' - git log HEAD~250 | grep "^ " > output && - i=50 && + git log HEAD~$remove_notes | grep "^ " > output && + i=$(($num_notes - $remove_notes)) && while test $i -gt 0 do echo " commit #$i" && @@ -67,16 +111,29 @@ test_expect_success 'most notes deleted correctly with git-notes' ' test_cmp expect output ' -test_expect_success 'deleting most notes triggers fanout consolidation' ' - # Expect entire notes tree to have a fanout == 0 - git ls-tree -r --name-only refs/notes/commits | - while read path +test_expect_success 'stable fanout 1 is followed by stable fanout 0' ' + i=$remove_notes && + fanout=1 && + while test $i -gt 0 do - echo $path | grep -v "^../.*" || { - echo "Invalid path \"$path\"" && - return 1; - } - done + i=$(($i - 1)) && + if touched_one_note_with_fanout refs/notes/commits~$i D $fanout + then + continue + elif test $fanout -eq 1 + then + fanout=0 && + if all_notes_have_fanout refs/notes/commits~$i $fanout + then + echo "Fanout 1 -> 0 at refs/notes/commits~$i" && + continue + fi + fi && + echo "Failed fanout=$fanout check at refs/notes/commits~$i" && + git ls-tree -r --name-only refs/notes/commits~$i && + return 1 + done && + all_notes_have_fanout refs/notes/commits 0 ' test_done diff --git a/t/t3308-notes-merge.sh b/t/t3308-notes-merge.sh index d60588ec8f..790e292966 100755 --- a/t/t3308-notes-merge.sh +++ b/t/t3308-notes-merge.sh @@ -20,7 +20,34 @@ test_expect_success setup ' git notes add -m "Notes on 3rd commit" 3rd && git notes add -m "Notes on 4th commit" 4th && # Copy notes to remote-notes - git fetch . refs/notes/*:refs/remote-notes/origin/* + git fetch . refs/notes/*:refs/remote-notes/origin/* && + + test_oid_init && + test_oid_cache <<-EOF + hash4a sha1:5e93d24084d32e1cb61f7070505b9d2530cca987 + hash3a sha1:8366731eeee53787d2bdf8fc1eff7d94757e8da0 + hash2a sha1:eede89064cd42441590d6afec6c37b321ada3389 + hash1a sha1:daa55ffad6cb99bf64226532147ffcaf5ce8bdd1 + hash5b sha1:0f2efbd00262f2fd41dfae33df8765618eeacd99 + hash4b sha1:dec2502dac3ea161543f71930044deff93fa945c + hash3b sha1:4069cdb399fd45463ec6eef8e051a16a03592d91 + hash2c sha1:d000d30e6ddcfce3a8122c403226a2ce2fd04d9d + hash1c sha1:43add6bd0c8c0bc871ac7991e0f5573cfba27804 + hash4d sha1:1f257a3a90328557c452f0817d6cc50c89d315d4 + hash3d sha1:05a4927951bcef347f51486575b878b2b60137f2 + + hash4a sha256:eef876be1d32ac2e2e42240e0429325cec116e55e88cb2969899fac695aa762f + hash3a sha256:cf7cd1bc091d7ba4166a86df864110e42087cd893a5ae96bc50d637e0290939d + hash2a sha256:21ddde7ebce2c285213898cb04deca0fd3209610cf7aaf8222e4e2f45262fae2 + hash1a sha256:f9fe0eda16c6027732ed9d4295689a03abd16f893be69b3dcbf4037ddb191921 + hash5b sha256:20046f2244577797a9e3d3f790ea9eca4d8a6bafb2a5570bcb0e03aa02ce100b + hash4b sha256:f90563d134c61a95bb88afbd45d48ccc9e919c62aa6fbfcd483302b3e4d8dbcb + hash3b sha256:988f2aca9f2d87e93e6a73197c2bb99560cc44a2f92d18653968f956f01221e0 + hash2c sha256:84153b777b4d42827a756c6578dcdb59d8ae5d1360b874fb37c430150c825c26 + hash1c sha256:9beb2bc4eef72e4c4087be168a20573e34d993d9ab1883055f23e322afa06567 + hash4d sha256:32de39dc06e679a7abb2d4a55ede7709b3124340a4a90aa305971b1c72ac319d + hash3d sha256:fa73b20e41cbb7541c4c81d1535016131dbfbeb05bf6a71f6115e9cad31c7af5 + EOF ' commit_sha1=$(git rev-parse 1st^{commit}) @@ -40,10 +67,10 @@ verify_notes () { } cat <<EOF | sort >expect_notes_x -5e93d24084d32e1cb61f7070505b9d2530cca987 $commit_sha4 -8366731eeee53787d2bdf8fc1eff7d94757e8da0 $commit_sha3 -eede89064cd42441590d6afec6c37b321ada3389 $commit_sha2 -daa55ffad6cb99bf64226532147ffcaf5ce8bdd1 $commit_sha1 +$(test_oid hash4a) $commit_sha4 +$(test_oid hash3a) $commit_sha3 +$(test_oid hash2a) $commit_sha2 +$(test_oid hash1a) $commit_sha1 EOF cat >expect_log_x <<EOF @@ -126,10 +153,10 @@ test_expect_success 'merge previous notes commit (y^ => y) => No-op' ' ' cat <<EOF | sort >expect_notes_y -0f2efbd00262f2fd41dfae33df8765618eeacd99 $commit_sha5 -dec2502dac3ea161543f71930044deff93fa945c $commit_sha4 -4069cdb399fd45463ec6eef8e051a16a03592d91 $commit_sha3 -daa55ffad6cb99bf64226532147ffcaf5ce8bdd1 $commit_sha1 +$(test_oid hash5b) $commit_sha5 +$(test_oid hash4b) $commit_sha4 +$(test_oid hash3b) $commit_sha3 +$(test_oid hash1a) $commit_sha1 EOF cat >expect_log_y <<EOF @@ -193,11 +220,11 @@ test_expect_success 'merge empty notes ref (z => y)' ' ' cat <<EOF | sort >expect_notes_y -0f2efbd00262f2fd41dfae33df8765618eeacd99 $commit_sha5 -dec2502dac3ea161543f71930044deff93fa945c $commit_sha4 -4069cdb399fd45463ec6eef8e051a16a03592d91 $commit_sha3 -d000d30e6ddcfce3a8122c403226a2ce2fd04d9d $commit_sha2 -43add6bd0c8c0bc871ac7991e0f5573cfba27804 $commit_sha1 +$(test_oid hash5b) $commit_sha5 +$(test_oid hash4b) $commit_sha4 +$(test_oid hash3b) $commit_sha3 +$(test_oid hash2c) $commit_sha2 +$(test_oid hash1c) $commit_sha1 EOF cat >expect_log_y <<EOF @@ -231,9 +258,9 @@ test_expect_success 'change notes on other notes ref (y)' ' ' cat <<EOF | sort >expect_notes_x -0f2efbd00262f2fd41dfae33df8765618eeacd99 $commit_sha5 -1f257a3a90328557c452f0817d6cc50c89d315d4 $commit_sha4 -daa55ffad6cb99bf64226532147ffcaf5ce8bdd1 $commit_sha1 +$(test_oid hash5b) $commit_sha5 +$(test_oid hash4d) $commit_sha4 +$(test_oid hash1a) $commit_sha1 EOF cat >expect_log_x <<EOF @@ -262,10 +289,10 @@ test_expect_success 'change notes on notes ref (x)' ' ' cat <<EOF | sort >expect_notes_x -0f2efbd00262f2fd41dfae33df8765618eeacd99 $commit_sha5 -1f257a3a90328557c452f0817d6cc50c89d315d4 $commit_sha4 -d000d30e6ddcfce3a8122c403226a2ce2fd04d9d $commit_sha2 -43add6bd0c8c0bc871ac7991e0f5573cfba27804 $commit_sha1 +$(test_oid hash5b) $commit_sha5 +$(test_oid hash4d) $commit_sha4 +$(test_oid hash2c) $commit_sha2 +$(test_oid hash1c) $commit_sha1 EOF cat >expect_log_x <<EOF @@ -296,8 +323,8 @@ test_expect_success 'merge y into x => Non-conflicting 3-way merge' ' ' cat <<EOF | sort >expect_notes_w -05a4927951bcef347f51486575b878b2b60137f2 $commit_sha3 -d000d30e6ddcfce3a8122c403226a2ce2fd04d9d $commit_sha2 +$(test_oid hash3d) $commit_sha3 +$(test_oid hash2c) $commit_sha2 EOF cat >expect_log_w <<EOF @@ -326,11 +353,11 @@ test_expect_success 'create notes on new, separate notes ref (w)' ' ' cat <<EOF | sort >expect_notes_x -0f2efbd00262f2fd41dfae33df8765618eeacd99 $commit_sha5 -1f257a3a90328557c452f0817d6cc50c89d315d4 $commit_sha4 -05a4927951bcef347f51486575b878b2b60137f2 $commit_sha3 -d000d30e6ddcfce3a8122c403226a2ce2fd04d9d $commit_sha2 -43add6bd0c8c0bc871ac7991e0f5573cfba27804 $commit_sha1 +$(test_oid hash5b) $commit_sha5 +$(test_oid hash4d) $commit_sha4 +$(test_oid hash3d) $commit_sha3 +$(test_oid hash2c) $commit_sha2 +$(test_oid hash1c) $commit_sha1 EOF cat >expect_log_x <<EOF diff --git a/t/t3309-notes-merge-auto-resolve.sh b/t/t3309-notes-merge-auto-resolve.sh index 14c2adf970..141d3e4ca4 100755 --- a/t/t3309-notes-merge-auto-resolve.sh +++ b/t/t3309-notes-merge-auto-resolve.sh @@ -23,7 +23,67 @@ test_expect_success 'setup commits' ' test_commit 12th && test_commit 13th && test_commit 14th && - test_commit 15th + test_commit 15th && + + test_oid_cache <<-EOF + hash15a sha1:457a85d6c814ea208550f15fcc48f804ac8dc023 + hash14a sha1:b0c95b954301d69da2bc3723f4cb1680d355937c + hash13a sha1:5d30216a129eeffa97d9694ffe8c74317a560315 + hash12a sha1:dd161bc149470fd890dd4ab52a4cbd79bbd18c36 + hash11a sha1:7abbc45126d680336fb24294f013a7cdfa3ed545 + hash10a sha1:b8d03e173f67f6505a76f6e00cf93440200dd9be + hash09a sha1:20c613c835011c48a5abe29170a2402ca6354910 + hash08a sha1:a3daf8a1e4e5dc3409a303ad8481d57bfea7f5d6 + hash07a sha1:897003322b53bc6ca098e9324ee508362347e734 + hash06a sha1:11d97fdebfa5ceee540a3da07bce6fa0222bc082 + hash15b sha1:68b8630d25516028bed862719855b3d6768d7833 + hash14b sha1:5de7ea7ad4f47e7ff91989fb82234634730f75df + hash13b sha1:3a631fdb6f41b05b55d8f4baf20728ba8f6fccbc + hash12b sha1:a66055fa82f7a03fe0c02a6aba3287a85abf7c62 + hash05b sha1:154508c7a0bcad82b6fe4b472bc4c26b3bf0825b + hash04b sha1:e2bfd06a37dd2031684a59a6e2b033e212239c78 + hash03b sha1:5772f42408c0dd6f097a7ca2d24de0e78d1c46b1 + hash15c sha1:9b4b2c61f0615412da3c10f98ff85b57c04ec765 + hash11c sha1:7e3c53503a3db8dd996cb62e37c66e070b44b54d + hash08c sha1:851e1638784a884c7dd26c5d41f3340f6387413a + hash05c sha1:99fc34adfc400b95c67b013115e37e31aa9a6d23 + hash02c sha1:283b48219aee9a4105f6cab337e789065c82c2b9 + hash15d sha1:7c4e546efd0fe939f876beb262ece02797880b54 + hash05d sha1:6c841cc36ea496027290967ca96bd2bef54dbb47 + hash15e sha1:d682107b8bf7a7aea1e537a8d5cb6a12b60135f1 + hash05e sha1:357b6ca14c7afd59b7f8b8aaaa6b8b723771135b + hash15f sha1:6be90240b5f54594203e25d9f2f64b7567175aee + hash05f sha1:660311d7f78dc53db12ac373a43fca7465381a7e + + hash15a sha256:45b1558e5c1b75f570010fa48aaa67bb2289fcd431b34ad81cb4c8b95f4f872a + hash14a sha256:6e7af179ea4dd28afdc83ae6912ba0098cdeff764b26a8b750b157dd81749092 + hash13a sha256:7353089961baf555388e1bac68c67c8ea94b08ccbd97532201cf7f6790703052 + hash12a sha256:5863e4521689ee1879ceab3b38d39e93ab5b51ec70aaf6a96ad388fbdedfa25e + hash11a sha256:82a0ec0338b4ecf8b44304badf4ad38d7469dc41827f38d7ba6c42e3bae3ee98 + hash10a sha256:e84f2564e92de9792c93b8d197262c735d7ccb1de6025cef8759af8f6c3308eb + hash09a sha256:4dd07764bcec696f195c0ea71ae89e174876403af1637e4642b8f4453fd23028 + hash08a sha256:02132c4546cd88a1d0aa5854dd55da120927f7904ba16afe36fe03e91a622067 + hash07a sha256:369baf7d00c6720efdc10273493555f943051f84a4706fb24caeb353fa4789db + hash06a sha256:52d32c10353583b2d96a5849b1f1f43c8018e76f3e8ef1b0d46eb5cff7cdefaf + hash15b sha256:345e6660b345fa174738a31a7a59423c394bdf414804e200bc510c65d971ae96 + hash14b sha256:7653a6596021c52e405cba979eea15a729993e7102b9a61ba4667e34f0ead4a1 + hash13b sha256:0f202a0b6b9690de2349c173dfd766a37e82744f61c14f1c389306f1d69f470b + hash12b sha256:eb00f219c026136ea6535b16ff8ec3efa510e6bf50098ca041e1a2a1d4b79840 + hash05b sha256:993b2290cd0c24c27c849d99f1904f3b590f77af0f539932734ad05679ac5a2f + hash04b sha256:c7fba0d6104917fbf35258f40b9fa4fc697cfa992deecd1570a3b08d0a5587a9 + hash03b sha256:7287a2d78a3766c181b08df38951d784b08b72a44f571ed6d855bd0be22c70f6 + hash15c sha256:62316660a22bf97857dc4a16709ec4d93a224e8c9f37d661ef91751e1f4c4166 + hash11c sha256:51c3763de9b08309370adc5036d58debb331980e73097902957c444602551daa + hash08c sha256:22cf1fa29599898a7218c51135d66ed85d22aad584f77db3305dedce4c3d4798 + hash05c sha256:2508fd86db980f0508893a1c1571bdf3b2ee113dc25ddb1a3a2fb94bd6cd0d58 + hash02c sha256:63bb527e0b4e1c8e1dd0d54dd778ca7c3718689fd6e37c473044cfbcf1cacfdb + hash15d sha256:667acb4e2d5f8df15e5aea4506dfd16d25bc7feca70fdb0d965a7222f983bb88 + hash05d sha256:09e6b5a6fe666c4a027674b6611a254b7d2528cd211c6b5288d1b4db6c741dfa + hash15e sha256:e8cbf52f6fcadc6de3c7761e64a89e9fe38d19a03d3e28ef6ca8596d93fc4f3a + hash05e sha256:cdb1e19f7ba1539f95af51a57edeb88a7ecc97d3c2f52da8c4c86af308595607 + hash15f sha256:29c14cb92da448a923963b8a43994268b19c2e57913de73f3667421fd2c0eeec + hash05f sha256:14a6e641b2c0a9f398ebac6b4d34afa5efea4c52d2631382f45f8f662266903b + EOF ' commit_sha1=$(git rev-parse 1st^{commit}) @@ -68,16 +128,16 @@ test_expect_success 'setup merge base (x)' ' ' cat <<EOF | sort >expect_notes_x -457a85d6c814ea208550f15fcc48f804ac8dc023 $commit_sha15 -b0c95b954301d69da2bc3723f4cb1680d355937c $commit_sha14 -5d30216a129eeffa97d9694ffe8c74317a560315 $commit_sha13 -dd161bc149470fd890dd4ab52a4cbd79bbd18c36 $commit_sha12 -7abbc45126d680336fb24294f013a7cdfa3ed545 $commit_sha11 -b8d03e173f67f6505a76f6e00cf93440200dd9be $commit_sha10 -20c613c835011c48a5abe29170a2402ca6354910 $commit_sha9 -a3daf8a1e4e5dc3409a303ad8481d57bfea7f5d6 $commit_sha8 -897003322b53bc6ca098e9324ee508362347e734 $commit_sha7 -11d97fdebfa5ceee540a3da07bce6fa0222bc082 $commit_sha6 +$(test_oid hash15a) $commit_sha15 +$(test_oid hash14a) $commit_sha14 +$(test_oid hash13a) $commit_sha13 +$(test_oid hash12a) $commit_sha12 +$(test_oid hash11a) $commit_sha11 +$(test_oid hash10a) $commit_sha10 +$(test_oid hash09a) $commit_sha9 +$(test_oid hash08a) $commit_sha8 +$(test_oid hash07a) $commit_sha7 +$(test_oid hash06a) $commit_sha6 EOF cat >expect_log_x <<EOF @@ -141,16 +201,16 @@ test_expect_success 'setup local branch (y)' ' ' cat <<EOF | sort >expect_notes_y -68b8630d25516028bed862719855b3d6768d7833 $commit_sha15 -5de7ea7ad4f47e7ff91989fb82234634730f75df $commit_sha14 -3a631fdb6f41b05b55d8f4baf20728ba8f6fccbc $commit_sha13 -a66055fa82f7a03fe0c02a6aba3287a85abf7c62 $commit_sha12 -7abbc45126d680336fb24294f013a7cdfa3ed545 $commit_sha11 -b8d03e173f67f6505a76f6e00cf93440200dd9be $commit_sha10 -20c613c835011c48a5abe29170a2402ca6354910 $commit_sha9 -154508c7a0bcad82b6fe4b472bc4c26b3bf0825b $commit_sha5 -e2bfd06a37dd2031684a59a6e2b033e212239c78 $commit_sha4 -5772f42408c0dd6f097a7ca2d24de0e78d1c46b1 $commit_sha3 +$(test_oid hash15b) $commit_sha15 +$(test_oid hash14b) $commit_sha14 +$(test_oid hash13b) $commit_sha13 +$(test_oid hash12b) $commit_sha12 +$(test_oid hash11a) $commit_sha11 +$(test_oid hash10a) $commit_sha10 +$(test_oid hash09a) $commit_sha9 +$(test_oid hash05b) $commit_sha5 +$(test_oid hash04b) $commit_sha4 +$(test_oid hash03b) $commit_sha3 EOF cat >expect_log_y <<EOF @@ -214,16 +274,16 @@ test_expect_success 'setup remote branch (z)' ' ' cat <<EOF | sort >expect_notes_z -9b4b2c61f0615412da3c10f98ff85b57c04ec765 $commit_sha15 -5de7ea7ad4f47e7ff91989fb82234634730f75df $commit_sha14 -5d30216a129eeffa97d9694ffe8c74317a560315 $commit_sha13 -7e3c53503a3db8dd996cb62e37c66e070b44b54d $commit_sha11 -b8d03e173f67f6505a76f6e00cf93440200dd9be $commit_sha10 -851e1638784a884c7dd26c5d41f3340f6387413a $commit_sha8 -897003322b53bc6ca098e9324ee508362347e734 $commit_sha7 -99fc34adfc400b95c67b013115e37e31aa9a6d23 $commit_sha5 -e2bfd06a37dd2031684a59a6e2b033e212239c78 $commit_sha4 -283b48219aee9a4105f6cab337e789065c82c2b9 $commit_sha2 +$(test_oid hash15c) $commit_sha15 +$(test_oid hash14b) $commit_sha14 +$(test_oid hash13a) $commit_sha13 +$(test_oid hash11c) $commit_sha11 +$(test_oid hash10a) $commit_sha10 +$(test_oid hash08c) $commit_sha8 +$(test_oid hash07a) $commit_sha7 +$(test_oid hash05c) $commit_sha5 +$(test_oid hash04b) $commit_sha4 +$(test_oid hash02c) $commit_sha2 EOF cat >expect_log_z <<EOF @@ -306,16 +366,16 @@ test_expect_success 'merge z into y with invalid configuration option => Fail/No ' cat <<EOF | sort >expect_notes_ours -68b8630d25516028bed862719855b3d6768d7833 $commit_sha15 -5de7ea7ad4f47e7ff91989fb82234634730f75df $commit_sha14 -3a631fdb6f41b05b55d8f4baf20728ba8f6fccbc $commit_sha13 -a66055fa82f7a03fe0c02a6aba3287a85abf7c62 $commit_sha12 -7e3c53503a3db8dd996cb62e37c66e070b44b54d $commit_sha11 -b8d03e173f67f6505a76f6e00cf93440200dd9be $commit_sha10 -154508c7a0bcad82b6fe4b472bc4c26b3bf0825b $commit_sha5 -e2bfd06a37dd2031684a59a6e2b033e212239c78 $commit_sha4 -5772f42408c0dd6f097a7ca2d24de0e78d1c46b1 $commit_sha3 -283b48219aee9a4105f6cab337e789065c82c2b9 $commit_sha2 +$(test_oid hash15b) $commit_sha15 +$(test_oid hash14b) $commit_sha14 +$(test_oid hash13b) $commit_sha13 +$(test_oid hash12b) $commit_sha12 +$(test_oid hash11c) $commit_sha11 +$(test_oid hash10a) $commit_sha10 +$(test_oid hash05b) $commit_sha5 +$(test_oid hash04b) $commit_sha4 +$(test_oid hash03b) $commit_sha3 +$(test_oid hash02c) $commit_sha2 EOF cat >expect_log_ours <<EOF @@ -395,16 +455,16 @@ test_expect_success 'reset to pre-merge state (y)' ' ' cat <<EOF | sort >expect_notes_theirs -9b4b2c61f0615412da3c10f98ff85b57c04ec765 $commit_sha15 -5de7ea7ad4f47e7ff91989fb82234634730f75df $commit_sha14 -3a631fdb6f41b05b55d8f4baf20728ba8f6fccbc $commit_sha13 -7e3c53503a3db8dd996cb62e37c66e070b44b54d $commit_sha11 -b8d03e173f67f6505a76f6e00cf93440200dd9be $commit_sha10 -851e1638784a884c7dd26c5d41f3340f6387413a $commit_sha8 -99fc34adfc400b95c67b013115e37e31aa9a6d23 $commit_sha5 -e2bfd06a37dd2031684a59a6e2b033e212239c78 $commit_sha4 -5772f42408c0dd6f097a7ca2d24de0e78d1c46b1 $commit_sha3 -283b48219aee9a4105f6cab337e789065c82c2b9 $commit_sha2 +$(test_oid hash15c) $commit_sha15 +$(test_oid hash14b) $commit_sha14 +$(test_oid hash13b) $commit_sha13 +$(test_oid hash11c) $commit_sha11 +$(test_oid hash10a) $commit_sha10 +$(test_oid hash08c) $commit_sha8 +$(test_oid hash05c) $commit_sha5 +$(test_oid hash04b) $commit_sha4 +$(test_oid hash03b) $commit_sha3 +$(test_oid hash02c) $commit_sha2 EOF cat >expect_log_theirs <<EOF @@ -473,17 +533,17 @@ test_expect_success 'reset to pre-merge state (y)' ' ' cat <<EOF | sort >expect_notes_union -7c4e546efd0fe939f876beb262ece02797880b54 $commit_sha15 -5de7ea7ad4f47e7ff91989fb82234634730f75df $commit_sha14 -3a631fdb6f41b05b55d8f4baf20728ba8f6fccbc $commit_sha13 -a66055fa82f7a03fe0c02a6aba3287a85abf7c62 $commit_sha12 -7e3c53503a3db8dd996cb62e37c66e070b44b54d $commit_sha11 -b8d03e173f67f6505a76f6e00cf93440200dd9be $commit_sha10 -851e1638784a884c7dd26c5d41f3340f6387413a $commit_sha8 -6c841cc36ea496027290967ca96bd2bef54dbb47 $commit_sha5 -e2bfd06a37dd2031684a59a6e2b033e212239c78 $commit_sha4 -5772f42408c0dd6f097a7ca2d24de0e78d1c46b1 $commit_sha3 -283b48219aee9a4105f6cab337e789065c82c2b9 $commit_sha2 +$(test_oid hash15d) $commit_sha15 +$(test_oid hash14b) $commit_sha14 +$(test_oid hash13b) $commit_sha13 +$(test_oid hash12b) $commit_sha12 +$(test_oid hash11c) $commit_sha11 +$(test_oid hash10a) $commit_sha10 +$(test_oid hash08c) $commit_sha8 +$(test_oid hash05d) $commit_sha5 +$(test_oid hash04b) $commit_sha4 +$(test_oid hash03b) $commit_sha3 +$(test_oid hash02c) $commit_sha2 EOF cat >expect_log_union <<EOF @@ -574,17 +634,17 @@ test_expect_success 'merge z into y with "manual" per-ref only checks specific r ' cat <<EOF | sort >expect_notes_union2 -d682107b8bf7a7aea1e537a8d5cb6a12b60135f1 $commit_sha15 -5de7ea7ad4f47e7ff91989fb82234634730f75df $commit_sha14 -3a631fdb6f41b05b55d8f4baf20728ba8f6fccbc $commit_sha13 -a66055fa82f7a03fe0c02a6aba3287a85abf7c62 $commit_sha12 -7e3c53503a3db8dd996cb62e37c66e070b44b54d $commit_sha11 -b8d03e173f67f6505a76f6e00cf93440200dd9be $commit_sha10 -851e1638784a884c7dd26c5d41f3340f6387413a $commit_sha8 -357b6ca14c7afd59b7f8b8aaaa6b8b723771135b $commit_sha5 -e2bfd06a37dd2031684a59a6e2b033e212239c78 $commit_sha4 -5772f42408c0dd6f097a7ca2d24de0e78d1c46b1 $commit_sha3 -283b48219aee9a4105f6cab337e789065c82c2b9 $commit_sha2 +$(test_oid hash15e) $commit_sha15 +$(test_oid hash14b) $commit_sha14 +$(test_oid hash13b) $commit_sha13 +$(test_oid hash12b) $commit_sha12 +$(test_oid hash11c) $commit_sha11 +$(test_oid hash10a) $commit_sha10 +$(test_oid hash08c) $commit_sha8 +$(test_oid hash05e) $commit_sha5 +$(test_oid hash04b) $commit_sha4 +$(test_oid hash03b) $commit_sha3 +$(test_oid hash02c) $commit_sha2 EOF cat >expect_log_union2 <<EOF @@ -648,17 +708,17 @@ test_expect_success 'reset to pre-merge state (z)' ' ' cat <<EOF | sort >expect_notes_cat_sort_uniq -6be90240b5f54594203e25d9f2f64b7567175aee $commit_sha15 -5de7ea7ad4f47e7ff91989fb82234634730f75df $commit_sha14 -3a631fdb6f41b05b55d8f4baf20728ba8f6fccbc $commit_sha13 -a66055fa82f7a03fe0c02a6aba3287a85abf7c62 $commit_sha12 -7e3c53503a3db8dd996cb62e37c66e070b44b54d $commit_sha11 -b8d03e173f67f6505a76f6e00cf93440200dd9be $commit_sha10 -851e1638784a884c7dd26c5d41f3340f6387413a $commit_sha8 -660311d7f78dc53db12ac373a43fca7465381a7e $commit_sha5 -e2bfd06a37dd2031684a59a6e2b033e212239c78 $commit_sha4 -5772f42408c0dd6f097a7ca2d24de0e78d1c46b1 $commit_sha3 -283b48219aee9a4105f6cab337e789065c82c2b9 $commit_sha2 +$(test_oid hash15f) $commit_sha15 +$(test_oid hash14b) $commit_sha14 +$(test_oid hash13b) $commit_sha13 +$(test_oid hash12b) $commit_sha12 +$(test_oid hash11c) $commit_sha11 +$(test_oid hash10a) $commit_sha10 +$(test_oid hash08c) $commit_sha8 +$(test_oid hash05f) $commit_sha5 +$(test_oid hash04b) $commit_sha4 +$(test_oid hash03b) $commit_sha3 +$(test_oid hash02c) $commit_sha2 EOF cat >expect_log_cat_sort_uniq <<EOF diff --git a/t/t3310-notes-merge-manual-resolve.sh b/t/t3310-notes-merge-manual-resolve.sh index 2dea846e25..d3d72e25fe 100755 --- a/t/t3310-notes-merge-manual-resolve.sh +++ b/t/t3310-notes-merge-manual-resolve.sh @@ -13,7 +13,39 @@ test_expect_success 'setup commits' ' test_commit 2nd && test_commit 3rd && test_commit 4th && - test_commit 5th + test_commit 5th && + + test_oid_cache <<-EOF + hash04a sha1:6e8e3febca3c2bb896704335cc4d0c34cb2f8715 + hash03a sha1:e5388c10860456ee60673025345fe2e153eb8cf8 + hash02a sha1:ceefa674873670e7ecd131814d909723cce2b669 + hash04b sha1:e2bfd06a37dd2031684a59a6e2b033e212239c78 + hash03b sha1:5772f42408c0dd6f097a7ca2d24de0e78d1c46b1 + hash01b sha1:b0a6021ec006d07e80e9b20ec9b444cbd9d560d3 + hash04c sha1:cff59c793c20bb49a4e01bc06fb06bad642e0d54 + hash02c sha1:283b48219aee9a4105f6cab337e789065c82c2b9 + hash01c sha1:0a81da8956346e19bcb27a906f04af327e03e31b + hash04d sha1:00494adecf2d9635a02fa431308d67993f853968 + hash01e sha1:f75d1df88cbfe4258d49852f26cfc83f2ad4494b + hash04f sha1:021faa20e931fb48986ffc6282b4bb05553ac946 + hash01f sha1:0a59e787e6d688aa6309e56e8c1b89431a0fc1c1 + hash05g sha1:304dfb4325cf243025b9957486eb605a9b51c199 + + hash04a sha256:f18a935e65866345098b3b754071dbf9f3aa3520eb27a7b036b278c5e2f1ed7e + hash03a sha256:713035dc94067a64e5fa6e4e1821b7c3bde49a77c7cb3f80eaadefa1ca41b3d2 + hash02a sha256:f160a67e048b6fa75bec3952184154045076692cf5dccd3da21e3fd34b7a3f0f + hash04b sha256:c7fba0d6104917fbf35258f40b9fa4fc697cfa992deecd1570a3b08d0a5587a9 + hash03b sha256:7287a2d78a3766c181b08df38951d784b08b72a44f571ed6d855bd0be22c70f6 + hash01b sha256:da96cf778c15d0a2bb76f98b2a62f6c9c01730fa7030e8f08ef0191048e7d620 + hash04c sha256:cb615d2def4b834d5f55b2351df97dc92bee4f5009d285201427f349081c8aca + hash02c sha256:63bb527e0b4e1c8e1dd0d54dd778ca7c3718689fd6e37c473044cfbcf1cacfdb + hash01c sha256:5b87237ac1fbae0246256fed9f9a1f077c4140fb7e6444925f8dbfa5ae406cd8 + hash04d sha256:eeddc9f9f6cb3d6b39b861659853f10891dc373e0b6eecb09e03e39b6ce64714 + hash01e sha256:108f521b1a74c2e6d0b52a4eda87e09162bf847f7d190cfce496ee1af0b29a5a + hash04f sha256:901acda0454502b3bbd281f130c419e6c8de78afcf72a8def8d45ad31462bce4 + hash01f sha256:a2d99d1b8bf23c8af7d9d91368454adc110dfd5cc068a4cebb486ee8f5a1e16c + hash05g sha256:4fef015b01da8efe929a68e3bb9b8fbad81f53995f097befe8ebc93f12ab98ec + EOF ' commit_sha1=$(git rev-parse 1st^{commit}) @@ -32,10 +64,16 @@ verify_notes () { test_cmp "expect_log_$notes_ref" "output_log_$notes_ref" } +notes_merge_files_gone () { + # No .git/NOTES_MERGE_* files left + { ls .git/NOTES_MERGE_* >output || :; } && + test_must_be_empty output +} + cat <<EOF | sort >expect_notes_x -6e8e3febca3c2bb896704335cc4d0c34cb2f8715 $commit_sha4 -e5388c10860456ee60673025345fe2e153eb8cf8 $commit_sha3 -ceefa674873670e7ecd131814d909723cce2b669 $commit_sha2 +$(test_oid hash04a) $commit_sha4 +$(test_oid hash03a) $commit_sha3 +$(test_oid hash02a) $commit_sha2 EOF cat >expect_log_x <<EOF @@ -63,9 +101,9 @@ test_expect_success 'setup merge base (x)' ' ' cat <<EOF | sort >expect_notes_y -e2bfd06a37dd2031684a59a6e2b033e212239c78 $commit_sha4 -5772f42408c0dd6f097a7ca2d24de0e78d1c46b1 $commit_sha3 -b0a6021ec006d07e80e9b20ec9b444cbd9d560d3 $commit_sha1 +$(test_oid hash04b) $commit_sha4 +$(test_oid hash03b) $commit_sha3 +$(test_oid hash01b) $commit_sha1 EOF cat >expect_log_y <<EOF @@ -95,9 +133,9 @@ test_expect_success 'setup local branch (y)' ' ' cat <<EOF | sort >expect_notes_z -cff59c793c20bb49a4e01bc06fb06bad642e0d54 $commit_sha4 -283b48219aee9a4105f6cab337e789065c82c2b9 $commit_sha2 -0a81da8956346e19bcb27a906f04af327e03e31b $commit_sha1 +$(test_oid hash04c) $commit_sha4 +$(test_oid hash02c) $commit_sha2 +$(test_oid hash01c) $commit_sha1 EOF cat >expect_log_z <<EOF @@ -193,9 +231,9 @@ test_expect_success 'merge z into m (== y) with default ("manual") resolver => C ' cat <<EOF | sort >expect_notes_z -00494adecf2d9635a02fa431308d67993f853968 $commit_sha4 -283b48219aee9a4105f6cab337e789065c82c2b9 $commit_sha2 -0a81da8956346e19bcb27a906f04af327e03e31b $commit_sha1 +$(test_oid hash04d) $commit_sha4 +$(test_oid hash02c) $commit_sha2 +$(test_oid hash01c) $commit_sha1 EOF cat >expect_log_z <<EOF @@ -231,8 +269,8 @@ test_expect_success 'cannot do merge w/conflicts when previous merge is unfinish # Setup non-conflicting merge between x and new notes ref w cat <<EOF | sort >expect_notes_w -ceefa674873670e7ecd131814d909723cce2b669 $commit_sha2 -f75d1df88cbfe4258d49852f26cfc83f2ad4494b $commit_sha1 +$(test_oid hash02a) $commit_sha2 +$(test_oid hash01e) $commit_sha1 EOF cat >expect_log_w <<EOF @@ -258,10 +296,10 @@ test_expect_success 'setup unrelated notes ref (w)' ' ' cat <<EOF | sort >expect_notes_w -6e8e3febca3c2bb896704335cc4d0c34cb2f8715 $commit_sha4 -e5388c10860456ee60673025345fe2e153eb8cf8 $commit_sha3 -ceefa674873670e7ecd131814d909723cce2b669 $commit_sha2 -f75d1df88cbfe4258d49852f26cfc83f2ad4494b $commit_sha1 +$(test_oid hash04a) $commit_sha4 +$(test_oid hash03a) $commit_sha3 +$(test_oid hash02a) $commit_sha2 +$(test_oid hash01e) $commit_sha1 EOF cat >expect_log_w <<EOF @@ -291,10 +329,10 @@ test_expect_success 'can do merge without conflicts even if previous merge is un ' cat <<EOF | sort >expect_notes_m -021faa20e931fb48986ffc6282b4bb05553ac946 $commit_sha4 -5772f42408c0dd6f097a7ca2d24de0e78d1c46b1 $commit_sha3 -283b48219aee9a4105f6cab337e789065c82c2b9 $commit_sha2 -0a59e787e6d688aa6309e56e8c1b89431a0fc1c1 $commit_sha1 +$(test_oid hash04f) $commit_sha4 +$(test_oid hash03b) $commit_sha3 +$(test_oid hash02c) $commit_sha2 +$(test_oid hash01f) $commit_sha1 EOF cat >expect_log_m <<EOF @@ -335,9 +373,7 @@ EOF y and z notes on 4th commit EOF git notes merge --commit && - # No .git/NOTES_MERGE_* files left - test_might_fail ls .git/NOTES_MERGE_* >output 2>/dev/null && - test_must_be_empty output && + notes_merge_files_gone && # Merge commit has pre-merge y and pre-merge z as parents test "$(git rev-parse refs/notes/m^1)" = "$(cat pre_merge_y)" && test "$(git rev-parse refs/notes/m^2)" = "$(cat pre_merge_z)" && @@ -397,9 +433,7 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol test_expect_success 'abort notes merge' ' git notes merge --abort && - # No .git/NOTES_MERGE_* files left - test_might_fail ls .git/NOTES_MERGE_* >output 2>/dev/null && - test_must_be_empty output && + notes_merge_files_gone && # m has not moved (still == y) test "$(git rev-parse refs/notes/m)" = "$(cat pre_merge_y)" && # Verify that other notes refs has not changed (w, x, y and z) @@ -430,9 +464,9 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol ' cat <<EOF | sort >expect_notes_m -304dfb4325cf243025b9957486eb605a9b51c199 $commit_sha5 -283b48219aee9a4105f6cab337e789065c82c2b9 $commit_sha2 -0a59e787e6d688aa6309e56e8c1b89431a0fc1c1 $commit_sha1 +$(test_oid hash05g) $commit_sha5 +$(test_oid hash02c) $commit_sha2 +$(test_oid hash01f) $commit_sha1 EOF cat >expect_log_m <<EOF @@ -464,9 +498,7 @@ EOF echo "new note on 5th commit" > .git/NOTES_MERGE_WORKTREE/$commit_sha5 && # Finalize merge git notes merge --commit && - # No .git/NOTES_MERGE_* files left - test_might_fail ls .git/NOTES_MERGE_* >output 2>/dev/null && - test_must_be_empty output && + notes_merge_files_gone && # Merge commit has pre-merge y and pre-merge z as parents test "$(git rev-parse refs/notes/m^1)" = "$(cat pre_merge_y)" && test "$(git rev-parse refs/notes/m^2)" = "$(cat pre_merge_z)" && @@ -553,9 +585,7 @@ EOF test_expect_success 'resolve situation by aborting the notes merge' ' git notes merge --abort && - # No .git/NOTES_MERGE_* files left - test_might_fail ls .git/NOTES_MERGE_* >output 2>/dev/null && - test_must_be_empty output && + notes_merge_files_gone && # m has not moved (still == w) test "$(git rev-parse refs/notes/m)" = "$(git rev-parse refs/notes/w)" && # Verify that other notes refs has not changed (w, x, y and z) diff --git a/t/t3311-notes-merge-fanout.sh b/t/t3311-notes-merge-fanout.sh index 37151a3adc..5b675417e9 100755 --- a/t/t3311-notes-merge-fanout.sh +++ b/t/t3311-notes-merge-fanout.sh @@ -29,15 +29,10 @@ verify_fanout () { git ls-tree -r --name-only "refs/notes/$notes_ref" | while read path do - case "$path" in - ??/??????????????????????????????????????) - : true - ;; - *) + echo "$path" | grep "^../[0-9a-f]*$" || { echo "Invalid path \"$path\"" && - return 1 - ;; - esac + return 1; + } done } @@ -48,15 +43,10 @@ verify_no_fanout () { git ls-tree -r --name-only "refs/notes/$notes_ref" | while read path do - case "$path" in - ????????????????????????????????????????) - : true - ;; - *) + echo "$path" | grep -v "^../.*" || { echo "Invalid path \"$path\"" && - return 1 - ;; - esac + return 1; + } done } @@ -67,7 +57,27 @@ test_expect_success 'setup a few initial commits with notes (notes ref: x)' ' do test_commit "commit$i" >/dev/null && git notes add -m "notes for commit$i" || return 1 - done + done && + + git log --format=oneline && + + test_oid_cache <<-EOF + hash05a sha1:aed91155c7a72c2188e781fdf40e0f3761b299db + hash04a sha1:99fab268f9d7ee7b011e091a436c78def8eeee69 + hash03a sha1:953c20ae26c7aa0b428c20693fe38bc687f9d1a9 + hash02a sha1:6358796131b8916eaa2dde6902642942a1cb37e1 + hash01a sha1:b02d459c32f0e68f2fe0981033bb34f38776ba47 + hash03b sha1:9f506ee70e20379d7f78204c77b334f43d77410d + hash02b sha1:23a47d6ea7d589895faf800752054818e1e7627b + + hash05a sha256:3aae5d26619d96dba93795f66325716e4cbc486884f95a6adee8fb0615a76d12 + hash04a sha256:07e43dd3d89fe634d3252e253b426aacc7285a995dcdbcf94ac284060a1122cf + hash03a sha256:26fb52eaa7f4866bf735254587be7b31209ec10e525912ffd8e8ba549ba892ff + hash02a sha256:b57ebdf23634e750dcbc4b9a37991d70f90830d568a0e4529ce9de0a3f8d605c + hash01a sha256:377903b1572bd5117087a5518fcb1011b5053cccbc59e3c7c823a8615204173b + hash03b sha256:04e7b392fda7c185bfa17c9179b56db732edc2dc2b3bf887308dcaabb717270d + hash02b sha256:66099aaaec49a485ed990acadd9a9b81232ea592079964113d8f581ff69ef50b + EOF ' commit_sha1=$(git rev-parse commit1^{commit}) @@ -77,11 +87,11 @@ commit_sha4=$(git rev-parse commit4^{commit}) commit_sha5=$(git rev-parse commit5^{commit}) cat <<EOF | sort >expect_notes_x -aed91155c7a72c2188e781fdf40e0f3761b299db $commit_sha5 -99fab268f9d7ee7b011e091a436c78def8eeee69 $commit_sha4 -953c20ae26c7aa0b428c20693fe38bc687f9d1a9 $commit_sha3 -6358796131b8916eaa2dde6902642942a1cb37e1 $commit_sha2 -b02d459c32f0e68f2fe0981033bb34f38776ba47 $commit_sha1 +$(test_oid hash05a) $commit_sha5 +$(test_oid hash04a) $commit_sha4 +$(test_oid hash03a) $commit_sha3 +$(test_oid hash02a) $commit_sha2 +$(test_oid hash01a) $commit_sha1 EOF cat >expect_log_x <<EOF @@ -145,9 +155,9 @@ test_expect_success 'Fast-forward merge (y => x)' ' ' cat <<EOF | sort >expect_notes_z -9f506ee70e20379d7f78204c77b334f43d77410d $commit_sha3 -23a47d6ea7d589895faf800752054818e1e7627b $commit_sha2 -b02d459c32f0e68f2fe0981033bb34f38776ba47 $commit_sha1 +$(test_oid hash03b) $commit_sha3 +$(test_oid hash02b) $commit_sha2 +$(test_oid hash01a) $commit_sha1 EOF cat >expect_log_z <<EOF diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh index 221b35f2df..40d2975995 100755 --- a/t/t3400-rebase.sh +++ b/t/t3400-rebase.sh @@ -143,11 +143,11 @@ test_expect_success 'setup: recover' ' test_expect_success 'Show verbose error when HEAD could not be detached' ' >B && + test_when_finished "rm -f B" && test_must_fail git rebase topic 2>output.err >output.out && test_i18ngrep "The following untracked working tree files would be overwritten by checkout:" output.err && test_i18ngrep B output.err ' -rm -f B test_expect_success 'fail when upstream arg is missing and not on branch' ' git checkout topic && @@ -165,19 +165,37 @@ test_expect_success 'rebase works with format.useAutoBase' ' git rebase master ' -test_expect_success 'default to common base in @{upstream}s reflog if no upstream arg' ' +test_expect_success 'default to common base in @{upstream}s reflog if no upstream arg (--merge)' ' git checkout -b default-base master && git checkout -b default topic && git config branch.default.remote . && git config branch.default.merge refs/heads/default-base && - git rebase && + git rebase --merge && git rev-parse --verify default-base >expect && git rev-parse default~1 >actual && test_cmp expect actual && git checkout default-base && git reset --hard HEAD^ && git checkout default && - git rebase && + git rebase --merge && + git rev-parse --verify default-base >expect && + git rev-parse default~1 >actual && + test_cmp expect actual +' + +test_expect_success 'default to common base in @{upstream}s reflog if no upstream arg (--apply)' ' + git checkout -B default-base master && + git checkout -B default topic && + git config branch.default.remote . && + git config branch.default.merge refs/heads/default-base && + git rebase --apply && + git rev-parse --verify default-base >expect && + git rev-parse default~1 >actual && + test_cmp expect actual && + git checkout default-base && + git reset --hard HEAD^ && + git checkout default && + git rebase --apply && git rev-parse --verify default-base >expect && git rev-parse default~1 >actual && test_cmp expect actual @@ -206,9 +224,15 @@ test_expect_success 'cherry-picked commits and fork-point work together' ' test_cmp expect D ' -test_expect_success 'rebase -q is quiet' ' +test_expect_success 'rebase --apply -q is quiet' ' git checkout -b quiet topic && - git rebase -q master >output.out 2>&1 && + git rebase --apply -q master >output.out 2>&1 && + test_must_be_empty output.out +' + +test_expect_success 'rebase --merge -q is quiet' ' + git checkout -B quiet topic && + git rebase --merge -q master >output.out 2>&1 && test_must_be_empty output.out ' @@ -291,7 +315,7 @@ EOF test_cmp From_.msg out ' -test_expect_success 'rebase --am and --show-current-patch' ' +test_expect_success 'rebase --apply and --show-current-patch' ' test_create_repo conflict-apply && ( cd conflict-apply && @@ -301,13 +325,13 @@ test_expect_success 'rebase --am and --show-current-patch' ' echo two >>init.t && git commit -a -m two && git tag two && - test_must_fail git rebase -f --onto init HEAD^ && + test_must_fail git rebase --apply -f --onto init HEAD^ && GIT_TRACE=1 git rebase --show-current-patch >/dev/null 2>stderr && grep "show.*$(git rev-parse two)" stderr ) ' -test_expect_success 'rebase --am and .gitattributes' ' +test_expect_success 'rebase --apply and .gitattributes' ' test_create_repo attributes && ( cd attributes && @@ -377,4 +401,22 @@ test_expect_success 'rebase -c rebase.useBuiltin=false warning' ' test_must_be_empty err ' +test_expect_success 'switch to branch checked out here' ' + git checkout master && + git rebase master master +' + +test_expect_success 'switch to branch not checked out' ' + git checkout master && + git branch other && + git rebase master other +' + +test_expect_success 'refuse to switch to branch checked out elsewhere' ' + git checkout master && + git worktree add wt && + test_must_fail git -C wt rebase master master 2>err && + test_i18ngrep "already checked out" err +' + test_done diff --git a/t/t3401-rebase-and-am-rename.sh b/t/t3401-rebase-and-am-rename.sh index a0b9438b22..f18bae9450 100755 --- a/t/t3401-rebase-and-am-rename.sh +++ b/t/t3401-rebase-and-am-rename.sh @@ -52,13 +52,13 @@ test_expect_success 'rebase --interactive: directory rename detected' ' ) ' -test_expect_failure 'rebase (am): directory rename detected' ' +test_expect_failure 'rebase --apply: directory rename detected' ' ( cd dir-rename && git checkout B^0 && - git -c merge.directoryRenames=true rebase A && + git -c merge.directoryRenames=true rebase --apply A && git ls-files -s >out && test_line_count = 5 out && diff --git a/t/t3402-rebase-merge.sh b/t/t3402-rebase-merge.sh index a1ec501a87..6e032716a6 100755 --- a/t/t3402-rebase-merge.sh +++ b/t/t3402-rebase-merge.sh @@ -162,4 +162,81 @@ test_expect_success 'rebase --skip works with two conflicts in a row' ' git rebase --skip ' +test_expect_success '--reapply-cherry-picks' ' + git init repo && + + # O(1-10) -- O(1-11) -- O(0-10) master + # \ + # -- O(1-11) -- O(1-12) otherbranch + + printf "Line %d\n" $(test_seq 1 10) >repo/file.txt && + git -C repo add file.txt && + git -C repo commit -m "base commit" && + + printf "Line %d\n" $(test_seq 1 11) >repo/file.txt && + git -C repo commit -a -m "add 11" && + + printf "Line %d\n" $(test_seq 0 10) >repo/file.txt && + git -C repo commit -a -m "add 0 delete 11" && + + git -C repo checkout -b otherbranch HEAD^^ && + printf "Line %d\n" $(test_seq 1 11) >repo/file.txt && + git -C repo commit -a -m "add 11 in another branch" && + + printf "Line %d\n" $(test_seq 1 12) >repo/file.txt && + git -C repo commit -a -m "add 12 in another branch" && + + # Regular rebase fails, because the 1-11 commit is deduplicated + test_must_fail git -C repo rebase --merge master 2> err && + test_i18ngrep "error: could not apply.*add 12 in another branch" err && + git -C repo rebase --abort && + + # With --reapply-cherry-picks, it works + git -C repo rebase --merge --reapply-cherry-picks master +' + +test_expect_success '--reapply-cherry-picks refrains from reading unneeded blobs' ' + git init server && + + # O(1-10) -- O(1-11) -- O(1-12) master + # \ + # -- O(0-10) otherbranch + + printf "Line %d\n" $(test_seq 1 10) >server/file.txt && + git -C server add file.txt && + git -C server commit -m "merge base" && + + printf "Line %d\n" $(test_seq 1 11) >server/file.txt && + git -C server commit -a -m "add 11" && + + printf "Line %d\n" $(test_seq 1 12) >server/file.txt && + git -C server commit -a -m "add 12" && + + git -C server checkout -b otherbranch HEAD^^ && + printf "Line %d\n" $(test_seq 0 10) >server/file.txt && + git -C server commit -a -m "add 0" && + + test_config -C server uploadpack.allowfilter 1 && + test_config -C server uploadpack.allowanysha1inwant 1 && + + git clone --filter=blob:none "file://$(pwd)/server" client && + git -C client checkout origin/master && + git -C client checkout origin/otherbranch && + + # Sanity check to ensure that the blobs from the merge base and "add + # 11" are missing + git -C client rev-list --objects --all --missing=print >missing_list && + MERGE_BASE_BLOB=$(git -C server rev-parse master^^:file.txt) && + ADD_11_BLOB=$(git -C server rev-parse master^:file.txt) && + grep "[?]$MERGE_BASE_BLOB" missing_list && + grep "[?]$ADD_11_BLOB" missing_list && + + git -C client rebase --merge --reapply-cherry-picks origin/master && + + # The blob from the merge base had to be fetched, but not "add 11" + git -C client rev-list --objects --all --missing=print >missing_list && + ! grep "[?]$MERGE_BASE_BLOB" missing_list && + grep "[?]$ADD_11_BLOB" missing_list +' + test_done diff --git a/t/t3403-rebase-skip.sh b/t/t3403-rebase-skip.sh index ee8a8dba52..a927774910 100755 --- a/t/t3403-rebase-skip.sh +++ b/t/t3403-rebase-skip.sh @@ -29,6 +29,13 @@ test_expect_success setup ' test_tick && git commit -m reverted-goodbye && git tag reverted-goodbye && + git checkout goodbye && + test_tick && + GIT_AUTHOR_NAME="Another Author" \ + GIT_AUTHOR_EMAIL="another.author@example.com" \ + git commit --amend --no-edit -m amended-goodbye && + test_tick && + git tag amended-goodbye && git checkout -f skip-reference && echo moo > hello && @@ -85,6 +92,78 @@ test_expect_success 'moved back to branch correctly' ' test_debug 'gitk --all & sleep 1' +test_expect_success 'correct advice upon picking empty commit' ' + test_when_finished "git rebase --abort" && + test_must_fail git rebase -i --onto goodbye \ + amended-goodbye^ amended-goodbye 2>err && + test_i18ngrep "previous cherry-pick is now empty" err && + test_i18ngrep "git rebase --skip" err && + test_must_fail git commit && + test_i18ngrep "git rebase --skip" err +' + +test_expect_success 'correct authorship when committing empty pick' ' + test_when_finished "git rebase --abort" && + test_must_fail git rebase -i --onto goodbye \ + amended-goodbye^ amended-goodbye && + git commit --allow-empty && + git log --pretty=format:"%an <%ae>%n%ad%B" -1 amended-goodbye >expect && + git log --pretty=format:"%an <%ae>%n%ad%B" -1 HEAD >actual && + test_cmp expect actual +' + +test_expect_success 'correct advice upon rewording empty commit' ' + test_when_finished "git rebase --abort" && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="reword 1" git rebase -i \ + --onto goodbye amended-goodbye^ amended-goodbye 2>err + ) && + test_i18ngrep "previous cherry-pick is now empty" err && + test_i18ngrep "git rebase --skip" err && + test_must_fail git commit && + test_i18ngrep "git rebase --skip" err +' + +test_expect_success 'correct advice upon editing empty commit' ' + test_when_finished "git rebase --abort" && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="edit 1" git rebase -i \ + --onto goodbye amended-goodbye^ amended-goodbye 2>err + ) && + test_i18ngrep "previous cherry-pick is now empty" err && + test_i18ngrep "git rebase --skip" err && + test_must_fail git commit && + test_i18ngrep "git rebase --skip" err +' + +test_expect_success 'correct advice upon cherry-picking an empty commit during a rebase' ' + test_when_finished "git rebase --abort" && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="1 exec_git_cherry-pick_amended-goodbye" \ + git rebase -i goodbye^ goodbye 2>err + ) && + test_i18ngrep "previous cherry-pick is now empty" err && + test_i18ngrep "git cherry-pick --skip" err && + test_must_fail git commit 2>err && + test_i18ngrep "git cherry-pick --skip" err +' + +test_expect_success 'correct advice upon multi cherry-pick picking an empty commit during a rebase' ' + test_when_finished "git rebase --abort" && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="1 exec_git_cherry-pick_goodbye_amended-goodbye" \ + git rebase -i goodbye^^ goodbye 2>err + ) && + test_i18ngrep "previous cherry-pick is now empty" err && + test_i18ngrep "git cherry-pick --skip" err && + test_must_fail git commit 2>err && + test_i18ngrep "git cherry-pick --skip" err +' + test_expect_success 'fixup that empties commit fails' ' test_when_finished "git rebase --abort" && ( diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index ae6e55ce79..4a7d21f898 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -72,15 +72,16 @@ test_expect_success 'rebase --keep-empty' ' test_line_count = 6 actual ' -test_expect_success 'rebase -i with empty HEAD' ' +test_expect_success 'rebase -i with empty todo list' ' cat >expect <<-\EOF && error: nothing to do EOF ( set_fake_editor && - test_must_fail env FAKE_LINES="1 exec_true" \ - git rebase -i HEAD^ >actual 2>&1 + test_must_fail env FAKE_LINES="#" \ + git rebase -i HEAD^ >output 2>&1 ) && + tail -n 1 output >actual && # Ignore output about changing todo list test_i18ncmp expect actual ' @@ -186,7 +187,7 @@ test_expect_success 'no changes are a nop' ' git checkout branch2 && git rebase -i F && test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch2" && - test $(git rev-parse I) = $(git rev-parse HEAD) + test_cmp_rev I HEAD ' test_expect_success 'test the [branch] option' ' @@ -195,16 +196,16 @@ test_expect_success 'test the [branch] option' ' git commit -m "stop here" && git rebase -i F branch2 && test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch2" && - test $(git rev-parse I) = $(git rev-parse branch2) && - test $(git rev-parse I) = $(git rev-parse HEAD) + test_cmp_rev I branch2 && + test_cmp_rev I HEAD ' test_expect_success 'test --onto <branch>' ' git checkout -b test-onto branch2 && git rebase -i --onto branch1 F && test "$(git symbolic-ref -q HEAD)" = "refs/heads/test-onto" && - test $(git rev-parse HEAD^) = $(git rev-parse branch1) && - test $(git rev-parse I) = $(git rev-parse branch2) + test_cmp_rev HEAD^ branch1 && + test_cmp_rev I branch2 ' test_expect_success 'rebase on top of a non-conflicting commit' ' @@ -213,16 +214,16 @@ test_expect_success 'rebase on top of a non-conflicting commit' ' git rebase -i branch2 && test file6 = $(git diff --name-only original-branch1) && test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch1" && - test $(git rev-parse I) = $(git rev-parse branch2) && - test $(git rev-parse I) = $(git rev-parse HEAD~2) + test_cmp_rev I branch2 && + test_cmp_rev I HEAD~2 ' test_expect_success 'reflog for the branch shows state before rebase' ' - test $(git rev-parse branch1@{1}) = $(git rev-parse original-branch1) + test_cmp_rev branch1@{1} original-branch1 ' test_expect_success 'reflog for the branch shows correct finish message' ' - printf "rebase -i (finish): refs/heads/branch1 onto %s\n" \ + printf "rebase (finish): refs/heads/branch1 onto %s\n" \ "$(git rev-parse branch2)" >expected && git log -g --pretty=%gs -1 refs/heads/branch1 >actual && test_cmp expected actual @@ -278,7 +279,7 @@ test_expect_success 'show conflicted patch' ' test_expect_success 'abort' ' git rebase --abort && - test $(git rev-parse new-branch1) = $(git rev-parse HEAD) && + test_cmp_rev new-branch1 HEAD && test "$(git symbolic-ref -q HEAD)" = "refs/heads/branch1" && test_path_is_missing .git/rebase-merge ' @@ -321,7 +322,7 @@ test_expect_success 'retain authorship w/ conflicts' ' echo resolved >conflict && git add conflict && git rebase --continue && - test $(git rev-parse conflict-a^0) = $(git rev-parse HEAD^) && + test_cmp_rev conflict-a^0 HEAD^ && git show >out && grep AttributeMe out ' @@ -338,7 +339,7 @@ test_expect_success 'squash' ' git rebase -i --onto master HEAD~2 ) && test B = $(cat file7) && - test $(git rev-parse HEAD^) = $(git rev-parse master) + test_cmp_rev HEAD^ master ' test_expect_success 'retain authorship when squashing' ' @@ -397,9 +398,9 @@ test_expect_success REBASE_P 'preserve merges with -p' ' git update-index --refresh && git diff-files --quiet && git diff-index --quiet --cached HEAD -- && - test $(git rev-parse HEAD~6) = $(git rev-parse branch1) && - test $(git rev-parse HEAD~4^2) = $(git rev-parse to-be-preserved) && - test $(git rev-parse HEAD^^2^) = $(git rev-parse HEAD^^^) && + test_cmp_rev HEAD~6 branch1 && + test_cmp_rev HEAD~4^2 to-be-preserved && + test_cmp_rev HEAD^^2^ HEAD^^^ && test $(git show HEAD~5:file1) = B && test $(git show HEAD~3:file1) = C && test $(git show HEAD:file1) = E && @@ -431,7 +432,7 @@ test_expect_success '--continue tries to commit' ' git add file1 && FAKE_COMMIT_MESSAGE="chouette!" git rebase --continue ) && - test $(git rev-parse HEAD^) = $(git rev-parse new-branch1) && + test_cmp_rev HEAD^ new-branch1 && git show HEAD | grep chouette ' @@ -738,7 +739,7 @@ test_expect_success 'do "noop" when there is nothing to cherry-pick' ' --author="Somebody else <somebody@else.com>" && test $(git rev-parse branch3) != $(git rev-parse branch4) && git rebase -i branch3 && - test $(git rev-parse branch3) = $(git rev-parse branch4) + test_cmp_rev branch3 branch4 ' @@ -797,7 +798,7 @@ test_expect_success 'rebase -i continue with unstaged submodule' ' test_must_fail git rebase -i submodule-base && git reset && git rebase --continue && - test $(git rev-parse submodule-base) = $(git rev-parse HEAD) + test_cmp_rev submodule-base HEAD ' test_expect_success 'avoid unnecessary reset' ' @@ -820,7 +821,7 @@ test_expect_success 'reword' ' git rebase -i A && git show HEAD | grep "E changed" && test $(git rev-parse master) != $(git rev-parse HEAD) && - test $(git rev-parse master^) = $(git rev-parse HEAD^) && + test_cmp_rev master^ HEAD^ && FAKE_LINES="1 2 reword 3 4" FAKE_COMMIT_MESSAGE="D changed" \ git rebase -i A && git show HEAD^ | grep "D changed" && @@ -884,7 +885,7 @@ test_expect_success 'always cherry-pick with --no-ff' ' git diff HEAD~$p original-no-ff-branch~$p > out && test_must_be_empty out done && - test $(git rev-parse HEAD~3) = $(git rev-parse original-no-ff-branch~3) && + test_cmp_rev HEAD~3 original-no-ff-branch~3 && git diff HEAD~3 original-no-ff-branch~3 > out && test_must_be_empty out ' @@ -1137,7 +1138,7 @@ test_expect_success C_LOCALE_OUTPUT 'rebase --edit-todo does not work on non-int git checkout conflict-branch && ( set_fake_editor && - test_must_fail git rebase -f --onto HEAD~2 HEAD~ && + test_must_fail git rebase -f --apply --onto HEAD~2 HEAD~ && test_must_fail git rebase --edit-todo ) && git rebase --abort @@ -1161,10 +1162,10 @@ test_expect_success 'rebase -i produces readable reflog' ' git branch -f branch-reflog-test H && git rebase -i --onto I F branch-reflog-test && cat >expect <<-\EOF && - rebase -i (finish): returning to refs/heads/branch-reflog-test - rebase -i (pick): H - rebase -i (pick): G - rebase -i (start): checkout I + rebase (finish): returning to refs/heads/branch-reflog-test + rebase (pick): H + rebase (pick): G + rebase (start): checkout I EOF git reflog -n4 HEAD | sed "s/[^:]*: //" >actual && @@ -1264,13 +1265,26 @@ test_expect_success SHA1 'short SHA-1 setup' ' test_expect_success SHA1 'short SHA-1 collide' ' test_when_finished "reset_rebase && git checkout master" && git checkout collide && + colliding_sha1=6bcda37 && + test $colliding_sha1 = "$(git rev-parse HEAD | cut -c 1-7)" && ( unset test_tick && test_tick && set_fake_editor && FAKE_COMMIT_MESSAGE="collide2 ac4f2ee" \ - FAKE_LINES="reword 1 2" git rebase -i HEAD~2 - ) + FAKE_LINES="reword 1 break 2" git rebase -i HEAD~2 && + test $colliding_sha1 = "$(git rev-parse HEAD | cut -c 1-7)" && + grep "^pick $colliding_sha1 " \ + .git/rebase-merge/git-rebase-todo.tmp && + grep "^pick [0-9a-f]\{40\}" \ + .git/rebase-merge/git-rebase-todo && + grep "^pick [0-9a-f]\{40\}" \ + .git/rebase-merge/git-rebase-todo.backup && + git rebase --continue + ) && + collide2="$(git rev-parse HEAD~1 | cut -c 1-4)" && + collide3="$(git rev-parse collide3 | cut -c 1-4)" && + test "$collide2" = "$collide3" ' test_expect_success 'respect core.abbrev' ' @@ -1450,6 +1464,127 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = error' ' test B = $(git cat-file commit HEAD^ | sed -ne \$p) ' +test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = ignore' ' + test_config rebase.missingCommitsCheck ignore && + rebase_setup_and_clean missing-commit && + ( + set_fake_editor && + FAKE_LINES="break 1 2 3 4 5" git rebase -i --root && + FAKE_LINES="1 2 3 4" git rebase --edit-todo && + git rebase --continue 2>actual + ) && + test D = $(git cat-file commit HEAD | sed -ne \$p) && + test_i18ngrep \ + "Successfully rebased and updated refs/heads/missing-commit" \ + actual +' + +test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = warn' ' + cat >expect <<-EOF && + error: invalid line 1: badcmd $(git rev-list --pretty=oneline --abbrev-commit -1 master~4) + Warning: some commits may have been dropped accidentally. + Dropped commits (newer to older): + - $(git rev-list --pretty=oneline --abbrev-commit -1 master) + - $(git rev-list --pretty=oneline --abbrev-commit -1 master~4) + To avoid this message, use "drop" to explicitly remove a commit. + EOF + head -n4 expect >expect.2 && + tail -n1 expect >>expect.2 && + tail -n4 expect.2 >expect.3 && + test_config rebase.missingCommitsCheck warn && + rebase_setup_and_clean missing-commit && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="bad 1 2 3 4 5" \ + git rebase -i --root && + cp .git/rebase-merge/git-rebase-todo.backup orig && + FAKE_LINES="2 3 4" git rebase --edit-todo 2>actual.2 && + head -n6 actual.2 >actual && + test_i18ncmp expect actual && + cp orig .git/rebase-merge/git-rebase-todo && + FAKE_LINES="1 2 3 4" git rebase --edit-todo 2>actual.2 && + head -n4 actual.2 >actual && + test_i18ncmp expect.3 actual && + git rebase --continue 2>actual + ) && + test D = $(git cat-file commit HEAD | sed -ne \$p) && + test_i18ngrep \ + "Successfully rebased and updated refs/heads/missing-commit" \ + actual +' + +test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = error' ' + cat >expect <<-EOF && + error: invalid line 1: badcmd $(git rev-list --pretty=oneline --abbrev-commit -1 master~4) + Warning: some commits may have been dropped accidentally. + Dropped commits (newer to older): + - $(git rev-list --pretty=oneline --abbrev-commit -1 master) + - $(git rev-list --pretty=oneline --abbrev-commit -1 master~4) + To avoid this message, use "drop" to explicitly remove a commit. + + Use '\''git config rebase.missingCommitsCheck'\'' to change the level of warnings. + The possible behaviours are: ignore, warn, error. + + You can fix this with '\''git rebase --edit-todo'\'' and then run '\''git rebase --continue'\''. + Or you can abort the rebase with '\''git rebase --abort'\''. + EOF + tail -n11 expect >expect.2 && + head -n3 expect.2 >expect.3 && + tail -n7 expect.2 >>expect.3 && + test_config rebase.missingCommitsCheck error && + rebase_setup_and_clean missing-commit && + ( + set_fake_editor && + test_must_fail env FAKE_LINES="bad 1 2 3 4 5" \ + git rebase -i --root && + cp .git/rebase-merge/git-rebase-todo.backup orig && + test_must_fail env FAKE_LINES="2 3 4" \ + git rebase --edit-todo 2>actual && + test_i18ncmp expect actual && + test_must_fail git rebase --continue 2>actual && + test_i18ncmp expect.2 actual && + test_must_fail git rebase --edit-todo && + cp orig .git/rebase-merge/git-rebase-todo && + test_must_fail env FAKE_LINES="1 2 3 4" \ + git rebase --edit-todo 2>actual && + test_i18ncmp expect.3 actual && + test_must_fail git rebase --continue 2>actual && + test_i18ncmp expect.3 actual && + cp orig .git/rebase-merge/git-rebase-todo && + FAKE_LINES="1 2 3 4 drop 5" git rebase --edit-todo && + git rebase --continue 2>actual + ) && + test D = $(git cat-file commit HEAD | sed -ne \$p) && + test_i18ngrep \ + "Successfully rebased and updated refs/heads/missing-commit" \ + actual +' + +test_expect_success 'rebase.missingCommitsCheck = error after resolving conflicts' ' + test_config rebase.missingCommitsCheck error && + ( + set_fake_editor && + FAKE_LINES="drop 1 break 2 3 4" git rebase -i A E + ) && + git rebase --edit-todo && + test_must_fail git rebase --continue && + echo x >file1 && + git add file1 && + git rebase --continue +' + +test_expect_success 'rebase.missingCommitsCheck = error when editing for a second time' ' + test_config rebase.missingCommitsCheck error && + ( + set_fake_editor && + FAKE_LINES="1 break 2 3" git rebase -i A D && + cp .git/rebase-merge/git-rebase-todo todo && + test_must_fail env FAKE_LINES=2 git rebase --edit-todo && + GIT_SEQUENCE_EDITOR="cp todo" git rebase --edit-todo && + git rebase --continue + ) +' + test_expect_success 'respects rebase.abbreviateCommands with fixup, squash and exec' ' rebase_setup_and_clean abbrevcmd && test_commit "first" file1.txt "first line" first && @@ -1599,6 +1734,32 @@ test_expect_success 'post-commit hook is called' ' test_cmp expect actual ' +test_expect_success 'correct error message for partial commit after empty pick' ' + test_when_finished "git rebase --abort" && + ( + set_fake_editor && + FAKE_LINES="2 1 1" && + export FAKE_LINES && + test_must_fail git rebase -i A D + ) && + echo x >file1 && + test_must_fail git commit file1 2>err && + test_i18ngrep "cannot do a partial commit during a rebase." err +' + +test_expect_success 'correct error message for commit --amend after empty pick' ' + test_when_finished "git rebase --abort" && + ( + set_fake_editor && + FAKE_LINES="1 1" && + export FAKE_LINES && + test_must_fail git rebase -i A D + ) && + echo x>file1 && + test_must_fail git commit -a --amend 2>err && + test_i18ngrep "middle of a rebase -- cannot amend." err +' + # This must be the last test in this file test_expect_success '$EDITOR and friends are unchanged' ' test_editor_unchanged diff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh index b393e1e9fe..927a4f4a4e 100755 --- a/t/t3406-rebase-message.sh +++ b/t/t3406-rebase-message.sh @@ -18,32 +18,29 @@ test_expect_success 'setup' ' ' test_expect_success 'rebase -m' ' - git rebase -m master >report && - >expect && - sed -n -e "/^Already applied: /p" \ - -e "/^Committed: /p" report >actual && - test_cmp expect actual + git rebase -m master >actual && + test_must_be_empty actual ' test_expect_success 'rebase against master twice' ' - git rebase master >out && + git rebase --apply master >out && test_i18ngrep "Current branch topic is up to date" out ' test_expect_success 'rebase against master twice with --force' ' - git rebase --force-rebase master >out && + git rebase --force-rebase --apply master >out && test_i18ngrep "Current branch topic is up to date, rebase forced" out ' test_expect_success 'rebase against master twice from another branch' ' git checkout topic^ && - git rebase master topic >out && + git rebase --apply master topic >out && test_i18ngrep "Current branch topic is up to date" out ' test_expect_success 'rebase fast-forward to master' ' git checkout topic^ && - git rebase topic >out && + git rebase --apply topic >out && test_i18ngrep "Fast-forwarded HEAD to topic" out ' @@ -95,9 +92,9 @@ test_expect_success 'GIT_REFLOG_ACTION' ' git rebase reflog-onto && git log -g --format=%gs -3 >actual && cat >expect <<-\EOF && - rebase finished: returning to refs/heads/reflog-topic - rebase: reflog-to-rebase - rebase: checkout reflog-onto + rebase (finish): returning to refs/heads/reflog-topic + rebase (pick): reflog-to-rebase + rebase (start): checkout reflog-onto EOF test_cmp expect actual && @@ -105,9 +102,9 @@ test_expect_success 'GIT_REFLOG_ACTION' ' GIT_REFLOG_ACTION=change-the-reflog git rebase reflog-onto && git log -g --format=%gs -3 >actual && cat >expect <<-\EOF && - rebase finished: returning to refs/heads/reflog-prefix - change-the-reflog: reflog-to-rebase - change-the-reflog: checkout reflog-onto + change-the-reflog (finish): returning to refs/heads/reflog-prefix + change-the-reflog (pick): reflog-to-rebase + change-the-reflog (start): checkout reflog-onto EOF test_cmp expect actual ' diff --git a/t/t3407-rebase-abort.sh b/t/t3407-rebase-abort.sh index 910f218284..97efea0f56 100755 --- a/t/t3407-rebase-abort.sh +++ b/t/t3407-rebase-abort.sh @@ -96,14 +96,14 @@ testrebase() { ' } -testrebase "" .git/rebase-apply +testrebase " --apply" .git/rebase-apply testrebase " --merge" .git/rebase-merge -test_expect_success 'rebase --quit' ' +test_expect_success 'rebase --apply --quit' ' cd "$work_dir" && # Clean up the state from the previous one git reset --hard pre-rebase && - test_must_fail git rebase master && + test_must_fail git rebase --apply master && test_path_is_dir .git/rebase-apply && head_before=$(git rev-parse HEAD) && git rebase --quit && diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh index 22d218698e..093de9005b 100755 --- a/t/t3415-rebase-autosquash.sh +++ b/t/t3415-rebase-autosquash.sh @@ -25,6 +25,13 @@ test_expect_success setup ' ' test_auto_fixup () { + no_squash= && + if test "x$1" = 'x!' + then + no_squash=true + shift + fi && + git reset --hard base && echo 1 >file1 && git add -u && @@ -35,10 +42,19 @@ test_auto_fixup () { test_tick && git rebase $2 -i HEAD^^^ && git log --oneline >actual && - test_line_count = 3 actual && - git diff --exit-code $1 && - test 1 = "$(git cat-file blob HEAD^:file1)" && - test 1 = $(git cat-file commit HEAD^ | grep first | wc -l) + if test -n "$no_squash" + then + test_line_count = 4 actual + else + test_line_count = 3 actual && + git diff --exit-code $1 && + echo 1 >expect && + git cat-file blob HEAD^:file1 >actual && + test_cmp expect actual && + git cat-file commit HEAD^ >commit && + grep first commit >actual && + test_line_count = 1 actual + fi } test_expect_success 'auto fixup (option)' ' @@ -48,12 +64,19 @@ test_expect_success 'auto fixup (option)' ' test_expect_success 'auto fixup (config)' ' git config rebase.autosquash true && test_auto_fixup final-fixup-config-true && - test_must_fail test_auto_fixup fixup-config-true-no --no-autosquash && + test_auto_fixup ! fixup-config-true-no --no-autosquash && git config rebase.autosquash false && - test_must_fail test_auto_fixup final-fixup-config-false + test_auto_fixup ! final-fixup-config-false ' test_auto_squash () { + no_squash= && + if test "x$1" = 'x!' + then + no_squash=true + shift + fi && + git reset --hard base && echo 1 >file1 && git add -u && @@ -64,10 +87,19 @@ test_auto_squash () { test_tick && git rebase $2 -i HEAD^^^ && git log --oneline >actual && - test_line_count = 3 actual && - git diff --exit-code $1 && - test 1 = "$(git cat-file blob HEAD^:file1)" && - test 2 = $(git cat-file commit HEAD^ | grep first | wc -l) + if test -n "$no_squash" + then + test_line_count = 4 actual + else + test_line_count = 3 actual && + git diff --exit-code $1 && + echo 1 >expect && + git cat-file blob HEAD^:file1 >actual && + test_cmp expect actual && + git cat-file commit HEAD^ >commit && + grep first commit >actual && + test_line_count = 2 actual + fi } test_expect_success 'auto squash (option)' ' @@ -77,9 +109,9 @@ test_expect_success 'auto squash (option)' ' test_expect_success 'auto squash (config)' ' git config rebase.autosquash true && test_auto_squash final-squash-config-true && - test_must_fail test_auto_squash squash-config-true-no --no-autosquash && + test_auto_squash ! squash-config-true-no --no-autosquash && git config rebase.autosquash false && - test_must_fail test_auto_squash final-squash-config-false + test_auto_squash ! final-squash-config-false ' test_expect_success 'misspelled auto squash' ' @@ -94,7 +126,8 @@ test_expect_success 'misspelled auto squash' ' git log --oneline >actual && test_line_count = 4 actual && git diff --exit-code final-missquash && - test 0 = $(git rev-list final-missquash...HEAD | wc -l) + git rev-list final-missquash...HEAD >list && + test_must_be_empty list ' test_expect_success 'auto squash that matches 2 commits' ' @@ -113,9 +146,15 @@ test_expect_success 'auto squash that matches 2 commits' ' git log --oneline >actual && test_line_count = 4 actual && git diff --exit-code final-multisquash && - test 1 = "$(git cat-file blob HEAD^^:file1)" && - test 2 = $(git cat-file commit HEAD^^ | grep first | wc -l) && - test 1 = $(git cat-file commit HEAD | grep first | wc -l) + echo 1 >expect && + git cat-file blob HEAD^^:file1 >actual && + test_cmp expect actual && + git cat-file commit HEAD^^ >commit && + grep first commit >actual && + test_line_count = 2 actual && + git cat-file commit HEAD >commit && + grep first commit >actual && + test_line_count = 1 actual ' test_expect_success 'auto squash that matches a commit after the squash' ' @@ -134,25 +173,38 @@ test_expect_success 'auto squash that matches a commit after the squash' ' git log --oneline >actual && test_line_count = 5 actual && git diff --exit-code final-presquash && - test 0 = "$(git cat-file blob HEAD^^:file1)" && - test 1 = "$(git cat-file blob HEAD^:file1)" && - test 1 = $(git cat-file commit HEAD | grep third | wc -l) && - test 1 = $(git cat-file commit HEAD^ | grep third | wc -l) + echo 0 >expect && + git cat-file blob HEAD^^:file1 >actual && + test_cmp expect actual && + echo 1 >expect && + git cat-file blob HEAD^:file1 >actual && + test_cmp expect actual && + git cat-file commit HEAD >commit && + grep third commit >actual && + test_line_count = 1 actual && + git cat-file commit HEAD^ >commit && + grep third commit >actual && + test_line_count = 1 actual ' test_expect_success 'auto squash that matches a sha1' ' git reset --hard base && echo 1 >file1 && git add -u && test_tick && - git commit -m "squash! $(git rev-parse --short HEAD^)" && + oid=$(git rev-parse --short HEAD^) && + git commit -m "squash! $oid" && git tag final-shasquash && test_tick && git rebase --autosquash -i HEAD^^^ && git log --oneline >actual && test_line_count = 3 actual && git diff --exit-code final-shasquash && - test 1 = "$(git cat-file blob HEAD^:file1)" && - test 1 = $(git cat-file commit HEAD^ | grep squash | wc -l) + echo 1 >expect && + git cat-file blob HEAD^:file1 >actual && + test_cmp expect actual && + git cat-file commit HEAD^ >commit && + grep squash commit >actual && + test_line_count = 1 actual ' test_expect_success 'auto squash that matches longer sha1' ' @@ -160,15 +212,20 @@ test_expect_success 'auto squash that matches longer sha1' ' echo 1 >file1 && git add -u && test_tick && - git commit -m "squash! $(git rev-parse --short=11 HEAD^)" && + oid=$(git rev-parse --short=11 HEAD^) && + git commit -m "squash! $oid" && git tag final-longshasquash && test_tick && git rebase --autosquash -i HEAD^^^ && git log --oneline >actual && test_line_count = 3 actual && git diff --exit-code final-longshasquash && - test 1 = "$(git cat-file blob HEAD^:file1)" && - test 1 = $(git cat-file commit HEAD^ | grep squash | wc -l) + echo 1 >expect && + git cat-file blob HEAD^:file1 >actual && + test_cmp expect actual && + git cat-file commit HEAD^ >commit && + grep squash commit >actual && + test_line_count = 1 actual ' test_auto_commit_flags () { @@ -183,8 +240,12 @@ test_auto_commit_flags () { git log --oneline >actual && test_line_count = 3 actual && git diff --exit-code final-commit-$1 && - test 1 = "$(git cat-file blob HEAD^:file1)" && - test $2 = $(git cat-file commit HEAD^ | grep first | wc -l) + echo 1 >expect && + git cat-file blob HEAD^:file1 >actual && + test_cmp expect actual && + git cat-file commit HEAD^ >commit && + grep first commit >actual && + test_line_count = $2 actual } test_expect_success 'use commit --fixup' ' @@ -210,11 +271,15 @@ test_auto_fixup_fixup () { ( set_cat_todo_editor && test_must_fail git rebase --autosquash -i HEAD^^^^ >actual && + head=$(git rev-parse --short HEAD) && + parent1=$(git rev-parse --short HEAD^) && + parent2=$(git rev-parse --short HEAD^^) && + parent3=$(git rev-parse --short HEAD^^^) && cat >expected <<-EOF && - pick $(git rev-parse --short HEAD^^^) first commit - $1 $(git rev-parse --short HEAD^) $1! first - $1 $(git rev-parse --short HEAD) $1! $2! first - pick $(git rev-parse --short HEAD^^) second commit + pick $parent3 first commit + $1 $parent1 $1! first + $1 $head $1! $2! first + pick $parent2 second commit EOF test_cmp expected actual ) && @@ -222,13 +287,17 @@ test_auto_fixup_fixup () { git log --oneline >actual && test_line_count = 3 actual git diff --exit-code "final-$1-$2" && - test 2 = "$(git cat-file blob HEAD^:file1)" && + echo 2 >expect && + git cat-file blob HEAD^:file1 >actual && + test_cmp expect actual && + git cat-file commit HEAD^ >commit && + grep first commit >actual && if test "$1" = "fixup" then - test 1 = $(git cat-file commit HEAD^ | grep first | wc -l) + test_line_count = 1 actual elif test "$1" = "squash" then - test 3 = $(git cat-file commit HEAD^ | grep first | wc -l) + test_line_count = 3 actual else false fi @@ -256,19 +325,25 @@ test_expect_success C_LOCALE_OUTPUT 'autosquash with custom inst format' ' echo 2 >file1 && git add -u && test_tick && - git commit -m "squash! $(git rev-parse --short HEAD^)" && + oid=$(git rev-parse --short HEAD^) && + git commit -m "squash! $oid" && echo 1 >file1 && git add -u && test_tick && - git commit -m "squash! $(git log -n 1 --format=%s HEAD~2)" && + subject=$(git log -n 1 --format=%s HEAD~2) && + git commit -m "squash! $subject" && git tag final-squash-instFmt && test_tick && git rebase --autosquash -i HEAD~4 && git log --oneline >actual && test_line_count = 3 actual && git diff --exit-code final-squash-instFmt && - test 1 = "$(git cat-file blob HEAD^:file1)" && - test 2 = $(git cat-file commit HEAD^ | grep squash | wc -l) + echo 1 >expect && + git cat-file blob HEAD^:file1 >actual && + test_cmp expect actual && + git cat-file commit HEAD^ >commit && + grep squash commit >actual && + test_line_count = 2 actual ' test_expect_success 'autosquash with empty custom instructionFormat' ' diff --git a/t/t3417-rebase-whitespace-fix.sh b/t/t3417-rebase-whitespace-fix.sh index e85cdc7037..946e92f8da 100755 --- a/t/t3417-rebase-whitespace-fix.sh +++ b/t/t3417-rebase-whitespace-fix.sh @@ -52,7 +52,7 @@ test_expect_success 'blank line at end of file; extend at end of file' ' git commit --allow-empty -m "Initial empty commit" && git add file && git commit -m first && mv second file && - git add file && git commit -m second && + git add file && git commit -m second && git rebase --whitespace=fix HEAD^^ && git diff --exit-code HEAD^:file expect-first && test_cmp expect-second file @@ -118,7 +118,7 @@ test_expect_success 'at beginning of file' ' for i in 1 2 3 4 5; do echo $i done >> file && - git commit -m more file && + git commit -m more file && git rebase --whitespace=fix HEAD^^ && test_cmp expect-beginning file ' diff --git a/t/t3419-rebase-patch-id.sh b/t/t3419-rebase-patch-id.sh index 49f548cdb9..1f32faa4a4 100755 --- a/t/t3419-rebase-patch-id.sh +++ b/t/t3419-rebase-patch-id.sh @@ -4,15 +4,6 @@ test_description='git rebase - test patch id computation' . ./test-lib.sh -count () { - i=0 - while test $i -lt $1 - do - echo "$i" - i=$(($i+1)) - done -} - scramble () { i=0 while read x @@ -26,75 +17,55 @@ scramble () { mv -f "$1.new" "$1" } -run () { - echo \$ "$@" - /usr/bin/time "$@" >/dev/null -} - test_expect_success 'setup' ' git commit --allow-empty -m initial && git tag root ' -do_tests () { - nlines=$1 pr=${2-} - - test_expect_success $pr "setup: $nlines lines" " - rm -f .gitattributes && - git checkout -q -f master && - git reset --hard root && - count $nlines >file && - git add file && - git commit -q -m initial && - git branch -f other && - - scramble file && - git add file && - git commit -q -m 'change big file' && - - git checkout -q other && - : >newfile && - git add newfile && - git commit -q -m 'add small file' && - - git cherry-pick master >/dev/null 2>&1 - " - - test_debug " - run git diff master^\! - " - - test_expect_success $pr 'setup attributes' " - echo 'file binary' >.gitattributes - " - - test_debug " - run git format-patch --stdout master && - run git format-patch --stdout --ignore-if-in-upstream master - " +test_expect_success 'setup: 500 lines' ' + rm -f .gitattributes && + git checkout -q -f master && + git reset --hard root && + test_seq 500 >file && + git add file && + git commit -q -m initial && + git branch -f other && + + scramble file && + git add file && + git commit -q -m "change big file" && + + git checkout -q other && + : >newfile && + git add newfile && + git commit -q -m "add small file" && + + git cherry-pick master >/dev/null 2>&1 +' - test_expect_success $pr 'detect upstream patch' ' - git checkout -q master && - scramble file && - git add file && - git commit -q -m "change big file again" && - git checkout -q other^{} && - git rebase master && - test_must_fail test -n "$(git rev-list master...HEAD~)" - ' +test_expect_success 'setup attributes' ' + echo "file binary" >.gitattributes +' - test_expect_success $pr 'do not drop patch' ' - git branch -f squashed master && - git checkout -q -f squashed && - git reset -q --soft HEAD~2 && - git commit -q -m squashed && - git checkout -q other^{} && - test_must_fail git rebase squashed && - rm -rf .git/rebase-apply - ' -} +test_expect_success 'detect upstream patch' ' + git checkout -q master && + scramble file && + git add file && + git commit -q -m "change big file again" && + git checkout -q other^{} && + git rebase master && + git rev-list master...HEAD~ >revs && + test_must_be_empty revs +' -do_tests 500 -do_tests 50000 EXPENSIVE +test_expect_success 'do not drop patch' ' + git branch -f squashed master && + git checkout -q -f squashed && + git reset -q --soft HEAD~2 && + git commit -q -m squashed && + git checkout -q other^{} && + test_must_fail git rebase squashed && + git rebase --quit +' test_done diff --git a/t/t3420-rebase-autostash.sh b/t/t3420-rebase-autostash.sh index 5f7e73cf83..ca331733fb 100755 --- a/t/t3420-rebase-autostash.sh +++ b/t/t3420-rebase-autostash.sh @@ -34,7 +34,7 @@ test_expect_success setup ' remove_progress_re="$(printf "s/.*\\r//")" ' -create_expected_success_am () { +create_expected_success_apply () { cat >expected <<-EOF $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual) First, rewinding head to replay your work on top of it... @@ -44,7 +44,7 @@ create_expected_success_am () { EOF } -create_expected_success_interactive () { +create_expected_success_merge () { q_to_cr >expected <<-EOF $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual) Applied autostash. @@ -52,7 +52,7 @@ create_expected_success_interactive () { EOF } -create_expected_failure_am () { +create_expected_failure_apply () { cat >expected <<-EOF $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual) First, rewinding head to replay your work on top of it... @@ -64,7 +64,7 @@ create_expected_failure_am () { EOF } -create_expected_failure_interactive () { +create_expected_failure_merge () { cat >expected <<-EOF $(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual) Applying autostash resulted in conflicts. @@ -101,9 +101,9 @@ testrebase () { test_expect_success "rebase$type --autostash: check output" ' test_when_finished git branch -D rebased-feature-branch && - suffix=${type#\ --} && suffix=${suffix:-am} && - if test ${suffix} = "merge"; then - suffix=interactive + suffix=${type#\ --} && suffix=${suffix:-apply} && + if test ${suffix} = "interactive"; then + suffix=merge fi && create_expected_success_$suffix && sed "$remove_progress_re" <actual >actual2 && @@ -184,6 +184,26 @@ testrebase () { git checkout feature-branch ' + test_expect_success "rebase$type: --quit" ' + test_config rebase.autostash true && + git reset --hard && + git checkout -b rebased-feature-branch feature-branch && + test_when_finished git branch -D rebased-feature-branch && + echo dirty >>file3 && + git diff >expect && + test_must_fail git rebase$type related-onto-branch && + test_path_is_file $dotest/autostash && + test_path_is_missing file3 && + git rebase --quit && + test_when_finished git stash drop && + test_path_is_missing $dotest/autostash && + ! grep dirty file3 && + git stash show -p >actual && + test_cmp expect actual && + git reset --hard && + git checkout feature-branch + ' + test_expect_success "rebase$type: non-conflicting rebase, conflicting stash" ' test_config rebase.autostash true && git reset --hard && @@ -202,9 +222,9 @@ testrebase () { test_expect_success "rebase$type: check output with conflicting stash" ' test_when_finished git branch -D rebased-feature-branch && - suffix=${type#\ --} && suffix=${suffix:-am} && - if test ${suffix} = "merge"; then - suffix=interactive + suffix=${type#\ --} && suffix=${suffix:-apply} && + if test ${suffix} = "interactive"; then + suffix=merge fi && create_expected_failure_$suffix && sed "$remove_progress_re" <actual >actual2 && @@ -234,7 +254,7 @@ test_expect_success "rebase: noop rebase" ' git checkout feature-branch ' -testrebase "" .git/rebase-apply +testrebase " --apply" .git/rebase-apply testrebase " --merge" .git/rebase-merge testrebase " --interactive" .git/rebase-merge diff --git a/t/t3421-rebase-topology-linear.sh b/t/t3421-rebase-topology-linear.sh index 325072b0a3..4a9204b4b6 100755 --- a/t/t3421-rebase-topology-linear.sh +++ b/t/t3421-rebase-topology-linear.sh @@ -26,7 +26,7 @@ test_run_rebase () { test_linear_range 'd e' c.. " } -test_run_rebase success '' +test_run_rebase success --apply test_run_rebase success -m test_run_rebase success -i test_have_prereq !REBASE_P || test_run_rebase success -p @@ -50,7 +50,7 @@ test_run_rebase () { test_cmp_rev e HEAD " } -test_run_rebase success '' +test_run_rebase success --apply test_run_rebase success -m test_run_rebase success -i test_have_prereq !REBASE_P || test_run_rebase success -p @@ -66,7 +66,7 @@ test_run_rebase () { test_linear_range 'd e' b.. " } -test_run_rebase success '' +test_run_rebase success --apply test_run_rebase success --fork-point test_run_rebase success -m test_run_rebase success -i @@ -83,7 +83,7 @@ test_run_rebase () { test_linear_range 'd e' branch-b.. " } -test_run_rebase success '' +test_run_rebase success --apply test_run_rebase success --fork-point test_run_rebase success -m test_run_rebase success -i @@ -98,7 +98,7 @@ test_run_rebase () { test_cmp_rev e HEAD " } -test_run_rebase success '' +test_run_rebase success --apply test_run_rebase success --fork-point test_run_rebase success -m test_run_rebase success -i @@ -139,7 +139,7 @@ test_run_rebase () { test_linear_range 'd i' h.. " } -test_run_rebase success '' +test_run_rebase success --apply test_run_rebase success -m test_run_rebase success -i test_have_prereq !REBASE_P || test_run_rebase success -p @@ -154,7 +154,7 @@ test_run_rebase () { test_linear_range 'd' h.. " } -test_run_rebase success '' +test_run_rebase success --apply test_run_rebase success -m test_run_rebase success -i test_have_prereq !REBASE_P || test_run_rebase success -p @@ -169,7 +169,7 @@ test_run_rebase () { test_linear_range 'd i' f.. " } -test_run_rebase success '' +test_run_rebase success --apply test_run_rebase success -m test_run_rebase success -i test_have_prereq !REBASE_P || test_run_rebase success -p @@ -184,7 +184,7 @@ test_run_rebase () { test_linear_range 'd gp i' h.. " } -test_run_rebase success '' +test_run_rebase success --apply test_run_rebase success -m test_run_rebase success -i test_have_prereq !REBASE_P || test_run_rebase success -p @@ -205,32 +205,31 @@ test_expect_success 'setup of linear history for empty commit tests' ' test_run_rebase () { result=$1 shift - test_expect_$result "rebase $* drops empty commit" " + test_expect_$result "rebase $* keeps begin-empty commits" " reset_rebase && - git rebase $* c l && - test_cmp_rev c HEAD~2 && - test_linear_range 'd l' c.. + git rebase $* j l && + test_cmp_rev c HEAD~4 && + test_linear_range 'j d k l' c.. " } -test_run_rebase success '' +test_run_rebase failure --apply test_run_rebase success -m test_run_rebase success -i -test_have_prereq !REBASE_P || test_run_rebase success -p +test_have_prereq !REBASE_P || test_run_rebase failure -p test_run_rebase () { result=$1 shift - test_expect_$result "rebase $* --keep-empty" " + test_expect_$result "rebase $* --no-keep-empty drops begin-empty commits" " reset_rebase && - git rebase $* --keep-empty c l && - test_cmp_rev c HEAD~3 && - test_linear_range 'd k l' c.. + git rebase $* --no-keep-empty c l && + test_cmp_rev c HEAD~2 && + test_linear_range 'd l' c.. " } -test_run_rebase success '' test_run_rebase success -m test_run_rebase success -i -test_have_prereq !REBASE_P || test_run_rebase failure -p +test_have_prereq !REBASE_P || test_run_rebase success -p test_run_rebase () { result=$1 @@ -242,10 +241,9 @@ test_run_rebase () { test_linear_range 'd k l' j.. " } -test_run_rebase success '' test_run_rebase success -m test_run_rebase success -i -test_have_prereq !REBASE_P || test_run_rebase failure -p +test_have_prereq !REBASE_P || test_run_rebase success -p test_run_rebase success --rebase-merges # m @@ -282,7 +280,7 @@ test_run_rebase () { test_linear_range 'x y' c.. " } -test_run_rebase success '' +test_run_rebase success --apply test_run_rebase success -m test_run_rebase success -i test_have_prereq !REBASE_P || test_run_rebase success -p @@ -297,7 +295,7 @@ test_run_rebase () { test_linear_range 'x y' c.. " } -test_run_rebase success '' +test_run_rebase success --apply test_run_rebase success -m test_run_rebase success -i test_have_prereq !REBASE_P || test_run_rebase failure -p @@ -312,7 +310,7 @@ test_run_rebase () { test_linear_range 'x y' m.. " } -test_run_rebase success '' +test_run_rebase success --apply test_run_rebase success -m test_run_rebase success -i test_have_prereq !REBASE_P || test_run_rebase success -p @@ -328,7 +326,7 @@ test_run_rebase () { " } -test_run_rebase success '' +test_run_rebase success --apply test_run_rebase success -m test_run_rebase success -i test_have_prereq !REBASE_P || test_run_rebase failure -p @@ -343,7 +341,7 @@ test_run_rebase () { test_linear_range 'x y' m.. " } -test_run_rebase success '' +test_run_rebase success --apply test_run_rebase success -m test_run_rebase success -i test_have_prereq !REBASE_P || test_run_rebase failure -p diff --git a/t/t3424-rebase-empty.sh b/t/t3424-rebase-empty.sh new file mode 100755 index 0000000000..5e1045a0af --- /dev/null +++ b/t/t3424-rebase-empty.sh @@ -0,0 +1,170 @@ +#!/bin/sh + +test_description='git rebase of commits that start or become empty' + +. ./test-lib.sh + +test_expect_success 'setup test repository' ' + test_write_lines 1 2 3 4 5 6 7 8 9 10 >numbers && + test_write_lines A B C D E F G H I J >letters && + git add numbers letters && + git commit -m A && + + git branch upstream && + git branch localmods && + + git checkout upstream && + test_write_lines A B C D E >letters && + git add letters && + git commit -m B && + + test_write_lines 1 2 3 4 five 6 7 8 9 ten >numbers && + git add numbers && + git commit -m C && + + git checkout localmods && + test_write_lines 1 2 3 4 five 6 7 8 9 10 >numbers && + git add numbers && + git commit -m C2 && + + git commit --allow-empty -m D && + + test_write_lines A B C D E >letters && + git add letters && + git commit -m "Five letters ought to be enough for anybody" +' + +test_expect_failure 'rebase (apply-backend)' ' + test_when_finished "git rebase --abort" && + git checkout -B testing localmods && + # rebase (--apply) should not drop commits that start empty + git rebase --apply upstream && + + test_write_lines D C B A >expect && + git log --format=%s >actual && + test_cmp expect actual +' + +test_expect_success 'rebase --merge --empty=drop' ' + git checkout -B testing localmods && + git rebase --merge --empty=drop upstream && + + test_write_lines D C B A >expect && + git log --format=%s >actual && + test_cmp expect actual +' + +test_expect_success 'rebase --merge uses default of --empty=drop' ' + git checkout -B testing localmods && + git rebase --merge upstream && + + test_write_lines D C B A >expect && + git log --format=%s >actual && + test_cmp expect actual +' + +test_expect_success 'rebase --merge --empty=keep' ' + git checkout -B testing localmods && + git rebase --merge --empty=keep upstream && + + test_write_lines D C2 C B A >expect && + git log --format=%s >actual && + test_cmp expect actual +' + +test_expect_success 'rebase --merge --empty=ask' ' + git checkout -B testing localmods && + test_must_fail git rebase --merge --empty=ask upstream && + + git rebase --skip && + + test_write_lines D C B A >expect && + git log --format=%s >actual && + test_cmp expect actual +' + +test_expect_success 'rebase --interactive --empty=drop' ' + git checkout -B testing localmods && + git rebase --interactive --empty=drop upstream && + + test_write_lines D C B A >expect && + git log --format=%s >actual && + test_cmp expect actual +' + +test_expect_success 'rebase --interactive --empty=keep' ' + git checkout -B testing localmods && + git rebase --interactive --empty=keep upstream && + + test_write_lines D C2 C B A >expect && + git log --format=%s >actual && + test_cmp expect actual +' + +test_expect_success 'rebase --interactive --empty=ask' ' + git checkout -B testing localmods && + test_must_fail git rebase --interactive --empty=ask upstream && + + git rebase --skip && + + test_write_lines D C B A >expect && + git log --format=%s >actual && + test_cmp expect actual +' + +test_expect_success 'rebase --interactive uses default of --empty=ask' ' + git checkout -B testing localmods && + test_must_fail git rebase --interactive upstream && + + git rebase --skip && + + test_write_lines D C B A >expect && + git log --format=%s >actual && + test_cmp expect actual +' + +test_expect_success 'rebase --merge --empty=drop --keep-empty' ' + git checkout -B testing localmods && + git rebase --merge --empty=drop --keep-empty upstream && + + test_write_lines D C B A >expect && + git log --format=%s >actual && + test_cmp expect actual +' + +test_expect_success 'rebase --merge --empty=drop --no-keep-empty' ' + git checkout -B testing localmods && + git rebase --merge --empty=drop --no-keep-empty upstream && + + test_write_lines C B A >expect && + git log --format=%s >actual && + test_cmp expect actual +' + +test_expect_success 'rebase --merge --empty=keep --keep-empty' ' + git checkout -B testing localmods && + git rebase --merge --empty=keep --keep-empty upstream && + + test_write_lines D C2 C B A >expect && + git log --format=%s >actual && + test_cmp expect actual +' + +test_expect_success 'rebase --merge --empty=keep --no-keep-empty' ' + git checkout -B testing localmods && + git rebase --merge --empty=keep --no-keep-empty upstream && + + test_write_lines C2 C B A >expect && + git log --format=%s >actual && + test_cmp expect actual +' + +test_expect_success 'rebase --merge does not leave state laying around' ' + git checkout -B testing localmods~2 && + git rebase --merge upstream && + + test_path_is_missing .git/CHERRY_PICK_HEAD && + test_path_is_missing .git/MERGE_MSG +' + +test_done diff --git a/t/t3425-rebase-topology-merges.sh b/t/t3425-rebase-topology-merges.sh index fd8efe84fe..e42faa44e7 100755 --- a/t/t3425-rebase-topology-merges.sh +++ b/t/t3425-rebase-topology-merges.sh @@ -54,7 +54,7 @@ test_run_rebase () { test_linear_range 'n o' e.. " } -test_run_rebase success '' +test_run_rebase success --apply test_run_rebase success -m test_run_rebase success -i @@ -70,7 +70,7 @@ test_run_rebase () { test_linear_range "\'"$expected"\'" d.. " } -test_run_rebase success 'n o e' '' +test_run_rebase success 'n o e' --apply test_run_rebase success 'n o e' -m test_run_rebase success 'n o e' -i @@ -86,7 +86,7 @@ test_run_rebase () { test_linear_range "\'"$expected"\'" c.. " } -test_run_rebase success 'd n o e' '' +test_run_rebase success 'd n o e' --apply test_run_rebase success 'd n o e' -m test_run_rebase success 'd n o e' -i @@ -102,7 +102,7 @@ test_run_rebase () { test_linear_range "\'"$expected"\'" c.. " } -test_run_rebase success 'd n o e' '' +test_run_rebase success 'd n o e' --apply test_run_rebase success 'd n o e' -m test_run_rebase success 'd n o e' -i diff --git a/t/t3427-rebase-subtree.sh b/t/t3427-rebase-subtree.sh index bec48e6a1f..79e43a370b 100755 --- a/t/t3427-rebase-subtree.sh +++ b/t/t3427-rebase-subtree.sh @@ -85,23 +85,23 @@ test_expect_failure REBASE_P 'Rebase -Xsubtree --keep-empty --preserve-merges -- verbose test "$(commit_message HEAD)" = "Empty commit" ' -test_expect_success 'Rebase -Xsubtree --keep-empty --onto commit' ' +test_expect_success 'Rebase -Xsubtree --empty=ask --onto commit' ' reset_rebase && git checkout -b rebase-onto to-rebase && - test_must_fail git rebase -Xsubtree=files_subtree --keep-empty --onto files-master master && + test_must_fail git rebase -Xsubtree=files_subtree --empty=ask --onto files-master master && : first pick results in no changes && - git rebase --continue && + git rebase --skip && verbose test "$(commit_message HEAD~2)" = "master4" && verbose test "$(commit_message HEAD~)" = "files_subtree/master5" && verbose test "$(commit_message HEAD)" = "Empty commit" ' -test_expect_success 'Rebase -Xsubtree --keep-empty --rebase-merges --onto commit' ' +test_expect_success 'Rebase -Xsubtree --empty=ask --rebase-merges --onto commit' ' reset_rebase && git checkout -b rebase-merges-onto to-rebase && - test_must_fail git rebase -Xsubtree=files_subtree --keep-empty --rebase-merges --onto files-master --root && + test_must_fail git rebase -Xsubtree=files_subtree --empty=ask --rebase-merges --onto files-master --root && : first pick results in no changes && - git rebase --continue && + git rebase --skip && verbose test "$(commit_message HEAD~2)" = "master4" && verbose test "$(commit_message HEAD~)" = "files_subtree/master5" && verbose test "$(commit_message HEAD)" = "Empty commit" diff --git a/t/t3430-rebase-merges.sh b/t/t3430-rebase-merges.sh index e72ca348ea..a1bc3e2001 100755 --- a/t/t3430-rebase-merges.sh +++ b/t/t3430-rebase-merges.sh @@ -20,12 +20,11 @@ Initial setup: ' . ./test-lib.sh . "$TEST_DIRECTORY"/lib-rebase.sh +. "$TEST_DIRECTORY"/lib-log-graph.sh test_cmp_graph () { cat >expect && - git log --graph --boundary --format=%s "$@" >output && - sed "s/ *$//" <output >output.trimmed && - test_cmp expect output.trimmed + lib_test_cmp_graph --boundary --format=%s "$@" } test_expect_success 'setup' ' diff --git a/t/t3431-rebase-fork-point.sh b/t/t3431-rebase-fork-point.sh index 78851b9a2a..172562789e 100755 --- a/t/t3431-rebase-fork-point.sh +++ b/t/t3431-rebase-fork-point.sh @@ -47,11 +47,31 @@ test_rebase 'G F B A' --keep-base test_rebase 'G F C E D B A' --no-fork-point test_rebase 'G F C D B A' --no-fork-point --onto D test_rebase 'G F C B A' --no-fork-point --keep-base + test_rebase 'G F E D B A' --fork-point refs/heads/master +test_rebase 'G F E D B A' --fork-point master + test_rebase 'G F D B A' --fork-point --onto D refs/heads/master +test_rebase 'G F D B A' --fork-point --onto D master + test_rebase 'G F B A' --fork-point --keep-base refs/heads/master +test_rebase 'G F B A' --fork-point --keep-base master + test_rebase 'G F C E D B A' refs/heads/master +test_rebase 'G F C E D B A' master + test_rebase 'G F C D B A' --onto D refs/heads/master +test_rebase 'G F C D B A' --onto D master + test_rebase 'G F C B A' --keep-base refs/heads/master +test_rebase 'G F C B A' --keep-base master + +test_expect_success 'git rebase --fork-point with ambigous refname' ' + git checkout master && + git checkout -b one && + git checkout side && + git tag one && + test_must_fail git rebase --fork-point --onto D one +' test_done diff --git a/t/t3432-rebase-fast-forward.sh b/t/t3432-rebase-fast-forward.sh index 92f95b57da..6f0452c0ea 100755 --- a/t/t3432-rebase-fast-forward.sh +++ b/t/t3432-rebase-fast-forward.sh @@ -28,8 +28,12 @@ test_rebase_same_head () { shift && cmp_f="$1" && shift && - test_rebase_same_head_ $status_n $what_n $cmp_n "" "$*" && - test_rebase_same_head_ $status_f $what_f $cmp_f " --no-ff" "$*" + test_rebase_same_head_ $status_n $what_n $cmp_n 0 " --apply" "$*" && + test_rebase_same_head_ $status_f $what_f $cmp_f 0 " --apply --no-ff" "$*" + test_rebase_same_head_ $status_n $what_n $cmp_n 0 " --merge" "$*" && + test_rebase_same_head_ $status_f $what_f $cmp_f 0 " --merge --no-ff" "$*" + test_rebase_same_head_ $status_n $what_n $cmp_n 1 " --merge" "$*" && + test_rebase_same_head_ $status_f $what_f $cmp_f 1 " --merge --no-ff" "$*" } test_rebase_same_head_ () { @@ -39,24 +43,32 @@ test_rebase_same_head_ () { shift && cmp="$1" && shift && + abbreviate="$1" && + shift && flag="$1" shift && - test_expect_$status "git rebase$flag $* with $changes is $what with $cmp HEAD" " + if test $abbreviate -eq 1 + then + msg="git rebase$flag $* (rebase.abbreviateCommands = true) with $changes is $what with $cmp HEAD" + else + msg="git rebase$flag $* with $changes is $what with $cmp HEAD" + fi && + test_expect_$status "$msg" " + if test $abbreviate -eq 1 + then + test_config rebase.abbreviateCommands true + fi && oldhead=\$(git rev-parse HEAD) && test_when_finished 'git reset --hard \$oldhead' && + cp .git/logs/HEAD expect && git rebase$flag $* >stdout && if test $what = work then - # Must check this case first, for 'is up to - # date, rebase forced[...]rewinding head' cases - test_i18ngrep 'rewinding head' stdout + old=\$(wc -l <expect) && + test_line_count '-gt' \$old .git/logs/HEAD elif test $what = noop then - test_i18ngrep 'is up to date' stdout && - test_i18ngrep ! 'rebase forced' stdout - elif test $what = noop-force - then - test_i18ngrep 'is up to date, rebase forced' stdout + test_cmp expect .git/logs/HEAD fi && newhead=\$(git rev-parse HEAD) && if test $cmp = same @@ -71,14 +83,14 @@ test_rebase_same_head_ () { changes='no changes' test_rebase_same_head success noop same success work same -test_rebase_same_head success noop same success noop-force same master -test_rebase_same_head success noop same success noop-force diff --onto B B -test_rebase_same_head success noop same success noop-force diff --onto B... B -test_rebase_same_head success noop same success noop-force same --onto master... master -test_rebase_same_head success noop same success noop-force same --keep-base master -test_rebase_same_head success noop same success noop-force same --keep-base -test_rebase_same_head success noop same success noop-force same --no-fork-point -test_rebase_same_head success noop same success noop-force same --keep-base --no-fork-point +test_rebase_same_head success noop same success work same master +test_rebase_same_head success noop same success work diff --onto B B +test_rebase_same_head success noop same success work diff --onto B... B +test_rebase_same_head success noop same success work same --onto master... master +test_rebase_same_head success noop same success work same --keep-base master +test_rebase_same_head success noop same success work same --keep-base +test_rebase_same_head success noop same success work same --no-fork-point +test_rebase_same_head success noop same success work same --keep-base --no-fork-point test_rebase_same_head success noop same success work same --fork-point master test_rebase_same_head success noop same success work diff --fork-point --onto B B test_rebase_same_head success noop same success work diff --fork-point --onto B... B @@ -91,14 +103,14 @@ test_expect_success 'add work same to side' ' changes='our changes' test_rebase_same_head success noop same success work same -test_rebase_same_head success noop same success noop-force same master -test_rebase_same_head success noop same success noop-force diff --onto B B -test_rebase_same_head success noop same success noop-force diff --onto B... B -test_rebase_same_head success noop same success noop-force same --onto master... master -test_rebase_same_head success noop same success noop-force same --keep-base master -test_rebase_same_head success noop same success noop-force same --keep-base -test_rebase_same_head success noop same success noop-force same --no-fork-point -test_rebase_same_head success noop same success noop-force same --keep-base --no-fork-point +test_rebase_same_head success noop same success work same master +test_rebase_same_head success noop same success work diff --onto B B +test_rebase_same_head success noop same success work diff --onto B... B +test_rebase_same_head success noop same success work same --onto master... master +test_rebase_same_head success noop same success work same --keep-base master +test_rebase_same_head success noop same success work same --keep-base +test_rebase_same_head success noop same success work same --no-fork-point +test_rebase_same_head success noop same success work same --keep-base --no-fork-point test_rebase_same_head success noop same success work same --fork-point master test_rebase_same_head success noop same success work diff --fork-point --onto B B test_rebase_same_head success noop same success work diff --fork-point --onto B... B @@ -112,8 +124,8 @@ test_expect_success 'add work same to upstream' ' ' changes='our and their changes' -test_rebase_same_head success noop same success noop-force diff --onto B B -test_rebase_same_head success noop same success noop-force diff --onto B... B +test_rebase_same_head success noop same success work diff --onto B B +test_rebase_same_head success noop same success work diff --onto B... B test_rebase_same_head success noop same success work diff --onto master... master test_rebase_same_head success noop same success work diff --keep-base master test_rebase_same_head success noop same success work diff --keep-base diff --git a/t/t3433-rebase-across-mode-change.sh b/t/t3433-rebase-across-mode-change.sh new file mode 100755 index 0000000000..05df964670 --- /dev/null +++ b/t/t3433-rebase-across-mode-change.sh @@ -0,0 +1,48 @@ +#!/bin/sh + +test_description='git rebase across mode change' + +. ./test-lib.sh + +test_expect_success 'setup' ' + mkdir DS && + >DS/whatever && + git add DS && + git commit -m base && + + git branch side1 && + git branch side2 && + + git checkout side1 && + git rm -rf DS && + test_ln_s_add unrelated DS && + git commit -m side1 && + + git checkout side2 && + >unrelated && + git add unrelated && + git commit -m commit1 && + + echo >>unrelated && + git commit -am commit2 +' + +test_expect_success 'rebase changes with the apply backend' ' + test_when_finished "git rebase --abort || true" && + git checkout -b apply-backend side2 && + git rebase side1 +' + +test_expect_success 'rebase changes with the merge backend' ' + test_when_finished "git rebase --abort || true" && + git checkout -b merge-backend side2 && + git rebase -m side1 +' + +test_expect_success 'rebase changes with the merge backend with a delay' ' + test_when_finished "git rebase --abort || true" && + git checkout -b merge-delay-backend side2 && + git rebase -m --exec "sleep 1" side1 +' + +test_done diff --git a/t/t3435-rebase-gpg-sign.sh b/t/t3435-rebase-gpg-sign.sh new file mode 100755 index 0000000000..b47c59c190 --- /dev/null +++ b/t/t3435-rebase-gpg-sign.sh @@ -0,0 +1,71 @@ +#!/bin/sh +# +# Copyright (c) 2020 Doan Tran Cong Danh +# + +test_description='test rebase --[no-]gpg-sign' + +. ./test-lib.sh +. "$TEST_DIRECTORY/lib-rebase.sh" +. "$TEST_DIRECTORY/lib-gpg.sh" + +if ! test_have_prereq GPG +then + skip_all='skip all test rebase --[no-]gpg-sign, gpg not available' + test_done +fi + +test_rebase_gpg_sign () { + local must_fail= will=will fake_editor= + if test "x$1" = "x!" + then + must_fail=test_must_fail + will="won't" + shift + fi + conf=$1 + shift + test_expect_success "rebase $* with commit.gpgsign=$conf $will sign commit" " + git reset two && + git config commit.gpgsign $conf && + set_fake_editor && + FAKE_LINES='r 1 p 2' git rebase --force-rebase --root $* && + $must_fail git verify-commit HEAD^ && + $must_fail git verify-commit HEAD + " +} + +test_expect_success 'setup' ' + test_commit one && + test_commit two && + test_must_fail git verify-commit HEAD && + test_must_fail git verify-commit HEAD^ +' + +test_expect_success 'setup: merge commit' ' + test_commit fork-point && + git switch -c side && + test_commit three && + git switch master && + git merge --no-ff side && + git tag merged +' + +test_rebase_gpg_sign ! false +test_rebase_gpg_sign true +test_rebase_gpg_sign ! true --no-gpg-sign +test_rebase_gpg_sign ! true --gpg-sign --no-gpg-sign +test_rebase_gpg_sign false --no-gpg-sign --gpg-sign +test_rebase_gpg_sign true -i +test_rebase_gpg_sign ! true -i --no-gpg-sign +test_rebase_gpg_sign ! true -i --gpg-sign --no-gpg-sign +test_rebase_gpg_sign false -i --no-gpg-sign --gpg-sign + +test_expect_failure 'rebase -p --no-gpg-sign override commit.gpgsign' ' + git reset --hard merged && + git config commit.gpgsign true && + git rebase -p --no-gpg-sign --onto=one fork-point master && + test_must_fail git verify-commit HEAD +' + +test_done diff --git a/t/t3504-cherry-pick-rerere.sh b/t/t3504-cherry-pick-rerere.sh index a267b2d144..80a0d08706 100755 --- a/t/t3504-cherry-pick-rerere.sh +++ b/t/t3504-cherry-pick-rerere.sh @@ -94,8 +94,10 @@ test_expect_success 'cherry-pick --rerere-autoupdate more than once' ' test_expect_success 'cherry-pick conflict without rerere' ' test_config rerere.enabled false && - test_must_fail git cherry-pick master && - test_must_fail test_cmp expect foo + test_must_fail git cherry-pick foo-master && + grep ===== foo && + grep foo-dev foo && + grep foo-master foo ' test_done diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh index 9b9b4ca8d4..752bc43487 100755 --- a/t/t3507-cherry-pick-conflict.sh +++ b/t/t3507-cherry-pick-conflict.sh @@ -161,6 +161,29 @@ test_expect_success 'successful commit clears CHERRY_PICK_HEAD' ' test_must_fail git rev-parse --verify CHERRY_PICK_HEAD ' + +test_expect_success 'partial commit of cherry-pick fails' ' + pristine_detach initial && + + test_must_fail git cherry-pick picked && + echo resolved >foo && + git add foo && + test_must_fail git commit foo 2>err && + + test_i18ngrep "cannot do a partial commit during a cherry-pick." err +' + +test_expect_success 'commit --amend of cherry-pick fails' ' + pristine_detach initial && + + test_must_fail git cherry-pick picked && + echo resolved >foo && + git add foo && + test_must_fail git commit --amend 2>err && + + test_i18ngrep "in the middle of a cherry-pick -- cannot amend." err +' + test_expect_success 'successful final commit clears cherry-pick state' ' pristine_detach initial && @@ -168,7 +191,7 @@ test_expect_success 'successful final commit clears cherry-pick state' ' echo resolved >foo && test_path_is_file .git/sequencer/todo && git commit -a && - test_must_fail test_path_exists .git/sequencer + test_path_is_missing .git/sequencer ' test_expect_success 'reset after final pick clears cherry-pick state' ' @@ -178,7 +201,7 @@ test_expect_success 'reset after final pick clears cherry-pick state' ' echo resolved >foo && test_path_is_file .git/sequencer/todo && git reset && - test_must_fail test_path_exists .git/sequencer + test_path_is_missing .git/sequencer ' test_expect_success 'failed cherry-pick produces dirty index' ' @@ -381,23 +404,23 @@ test_expect_success 'failed commit does not clear REVERT_HEAD' ' ' test_expect_success 'successful final commit clears revert state' ' - pristine_detach picked-signed && + pristine_detach picked-signed && - test_must_fail git revert picked-signed base && - echo resolved >foo && - test_path_is_file .git/sequencer/todo && - git commit -a && - test_must_fail test_path_exists .git/sequencer + test_must_fail git revert picked-signed base && + echo resolved >foo && + test_path_is_file .git/sequencer/todo && + git commit -a && + test_path_is_missing .git/sequencer ' test_expect_success 'reset after final pick clears revert state' ' - pristine_detach picked-signed && + pristine_detach picked-signed && - test_must_fail git revert picked-signed base && - echo resolved >foo && - test_path_is_file .git/sequencer/todo && - git reset && - test_must_fail test_path_exists .git/sequencer + test_must_fail git revert picked-signed base && + echo resolved >foo && + test_path_is_file .git/sequencer/todo && + git reset && + test_path_is_missing .git/sequencer ' test_expect_success 'revert conflict, diff3 -m style' ' diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh index 793bcc7fe3..5b94fdaa67 100755 --- a/t/t3510-cherry-pick-sequence.sh +++ b/t/t3510-cherry-pick-sequence.sh @@ -123,7 +123,8 @@ test_expect_success 'revert --skip to skip commit' ' test_expect_success 'skip "empty" commit' ' pristine_detach picked && test_commit dummy foo d && - test_must_fail git cherry-pick anotherpick && + test_must_fail git cherry-pick anotherpick 2>err && + test_i18ngrep "git cherry-pick --skip" err && git cherry-pick --skip && test_cmp_rev dummy HEAD ' diff --git a/t/t3514-cherry-pick-revert-gpg.sh b/t/t3514-cherry-pick-revert-gpg.sh new file mode 100755 index 0000000000..5b2e250eaa --- /dev/null +++ b/t/t3514-cherry-pick-revert-gpg.sh @@ -0,0 +1,86 @@ +#!/bin/sh +# +# Copyright (c) 2020 Doan Tran Cong Danh +# + +test_description='test {cherry-pick,revert} --[no-]gpg-sign' + +. ./test-lib.sh +. "$TEST_DIRECTORY/lib-gpg.sh" + +if ! test_have_prereq GPG +then + skip_all='skip all test {cherry-pick,revert} --[no-]gpg-sign, gpg not available' + test_done +fi + +test_gpg_sign () { + local must_fail= will=will fake_editor= + if test "x$1" = "x!" + then + must_fail=test_must_fail + will="won't" + shift + fi + conf=$1 + cmd=$2 + cmit=$3 + shift 3 + test_expect_success "$cmd $* $cmit with commit.gpgsign=$conf $will sign commit" " + git reset --hard tip && + git config commit.gpgsign $conf && + git $cmd $* $cmit && + git rev-list tip.. >rev-list && + $must_fail git verify-commit \$(cat rev-list) + " +} + +test_expect_success 'setup' ' + test_commit one && + git switch -c side && + test_commit side1 && + test_commit side2 && + git switch - && + test_commit two && + test_commit three && + test_commit tip +' + +test_gpg_sign ! false cherry-pick side +test_gpg_sign ! false cherry-pick ..side +test_gpg_sign true cherry-pick side +test_gpg_sign true cherry-pick ..side +test_gpg_sign ! true cherry-pick side --no-gpg-sign +test_gpg_sign ! true cherry-pick ..side --no-gpg-sign +test_gpg_sign ! true cherry-pick side --gpg-sign --no-gpg-sign +test_gpg_sign ! true cherry-pick ..side --gpg-sign --no-gpg-sign +test_gpg_sign false cherry-pick side --no-gpg-sign --gpg-sign +test_gpg_sign false cherry-pick ..side --no-gpg-sign --gpg-sign +test_gpg_sign true cherry-pick side --edit +test_gpg_sign true cherry-pick ..side --edit +test_gpg_sign ! true cherry-pick side --edit --no-gpg-sign +test_gpg_sign ! true cherry-pick ..side --edit --no-gpg-sign +test_gpg_sign ! true cherry-pick side --edit --gpg-sign --no-gpg-sign +test_gpg_sign ! true cherry-pick ..side --edit --gpg-sign --no-gpg-sign +test_gpg_sign false cherry-pick side --edit --no-gpg-sign --gpg-sign +test_gpg_sign false cherry-pick ..side --edit --no-gpg-sign --gpg-sign + +test_gpg_sign ! false revert HEAD --edit +test_gpg_sign ! false revert two.. --edit +test_gpg_sign true revert HEAD --edit +test_gpg_sign true revert two.. --edit +test_gpg_sign ! true revert HEAD --edit --no-gpg-sign +test_gpg_sign ! true revert two.. --edit --no-gpg-sign +test_gpg_sign ! true revert HEAD --edit --gpg-sign --no-gpg-sign +test_gpg_sign ! true revert two.. --edit --gpg-sign --no-gpg-sign +test_gpg_sign false revert HEAD --edit --no-gpg-sign --gpg-sign +test_gpg_sign false revert two.. --edit --no-gpg-sign --gpg-sign +test_gpg_sign true revert HEAD --no-edit +test_gpg_sign true revert two.. --no-edit +test_gpg_sign ! true revert HEAD --no-edit --no-gpg-sign +test_gpg_sign ! true revert two.. --no-edit --no-gpg-sign +test_gpg_sign ! true revert HEAD --no-edit --gpg-sign --no-gpg-sign +test_gpg_sign ! true revert two.. --no-edit --gpg-sign --no-gpg-sign +test_gpg_sign false revert HEAD --no-edit --no-gpg-sign --gpg-sign + +test_done diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh index 0ea858d652..f2c0168941 100755 --- a/t/t3600-rm.sh +++ b/t/t3600-rm.sh @@ -425,6 +425,13 @@ test_expect_success 'rm will error out on a modified .gitmodules file unless sta git status -s -uno >actual && test_cmp expect actual ' +test_expect_success 'rm will not error out on .gitmodules file with zero stat data' ' + git reset --hard && + git submodule update && + git read-tree HEAD && + git rm submod && + test_path_is_missing submod +' test_expect_success 'rm issues a warning when section is not found in .gitmodules' ' git reset --hard && diff --git a/t/t3601-rm-pathspec-file.sh b/t/t3601-rm-pathspec-file.sh new file mode 100755 index 0000000000..7de21f8bcf --- /dev/null +++ b/t/t3601-rm-pathspec-file.sh @@ -0,0 +1,79 @@ +#!/bin/sh + +test_description='rm --pathspec-from-file' + +. ./test-lib.sh + +test_tick + +test_expect_success setup ' + echo A >fileA.t && + echo B >fileB.t && + echo C >fileC.t && + echo D >fileD.t && + git add fileA.t fileB.t fileC.t fileD.t && + git commit -m "files" && + + git tag checkpoint +' + +restore_checkpoint () { + git reset --hard checkpoint +} + +verify_expect () { + git status --porcelain --untracked-files=no -- fileA.t fileB.t fileC.t fileD.t >actual && + test_cmp expect actual +} + +test_expect_success 'simplest' ' + restore_checkpoint && + + cat >expect <<-\EOF && + D fileA.t + EOF + + echo fileA.t | git rm --pathspec-from-file=- && + verify_expect +' + +test_expect_success '--pathspec-file-nul' ' + restore_checkpoint && + + cat >expect <<-\EOF && + D fileA.t + D fileB.t + EOF + + printf "fileA.t\0fileB.t\0" | git rm --pathspec-from-file=- --pathspec-file-nul && + verify_expect +' + +test_expect_success 'only touches what was listed' ' + restore_checkpoint && + + cat >expect <<-\EOF && + D fileB.t + D fileC.t + EOF + + printf "fileB.t\nfileC.t\n" | git rm --pathspec-from-file=- && + verify_expect +' + +test_expect_success 'error conditions' ' + restore_checkpoint && + echo fileA.t >list && + + test_must_fail git rm --pathspec-from-file=list -- fileA.t 2>err && + test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err && + + test_must_fail git rm --pathspec-file-nul 2>err && + test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err && + + >empty_list && + test_must_fail git rm --pathspec-from-file=empty_list 2>err && + test_i18ngrep -e "No pathspec was given. Which files should I remove?" err +' + +test_done diff --git a/t/t3700-add.sh b/t/t3700-add.sh index c325167b90..b7d4ba608c 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -192,7 +192,7 @@ test_expect_success 'git add --refresh with pathspec' ' test_must_be_empty actual && git diff-files --name-only >actual && - ! grep bar actual&& + ! grep bar actual && grep baz actual ' @@ -326,7 +326,9 @@ test_expect_success 'git add --dry-run of an existing file output' " cat >expect.err <<\EOF The following paths are ignored by one of your .gitignore files: ignored-file -Use -f if you really want to add them. +hint: Use -f if you really want to add them. +hint: Turn this message off by running +hint: "git config advice.addIgnoredFile false" EOF cat >expect.out <<\EOF add 'track-this' diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index 12ee321707..b3d8bb7577 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -68,6 +68,15 @@ test_expect_success 'revert works (initial)' ' ! grep . output ' +test_expect_success 'add untracked (multiple)' ' + test_when_finished "git reset && rm [1-9]" && + touch $(test_seq 9) && + test_write_lines a "2-5 8-" | git add -i -- [1-9] && + test_write_lines 2 3 4 5 8 9 >expected && + git ls-files [1-9] >output && + test_cmp expected output +' + test_expect_success 'setup (commit)' ' echo baseline >file && git add file && @@ -544,6 +553,19 @@ test_expect_success 'diffs can be colorized' ' grep "$(printf "\\033")" output ' +test_expect_success 'colorized diffs respect diff.wsErrorHighlight' ' + git reset --hard && + + echo "old " >test && + git add test && + echo "new " >test && + + printf y >y && + force_color git -c diff.wsErrorHighlight=all add -p >output.raw 2>&1 <y && + test_decode_color <output.raw >output && + grep "old<" output +' + test_expect_success 'diffFilter filters diff' ' git reset --hard && @@ -561,7 +583,7 @@ test_expect_success 'detect bogus diffFilter output' ' git reset --hard && echo content >test && - test_config interactive.diffFilter "echo too-short" && + test_config interactive.diffFilter "sed 1d" && printf y >y && test_must_fail force_color git add -p <y ' @@ -758,7 +780,7 @@ test_expect_success 'add -p patch editing works with pathological context lines' test_expect_success 'checkout -p works with pathological context lines' ' test_write_lines a a a a a a >a && git add a && - test_write_lines a b a b a b a b a b a > a&& + test_write_lines a b a b a b a b a b a >a && test_write_lines s n n y q | git checkout -p && test_write_lines a b a b a a b a b a >expect && test_cmp expect a diff --git a/t/t3704-add-pathspec-file.sh b/t/t3704-add-pathspec-file.sh index 3cfdb669b7..9e35c1fbca 100755 --- a/t/t3704-add-pathspec-file.sh +++ b/t/t3704-add-pathspec-file.sh @@ -97,7 +97,11 @@ test_expect_success 'CRLF delimiters' ' test_expect_success 'quotes' ' restore_checkpoint && - printf "\"file\\101.t\"" | git add --pathspec-from-file=- && + cat >list <<-\EOF && + "file\101.t" + EOF + + git add --pathspec-from-file=list && cat >expect <<-\EOF && A fileA.t @@ -108,7 +112,10 @@ test_expect_success 'quotes' ' test_expect_success 'quotes not compatible with --pathspec-file-nul' ' restore_checkpoint && - printf "\"file\\101.t\"" >list && + cat >list <<-\EOF && + "file\101.t" + EOF + test_must_fail git add --pathspec-from-file=list --pathspec-file-nul ' @@ -124,4 +131,29 @@ test_expect_success 'only touches what was listed' ' verify_expect ' +test_expect_success 'error conditions' ' + restore_checkpoint && + echo fileA.t >list && + >empty_list && + + test_must_fail git add --pathspec-from-file=list --interactive 2>err && + test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err && + + test_must_fail git add --pathspec-from-file=list --patch 2>err && + test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err && + + test_must_fail git add --pathspec-from-file=list --edit 2>err && + test_i18ngrep -e "--pathspec-from-file is incompatible with --edit" err && + + test_must_fail git add --pathspec-from-file=list -- fileA.t 2>err && + test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err && + + test_must_fail git add --pathspec-file-nul 2>err && + test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err && + + # This case succeeds, but still prints to stderr + git add --pathspec-from-file=empty_list 2>err && + test_i18ngrep -e "Nothing specified, nothing added." err +' + test_done diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh index ea56e85e70..9f7ca98967 100755 --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@ -285,6 +285,11 @@ test_expect_success 'stash --no-keep-index' ' test bar,bar2 = $(cat file),$(cat file2) ' +test_expect_success 'dont assume push with non-option args' ' + test_must_fail git stash -q drop 2>err && + test_i18ngrep -e "subcommand wasn'\''t specified; '\''push'\'' can'\''t be assumed due to unexpected token '\''drop'\''" err +' + test_expect_success 'stash --invalid-option' ' echo bar5 >file && echo bar6 >file2 && @@ -1285,4 +1290,18 @@ test_expect_success 'stash handles skip-worktree entries nicely' ' git rev-parse --verify refs/stash:A.t ' +test_expect_success 'stash -c stash.useBuiltin=false warning ' ' + expected="stash.useBuiltin support has been removed" && + + git -c stash.useBuiltin=false stash 2>err && + test_i18ngrep "$expected" err && + env GIT_TEST_STASH_USE_BUILTIN=false git stash 2>err && + test_i18ngrep "$expected" err && + + git -c stash.useBuiltin=true stash 2>err && + test_must_be_empty err && + env GIT_TEST_STASH_USE_BUILTIN=true git stash 2>err && + test_must_be_empty err +' + test_done diff --git a/t/t3904-stash-patch.sh b/t/t3904-stash-patch.sh index 9546b6f8a4..accfe3845c 100755 --- a/t/t3904-stash-patch.sh +++ b/t/t3904-stash-patch.sh @@ -89,7 +89,7 @@ test_expect_success 'none of this moved HEAD' ' verify_saved_head ' -test_expect_failure 'stash -p with split hunk' ' +test_expect_success 'stash -p with split hunk' ' git reset --hard && cat >test <<-\EOF && aaa @@ -106,8 +106,8 @@ test_expect_failure 'stash -p with split hunk' ' ccc EOF printf "%s\n" s n y q | - test_might_fail git stash -p 2>error && - ! test_must_be_empty error && + git stash -p 2>error && + test_must_be_empty error && grep "added line 1" test && ! grep "added line 2" test ' diff --git a/t/t3909-stash-pathspec-file.sh b/t/t3909-stash-pathspec-file.sh new file mode 100755 index 0000000000..55e050cfd4 --- /dev/null +++ b/t/t3909-stash-pathspec-file.sh @@ -0,0 +1,100 @@ +#!/bin/sh + +test_description='stash --pathspec-from-file' + +. ./test-lib.sh + +test_tick + +test_expect_success setup ' + >fileA.t && + >fileB.t && + >fileC.t && + >fileD.t && + git add fileA.t fileB.t fileC.t fileD.t && + git commit -m "Files" && + + git tag checkpoint +' + +restore_checkpoint () { + git reset --hard checkpoint +} + +verify_expect () { + git stash show --name-status >actual && + test_cmp expect actual +} + +test_expect_success 'simplest' ' + restore_checkpoint && + + # More files are written to make sure that git didnt ignore + # --pathspec-from-file, stashing everything + echo A >fileA.t && + echo B >fileB.t && + echo C >fileC.t && + echo D >fileD.t && + + cat >expect <<-\EOF && + M fileA.t + EOF + + echo fileA.t | git stash push --pathspec-from-file=- && + verify_expect +' + +test_expect_success '--pathspec-file-nul' ' + restore_checkpoint && + + # More files are written to make sure that git didnt ignore + # --pathspec-from-file, stashing everything + echo A >fileA.t && + echo B >fileB.t && + echo C >fileC.t && + echo D >fileD.t && + + cat >expect <<-\EOF && + M fileA.t + M fileB.t + EOF + + printf "fileA.t\0fileB.t\0" | git stash push --pathspec-from-file=- --pathspec-file-nul && + verify_expect +' + +test_expect_success 'only touches what was listed' ' + restore_checkpoint && + + # More files are written to make sure that git didnt ignore + # --pathspec-from-file, stashing everything + echo A >fileA.t && + echo B >fileB.t && + echo C >fileC.t && + echo D >fileD.t && + + cat >expect <<-\EOF && + M fileB.t + M fileC.t + EOF + + printf "fileB.t\nfileC.t\n" | git stash push --pathspec-from-file=- && + verify_expect +' + +test_expect_success 'error conditions' ' + restore_checkpoint && + echo A >fileA.t && + echo fileA.t >list && + + test_must_fail git stash push --pathspec-from-file=list --patch 2>err && + test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err && + + test_must_fail git stash push --pathspec-from-file=list -- fileA.t 2>err && + test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err && + + test_must_fail git stash push --pathspec-file-nul 2>err && + test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err +' + +test_done diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index 5ac94b390d..3f60f7d96c 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -95,6 +95,15 @@ test_expect_success setup ' git commit -m "update mode" && git checkout -f master && + GIT_AUTHOR_DATE="2006-06-26 00:06:00 +0000" && + GIT_COMMITTER_DATE="2006-06-26 00:06:00 +0000" && + export GIT_AUTHOR_DATE GIT_COMMITTER_DATE && + git checkout -b note initial && + git update-index --chmod=+x file2 && + git commit -m "update mode (file2)" && + git notes add -m "note" && + git checkout -f master && + # Same merge as master, but with parents reversed. Hide it in a # pseudo-ref to avoid impacting tests with --all. commit=$(echo reverse | @@ -120,6 +129,30 @@ test_expect_success setup ' +*++ [initial] Initial EOF +process_diffs () { + _x04="[0-9a-f][0-9a-f][0-9a-f][0-9a-f]" && + _x07="$_x05[0-9a-f][0-9a-f]" && + sed -e "s/$OID_REGEX/$ZERO_OID/g" \ + -e "s/From $_x40 /From $ZERO_OID /" \ + -e "s/from $_x40)/from $ZERO_OID)/" \ + -e "s/commit $_x40\$/commit $ZERO_OID/" \ + -e "s/commit $_x40 (/commit $ZERO_OID (/" \ + -e "s/$_x40 $_x40 $_x40/$ZERO_OID $ZERO_OID $ZERO_OID/" \ + -e "s/$_x40 $_x40 /$ZERO_OID $ZERO_OID /" \ + -e "s/^$_x40 $_x40$/$ZERO_OID $ZERO_OID/" \ + -e "s/^$_x40 /$ZERO_OID /" \ + -e "s/^$_x40$/$ZERO_OID/" \ + -e "s/$_x07\.\.$_x07/fffffff..fffffff/g" \ + -e "s/$_x07,$_x07\.\.$_x07/fffffff,fffffff..fffffff/g" \ + -e "s/$_x07 $_x07 $_x07/fffffff fffffff fffffff/g" \ + -e "s/$_x07 $_x07 /fffffff fffffff /g" \ + -e "s/Merge: $_x07 $_x07/Merge: fffffff fffffff/g" \ + -e "s/$_x07\.\.\./fffffff.../g" \ + -e "s/ $_x04\.\.\./ ffff.../g" \ + -e "s/ $_x04/ ffff/g" \ + "$1" +} + V=$(git version | sed -e 's/^git version //' -e 's/\./\\./g') while read magic cmd do @@ -158,13 +191,15 @@ do } >"$actual" && if test -f "$expect" then + process_diffs "$actual" >actual && + process_diffs "$expect" >expect && case $cmd in *format-patch* | *-stat*) - test_i18ncmp "$expect" "$actual";; + test_i18ncmp expect actual;; *) - test_cmp "$expect" "$actual";; + test_cmp expect actual;; esac && - rm -f "$actual" + rm -f "$actual" actual expect else # this is to help developing new tests. cp "$actual" "$expect" @@ -372,6 +407,9 @@ diff --no-index --raw --no-abbrev dir2 dir diff-tree --pretty --root --stat --compact-summary initial diff-tree --pretty -R --root --stat --compact-summary initial +diff-tree --pretty note +diff-tree --pretty --notes note +diff-tree --format=%N note diff-tree --stat --compact-summary initial mode diff-tree -R --stat --compact-summary initial mode EOF @@ -383,16 +421,22 @@ test_expect_success 'log -S requires an argument' ' test_expect_success 'diff --cached on unborn branch' ' echo ref: refs/heads/unborn >.git/HEAD && git diff --cached >result && - test_cmp "$TEST_DIRECTORY/t4013/diff.diff_--cached" result + process_diffs result >actual && + process_diffs "$TEST_DIRECTORY/t4013/diff.diff_--cached" >expected && + test_cmp expected actual ' test_expect_success 'diff --cached -- file on unborn branch' ' git diff --cached -- file0 >result && - test_cmp "$TEST_DIRECTORY/t4013/diff.diff_--cached_--_file0" result + process_diffs result >actual && + process_diffs "$TEST_DIRECTORY/t4013/diff.diff_--cached_--_file0" >expected && + test_cmp expected actual ' 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 + process_diffs result >actual && + process_diffs "$TEST_DIRECTORY/t4013/diff.diff_--line-prefix_--cached_--_file0" >expected && + test_cmp expected actual ' test_expect_success 'diff-tree --stdin with log formatting' ' diff --git a/t/t4013/diff.diff-tree_--format=%N_note b/t/t4013/diff.diff-tree_--format=%N_note new file mode 100644 index 0000000000..93042ed539 --- /dev/null +++ b/t/t4013/diff.diff-tree_--format=%N_note @@ -0,0 +1,6 @@ +$ git diff-tree --format=%N note +note + + +:100644 100755 01e79c32a8c99c557f0757da7cb6d65b3414466d 01e79c32a8c99c557f0757da7cb6d65b3414466d M file2 +$ diff --git a/t/t4013/diff.diff-tree_--pretty_--notes_note b/t/t4013/diff.diff-tree_--pretty_--notes_note new file mode 100644 index 0000000000..4d0bde601c --- /dev/null +++ b/t/t4013/diff.diff-tree_--pretty_--notes_note @@ -0,0 +1,12 @@ +$ git diff-tree --pretty --notes note +commit a6f364368ca320bc5a92e18912e16fa6b3dff598 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:06:00 2006 +0000 + + update mode (file2) + +Notes: + note + +:100644 100755 01e79c32a8c99c557f0757da7cb6d65b3414466d 01e79c32a8c99c557f0757da7cb6d65b3414466d M file2 +$ diff --git a/t/t4013/diff.diff-tree_--pretty_note b/t/t4013/diff.diff-tree_--pretty_note new file mode 100644 index 0000000000..1fa5967083 --- /dev/null +++ b/t/t4013/diff.diff-tree_--pretty_note @@ -0,0 +1,9 @@ +$ git diff-tree --pretty note +commit a6f364368ca320bc5a92e18912e16fa6b3dff598 +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:06:00 2006 +0000 + + update mode (file2) + +:100644 100755 01e79c32a8c99c557f0757da7cb6d65b3414466d 01e79c32a8c99c557f0757da7cb6d65b3414466d M file2 +$ diff --git a/t/t4013/diff.log_--decorate=full_--all b/t/t4013/diff.log_--decorate=full_--all index 2afe91f116..3f9b872ece 100644 --- a/t/t4013/diff.log_--decorate=full_--all +++ b/t/t4013/diff.log_--decorate=full_--all @@ -5,12 +5,27 @@ Date: Mon Jun 26 00:06:00 2006 +0000 update mode +commit a6f364368ca320bc5a92e18912e16fa6b3dff598 (refs/heads/note) +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:06:00 2006 +0000 + + update mode (file2) + +Notes: + note + commit cd4e72fd96faed3f0ba949dc42967430374e2290 (refs/heads/rearrange) Author: A U Thor <author@example.com> Date: Mon Jun 26 00:06:00 2006 +0000 Rearranged lines in dir/sub +commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits) +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:06:00 2006 +0000 + + Notes added by 'git notes add' + commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> refs/heads/master) Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> diff --git a/t/t4013/diff.log_--decorate_--all b/t/t4013/diff.log_--decorate_--all index d0f308ab2b..f5e20e1e14 100644 --- a/t/t4013/diff.log_--decorate_--all +++ b/t/t4013/diff.log_--decorate_--all @@ -5,12 +5,27 @@ Date: Mon Jun 26 00:06:00 2006 +0000 update mode +commit a6f364368ca320bc5a92e18912e16fa6b3dff598 (note) +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:06:00 2006 +0000 + + update mode (file2) + +Notes: + note + commit cd4e72fd96faed3f0ba949dc42967430374e2290 (rearrange) Author: A U Thor <author@example.com> Date: Mon Jun 26 00:06:00 2006 +0000 Rearranged lines in dir/sub +commit cbacedd14cb8b89255a2c02b59e77a2e9a8021a0 (refs/notes/commits) +Author: A U Thor <author@example.com> +Date: Mon Jun 26 00:06:00 2006 +0000 + + Notes added by 'git notes add' + commit 59d314ad6f356dd08601a4cd5e530381da3e3c64 (HEAD -> master) Merge: 9a6d494 c7a2ab9 Author: A U Thor <author@example.com> diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index b653dd7d44..db7e733af9 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -1161,6 +1161,59 @@ test_expect_success 'format-patch wraps extremely long from-header (rfc2047)' ' ' cat >expect <<'EOF' +From: Foö Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar + Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo + Bar Foo Bar Foo Bar Foo Bar <author@example.com> +EOF +test_expect_success 'format-patch wraps extremely long from-header (non-ASCII without Q-encoding)' ' + echo content >>file && + git add file && + GIT_AUTHOR_NAME="Foö Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar Foo Bar" \ + git commit -m author-check && + git format-patch --no-encode-email-headers --stdout -1 >patch && + sed -n "/^From: /p; /^ /p; /^$/q" patch >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +Subject: [PATCH] Foö +EOF +test_expect_success 'subject lines are unencoded with --no-encode-email-headers' ' + echo content >>file && + git add file && + git commit -m "Foö" && + git format-patch --no-encode-email-headers -1 --stdout >patch && + grep ^Subject: patch >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +Subject: [PATCH] Foö +EOF +test_expect_success 'subject lines are unencoded with format.encodeEmailHeaders=false' ' + echo content >>file && + git add file && + git commit -m "Foö" && + git config format.encodeEmailHeaders false && + git format-patch -1 --stdout >patch && + grep ^Subject: patch >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +Subject: [PATCH] =?UTF-8?q?Fo=C3=B6?= +EOF +test_expect_success '--encode-email-headers overrides format.encodeEmailHeaders' ' + echo content >>file && + git add file && + git commit -m "Foö" && + git config format.encodeEmailHeaders false && + git format-patch --encode-email-headers -1 --stdout >patch && + grep ^Subject: patch >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' Subject: header with . in it EOF test_expect_success 'subject lines do not have 822 atom-quoting' ' diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh index c0f4839543..9d07797579 100755 --- a/t/t4018-diff-funcname.sh +++ b/t/t4018-diff-funcname.sh @@ -38,6 +38,7 @@ diffpatterns=" golang html java + markdown matlab objc pascal @@ -106,7 +107,6 @@ do result=success fi test_expect_$result "hunk header: $i" " - test_when_finished 'cat actual' && # for debugging only git diff -U1 $i >actual && grep '@@ .* @@.*RIGHT' actual " diff --git a/t/t4018/markdown-heading-indented b/t/t4018/markdown-heading-indented new file mode 100644 index 0000000000..1991c2bd45 --- /dev/null +++ b/t/t4018/markdown-heading-indented @@ -0,0 +1,6 @@ +Indented headings are allowed, as long as the indent is no more than 3 spaces. + + ### RIGHT + +- something +- ChangeMe diff --git a/t/t4018/markdown-heading-non-headings b/t/t4018/markdown-heading-non-headings new file mode 100644 index 0000000000..c479c1a3f1 --- /dev/null +++ b/t/t4018/markdown-heading-non-headings @@ -0,0 +1,17 @@ +Headings can be right next to other lines of the file: +# RIGHT +Indents of four or more spaces make a code block: + + # code comment, not heading + +If there's no space after the final hash, it's not a heading: + +#hashtag + +Sequences of more than 6 hashes don't make a heading: + +####### over-enthusiastic heading + +So the detected heading should be right up at the start of this file. + +ChangeMe diff --git a/t/t4026-color.sh b/t/t4026-color.sh index 671e951ee5..c0b642c1ab 100755 --- a/t/t4026-color.sh +++ b/t/t4026-color.sh @@ -30,6 +30,14 @@ test_expect_success 'attribute before color name' ' color "bold red" "[1;31m" ' +test_expect_success 'aixterm bright fg color' ' + color "brightred" "[91m" +' + +test_expect_success 'aixterm bright bg color' ' + color "green brightblue" "[32;104m" +' + test_expect_success 'color name before attribute' ' color "red bold" "[1;31m" ' @@ -74,6 +82,10 @@ test_expect_success '0-7 are aliases for basic ANSI color names' ' color "0 7" "[30;47m" ' +test_expect_success '8-15 are aliases for aixterm color names' ' + color "12 13" "[94;105m" +' + test_expect_success '256 colors' ' color "254 bold 255" "[1;38;5;254;48;5;255m" ' diff --git a/t/t4054-diff-bogus-tree.sh b/t/t4054-diff-bogus-tree.sh index fcae82fffa..8c95f152b2 100755 --- a/t/t4054-diff-bogus-tree.sh +++ b/t/t4054-diff-bogus-tree.sh @@ -4,8 +4,9 @@ test_description='test diff with a bogus tree containing the null sha1' . ./test-lib.sh test_expect_success 'create bogus tree' ' + name=$(echo $ZERO_OID | sed -e "s/00/Q/g") && bogus_tree=$( - printf "100644 fooQQQQQQQQQQQQQQQQQQQQQ" | + printf "100644 fooQ$name" | q_to_nul | git hash-object -w --stdin -t tree ) diff --git a/t/t4057-diff-combined-paths.sh b/t/t4057-diff-combined-paths.sh index 4f4b541658..0b78573733 100755 --- a/t/t4057-diff-combined-paths.sh +++ b/t/t4057-diff-combined-paths.sh @@ -14,7 +14,7 @@ diffc_verify () { test_expect_success 'trivial merge - combine-diff empty' ' for i in $(test_seq 1 9) do - echo $i >$i.txt && + echo $i >$i.txt && git add $i.txt done && git commit -m "init" && diff --git a/t/t4060-diff-submodule-option-diff-format.sh b/t/t4060-diff-submodule-option-diff-format.sh index 9dcb69df5c..fc8229c726 100755 --- a/t/t4060-diff-submodule-option-diff-format.sh +++ b/t/t4060-diff-submodule-option-diff-format.sh @@ -42,6 +42,17 @@ commit_file () { git commit "$@" -m "Commit $*" >/dev/null } +diff_cmp () { + for i in "$1" "$2" + do + sed -e 's/^index 0000000\.\.[0-9a-f]*/index 0000000..1234567/' \ + -e 's/^index [0-9a-f]*\.\.[0-9a-f]*/index 1234567..89abcde/' \ + "$i" >"$i.compare" || return 1 + done && + test_cmp "$1.compare" "$2.compare" && + rm -f "$1.compare" "$2.compare" +} + test_expect_success 'setup repository' ' test_create_repo sm1 && add_file . foo && @@ -69,7 +80,7 @@ test_expect_success 'added submodule' ' @@ -0,0 +1 @@ +foo2 EOF - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'added submodule, set diff.submodule' ' @@ -93,7 +104,7 @@ test_expect_success 'added submodule, set diff.submodule' ' @@ -0,0 +1 @@ +foo2 EOF - test_cmp expected actual + diff_cmp expected actual ' test_expect_success '--submodule=short overrides diff.submodule' ' @@ -109,7 +120,7 @@ test_expect_success '--submodule=short overrides diff.submodule' ' @@ -0,0 +1 @@ +Subproject commit $fullhead1 EOF - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'diff.submodule does not affect plumbing' ' @@ -124,7 +135,7 @@ test_expect_success 'diff.submodule does not affect plumbing' ' @@ -0,0 +1 @@ +Subproject commit $fullhead1 EOF - test_cmp expected actual + diff_cmp expected actual ' commit_file sm1 && @@ -142,7 +153,7 @@ test_expect_success 'modified submodule(forward)' ' @@ -0,0 +1 @@ +foo3 EOF - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'modified submodule(forward)' ' @@ -157,7 +168,7 @@ test_expect_success 'modified submodule(forward)' ' @@ -0,0 +1 @@ +foo3 EOF - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'modified submodule(forward) --submodule' ' @@ -166,7 +177,7 @@ test_expect_success 'modified submodule(forward) --submodule' ' Submodule sm1 $head1..$head2: > Add foo3 ($added foo3) EOF - test_cmp expected actual + diff_cmp expected actual ' fullhead2=$(cd sm1; git rev-parse --verify HEAD) @@ -181,7 +192,7 @@ test_expect_success 'modified submodule(forward) --submodule=short' ' -Subproject commit $fullhead1 +Subproject commit $fullhead2 EOF - test_cmp expected actual + diff_cmp expected actual ' commit_file sm1 && @@ -210,7 +221,7 @@ test_expect_success 'modified submodule(backward)' ' @@ -1 +0,0 @@ -foo3 EOF - test_cmp expected actual + diff_cmp expected actual ' head4=$(add_file sm1 foo4 foo5) @@ -247,7 +258,7 @@ test_expect_success 'modified submodule(backward and forward)' ' @@ -0,0 +1 @@ +foo5 EOF - test_cmp expected actual + diff_cmp expected actual ' commit_file sm1 && @@ -291,7 +302,7 @@ test_expect_success 'typechanged submodule(submodule->blob), --cached' ' @@ -0,0 +1 @@ +sm1 EOF - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'typechanged submodule(submodule->blob)' ' @@ -327,7 +338,7 @@ test_expect_success 'typechanged submodule(submodule->blob)' ' @@ -0,0 +1 @@ +foo5 EOF - test_cmp expected actual + diff_cmp expected actual ' rm -rf sm1 && @@ -344,7 +355,7 @@ test_expect_success 'typechanged submodule(submodule->blob)' ' @@ -0,0 +1 @@ +sm1 EOF - test_cmp expected actual + diff_cmp expected actual ' rm -f sm1 && @@ -356,7 +367,7 @@ test_expect_success 'nonexistent commit' ' cat >expected <<-EOF && Submodule sm1 $head4...$head6 (commits not present) EOF - test_cmp expected actual + diff_cmp expected actual ' commit_file @@ -386,11 +397,12 @@ test_expect_success 'typechanged submodule(blob->submodule)' ' @@ -0,0 +1 @@ +foo7 EOF - test_cmp expected actual + diff_cmp expected actual ' commit_file sm1 && test_expect_success 'submodule is up to date' ' + head7=$(git -C sm1 rev-parse --short --verify HEAD) && git diff-index -p --submodule=diff HEAD >actual && test_must_be_empty actual ' @@ -401,7 +413,7 @@ test_expect_success 'submodule contains untracked content' ' cat >expected <<-EOF && Submodule sm1 contains untracked content EOF - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'submodule contains untracked content (untracked ignored)' ' @@ -433,7 +445,7 @@ test_expect_success 'submodule contains untracked and modified content' ' -foo6 +new EOF - test_cmp expected actual + diff_cmp expected actual ' # NOT OK @@ -450,7 +462,7 @@ test_expect_success 'submodule contains untracked and modified content (untracke -foo6 +new EOF - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'submodule contains untracked and modified content (dirty ignored)' ' @@ -478,7 +490,7 @@ test_expect_success 'submodule contains modified content' ' -foo6 +new EOF - test_cmp expected actual + diff_cmp expected actual ' (cd sm1; git commit -mchange foo6 >/dev/null) && @@ -486,7 +498,7 @@ 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: + Submodule sm1 $head7..$head8: diff --git a/sm1/foo6 b/sm1/foo6 index 462398b..3e75765 100644 --- a/sm1/foo6 @@ -495,7 +507,7 @@ test_expect_success 'submodule is modified' ' -foo6 +new EOF - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'modified submodule contains untracked content' ' @@ -503,7 +515,7 @@ test_expect_success 'modified submodule contains untracked content' ' git diff-index -p --submodule=diff HEAD >actual && cat >expected <<-EOF && Submodule sm1 contains untracked content - Submodule sm1 17243c9..$head8: + Submodule sm1 $head7..$head8: diff --git a/sm1/foo6 b/sm1/foo6 index 462398b..3e75765 100644 --- a/sm1/foo6 @@ -512,13 +524,13 @@ test_expect_success 'modified submodule contains untracked content' ' -foo6 +new EOF - test_cmp expected actual + diff_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: + Submodule sm1 $head7..$head8: diff --git a/sm1/foo6 b/sm1/foo6 index 462398b..3e75765 100644 --- a/sm1/foo6 @@ -527,13 +539,13 @@ test_expect_success 'modified submodule contains untracked content (untracked ig -foo6 +new EOF - test_cmp expected actual + diff_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: + Submodule sm1 $head7..$head8: diff --git a/sm1/foo6 b/sm1/foo6 index 462398b..3e75765 100644 --- a/sm1/foo6 @@ -542,7 +554,7 @@ test_expect_success 'modified submodule contains untracked content (dirty ignore -foo6 +new EOF - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'modified submodule contains untracked content (all ignored)' ' @@ -556,7 +568,7 @@ test_expect_success 'modified submodule contains untracked and modified content' cat >expected <<-EOF && Submodule sm1 contains untracked content Submodule sm1 contains modified content - Submodule sm1 17243c9..cfce562: + Submodule sm1 $head7..$head8: diff --git a/sm1/foo6 b/sm1/foo6 index 462398b..dfda541 100644 --- a/sm1/foo6 @@ -566,7 +578,7 @@ test_expect_success 'modified submodule contains untracked and modified content' +new +modification EOF - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'modified submodule contains untracked and modified content (untracked ignored)' ' @@ -574,7 +586,7 @@ test_expect_success 'modified submodule contains untracked and modified content git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual && cat >expected <<-EOF && Submodule sm1 contains modified content - Submodule sm1 17243c9..cfce562: + Submodule sm1 $head7..$head8: diff --git a/sm1/foo6 b/sm1/foo6 index 462398b..e20e2d9 100644 --- a/sm1/foo6 @@ -585,14 +597,14 @@ test_expect_success 'modified submodule contains untracked and modified content +modification +modification EOF - test_cmp expected actual + diff_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: + Submodule sm1 $head7..$head8: diff --git a/sm1/foo6 b/sm1/foo6 index 462398b..3e75765 100644 --- a/sm1/foo6 @@ -601,7 +613,7 @@ test_expect_success 'modified submodule contains untracked and modified content -foo6 +new EOF - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'modified submodule contains untracked and modified content (all ignored)' ' @@ -616,7 +628,7 @@ test_expect_success 'modified submodule contains modified content' ' git diff-index -p --submodule=diff HEAD >actual && cat >expected <<-EOF && Submodule sm1 contains modified content - Submodule sm1 17243c9..cfce562: + Submodule sm1 $head7..$head8: diff --git a/sm1/foo6 b/sm1/foo6 index 462398b..ac466ca 100644 --- a/sm1/foo6 @@ -629,29 +641,29 @@ test_expect_success 'modified submodule contains modified content' ' +modification +modification EOF - test_cmp expected actual + diff_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) + Submodule sm1 $head7...0000000 (submodule deleted) EOF - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'create second submodule' ' test_create_repo sm2 && - head7=$(add_file sm2 foo8 foo9) && + head9=$(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) + Submodule sm1 $head7...0000000 (submodule deleted) + Submodule sm2 0000000...$head9 (new submodule) diff --git a/sm2/foo8 b/sm2/foo8 new file mode 100644 index 0000000..db9916b @@ -667,13 +679,13 @@ test_expect_success 'multiple submodules' ' @@ -0,0 +1 @@ +foo9 EOF - test_cmp expected actual + diff_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) + Submodule sm2 0000000...$head9 (new submodule) diff --git a/sm2/foo8 b/sm2/foo8 new file mode 100644 index 0000000..db9916b @@ -689,15 +701,15 @@ test_expect_success 'path filter' ' @@ -0,0 +1 @@ +foo9 EOF - test_cmp expected actual + diff_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) + Submodule sm1 $head7...0000000 (submodule deleted) + Submodule sm2 0000000...$head9 (new submodule) diff --git a/sm2/foo8 b/sm2/foo8 new file mode 100644 index 0000000..db9916b @@ -713,7 +725,7 @@ test_expect_success 'given commit' ' @@ -0,0 +1 @@ +foo9 EOF - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'setup .git file for sm2' ' @@ -726,8 +738,8 @@ test_expect_success 'setup .git file for sm2' ' 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) + Submodule sm1 $head7...0000000 (submodule deleted) + Submodule sm2 0000000...$head9 (new submodule) diff --git a/sm2/foo8 b/sm2/foo8 new file mode 100644 index 0000000..db9916b @@ -743,25 +755,27 @@ test_expect_success 'diff --submodule=diff with .git file' ' @@ -0,0 +1 @@ +foo9 EOF - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'setup nested submodule' ' git submodule add -f ./sm2 && git commit -a -m "add sm2" && git -C sm2 submodule add ../sm2 nested && - git -C sm2 commit -a -m "nested sub" + git -C sm2 commit -a -m "nested sub" && + head10=$(git -C sm2 rev-parse --short --verify HEAD) ' test_expect_success 'move nested submodule HEAD' ' echo "nested content" >sm2/nested/file && git -C sm2/nested add file && - git -C sm2/nested commit --allow-empty -m "new HEAD" + git -C sm2/nested commit --allow-empty -m "new HEAD" && + head11=$(git -C sm2/nested rev-parse --short --verify HEAD) ' test_expect_success 'diff --submodule=diff with moved nested submodule HEAD' ' cat >expected <<-EOF && - Submodule nested a5a65c9..b55928c: + Submodule nested $head9..$head11: diff --git a/nested/file b/nested/file new file mode 100644 index 0000000..ca281f5 @@ -772,13 +786,13 @@ test_expect_success 'diff --submodule=diff with moved nested submodule HEAD' ' EOF git -C sm2 diff --submodule=diff >actual 2>err && test_must_be_empty err && - test_cmp expected actual + diff_cmp expected actual ' test_expect_success 'diff --submodule=diff recurses into nested submodules' ' cat >expected <<-EOF && Submodule sm2 contains modified content - Submodule sm2 a5a65c9..280969a: + Submodule sm2 $head9..$head10: diff --git a/sm2/.gitmodules b/sm2/.gitmodules new file mode 100644 index 0000000..3a816b8 @@ -788,7 +802,7 @@ test_expect_success 'diff --submodule=diff recurses into nested submodules' ' +[submodule "nested"] + path = nested + url = ../sm2 - Submodule nested 0000000...b55928c (new submodule) + Submodule nested 0000000...$head11 (new submodule) diff --git a/sm2/nested/file b/sm2/nested/file new file mode 100644 index 0000000..ca281f5 @@ -813,7 +827,7 @@ test_expect_success 'diff --submodule=diff recurses into nested submodules' ' EOF git diff --submodule=diff >actual 2>err && test_must_be_empty err && - test_cmp expected actual + diff_cmp expected actual ' test_done diff --git a/t/t4061-diff-indent.sh b/t/t4061-diff-indent.sh index 2affd7a100..0f7a6d97a8 100755 --- a/t/t4061-diff-indent.sh +++ b/t/t4061-diff-indent.sh @@ -17,7 +17,7 @@ compare_diff () { # Compare blame output using the expectation for a diff as reference. # Only look for the lines coming from non-boundary commits. compare_blame () { - sed -n -e "1,4d" -e "s/^\+//p" <"$1" >.tmp-1 + sed -n -e "1,4d" -e "s/^+//p" <"$1" >.tmp-1 sed -ne "s/^[^^][^)]*) *//p" <"$2" >.tmp-2 test_cmp .tmp-1 .tmp-2 && rm -f .tmp-1 .tmp-2 } diff --git a/t/t4066-diff-emit-delay.sh b/t/t4066-diff-emit-delay.sh index 5df6b5e64e..6331f63b12 100755 --- a/t/t4066-diff-emit-delay.sh +++ b/t/t4066-diff-emit-delay.sh @@ -18,7 +18,7 @@ test_expect_success 'set up history with a merge' ' ' test_expect_success 'log --cc -p --stat --color-moved' ' - cat >expect <<-\EOF && + cat >expect <<-EOF && commit D --- D.t | 1 + @@ -26,7 +26,7 @@ test_expect_success 'log --cc -p --stat --color-moved' ' diff --git a/D.t b/D.t new file mode 100644 - index 0000000..1784810 + index 0000000..$(git rev-parse --short D:D.t) --- /dev/null +++ b/D.t @@ -0,0 +1 @@ @@ -42,7 +42,7 @@ test_expect_success 'log --cc -p --stat --color-moved' ' diff --git a/C.t b/C.t new file mode 100644 - index 0000000..3cc58df + index 0000000..$(git rev-parse --short C:C.t) --- /dev/null +++ b/C.t @@ -0,0 +1 @@ @@ -54,7 +54,7 @@ test_expect_success 'log --cc -p --stat --color-moved' ' diff --git a/B.t b/B.t new file mode 100644 - index 0000000..223b783 + index 0000000..$(git rev-parse --short B:B.t) --- /dev/null +++ b/B.t @@ -0,0 +1 @@ @@ -66,7 +66,7 @@ test_expect_success 'log --cc -p --stat --color-moved' ' diff --git a/A.t b/A.t new file mode 100644 - index 0000000..f70f10e + index 0000000..$(git rev-parse --short A:A.t) --- /dev/null +++ b/A.t @@ -0,0 +1 @@ diff --git a/t/t4067-diff-partial-clone.sh b/t/t4067-diff-partial-clone.sh index 4831ad35e6..c1ed1c2fc4 100755 --- a/t/t4067-diff-partial-clone.sh +++ b/t/t4067-diff-partial-clone.sh @@ -131,4 +131,52 @@ test_expect_success 'diff with rename detection batches blobs' ' test_line_count = 1 done_lines ' +test_expect_success 'diff does not fetch anything if inexact rename detection is not needed' ' + test_when_finished "rm -rf server client trace" && + + test_create_repo server && + echo a >server/a && + printf "b\nb\nb\nb\nb\n" >server/b && + git -C server add a b && + git -C server commit -m x && + mv server/b server/c && + git -C server add c && + git -C server commit -a -m x && + + test_config -C server uploadpack.allowfilter 1 && + test_config -C server uploadpack.allowanysha1inwant 1 && + git clone --bare --filter=blob:limit=0 "file://$(pwd)/server" client && + + # Ensure no fetches. + GIT_TRACE_PACKET="$(pwd)/trace" git -C client diff --raw -M HEAD^ HEAD && + ! test_path_exists trace +' + +test_expect_success 'diff --break-rewrites fetches only if necessary, and batches blobs if it does' ' + test_when_finished "rm -rf server client trace" && + + test_create_repo server && + echo a >server/a && + printf "b\nb\nb\nb\nb\n" >server/b && + git -C server add a b && + git -C server commit -m x && + printf "c\nc\nc\nc\nc\n" >server/b && + git -C server commit -a -m x && + + test_config -C server uploadpack.allowfilter 1 && + test_config -C server uploadpack.allowanysha1inwant 1 && + git clone --bare --filter=blob:limit=0 "file://$(pwd)/server" client && + + # Ensure no fetches. + GIT_TRACE_PACKET="$(pwd)/trace" git -C client diff --raw -M HEAD^ HEAD && + ! test_path_exists trace && + + # But with --break-rewrites, ensure that there is exactly 1 negotiation + # by checking that there is only 1 "done" line sent. ("done" marks the + # end of negotiation.) + GIT_TRACE_PACKET="$(pwd)/trace" git -C client diff --break-rewrites --raw -M HEAD^ HEAD && + grep "git> done" trace >done_lines && + test_line_count = 1 done_lines +' + test_done diff --git a/t/t4117-apply-reject.sh b/t/t4117-apply-reject.sh index f7de6f077a..0ee93fe845 100755 --- a/t/t4117-apply-reject.sh +++ b/t/t4117-apply-reject.sh @@ -74,7 +74,7 @@ test_expect_success 'apply with --reject should fail but update the file' ' test_must_fail git apply --reject patch.1 && test_cmp expected file1 && - cat file1.rej && + test_path_is_file file1.rej && test_path_is_missing file2.rej ' @@ -87,7 +87,7 @@ test_expect_success 'apply with --reject should fail but update the file' ' test_path_is_missing file1 && test_cmp expected file2 && - cat file2.rej && + test_path_is_file file2.rej && test_path_is_missing file1.rej ' @@ -101,7 +101,7 @@ test_expect_success 'the same test with --verbose' ' test_path_is_missing file1 && test_cmp expected file2 && - cat file2.rej && + test_path_is_file file2.rej && test_path_is_missing file1.rej ' diff --git a/t/t4124-apply-ws-rule.sh b/t/t4124-apply-ws-rule.sh index ff51e9e789..0ca29821ec 100755 --- a/t/t4124-apply-ws-rule.sh +++ b/t/t4124-apply-ws-rule.sh @@ -35,9 +35,15 @@ prepare_test_file () { } apply_patch () { + cmd_prefix= && + if test "x$1" = 'x!' + then + cmd_prefix=test_must_fail && + shift + fi && >target && sed -e "s|\([ab]\)/file|\1/target|" <patch | - git apply "$@" + $cmd_prefix git apply "$@" } test_fix () { @@ -46,6 +52,13 @@ test_fix () { # find touched lines $DIFF file target | sed -n -e "s/^> //p" >fixed + # busybox's diff(1) doesn't output normal format + if ! test -s fixed + then + $DIFF -u file target | + grep -v '^+++ target' | + sed -ne "/^+/s/+//p" >fixed + fi # the changed lines are all expected to change fixed_cnt=$(wc -l <fixed) @@ -99,7 +112,7 @@ test_expect_success 'whitespace=warn, default rule' ' test_expect_success 'whitespace=error-all, default rule' ' - test_must_fail apply_patch --whitespace=error-all && + apply_patch ! --whitespace=error-all && test_must_be_empty target ' diff --git a/t/t4134-apply-submodule.sh b/t/t4134-apply-submodule.sh index 0043930ca6..99ed4cc546 100755 --- a/t/t4134-apply-submodule.sh +++ b/t/t4134-apply-submodule.sh @@ -8,6 +8,7 @@ test_description='git apply submodule tests' . ./test-lib.sh test_expect_success setup ' + test_oid_init && cat > create-sm.patch <<EOF && diff --git a/dir/sm b/dir/sm new file mode 160000 @@ -15,7 +16,7 @@ index 0000000..0123456 --- /dev/null +++ b/dir/sm @@ -0,0 +1 @@ -+Subproject commit 0123456789abcdef0123456789abcdef01234567 ++Subproject commit $(test_oid numeric) EOF cat > remove-sm.patch <<EOF diff --git a/dir/sm b/dir/sm @@ -24,7 +25,7 @@ index 0123456..0000000 --- a/dir/sm +++ /dev/null @@ -1 +0,0 @@ --Subproject commit 0123456789abcdef0123456789abcdef01234567 +-Subproject commit $(test_oid numeric) EOF ' diff --git a/t/t4150-am.sh b/t/t4150-am.sh index 4f1e24ecbe..bda4586a79 100755 --- a/t/t4150-am.sh +++ b/t/t4150-am.sh @@ -166,7 +166,7 @@ test_expect_success setup ' test_tick && git commit -m third && - git format-patch --stdout first >patch2 && + git format-patch --stdout first >patch2 && git checkout -b lorem && sed -n -e "11,\$p" msg >file && @@ -666,6 +666,26 @@ test_expect_success 'am --show-current-patch' ' test_cmp .git/rebase-apply/0001 actual.patch ' +test_expect_success 'am --show-current-patch=raw' ' + git am --show-current-patch=raw >actual.patch && + test_cmp .git/rebase-apply/0001 actual.patch +' + +test_expect_success 'am --show-current-patch=diff' ' + git am --show-current-patch=diff >actual.patch && + test_cmp .git/rebase-apply/patch actual.patch +' + +test_expect_success 'am accepts repeated --show-current-patch' ' + git am --show-current-patch --show-current-patch=raw >actual.patch && + test_cmp .git/rebase-apply/0001 actual.patch +' + +test_expect_success 'am detects incompatible --show-current-patch' ' + test_must_fail git am --show-current-patch=raw --show-current-patch=diff && + test_must_fail git am --show-current-patch --show-current-patch=diff +' + test_expect_success 'am --skip works' ' echo goodbye >expected && git am --skip && diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh index 55b7750ade..831d424c47 100755 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@ -25,6 +25,7 @@ test_description='git rerere . ./test-lib.sh test_expect_success 'setup' ' + test_oid_init && cat >a1 <<-\EOF && Some title ========== @@ -210,7 +211,7 @@ test_expect_success 'set up for garbage collection tests' ' echo Hello >$rr/preimage && echo World >$rr/postimage && - sha2=4000000000000000000000000000000000000000 && + sha2=$(test_oid deadbeef) && rr2=.git/rr-cache/$sha2 && mkdir $rr2 && echo Hello >$rr2/preimage && diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 2c9489484a..f1ea7d97f5 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -5,6 +5,11 @@ test_description='git log' . ./test-lib.sh . "$TEST_DIRECTORY/lib-gpg.sh" . "$TEST_DIRECTORY/lib-terminal.sh" +. "$TEST_DIRECTORY/lib-log-graph.sh" + +test_cmp_graph () { + lib_test_cmp_graph --format=%s "$@" +} test_expect_success setup ' @@ -87,12 +92,12 @@ test_expect_success 'format %w(,1,2)' ' ' cat > expect << EOF -804a787 sixth -394ef78 fifth -5d31159 fourth -2fbe8c0 third -f7dab8e second -3a2fdcb initial +$(git rev-parse --short :/sixth ) sixth +$(git rev-parse --short :/fifth ) fifth +$(git rev-parse --short :/fourth ) fourth +$(git rev-parse --short :/third ) third +$(git rev-parse --short :/second ) second +$(git rev-parse --short :/initial) initial EOF test_expect_success 'oneline' ' @@ -173,43 +178,45 @@ test_expect_success 'git config log.follow is overridden by --no-follow' ' verbose test "$actual" = "$expect" ' +# Note that these commits are intentionally listed out of order. +last_three="$(git rev-parse :/fourth :/sixth :/fifth)" cat > expect << EOF -804a787 sixth -394ef78 fifth -5d31159 fourth +$(git rev-parse --short :/sixth ) sixth +$(git rev-parse --short :/fifth ) fifth +$(git rev-parse --short :/fourth) fourth EOF test_expect_success 'git log --no-walk <commits> sorts by commit time' ' - git log --no-walk --oneline 5d31159 804a787 394ef78 > actual && + git log --no-walk --oneline $last_three > actual && test_cmp expect actual ' test_expect_success 'git log --no-walk=sorted <commits> sorts by commit time' ' - git log --no-walk=sorted --oneline 5d31159 804a787 394ef78 > actual && + git log --no-walk=sorted --oneline $last_three > actual && test_cmp expect actual ' cat > expect << EOF -=== 804a787 sixth -=== 394ef78 fifth -=== 5d31159 fourth +=== $(git rev-parse --short :/sixth ) sixth +=== $(git rev-parse --short :/fifth ) fifth +=== $(git rev-parse --short :/fourth) 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 && + git log --line-prefix="=== " --no-walk --oneline $last_three > actual && test_cmp expect actual ' cat > expect << EOF -5d31159 fourth -804a787 sixth -394ef78 fifth +$(git rev-parse --short :/fourth) fourth +$(git rev-parse --short :/sixth ) sixth +$(git rev-parse --short :/fifth ) fifth EOF test_expect_success 'git log --no-walk=unsorted <commits> leaves list of commits as given' ' - git log --no-walk=unsorted --oneline 5d31159 804a787 394ef78 > actual && + git log --no-walk=unsorted --oneline $last_three > actual && test_cmp expect actual ' test_expect_success 'git show <commits> leaves list of commits as given' ' - git show --oneline -s 5d31159 804a787 394ef78 > actual && + git show --oneline -s $last_three > actual && test_cmp expect actual ' @@ -450,8 +457,7 @@ cat > expect <<EOF EOF test_expect_success 'simple log --graph' ' - git log --graph --pretty=tformat:%s >actual && - test_cmp expect actual + test_cmp_graph ' cat > expect <<EOF @@ -465,8 +471,7 @@ cat > expect <<EOF 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_cmp_graph --line-prefix="123 " ' test_expect_success 'set up merge history' ' @@ -493,9 +498,7 @@ cat > expect <<\EOF EOF test_expect_success 'log --graph with merge' ' - git log --graph --date-order --pretty=tformat:%s | - sed "s/ *\$//" >actual && - test_cmp expect actual + test_cmp_graph --date-order ' cat > expect <<\EOF @@ -514,9 +517,7 @@ cat > expect <<\EOF 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_cmp_graph --line-prefix="| | | " --date-order ' cat > expect.colors <<\EOF @@ -536,9 +537,7 @@ EOF test_expect_success 'log --graph with merge with log.graphColors' ' test_config log.graphColors " blue,invalid-color, cyan, red , " && - git log --color=always --graph --date-order --pretty=tformat:%s | - test_decode_color | sed "s/ *\$//" >actual && - test_cmp expect.colors actual + lib_test_cmp_colored_graph --date-order --format=%s ' test_expect_success 'log --raw --graph -m with merge' ' @@ -674,9 +673,7 @@ cat > expect <<\EOF EOF test_expect_success 'log --graph with merge' ' - git log --graph --date-order --pretty=tformat:%s | - sed "s/ *\$//" >actual && - test_cmp expect actual + test_cmp_graph --date-order ' test_expect_success 'log.decorate configuration' ' @@ -745,7 +742,23 @@ test_expect_success 'decorate-refs with glob' ' octopus-a (octopus-a) reach EOF + cat >expect.no-decorate <<-\EOF && + Merge-tag-reach + Merge-tags-octopus-a-and-octopus-b + seventh + octopus-b + octopus-a + reach + EOF + git log -n6 --decorate=short --pretty="tformat:%f%d" \ + --decorate-refs="heads/octopus*" >actual && + test_cmp expect.decorate actual && git log -n6 --decorate=short --pretty="tformat:%f%d" \ + --decorate-refs-exclude="heads/octopus*" \ + --decorate-refs="heads/octopus*" >actual && + test_cmp expect.no-decorate actual && + git -c log.excludeDecoration="heads/octopus*" log \ + -n6 --decorate=short --pretty="tformat:%f%d" \ --decorate-refs="heads/octopus*" >actual && test_cmp expect.decorate actual ' @@ -790,6 +803,9 @@ test_expect_success 'decorate-refs-exclude with glob' ' EOF git log -n6 --decorate=short --pretty="tformat:%f%d" \ --decorate-refs-exclude="heads/octopus*" >actual && + test_cmp expect.decorate actual && + git -c log.excludeDecoration="heads/octopus*" log \ + -n6 --decorate=short --pretty="tformat:%f%d" >actual && test_cmp expect.decorate actual ' @@ -804,6 +820,9 @@ test_expect_success 'decorate-refs-exclude without globs' ' EOF git log -n6 --decorate=short --pretty="tformat:%f%d" \ --decorate-refs-exclude="tags/reach" >actual && + test_cmp expect.decorate actual && + git -c log.excludeDecoration="tags/reach" log \ + -n6 --decorate=short --pretty="tformat:%f%d" >actual && test_cmp expect.decorate actual ' @@ -819,11 +838,19 @@ test_expect_success 'multiple decorate-refs-exclude' ' git log -n6 --decorate=short --pretty="tformat:%f%d" \ --decorate-refs-exclude="heads/octopus*" \ --decorate-refs-exclude="tags/reach" >actual && + test_cmp expect.decorate actual && + git -c log.excludeDecoration="heads/octopus*" \ + -c log.excludeDecoration="tags/reach" log \ + -n6 --decorate=short --pretty="tformat:%f%d" >actual && + test_cmp expect.decorate actual && + git -c log.excludeDecoration="heads/octopus*" log \ + --decorate-refs-exclude="tags/reach" \ + -n6 --decorate=short --pretty="tformat:%f%d" >actual && test_cmp expect.decorate actual ' test_expect_success 'decorate-refs and decorate-refs-exclude' ' - cat >expect.decorate <<-\EOF && + cat >expect.no-decorate <<-\EOF && Merge-tag-reach (master) Merge-tags-octopus-a-and-octopus-b seventh @@ -834,6 +861,21 @@ test_expect_success 'decorate-refs and decorate-refs-exclude' ' git log -n6 --decorate=short --pretty="tformat:%f%d" \ --decorate-refs="heads/*" \ --decorate-refs-exclude="heads/oc*" >actual && + test_cmp expect.no-decorate actual +' + +test_expect_success 'deocrate-refs and log.excludeDecoration' ' + cat >expect.decorate <<-\EOF && + Merge-tag-reach (master) + Merge-tags-octopus-a-and-octopus-b + seventh + octopus-b (octopus-b) + octopus-a (octopus-a) + reach (reach) + EOF + git -c log.excludeDecoration="heads/oc*" log \ + --decorate-refs="heads/*" \ + -n6 --decorate=short --pretty="tformat:%f%d" >actual && test_cmp expect.decorate actual ' @@ -849,6 +891,10 @@ test_expect_success 'decorate-refs-exclude and simplify-by-decoration' ' git log -n6 --decorate=short --pretty="tformat:%f%d" \ --decorate-refs-exclude="*octopus*" \ --simplify-by-decoration >actual && + test_cmp expect.decorate actual && + git -c log.excludeDecoration="*octopus*" log \ + -n6 --decorate=short --pretty="tformat:%f%d" \ + --simplify-by-decoration >actual && test_cmp expect.decorate actual ' @@ -957,7 +1003,7 @@ cat >expect <<\EOF | | | | diff --git a/reach.t b/reach.t | | new file mode 100644 -| | index 0000000..10c9591 +| | index BEFORE..AFTER | | --- /dev/null | | +++ b/reach.t | | @@ -0,0 +1 @@ @@ -980,7 +1026,7 @@ cat >expect <<\EOF | | | | | | diff --git a/octopus-b.t b/octopus-b.t | | | new file mode 100644 -| | | index 0000000..d5fcad0 +| | | index BEFORE..AFTER | | | --- /dev/null | | | +++ b/octopus-b.t | | | @@ -0,0 +1 @@ @@ -996,7 +1042,7 @@ cat >expect <<\EOF | | | | diff --git a/octopus-a.t b/octopus-a.t | | new file mode 100644 -| | index 0000000..11ee015 +| | index BEFORE..AFTER | | --- /dev/null | | +++ b/octopus-a.t | | @@ -0,0 +1 @@ @@ -1012,7 +1058,7 @@ cat >expect <<\EOF | | diff --git a/seventh.t b/seventh.t | new file mode 100644 -| index 0000000..9744ffc +| index BEFORE..AFTER | --- /dev/null | +++ b/seventh.t | @@ -0,0 +1 @@ @@ -1046,7 +1092,7 @@ cat >expect <<\EOF | | | | | | | | diff --git a/tangle-a b/tangle-a | | | | new file mode 100644 -| | | | index 0000000..7898192 +| | | | index BEFORE..AFTER | | | | --- /dev/null | | | | +++ b/tangle-a | | | | @@ -0,0 +1 @@ @@ -1068,7 +1114,7 @@ cat >expect <<\EOF | | | | | | | | diff --git a/2 b/2 | | | | new file mode 100644 -| | | | index 0000000..0cfbf08 +| | | | index BEFORE..AFTER | | | | --- /dev/null | | | | +++ b/2 | | | | @@ -0,0 +1 @@ @@ -1084,7 +1130,7 @@ cat >expect <<\EOF | | | | | | | | diff --git a/1 b/1 | | | | new file mode 100644 -| | | | index 0000000..d00491f +| | | | index BEFORE..AFTER | | | | --- /dev/null | | | | +++ b/1 | | | | @@ -0,0 +1 @@ @@ -1100,7 +1146,7 @@ cat >expect <<\EOF | | | | | | | | diff --git a/one b/one | | | | new file mode 100644 -| | | | index 0000000..9a33383 +| | | | index BEFORE..AFTER | | | | --- /dev/null | | | | +++ b/one | | | | @@ -0,0 +1 @@ @@ -1116,7 +1162,7 @@ cat >expect <<\EOF | | | | | | diff --git a/a/two b/a/two | | | deleted file mode 100644 -| | | index 9245af5..0000000 +| | | index BEFORE..AFTER | | | --- a/a/two | | | +++ /dev/null | | | @@ -1 +0,0 @@ @@ -1132,7 +1178,7 @@ cat >expect <<\EOF | | | | | | diff --git a/a/two b/a/two | | | new file mode 100644 -| | | index 0000000..9245af5 +| | | index BEFORE..AFTER | | | --- /dev/null | | | +++ b/a/two | | | @@ -0,0 +1 @@ @@ -1148,7 +1194,7 @@ cat >expect <<\EOF | | | | diff --git a/ein b/ein | | new file mode 100644 -| | index 0000000..9d7e69f +| | index BEFORE..AFTER | | --- /dev/null | | +++ b/ein | | @@ -0,0 +1 @@ @@ -1165,14 +1211,14 @@ cat >expect <<\EOF | | diff --git a/ichi b/ichi | new file mode 100644 -| index 0000000..9d7e69f +| index BEFORE..AFTER | --- /dev/null | +++ b/ichi | @@ -0,0 +1 @@ | +ichi | diff --git a/one b/one | deleted file mode 100644 -| index 9d7e69f..0000000 +| index BEFORE..AFTER | --- a/one | +++ /dev/null | @@ -1 +0,0 @@ @@ -1187,7 +1233,7 @@ cat >expect <<\EOF | 1 file changed, 1 insertion(+), 1 deletion(-) | | diff --git a/one b/one -| index 5626abf..9d7e69f 100644 +| index BEFORE..AFTER 100644 | --- a/one | +++ b/one | @@ -1 +1 @@ @@ -1204,30 +1250,15 @@ cat >expect <<\EOF diff --git a/one b/one new file mode 100644 - index 0000000..5626abf + index BEFORE..AFTER --- /dev/null +++ b/one @@ -0,0 +1 @@ +one EOF -sanitize_output () { - sed -e 's/ *$//' \ - -e 's/commit [0-9a-f]*$/commit COMMIT_OBJECT_NAME/' \ - -e 's/Merge: [ 0-9a-f]*$/Merge: MERGE_PARENTS/' \ - -e 's/Merge tag.*/Merge HEADS DESCRIPTION/' \ - -e 's/Merge commit.*/Merge HEADS DESCRIPTION/' \ - -e 's/, 0 deletions(-)//' \ - -e 's/, 0 insertions(+)//' \ - -e 's/ 1 files changed, / 1 file changed, /' \ - -e 's/, 1 deletions(-)/, 1 deletion(-)/' \ - -e 's/, 1 insertions(+)/, 1 insertion(+)/' -} - test_expect_success 'log --graph with diff and stats' ' - git log --no-renames --graph --pretty=short --stat -p >actual && - sanitize_output >actual.sanitized <actual && - test_i18ncmp expect actual.sanitized + lib_test_cmp_short_graph --no-renames --stat -p ' cat >expect <<\EOF @@ -1247,7 +1278,7 @@ cat >expect <<\EOF *** | | *** | | diff --git a/reach.t b/reach.t *** | | new file mode 100644 -*** | | index 0000000..10c9591 +*** | | index BEFORE..AFTER *** | | --- /dev/null *** | | +++ b/reach.t *** | | @@ -0,0 +1 @@ @@ -1270,7 +1301,7 @@ cat >expect <<\EOF *** | | | *** | | | diff --git a/octopus-b.t b/octopus-b.t *** | | | new file mode 100644 -*** | | | index 0000000..d5fcad0 +*** | | | index BEFORE..AFTER *** | | | --- /dev/null *** | | | +++ b/octopus-b.t *** | | | @@ -0,0 +1 @@ @@ -1286,7 +1317,7 @@ cat >expect <<\EOF *** | | *** | | diff --git a/octopus-a.t b/octopus-a.t *** | | new file mode 100644 -*** | | index 0000000..11ee015 +*** | | index BEFORE..AFTER *** | | --- /dev/null *** | | +++ b/octopus-a.t *** | | @@ -0,0 +1 @@ @@ -1302,7 +1333,7 @@ cat >expect <<\EOF *** | *** | diff --git a/seventh.t b/seventh.t *** | new file mode 100644 -*** | index 0000000..9744ffc +*** | index BEFORE..AFTER *** | --- /dev/null *** | +++ b/seventh.t *** | @@ -0,0 +1 @@ @@ -1336,7 +1367,7 @@ cat >expect <<\EOF *** | | | | *** | | | | diff --git a/tangle-a b/tangle-a *** | | | | new file mode 100644 -*** | | | | index 0000000..7898192 +*** | | | | index BEFORE..AFTER *** | | | | --- /dev/null *** | | | | +++ b/tangle-a *** | | | | @@ -0,0 +1 @@ @@ -1358,7 +1389,7 @@ cat >expect <<\EOF *** | | | | *** | | | | diff --git a/2 b/2 *** | | | | new file mode 100644 -*** | | | | index 0000000..0cfbf08 +*** | | | | index BEFORE..AFTER *** | | | | --- /dev/null *** | | | | +++ b/2 *** | | | | @@ -0,0 +1 @@ @@ -1374,7 +1405,7 @@ cat >expect <<\EOF *** | | | | *** | | | | diff --git a/1 b/1 *** | | | | new file mode 100644 -*** | | | | index 0000000..d00491f +*** | | | | index BEFORE..AFTER *** | | | | --- /dev/null *** | | | | +++ b/1 *** | | | | @@ -0,0 +1 @@ @@ -1390,7 +1421,7 @@ cat >expect <<\EOF *** | | | | *** | | | | diff --git a/one b/one *** | | | | new file mode 100644 -*** | | | | index 0000000..9a33383 +*** | | | | index BEFORE..AFTER *** | | | | --- /dev/null *** | | | | +++ b/one *** | | | | @@ -0,0 +1 @@ @@ -1406,7 +1437,7 @@ cat >expect <<\EOF *** | | | *** | | | diff --git a/a/two b/a/two *** | | | deleted file mode 100644 -*** | | | index 9245af5..0000000 +*** | | | index BEFORE..AFTER *** | | | --- a/a/two *** | | | +++ /dev/null *** | | | @@ -1 +0,0 @@ @@ -1422,7 +1453,7 @@ cat >expect <<\EOF *** | | | *** | | | diff --git a/a/two b/a/two *** | | | new file mode 100644 -*** | | | index 0000000..9245af5 +*** | | | index BEFORE..AFTER *** | | | --- /dev/null *** | | | +++ b/a/two *** | | | @@ -0,0 +1 @@ @@ -1438,7 +1469,7 @@ cat >expect <<\EOF *** | | *** | | diff --git a/ein b/ein *** | | new file mode 100644 -*** | | index 0000000..9d7e69f +*** | | index BEFORE..AFTER *** | | --- /dev/null *** | | +++ b/ein *** | | @@ -0,0 +1 @@ @@ -1455,14 +1486,14 @@ cat >expect <<\EOF *** | *** | diff --git a/ichi b/ichi *** | new file mode 100644 -*** | index 0000000..9d7e69f +*** | index BEFORE..AFTER *** | --- /dev/null *** | +++ b/ichi *** | @@ -0,0 +1 @@ *** | +ichi *** | diff --git a/one b/one *** | deleted file mode 100644 -*** | index 9d7e69f..0000000 +*** | index BEFORE..AFTER *** | --- a/one *** | +++ /dev/null *** | @@ -1 +0,0 @@ @@ -1477,7 +1508,7 @@ cat >expect <<\EOF *** | 1 file changed, 1 insertion(+), 1 deletion(-) *** | *** | diff --git a/one b/one -*** | index 5626abf..9d7e69f 100644 +*** | index BEFORE..AFTER 100644 *** | --- a/one *** | +++ b/one *** | @@ -1 +1 @@ @@ -1494,7 +1525,7 @@ cat >expect <<\EOF *** *** diff --git a/one b/one *** new file mode 100644 -*** index 0000000..5626abf +*** index BEFORE..AFTER *** --- /dev/null *** +++ b/one *** @@ -0,0 +1 @@ @@ -1502,9 +1533,7 @@ cat >expect <<\EOF 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 + lib_test_cmp_short_graph --line-prefix="*** " --no-renames --stat -p ' cat >expect <<-\EOF @@ -1526,9 +1555,7 @@ cat >expect <<-\EOF EOF test_expect_success 'log --graph with --name-status' ' - git log --graph --format=%s --name-status tangle..reach >actual && - sanitize_output <actual >actual.sanitized && - test_cmp expect actual.sanitized + test_cmp_graph --name-status tangle..reach ' cat >expect <<-\EOF @@ -1550,9 +1577,7 @@ cat >expect <<-\EOF EOF test_expect_success 'log --graph with --name-only' ' - git log --graph --format=%s --name-only tangle..reach >actual && - sanitize_output <actual >actual.sanitized && - test_cmp expect actual.sanitized + test_cmp_graph --name-only tangle..reach ' test_expect_success 'dotdot is a parent directory' ' @@ -1631,6 +1656,86 @@ test_expect_success GPG 'log --graph --show-signature for merged tag' ' grep "^| | gpg: Good signature" actual ' +test_expect_success GPG 'log --graph --show-signature for merged tag in shallow clone' ' + test_when_finished "git reset --hard && git checkout master" && + git checkout -b plain-shallow master && + echo aaa >bar && + git add bar && + git commit -m bar_commit && + git checkout --detach master && + echo bbb >baz && + git add baz && + git commit -m baz_commit && + git tag -s -m signed_tag_msg signed_tag_shallow && + hash=$(git rev-parse HEAD) && + git checkout plain-shallow && + git merge --no-ff -m msg signed_tag_shallow && + git clone --depth 1 --no-local . shallow && + test_when_finished "rm -rf shallow" && + git -C shallow log --graph --show-signature -n1 plain-shallow >actual && + grep "tag signed_tag_shallow names a non-parent $hash" actual +' + +test_expect_success GPG 'log --graph --show-signature for merged tag with missing key' ' + test_when_finished "git reset --hard && git checkout master" && + git checkout -b plain-nokey master && + echo aaa >bar && + git add bar && + git commit -m bar_commit && + git checkout -b tagged-nokey master && + echo bbb >baz && + git add baz && + git commit -m baz_commit && + git tag -s -m signed_tag_msg signed_tag_nokey && + git checkout plain-nokey && + git merge --no-ff -m msg signed_tag_nokey && + GNUPGHOME=. git log --graph --show-signature -n1 plain-nokey >actual && + grep "^|\\\ merged tag" actual && + grep "^| | gpg: Signature made" actual && + grep "^| | gpg: Can'"'"'t check signature: \(public key not found\|No public key\)" actual +' + +test_expect_success GPG 'log --graph --show-signature for merged tag with bad signature' ' + test_when_finished "git reset --hard && git checkout master" && + git checkout -b plain-bad master && + echo aaa >bar && + git add bar && + git commit -m bar_commit && + git checkout -b tagged-bad master && + echo bbb >baz && + git add baz && + git commit -m baz_commit && + git tag -s -m signed_tag_msg signed_tag_bad && + git cat-file tag signed_tag_bad >raw && + sed -e "s/signed_tag_msg/forged/" raw >forged && + git hash-object -w -t tag forged >forged.tag && + git checkout plain-bad && + git merge --no-ff -m msg "$(cat forged.tag)" && + git log --graph --show-signature -n1 plain-bad >actual && + grep "^|\\\ merged tag" actual && + grep "^| | gpg: Signature made" actual && + grep "^| | gpg: BAD signature from" actual +' + +test_expect_success GPG 'log --show-signature for merged tag with GPG failure' ' + test_when_finished "git reset --hard && git checkout master" && + git checkout -b plain-fail master && + echo aaa >bar && + git add bar && + git commit -m bar_commit && + git checkout -b tagged-fail master && + echo bbb >baz && + git add baz && + git commit -m baz_commit && + git tag -s -m signed_tag_msg signed_tag_fail && + git checkout plain-fail && + git merge --no-ff -m msg signed_tag_fail && + TMPDIR="$(pwd)/bogus" git log --show-signature -n1 plain-fail >actual && + grep "^merged tag" actual && + grep "^No signature" actual && + ! grep "^gpg: Signature made" actual +' + test_expect_success GPGSM 'log --graph --show-signature for merged tag x509' ' test_when_finished "git reset --hard && git checkout master" && test_config gpg.format x509 && @@ -1652,6 +1757,51 @@ test_expect_success GPGSM 'log --graph --show-signature for merged tag x509' ' grep "^| | gpgsm: Good signature" actual ' +test_expect_success GPGSM 'log --graph --show-signature for merged tag x509 missing key' ' + test_when_finished "git reset --hard && git checkout master" && + test_config gpg.format x509 && + test_config user.signingkey $GIT_COMMITTER_EMAIL && + git checkout -b plain-x509-nokey master && + echo aaa >bar && + git add bar && + git commit -m bar_commit && + git checkout -b tagged-x509-nokey master && + echo bbb >baz && + git add baz && + git commit -m baz_commit && + git tag -s -m signed_tag_msg signed_tag_x509_nokey && + git checkout plain-x509-nokey && + git merge --no-ff -m msg signed_tag_x509_nokey && + GNUPGHOME=. git log --graph --show-signature -n1 plain-x509-nokey >actual && + grep "^|\\\ merged tag" actual && + grep "^| | gpgsm: certificate not found" actual +' + +test_expect_success GPGSM 'log --graph --show-signature for merged tag x509 bad signature' ' + test_when_finished "git reset --hard && git checkout master" && + test_config gpg.format x509 && + test_config user.signingkey $GIT_COMMITTER_EMAIL && + git checkout -b plain-x509-bad master && + echo aaa >bar && + git add bar && + git commit -m bar_commit && + git checkout -b tagged-x509-bad master && + echo bbb >baz && + git add baz && + git commit -m baz_commit && + git tag -s -m signed_tag_msg signed_tag_x509_bad && + git cat-file tag signed_tag_x509_bad >raw && + sed -e "s/signed_tag_msg/forged/" raw >forged && + git hash-object -w -t tag forged >forged.tag && + git checkout plain-x509-bad && + git merge --no-ff -m msg "$(cat forged.tag)" && + git log --graph --show-signature -n1 plain-x509-bad >actual && + grep "^|\\\ merged tag" actual && + grep "^| | gpgsm: Signature made" actual && + grep "^| | gpgsm: invalid 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 @@ -1709,10 +1859,10 @@ test_expect_success 'set up --source tests' ' ' test_expect_success 'log --source paints branch names' ' - cat >expect <<-\EOF && - 09e12a9 source-b three - 8e393e1 source-a two - 1ac6c77 source-b one + cat >expect <<-EOF && + $(git rev-parse --short :/three) source-b three + $(git rev-parse --short :/two ) source-a two + $(git rev-parse --short :/one ) source-b one EOF git log --oneline --source source-a source-b >actual && test_cmp expect actual @@ -1720,19 +1870,19 @@ test_expect_success 'log --source paints branch names' ' test_expect_success 'log --source paints tag names' ' git tag -m tagged source-tag && - cat >expect <<-\EOF && - 09e12a9 source-tag three - 8e393e1 source-a two - 1ac6c77 source-tag one + cat >expect <<-EOF && + $(git rev-parse --short :/three) source-tag three + $(git rev-parse --short :/two ) source-a two + $(git rev-parse --short :/one ) source-tag one EOF git log --oneline --source source-tag source-a >actual && test_cmp expect actual ' test_expect_success 'log --source paints symmetric ranges' ' - cat >expect <<-\EOF && - 09e12a9 source-b three - 8e393e1 source-a two + cat >expect <<-EOF && + $(git rev-parse --short :/three) source-b three + $(git rev-parse --short :/two ) source-a two EOF git log --oneline --source source-a...source-b >actual && test_cmp expect actual diff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh index 0288c17ec6..8ff8bd84c7 100755 --- a/t/t4204-patch-id.sh +++ b/t/t4204-patch-id.sh @@ -25,7 +25,7 @@ test_expect_success 'setup' ' test_expect_success 'patch-id output is well-formed' ' git log -p -1 | git patch-id >output && - grep "^[a-f0-9]\{40\} $(git rev-parse HEAD)$" output + grep "^$OID_REGEX $(git rev-parse HEAD)$" output ' #calculate patch id. Make sure output is not empty. diff --git a/t/t4208-log-magic-pathspec.sh b/t/t4208-log-magic-pathspec.sh index 4c8f3b8e1b..6cdbe4747a 100755 --- a/t/t4208-log-magic-pathspec.sh +++ b/t/t4208-log-magic-pathspec.sh @@ -55,6 +55,10 @@ test_expect_success '"git log -- :/a" should not be ambiguous' ' git log -- :/a ' +test_expect_success '"git log :/any/path/" should not segfault' ' + test_must_fail git log :/any/path/ +' + # This differs from the ":/a" check above in that :/in looks like a pathspec, # but doesn't match an actual file. test_expect_success '"git log :/in" should not be ambiguous' ' diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh index 8319163744..cda58186c2 100755 --- a/t/t4211-line-log.sh +++ b/t/t4211-line-log.sh @@ -4,6 +4,7 @@ test_description='test log -L' . ./test-lib.sh test_expect_success 'setup (import history)' ' + test_oid_init && git fast-import < "$TEST_DIRECTORY"/t4211/history.export && git reset --hard ' @@ -11,7 +12,7 @@ test_expect_success 'setup (import history)' ' canned_test_1 () { test_expect_$1 "$2" " git log $2 >actual && - test_cmp \"\$TEST_DIRECTORY\"/t4211/expect.$3 actual + test_cmp \"\$TEST_DIRECTORY\"/t4211/$(test_oid algo)/expect.$3 actual " } diff --git a/t/t4211/expect.beginning-of-file b/t/t4211/sha1/expect.beginning-of-file index 91b4054898..91b4054898 100644 --- a/t/t4211/expect.beginning-of-file +++ b/t/t4211/sha1/expect.beginning-of-file diff --git a/t/t4211/expect.end-of-file b/t/t4211/sha1/expect.end-of-file index bd25bb2f59..bd25bb2f59 100644 --- a/t/t4211/expect.end-of-file +++ b/t/t4211/sha1/expect.end-of-file diff --git a/t/t4211/expect.move-support-f b/t/t4211/sha1/expect.move-support-f index c905e01bc2..c905e01bc2 100644 --- a/t/t4211/expect.move-support-f +++ b/t/t4211/sha1/expect.move-support-f diff --git a/t/t4211/expect.multiple b/t/t4211/sha1/expect.multiple index 76ad5b598c..76ad5b598c 100644 --- a/t/t4211/expect.multiple +++ b/t/t4211/sha1/expect.multiple diff --git a/t/t4211/expect.multiple-overlapping b/t/t4211/sha1/expect.multiple-overlapping index d930b6eec4..d930b6eec4 100644 --- a/t/t4211/expect.multiple-overlapping +++ b/t/t4211/sha1/expect.multiple-overlapping diff --git a/t/t4211/expect.multiple-superset b/t/t4211/sha1/expect.multiple-superset index d930b6eec4..d930b6eec4 100644 --- a/t/t4211/expect.multiple-superset +++ b/t/t4211/sha1/expect.multiple-superset diff --git a/t/t4211/expect.parallel-change-f-to-main b/t/t4211/sha1/expect.parallel-change-f-to-main index 052def8074..052def8074 100644 --- a/t/t4211/expect.parallel-change-f-to-main +++ b/t/t4211/sha1/expect.parallel-change-f-to-main diff --git a/t/t4211/expect.simple-f b/t/t4211/sha1/expect.simple-f index a1f5bc49c8..a1f5bc49c8 100644 --- a/t/t4211/expect.simple-f +++ b/t/t4211/sha1/expect.simple-f diff --git a/t/t4211/expect.simple-f-to-main b/t/t4211/sha1/expect.simple-f-to-main index a475768710..a475768710 100644 --- a/t/t4211/expect.simple-f-to-main +++ b/t/t4211/sha1/expect.simple-f-to-main diff --git a/t/t4211/expect.simple-main b/t/t4211/sha1/expect.simple-main index 39ce39bebe..39ce39bebe 100644 --- a/t/t4211/expect.simple-main +++ b/t/t4211/sha1/expect.simple-main diff --git a/t/t4211/expect.simple-main-to-end b/t/t4211/sha1/expect.simple-main-to-end index 8480bd9cc4..8480bd9cc4 100644 --- a/t/t4211/expect.simple-main-to-end +++ b/t/t4211/sha1/expect.simple-main-to-end diff --git a/t/t4211/expect.two-ranges b/t/t4211/sha1/expect.two-ranges index 6109aa0dce..6109aa0dce 100644 --- a/t/t4211/expect.two-ranges +++ b/t/t4211/sha1/expect.two-ranges diff --git a/t/t4211/expect.vanishes-early b/t/t4211/sha1/expect.vanishes-early index 1f7cd06941..1f7cd06941 100644 --- a/t/t4211/expect.vanishes-early +++ b/t/t4211/sha1/expect.vanishes-early diff --git a/t/t4211/sha256/expect.beginning-of-file b/t/t4211/sha256/expect.beginning-of-file new file mode 100644 index 0000000000..5adfdfc1a1 --- /dev/null +++ b/t/t4211/sha256/expect.beginning-of-file @@ -0,0 +1,43 @@ +commit 62a40b38fa4f00800004aee81ef287b7201317594ebcb990f38cbe493b01d200 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:47:40 2013 +0100 + + change at very beginning + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -1,3 +1,4 @@ ++#include <unistd.h> + #include <stdio.h> + + long f(long x) + +commit ccf97b9878189c40a981da50b15713bb80a35755326320ec80900caf22ced46f +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:45:16 2013 +0100 + + touch both functions + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -1,3 +1,3 @@ + #include <stdio.h> + +-int f(int x) ++long f(long x) + +commit 1dd7e9b2b1699324b53b341e728653b913bc192a14dfea168c5b51f2b3d03592 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:48 2013 +0100 + + initial + +diff --git a/a.c b/a.c +--- /dev/null ++++ b/a.c +@@ -0,0 +1,3 @@ ++#include <stdio.h> ++ ++int f(int x) diff --git a/t/t4211/sha256/expect.end-of-file b/t/t4211/sha256/expect.end-of-file new file mode 100644 index 0000000000..03ab5c1784 --- /dev/null +++ b/t/t4211/sha256/expect.end-of-file @@ -0,0 +1,62 @@ +commit 5526ed05c2476b56af8b7be499e8f78bd50f490740733a9ca7e1f55878fa90a9 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:43 2013 +0100 + + change back to complete line + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -20,3 +20,5 @@ + printf("%ld\n", f(15)); + return 0; +-} +\ No newline at end of file ++} ++ ++/* incomplete lines are bad! */ + +commit 29f32ac3141c48b22803e5c4127b719917b67d0f8ca8c5248bebfa2a19f7da10 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:10 2013 +0100 + + change to an incomplete line at end + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -20,3 +20,3 @@ + printf("%ld\n", f(15)); + return 0; +-} ++} +\ No newline at end of file + +commit ccf97b9878189c40a981da50b15713bb80a35755326320ec80900caf22ced46f +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:45:16 2013 +0100 + + touch both functions + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -19,3 +19,3 @@ +- printf("%d\n", f(15)); ++ printf("%ld\n", f(15)); + return 0; + } + +commit 1dd7e9b2b1699324b53b341e728653b913bc192a14dfea168c5b51f2b3d03592 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:48 2013 +0100 + + initial + +diff --git a/a.c b/a.c +--- /dev/null ++++ b/a.c +@@ -0,0 +18,3 @@ ++ printf("%d\n", f(15)); ++ return 0; ++} diff --git a/t/t4211/sha256/expect.move-support-f b/t/t4211/sha256/expect.move-support-f new file mode 100644 index 0000000000..223b4ed2a0 --- /dev/null +++ b/t/t4211/sha256/expect.move-support-f @@ -0,0 +1,80 @@ +commit 4f7a58195a92c400e28a2354328587f1ff14fb77f5cf894536f17ccbc72931b9 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:49:50 2013 +0100 + + another simple change + +diff --git a/b.c b/b.c +--- a/b.c ++++ b/b.c +@@ -4,9 +4,9 @@ + long f(long x) + { + int s = 0; + while (x) { +- x >>= 1; ++ x /= 2; + s++; + } + return s; + } + +commit ccf97b9878189c40a981da50b15713bb80a35755326320ec80900caf22ced46f +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:45:16 2013 +0100 + + touch both functions + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,9 +3,9 @@ +-int f(int x) ++long f(long x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } + return s; + } + +commit f6434acd34260a6c9f61e96d96bf9a323d330561df5b1ca2631104f82026dfed +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:55 2013 +0100 + + change f() + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,8 +3,9 @@ + int f(int x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } ++ return s; + } + +commit 1dd7e9b2b1699324b53b341e728653b913bc192a14dfea168c5b51f2b3d03592 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:48 2013 +0100 + + initial + +diff --git a/a.c b/a.c +--- /dev/null ++++ b/a.c +@@ -0,0 +3,8 @@ ++int f(int x) ++{ ++ int s = 0; ++ while (x) { ++ x >>= 1; ++ s++; ++ } ++} diff --git a/t/t4211/sha256/expect.multiple b/t/t4211/sha256/expect.multiple new file mode 100644 index 0000000000..ca00409b9a --- /dev/null +++ b/t/t4211/sha256/expect.multiple @@ -0,0 +1,104 @@ +commit 5526ed05c2476b56af8b7be499e8f78bd50f490740733a9ca7e1f55878fa90a9 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:43 2013 +0100 + + change back to complete line + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -18,5 +18,7 @@ + int main () + { + printf("%ld\n", f(15)); + return 0; +-} +\ No newline at end of file ++} ++ ++/* incomplete lines are bad! */ + +commit 29f32ac3141c48b22803e5c4127b719917b67d0f8ca8c5248bebfa2a19f7da10 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:10 2013 +0100 + + change to an incomplete line at end + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -18,5 +18,5 @@ + int main () + { + printf("%ld\n", f(15)); + return 0; +-} ++} +\ No newline at end of file + +commit ccf97b9878189c40a981da50b15713bb80a35755326320ec80900caf22ced46f +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:45:16 2013 +0100 + + touch both functions + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,9 +3,9 @@ +-int f(int x) ++long f(long x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } + return s; + } +@@ -17,5 +17,5 @@ + int main () + { +- printf("%d\n", f(15)); ++ printf("%ld\n", f(15)); + return 0; + } + +commit f6434acd34260a6c9f61e96d96bf9a323d330561df5b1ca2631104f82026dfed +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:55 2013 +0100 + + change f() + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,8 +3,9 @@ + int f(int x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } ++ return s; + } + +commit 1dd7e9b2b1699324b53b341e728653b913bc192a14dfea168c5b51f2b3d03592 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:48 2013 +0100 + + initial + +diff --git a/a.c b/a.c +--- /dev/null ++++ b/a.c +@@ -0,0 +3,8 @@ ++int f(int x) ++{ ++ int s = 0; ++ while (x) { ++ x >>= 1; ++ s++; ++ } ++} diff --git a/t/t4211/sha256/expect.multiple-overlapping b/t/t4211/sha256/expect.multiple-overlapping new file mode 100644 index 0000000000..9015a45a25 --- /dev/null +++ b/t/t4211/sha256/expect.multiple-overlapping @@ -0,0 +1,187 @@ +commit 5526ed05c2476b56af8b7be499e8f78bd50f490740733a9ca7e1f55878fa90a9 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:43 2013 +0100 + + change back to complete line + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -4,19 +4,21 @@ + long f(long x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } + return s; + } + + /* + * This is only an example! + */ + + int main () + { + printf("%ld\n", f(15)); + return 0; +-} +\ No newline at end of file ++} ++ ++/* incomplete lines are bad! */ + +commit 29f32ac3141c48b22803e5c4127b719917b67d0f8ca8c5248bebfa2a19f7da10 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:10 2013 +0100 + + change to an incomplete line at end + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -4,19 +4,19 @@ + long f(long x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } + return s; + } + + /* + * This is only an example! + */ + + int main () + { + printf("%ld\n", f(15)); + return 0; +-} ++} +\ No newline at end of file + +commit 5a1b3989063d55e71e7685efa3392f133385b4034bddde530dcb5090d8b8b8ca +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:45:41 2013 +0100 + + touch comment + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,19 +3,19 @@ + long f(long x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } + return s; + } + + /* +- * A comment. ++ * This is only an example! + */ + + int main () + { + printf("%ld\n", f(15)); + return 0; + } + +commit ccf97b9878189c40a981da50b15713bb80a35755326320ec80900caf22ced46f +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:45:16 2013 +0100 + + touch both functions + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,19 +3,19 @@ +-int f(int x) ++long f(long x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } + return s; + } + + /* + * A comment. + */ + + int main () + { +- printf("%d\n", f(15)); ++ printf("%ld\n", f(15)); + return 0; + } + +commit f6434acd34260a6c9f61e96d96bf9a323d330561df5b1ca2631104f82026dfed +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:55 2013 +0100 + + change f() + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,18 +3,19 @@ + int f(int x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } ++ return s; + } + + /* + * A comment. + */ + + int main () + { + printf("%d\n", f(15)); + return 0; + } + +commit 1dd7e9b2b1699324b53b341e728653b913bc192a14dfea168c5b51f2b3d03592 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:48 2013 +0100 + + initial + +diff --git a/a.c b/a.c +--- /dev/null ++++ b/a.c +@@ -0,0 +3,18 @@ ++int f(int x) ++{ ++ int s = 0; ++ while (x) { ++ x >>= 1; ++ s++; ++ } ++} ++ ++/* ++ * A comment. ++ */ ++ ++int main () ++{ ++ printf("%d\n", f(15)); ++ return 0; ++} diff --git a/t/t4211/sha256/expect.multiple-superset b/t/t4211/sha256/expect.multiple-superset new file mode 100644 index 0000000000..9015a45a25 --- /dev/null +++ b/t/t4211/sha256/expect.multiple-superset @@ -0,0 +1,187 @@ +commit 5526ed05c2476b56af8b7be499e8f78bd50f490740733a9ca7e1f55878fa90a9 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:43 2013 +0100 + + change back to complete line + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -4,19 +4,21 @@ + long f(long x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } + return s; + } + + /* + * This is only an example! + */ + + int main () + { + printf("%ld\n", f(15)); + return 0; +-} +\ No newline at end of file ++} ++ ++/* incomplete lines are bad! */ + +commit 29f32ac3141c48b22803e5c4127b719917b67d0f8ca8c5248bebfa2a19f7da10 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:10 2013 +0100 + + change to an incomplete line at end + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -4,19 +4,19 @@ + long f(long x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } + return s; + } + + /* + * This is only an example! + */ + + int main () + { + printf("%ld\n", f(15)); + return 0; +-} ++} +\ No newline at end of file + +commit 5a1b3989063d55e71e7685efa3392f133385b4034bddde530dcb5090d8b8b8ca +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:45:41 2013 +0100 + + touch comment + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,19 +3,19 @@ + long f(long x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } + return s; + } + + /* +- * A comment. ++ * This is only an example! + */ + + int main () + { + printf("%ld\n", f(15)); + return 0; + } + +commit ccf97b9878189c40a981da50b15713bb80a35755326320ec80900caf22ced46f +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:45:16 2013 +0100 + + touch both functions + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,19 +3,19 @@ +-int f(int x) ++long f(long x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } + return s; + } + + /* + * A comment. + */ + + int main () + { +- printf("%d\n", f(15)); ++ printf("%ld\n", f(15)); + return 0; + } + +commit f6434acd34260a6c9f61e96d96bf9a323d330561df5b1ca2631104f82026dfed +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:55 2013 +0100 + + change f() + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,18 +3,19 @@ + int f(int x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } ++ return s; + } + + /* + * A comment. + */ + + int main () + { + printf("%d\n", f(15)); + return 0; + } + +commit 1dd7e9b2b1699324b53b341e728653b913bc192a14dfea168c5b51f2b3d03592 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:48 2013 +0100 + + initial + +diff --git a/a.c b/a.c +--- /dev/null ++++ b/a.c +@@ -0,0 +3,18 @@ ++int f(int x) ++{ ++ int s = 0; ++ while (x) { ++ x >>= 1; ++ s++; ++ } ++} ++ ++/* ++ * A comment. ++ */ ++ ++int main () ++{ ++ printf("%d\n", f(15)); ++ return 0; ++} diff --git a/t/t4211/sha256/expect.parallel-change-f-to-main b/t/t4211/sha256/expect.parallel-change-f-to-main new file mode 100644 index 0000000000..e68f8928ea --- /dev/null +++ b/t/t4211/sha256/expect.parallel-change-f-to-main @@ -0,0 +1,160 @@ +commit 98117c2059b76c36995748fb97b02542aef477fe26379e94c18fd70f7790bc67 +Merge: b511694 4f7a581 +Author: Thomas Rast <trast@inf.ethz.ch> +Date: Fri Apr 12 16:16:24 2013 +0200 + + Merge across the rename + + +commit 4f7a58195a92c400e28a2354328587f1ff14fb77f5cf894536f17ccbc72931b9 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:49:50 2013 +0100 + + another simple change + +diff --git a/b.c b/b.c +--- a/b.c ++++ b/b.c +@@ -4,14 +4,14 @@ + long f(long x) + { + int s = 0; + while (x) { +- x >>= 1; ++ x /= 2; + s++; + } + return s; + } + + /* + * This is only an example! + */ + + +commit b511694f5337663fbd697622993a5f8e1099eca84be4df313f2b3ee94a098b42 +Author: Thomas Rast <trast@inf.ethz.ch> +Date: Fri Apr 12 16:15:57 2013 +0200 + + change on another line of history while rename happens + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -4,14 +4,14 @@ + long f(long x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } + return s; + } + + /* +- * This is only an example! ++ * This is only a short example! + */ + + +commit 5a1b3989063d55e71e7685efa3392f133385b4034bddde530dcb5090d8b8b8ca +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:45:41 2013 +0100 + + touch comment + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,14 +3,14 @@ + long f(long x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } + return s; + } + + /* +- * A comment. ++ * This is only an example! + */ + + +commit ccf97b9878189c40a981da50b15713bb80a35755326320ec80900caf22ced46f +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:45:16 2013 +0100 + + touch both functions + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,14 +3,14 @@ +-int f(int x) ++long f(long x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } + return s; + } + + /* + * A comment. + */ + + +commit f6434acd34260a6c9f61e96d96bf9a323d330561df5b1ca2631104f82026dfed +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:55 2013 +0100 + + change f() + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,13 +3,14 @@ + int f(int x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } ++ return s; + } + + /* + * A comment. + */ + + +commit 1dd7e9b2b1699324b53b341e728653b913bc192a14dfea168c5b51f2b3d03592 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:48 2013 +0100 + + initial + +diff --git a/a.c b/a.c +--- /dev/null ++++ b/a.c +@@ -0,0 +3,13 @@ ++int f(int x) ++{ ++ int s = 0; ++ while (x) { ++ x >>= 1; ++ s++; ++ } ++} ++ ++/* ++ * A comment. ++ */ ++ diff --git a/t/t4211/sha256/expect.simple-f b/t/t4211/sha256/expect.simple-f new file mode 100644 index 0000000000..65508d7c0b --- /dev/null +++ b/t/t4211/sha256/expect.simple-f @@ -0,0 +1,59 @@ +commit ccf97b9878189c40a981da50b15713bb80a35755326320ec80900caf22ced46f +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:45:16 2013 +0100 + + touch both functions + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,9 +3,9 @@ +-int f(int x) ++long f(long x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } + return s; + } + +commit f6434acd34260a6c9f61e96d96bf9a323d330561df5b1ca2631104f82026dfed +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:55 2013 +0100 + + change f() + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,8 +3,9 @@ + int f(int x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } ++ return s; + } + +commit 1dd7e9b2b1699324b53b341e728653b913bc192a14dfea168c5b51f2b3d03592 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:48 2013 +0100 + + initial + +diff --git a/a.c b/a.c +--- /dev/null ++++ b/a.c +@@ -0,0 +3,8 @@ ++int f(int x) ++{ ++ int s = 0; ++ while (x) { ++ x >>= 1; ++ s++; ++ } ++} diff --git a/t/t4211/sha256/expect.simple-f-to-main b/t/t4211/sha256/expect.simple-f-to-main new file mode 100644 index 0000000000..77b721c196 --- /dev/null +++ b/t/t4211/sha256/expect.simple-f-to-main @@ -0,0 +1,100 @@ +commit 5a1b3989063d55e71e7685efa3392f133385b4034bddde530dcb5090d8b8b8ca +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:45:41 2013 +0100 + + touch comment + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,14 +3,14 @@ + long f(long x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } + return s; + } + + /* +- * A comment. ++ * This is only an example! + */ + + +commit ccf97b9878189c40a981da50b15713bb80a35755326320ec80900caf22ced46f +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:45:16 2013 +0100 + + touch both functions + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,14 +3,14 @@ +-int f(int x) ++long f(long x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } + return s; + } + + /* + * A comment. + */ + + +commit f6434acd34260a6c9f61e96d96bf9a323d330561df5b1ca2631104f82026dfed +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:55 2013 +0100 + + change f() + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,13 +3,14 @@ + int f(int x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } ++ return s; + } + + /* + * A comment. + */ + + +commit 1dd7e9b2b1699324b53b341e728653b913bc192a14dfea168c5b51f2b3d03592 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:48 2013 +0100 + + initial + +diff --git a/a.c b/a.c +--- /dev/null ++++ b/a.c +@@ -0,0 +3,13 @@ ++int f(int x) ++{ ++ int s = 0; ++ while (x) { ++ x >>= 1; ++ s++; ++ } ++} ++ ++/* ++ * A comment. ++ */ ++ diff --git a/t/t4211/sha256/expect.simple-main b/t/t4211/sha256/expect.simple-main new file mode 100644 index 0000000000..d20708c9f9 --- /dev/null +++ b/t/t4211/sha256/expect.simple-main @@ -0,0 +1,68 @@ +commit 5526ed05c2476b56af8b7be499e8f78bd50f490740733a9ca7e1f55878fa90a9 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:43 2013 +0100 + + change back to complete line + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -18,5 +18,5 @@ + int main () + { + printf("%ld\n", f(15)); + return 0; +-} +\ No newline at end of file ++} + +commit 29f32ac3141c48b22803e5c4127b719917b67d0f8ca8c5248bebfa2a19f7da10 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:10 2013 +0100 + + change to an incomplete line at end + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -18,5 +18,5 @@ + int main () + { + printf("%ld\n", f(15)); + return 0; +-} ++} +\ No newline at end of file + +commit ccf97b9878189c40a981da50b15713bb80a35755326320ec80900caf22ced46f +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:45:16 2013 +0100 + + touch both functions + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -17,5 +17,5 @@ + int main () + { +- printf("%d\n", f(15)); ++ printf("%ld\n", f(15)); + return 0; + } + +commit 1dd7e9b2b1699324b53b341e728653b913bc192a14dfea168c5b51f2b3d03592 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:48 2013 +0100 + + initial + +diff --git a/a.c b/a.c +--- /dev/null ++++ b/a.c +@@ -0,0 +16,5 @@ ++int main () ++{ ++ printf("%d\n", f(15)); ++ return 0; ++} diff --git a/t/t4211/sha256/expect.simple-main-to-end b/t/t4211/sha256/expect.simple-main-to-end new file mode 100644 index 0000000000..617cdf3481 --- /dev/null +++ b/t/t4211/sha256/expect.simple-main-to-end @@ -0,0 +1,70 @@ +commit 5526ed05c2476b56af8b7be499e8f78bd50f490740733a9ca7e1f55878fa90a9 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:43 2013 +0100 + + change back to complete line + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -18,5 +18,7 @@ + int main () + { + printf("%ld\n", f(15)); + return 0; +-} +\ No newline at end of file ++} ++ ++/* incomplete lines are bad! */ + +commit 29f32ac3141c48b22803e5c4127b719917b67d0f8ca8c5248bebfa2a19f7da10 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:10 2013 +0100 + + change to an incomplete line at end + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -18,5 +18,5 @@ + int main () + { + printf("%ld\n", f(15)); + return 0; +-} ++} +\ No newline at end of file + +commit ccf97b9878189c40a981da50b15713bb80a35755326320ec80900caf22ced46f +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:45:16 2013 +0100 + + touch both functions + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -17,5 +17,5 @@ + int main () + { +- printf("%d\n", f(15)); ++ printf("%ld\n", f(15)); + return 0; + } + +commit 1dd7e9b2b1699324b53b341e728653b913bc192a14dfea168c5b51f2b3d03592 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:48 2013 +0100 + + initial + +diff --git a/a.c b/a.c +--- /dev/null ++++ b/a.c +@@ -0,0 +16,5 @@ ++int main () ++{ ++ printf("%d\n", f(15)); ++ return 0; ++} diff --git a/t/t4211/sha256/expect.two-ranges b/t/t4211/sha256/expect.two-ranges new file mode 100644 index 0000000000..af57c8b997 --- /dev/null +++ b/t/t4211/sha256/expect.two-ranges @@ -0,0 +1,102 @@ +commit 5526ed05c2476b56af8b7be499e8f78bd50f490740733a9ca7e1f55878fa90a9 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:43 2013 +0100 + + change back to complete line + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -18,5 +18,5 @@ + int main () + { + printf("%ld\n", f(15)); + return 0; +-} +\ No newline at end of file ++} + +commit 29f32ac3141c48b22803e5c4127b719917b67d0f8ca8c5248bebfa2a19f7da10 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:10 2013 +0100 + + change to an incomplete line at end + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -18,5 +18,5 @@ + int main () + { + printf("%ld\n", f(15)); + return 0; +-} ++} +\ No newline at end of file + +commit ccf97b9878189c40a981da50b15713bb80a35755326320ec80900caf22ced46f +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:45:16 2013 +0100 + + touch both functions + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,9 +3,9 @@ +-int f(int x) ++long f(long x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } + return s; + } +@@ -17,5 +17,5 @@ + int main () + { +- printf("%d\n", f(15)); ++ printf("%ld\n", f(15)); + return 0; + } + +commit f6434acd34260a6c9f61e96d96bf9a323d330561df5b1ca2631104f82026dfed +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:55 2013 +0100 + + change f() + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -3,8 +3,9 @@ + int f(int x) + { + int s = 0; + while (x) { + x >>= 1; + s++; + } ++ return s; + } + +commit 1dd7e9b2b1699324b53b341e728653b913bc192a14dfea168c5b51f2b3d03592 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:48 2013 +0100 + + initial + +diff --git a/a.c b/a.c +--- /dev/null ++++ b/a.c +@@ -0,0 +3,8 @@ ++int f(int x) ++{ ++ int s = 0; ++ while (x) { ++ x >>= 1; ++ s++; ++ } ++} diff --git a/t/t4211/sha256/expect.vanishes-early b/t/t4211/sha256/expect.vanishes-early new file mode 100644 index 0000000000..11ec9bdecf --- /dev/null +++ b/t/t4211/sha256/expect.vanishes-early @@ -0,0 +1,39 @@ +commit 5526ed05c2476b56af8b7be499e8f78bd50f490740733a9ca7e1f55878fa90a9 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:43 2013 +0100 + + change back to complete line + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -22,1 +24,1 @@ +-} +\ No newline at end of file ++/* incomplete lines are bad! */ + +commit 29f32ac3141c48b22803e5c4127b719917b67d0f8ca8c5248bebfa2a19f7da10 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:48:10 2013 +0100 + + change to an incomplete line at end + +diff --git a/a.c b/a.c +--- a/a.c ++++ b/a.c +@@ -22,1 +22,1 @@ +-} ++} +\ No newline at end of file + +commit 1dd7e9b2b1699324b53b341e728653b913bc192a14dfea168c5b51f2b3d03592 +Author: Thomas Rast <trast@student.ethz.ch> +Date: Thu Feb 28 10:44:48 2013 +0100 + + initial + +diff --git a/a.c b/a.c +--- /dev/null ++++ b/a.c +@@ -0,0 +20,1 @@ ++} diff --git a/t/t4214-log-graph-octopus.sh b/t/t4214-log-graph-octopus.sh index 40d27db674..a080325098 100755 --- a/t/t4214-log-graph-octopus.sh +++ b/t/t4214-log-graph-octopus.sh @@ -3,6 +3,16 @@ test_description='git log --graph of skewed left octopus merge.' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-log-graph.sh + +test_cmp_graph () { + cat >expect && + lib_test_cmp_graph --color=never --date-order --format=%s "$@" +} + +test_cmp_colored_graph () { + lib_test_cmp_colored_graph --date-order --format=%s "$@" +} test_expect_success 'set up merge history' ' test_commit initial && @@ -24,7 +34,7 @@ test_expect_success 'set up merge history' ' ' test_expect_success 'log --graph with tricky octopus merge, no color' ' - cat >expect.uncolored <<-\EOF && + test_cmp_graph left octopus-merge <<-\EOF * left | *-. octopus-merge |/|\ \ @@ -37,9 +47,6 @@ test_expect_success 'log --graph with tricky octopus merge, no color' ' |/ * initial EOF - git log --color=never --graph --date-order --pretty=tformat:%s left octopus-merge >actual.raw && - sed "s/ *\$//" actual.raw >actual && - test_cmp expect.uncolored actual ' test_expect_success 'log --graph with tricky octopus merge with colors' ' @@ -57,16 +64,14 @@ test_expect_success 'log --graph with tricky octopus merge with colors' ' <MAGENTA>|<RESET><MAGENTA>/<RESET> * initial EOF - git log --color=always --graph --date-order --pretty=tformat:%s left octopus-merge >actual.colors.raw && - test_decode_color <actual.colors.raw | sed "s/ *\$//" >actual.colors && - test_cmp expect.colors actual.colors + test_cmp_colored_graph left octopus-merge ' # Repeat the previous two tests with "normal" octopus merge (i.e., # without the first parent skewing to the "left" branch column). test_expect_success 'log --graph with normal octopus merge, no color' ' - cat >expect.uncolored <<-\EOF && + test_cmp_graph octopus-merge <<-\EOF *---. octopus-merge |\ \ \ | | | * 4 @@ -78,9 +83,6 @@ test_expect_success 'log --graph with normal octopus merge, no color' ' |/ * initial EOF - git log --color=never --graph --date-order --pretty=tformat:%s octopus-merge >actual.raw && - sed "s/ *\$//" actual.raw >actual && - test_cmp expect.uncolored actual ' test_expect_success 'log --graph with normal octopus merge with colors' ' @@ -97,13 +99,11 @@ test_expect_success 'log --graph with normal octopus merge with colors' ' * initial EOF test_config log.graphColors red,green,yellow,blue,magenta,cyan && - git log --color=always --graph --date-order --pretty=tformat:%s octopus-merge >actual.colors.raw && - test_decode_color <actual.colors.raw | sed "s/ *\$//" >actual.colors && - test_cmp expect.colors actual.colors + test_cmp_colored_graph octopus-merge ' test_expect_success 'log --graph with normal octopus merge and child, no color' ' - cat >expect.uncolored <<-\EOF && + test_cmp_graph after-merge <<-\EOF * after-merge *---. octopus-merge |\ \ \ @@ -116,9 +116,6 @@ test_expect_success 'log --graph with normal octopus merge and child, no color' |/ * initial EOF - git log --color=never --graph --date-order --pretty=tformat:%s after-merge >actual.raw && - sed "s/ *\$//" actual.raw >actual && - test_cmp expect.uncolored actual ' test_expect_success 'log --graph with normal octopus and child merge with colors' ' @@ -136,13 +133,11 @@ test_expect_success 'log --graph with normal octopus and child merge with colors * initial EOF test_config log.graphColors red,green,yellow,blue,magenta,cyan && - git log --color=always --graph --date-order --pretty=tformat:%s after-merge >actual.colors.raw && - test_decode_color <actual.colors.raw | sed "s/ *\$//" >actual.colors && - test_cmp expect.colors actual.colors + test_cmp_colored_graph after-merge ' test_expect_success 'log --graph with tricky octopus merge and its child, no color' ' - cat >expect.uncolored <<-\EOF && + test_cmp_graph left after-merge <<-\EOF * left | * after-merge | *-. octopus-merge @@ -156,9 +151,6 @@ test_expect_success 'log --graph with tricky octopus merge and its child, no col |/ * initial EOF - git log --color=never --graph --date-order --pretty=tformat:%s left after-merge >actual.raw && - sed "s/ *\$//" actual.raw >actual && - test_cmp expect.uncolored actual ' test_expect_success 'log --graph with tricky octopus merge and its child with colors' ' @@ -177,13 +169,11 @@ test_expect_success 'log --graph with tricky octopus merge and its child with co <CYAN>|<RESET><CYAN>/<RESET> * initial EOF - git log --color=always --graph --date-order --pretty=tformat:%s left after-merge >actual.colors.raw && - test_decode_color <actual.colors.raw | sed "s/ *\$//" >actual.colors && - test_cmp expect.colors actual.colors + test_cmp_colored_graph left after-merge ' test_expect_success 'log --graph with crossover in octopus merge, no color' ' - cat >expect.uncolored <<-\EOF && + test_cmp_graph after-4 octopus-merge <<-\EOF * after-4 | *---. octopus-merge | |\ \ \ @@ -200,9 +190,6 @@ test_expect_success 'log --graph with crossover in octopus merge, no color' ' |/ * initial EOF - git log --color=never --graph --date-order --pretty=tformat:%s after-4 octopus-merge >actual.raw && - sed "s/ *\$//" actual.raw >actual && - test_cmp expect.uncolored actual ' test_expect_success 'log --graph with crossover in octopus merge with colors' ' @@ -224,13 +211,11 @@ test_expect_success 'log --graph with crossover in octopus merge with colors' ' <MAGENTA>|<RESET><MAGENTA>/<RESET> * initial EOF - git log --color=always --graph --date-order --pretty=tformat:%s after-4 octopus-merge >actual.colors.raw && - test_decode_color <actual.colors.raw | sed "s/ *\$//" >actual.colors && - test_cmp expect.colors actual.colors + test_cmp_colored_graph after-4 octopus-merge ' test_expect_success 'log --graph with crossover in octopus merge and its child, no color' ' - cat >expect.uncolored <<-\EOF && + test_cmp_graph after-4 after-merge <<-\EOF * after-4 | * after-merge | *---. octopus-merge @@ -248,9 +233,6 @@ test_expect_success 'log --graph with crossover in octopus merge and its child, |/ * initial EOF - git log --color=never --graph --date-order --pretty=tformat:%s after-4 after-merge >actual.raw && - sed "s/ *\$//" actual.raw >actual && - test_cmp expect.uncolored actual ' test_expect_success 'log --graph with crossover in octopus merge and its child with colors' ' @@ -273,13 +255,11 @@ test_expect_success 'log --graph with crossover in octopus merge and its child w <CYAN>|<RESET><CYAN>/<RESET> * initial EOF - git log --color=always --graph --date-order --pretty=tformat:%s after-4 after-merge >actual.colors.raw && - test_decode_color <actual.colors.raw | sed "s/ *\$//" >actual.colors && - test_cmp expect.colors actual.colors + test_cmp_colored_graph after-4 after-merge ' test_expect_success 'log --graph with unrelated commit and octopus tip, no color' ' - cat >expect.uncolored <<-\EOF && + test_cmp_graph after-initial octopus-merge <<-\EOF * after-initial | *---. octopus-merge | |\ \ \ @@ -296,9 +276,6 @@ test_expect_success 'log --graph with unrelated commit and octopus tip, no color |/ * initial EOF - git log --color=never --graph --date-order --pretty=tformat:%s after-initial octopus-merge >actual.raw && - sed "s/ *\$//" actual.raw >actual && - test_cmp expect.uncolored actual ' test_expect_success 'log --graph with unrelated commit and octopus tip with colors' ' @@ -320,13 +297,11 @@ test_expect_success 'log --graph with unrelated commit and octopus tip with colo <RED>|<RESET><RED>/<RESET> * initial EOF - git log --color=always --graph --date-order --pretty=tformat:%s after-initial octopus-merge >actual.colors.raw && - test_decode_color <actual.colors.raw | sed "s/ *\$//" >actual.colors && - test_cmp expect.colors actual.colors + test_cmp_colored_graph after-initial octopus-merge ' test_expect_success 'log --graph with unrelated commit and octopus child, no color' ' - cat >expect.uncolored <<-\EOF && + test_cmp_graph after-initial after-merge <<-\EOF * after-initial | * after-merge | *---. octopus-merge @@ -344,9 +319,6 @@ test_expect_success 'log --graph with unrelated commit and octopus child, no col |/ * initial EOF - git log --color=never --graph --date-order --pretty=tformat:%s after-initial after-merge >actual.raw && - sed "s/ *\$//" actual.raw >actual && - test_cmp expect.uncolored actual ' test_expect_success 'log --graph with unrelated commit and octopus child with colors' ' @@ -369,9 +341,7 @@ test_expect_success 'log --graph with unrelated commit and octopus child with co <RED>|<RESET><RED>/<RESET> * initial EOF - git log --color=always --graph --date-order --pretty=tformat:%s after-initial after-merge >actual.colors.raw && - test_decode_color <actual.colors.raw | sed "s/ *\$//" >actual.colors && - test_cmp expect.colors actual.colors + test_cmp_colored_graph after-initial after-merge ' test_done diff --git a/t/t4215-log-skewed-merges.sh b/t/t4215-log-skewed-merges.sh index 5661ed5881..28d0779a8c 100755 --- a/t/t4215-log-skewed-merges.sh +++ b/t/t4215-log-skewed-merges.sh @@ -3,12 +3,11 @@ test_description='git log --graph of skewed merges' . ./test-lib.sh +. "$TEST_DIRECTORY"/lib-log-graph.sh check_graph () { cat >expect && - git log --graph --pretty=tformat:%s "$@" >actual.raw && - sed "s/ *$//" actual.raw >actual && - test_cmp expect actual + lib_test_cmp_graph --format=%s "$@" } test_expect_success 'log --graph with merge fusing with its left and right neighbors' ' @@ -306,9 +305,69 @@ test_expect_success 'log --graph with multiple tips and colors' ' <BLUE>|<RESET><BLUE>/<RESET> * 6_A EOF - git log --color=always --graph --date-order --pretty=tformat:%s 6_1 6_3 6_5 >actual.colors.raw && - test_decode_color <actual.colors.raw | sed "s/ *\$//" >actual.colors && - test_cmp expect.colors actual.colors + lib_test_cmp_colored_graph --date-order --pretty=tformat:%s 6_1 6_3 6_5 +' + +test_expect_success 'log --graph with multiple tips' ' + git checkout --orphan 7_1 && + test_commit 7_A && + test_commit 7_B && + test_commit 7_C && + git checkout -b 7_2 7_1~2 && + test_commit 7_D && + test_commit 7_E && + git checkout -b 7_3 7_1~1 && + test_commit 7_F && + test_commit 7_G && + git checkout -b 7_4 7_2~1 && + test_commit 7_H && + git checkout -b 7_5 7_1~2 && + test_commit 7_I && + git checkout -b 7_6 7_3~1 && + test_commit 7_J && + git checkout -b M_1 7_1 && + git merge --no-ff 7_2 -m 7_M1 && + git checkout -b M_3 7_3 && + git merge --no-ff 7_4 -m 7_M2 && + git checkout -b M_5 7_5 && + git merge --no-ff 7_6 -m 7_M3 && + git checkout -b M_7 7_1 && + git merge --no-ff 7_2 7_3 -m 7_M4 && + + check_graph M_1 M_3 M_5 M_7 <<-\EOF + * 7_M1 + |\ + | | * 7_M2 + | | |\ + | | | * 7_H + | | | | * 7_M3 + | | | | |\ + | | | | | * 7_J + | | | | * | 7_I + | | | | | | * 7_M4 + | |_|_|_|_|/|\ + |/| | | | |/ / + | | |_|_|/| / + | |/| | | |/ + | | | |_|/| + | | |/| | | + | | * | | | 7_G + | | | |_|/ + | | |/| | + | | * | | 7_F + | * | | | 7_E + | | |/ / + | |/| | + | * | | 7_D + | | |/ + | |/| + * | | 7_C + | |/ + |/| + * | 7_B + |/ + * 7_A + EOF ' test_done diff --git a/t/t4216-log-bloom.sh b/t/t4216-log-bloom.sh new file mode 100755 index 0000000000..21b68dd6c8 --- /dev/null +++ b/t/t4216-log-bloom.sh @@ -0,0 +1,155 @@ +#!/bin/sh + +test_description='git log for a path with Bloom filters' +. ./test-lib.sh + +GIT_TEST_COMMIT_GRAPH=0 +GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0 + +test_expect_success 'setup test - repo, commits, commit graph, log outputs' ' + git init && + mkdir A A/B A/B/C && + test_commit c1 A/file1 && + test_commit c2 A/B/file2 && + test_commit c3 A/B/C/file3 && + test_commit c4 A/file1 && + test_commit c5 A/B/file2 && + test_commit c6 A/B/C/file3 && + test_commit c7 A/file1 && + test_commit c8 A/B/file2 && + test_commit c9 A/B/C/file3 && + test_commit c10 file_to_be_deleted && + git checkout -b side HEAD~4 && + test_commit side-1 file4 && + git checkout master && + git merge side && + test_commit c11 file5 && + mv file5 file5_renamed && + git add file5_renamed && + git commit -m "rename" && + rm file_to_be_deleted && + git add . && + git commit -m "file removed" && + git commit-graph write --reachable --changed-paths +' +graph_read_expect () { + NUM_CHUNKS=5 + cat >expect <<- EOF + header: 43475048 1 1 $NUM_CHUNKS 0 + num_commits: $1 + chunks: oid_fanout oid_lookup commit_metadata bloom_indexes bloom_data + EOF + test-tool read-graph >actual && + test_cmp expect actual +} + +test_expect_success 'commit-graph write wrote out the bloom chunks' ' + graph_read_expect 15 +' + +# Turn off any inherited trace2 settings for this test. +sane_unset GIT_TRACE2 GIT_TRACE2_PERF GIT_TRACE2_EVENT +sane_unset GIT_TRACE2_PERF_BRIEF +sane_unset GIT_TRACE2_CONFIG_PARAMS + +setup () { + rm "$TRASH_DIRECTORY/trace.perf" + git -c core.commitGraph=false log --pretty="format:%s" $1 >log_wo_bloom && + GIT_TRACE2_PERF="$TRASH_DIRECTORY/trace.perf" git -c core.commitGraph=true log --pretty="format:%s" $1 >log_w_bloom +} + +test_bloom_filters_used () { + log_args=$1 + bloom_trace_prefix="statistics:{\"filter_not_present\":0,\"zero_length_filter\":0,\"maybe\"" + setup "$log_args" && + grep -q "$bloom_trace_prefix" "$TRASH_DIRECTORY/trace.perf" && + test_cmp log_wo_bloom log_w_bloom && + test_path_is_file "$TRASH_DIRECTORY/trace.perf" +} + +test_bloom_filters_not_used () { + log_args=$1 + setup "$log_args" && + !(grep -q "statistics:{\"filter_not_present\":" "$TRASH_DIRECTORY/trace.perf") && + test_cmp log_wo_bloom log_w_bloom +} + +for path in A A/B A/B/C A/file1 A/B/file2 A/B/C/file3 file4 file5 file5_renamed file_to_be_deleted +do + for option in "" \ + "--all" \ + "--full-history" \ + "--full-history --simplify-merges" \ + "--simplify-merges" \ + "--simplify-by-decoration" \ + "--follow" \ + "--first-parent" \ + "--topo-order" \ + "--date-order" \ + "--author-date-order" \ + "--ancestry-path side..master" + do + test_expect_success "git log option: $option for path: $path" ' + test_bloom_filters_used "$option -- $path" + ' + done +done + +test_expect_success 'git log -- folder works with and without the trailing slash' ' + test_bloom_filters_used "-- A" && + test_bloom_filters_used "-- A/" +' + +test_expect_success 'git log for path that does not exist. ' ' + test_bloom_filters_used "-- path_does_not_exist" +' + +test_expect_success 'git log with --walk-reflogs does not use Bloom filters' ' + test_bloom_filters_not_used "--walk-reflogs -- A" +' + +test_expect_success 'git log -- multiple path specs does not use Bloom filters' ' + test_bloom_filters_not_used "-- file4 A/file1" +' + +test_expect_success 'git log with wildcard that resolves to a single path uses Bloom filters' ' + test_bloom_filters_used "-- *4" && + test_bloom_filters_used "-- *renamed" +' + +test_expect_success 'git log with wildcard that resolves to a multiple paths does not uses Bloom filters' ' + test_bloom_filters_not_used "-- *" && + test_bloom_filters_not_used "-- file*" +' + +test_expect_success 'setup - add commit-graph to the chain without Bloom filters' ' + test_commit c14 A/anotherFile2 && + test_commit c15 A/B/anotherFile2 && + test_commit c16 A/B/C/anotherFile2 && + GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0 git commit-graph write --reachable --split && + test_line_count = 2 .git/objects/info/commit-graphs/commit-graph-chain +' + +test_expect_success 'Do not use Bloom filters if the latest graph does not have Bloom filters.' ' + test_bloom_filters_not_used "-- A/B" +' + +test_expect_success 'setup - add commit-graph to the chain with Bloom filters' ' + test_commit c17 A/anotherFile3 && + git commit-graph write --reachable --changed-paths --split && + test_line_count = 3 .git/objects/info/commit-graphs/commit-graph-chain +' + +test_bloom_filters_used_when_some_filters_are_missing () { + log_args=$1 + bloom_trace_prefix="statistics:{\"filter_not_present\":3,\"zero_length_filter\":0,\"maybe\":8,\"definitely_not\":6" + setup "$log_args" && + grep -q "$bloom_trace_prefix" "$TRASH_DIRECTORY/trace.perf" && + test_cmp log_wo_bloom log_w_bloom +} + +test_expect_success 'Use Bloom filters if they exist in the latest but not all commit graphs in the chain.' ' + test_bloom_filters_used_when_some_filters_are_missing "-- A/B" +' + +test_done diff --git a/t/t4254-am-corrupt.sh b/t/t4254-am-corrupt.sh index fd3bdbfe2c..daf01c309d 100755 --- a/t/t4254-am-corrupt.sh +++ b/t/t4254-am-corrupt.sh @@ -3,6 +3,37 @@ test_description='git am with corrupt input' . ./test-lib.sh +make_mbox_with_nul () { + space=' ' + q_nul_in_subject= + q_nul_in_body= + while test $# -ne 0 + do + case "$1" in + subject) q_nul_in_subject='=00' ;; + body) q_nul_in_body='=00' ;; + esac && + shift + done && + cat <<-EOF + From ec7364544f690c560304f5a5de9428ea3b978b26 Mon Sep 17 00:00:00 2001 + From: A U Thor <author@example.com> + Date: Sun, 19 Apr 2020 13:42:07 +0700 + Subject: [PATCH] =?ISO-8859-1?q?=C4=CB${q_nul_in_subject}=D1=CF=D6?= + MIME-Version: 1.0 + Content-Type: text/plain; charset=ISO-8859-1 + Content-Transfer-Encoding: quoted-printable + + abc${q_nul_in_body}def + --- + diff --git a/afile b/afile + new file mode 100644 + index 0000000000..e69de29bb2 + --$space + 2.26.1 + EOF +} + test_expect_success setup ' # Note the missing "+++" line: cat >bad-patch.diff <<-\EOF && @@ -25,13 +56,27 @@ test_expect_success setup ' # fatal: unable to write file '(null)' mode 100644: Bad address # Also, it had the unwanted side-effect of deleting f. test_expect_success 'try to apply corrupted patch' ' - test_must_fail git -c advice.amWorkDir=false am bad-patch.diff 2>actual -' - -test_expect_success 'compare diagnostic; ensure file is still here' ' + test_when_finished "git am --abort" && + test_must_fail git -c advice.amWorkDir=false am bad-patch.diff 2>actual && echo "error: git diff header lacks filename information (line 4)" >expected && test_path_is_file f && test_i18ncmp expected actual ' +test_expect_success "NUL in commit message's body" ' + test_when_finished "git am --abort" && + make_mbox_with_nul body >body.patch && + test_must_fail git am body.patch 2>err && + grep "a NUL byte in commit log message not allowed" err +' + +test_expect_success "NUL in commit message's header" " + test_when_finished 'git am --abort' && + make_mbox_with_nul subject >subject.patch && + test_must_fail git mailinfo msg patch <subject.patch 2>err && + grep \"a NUL byte in 'Subject' is not allowed\" err && + test_must_fail git am subject.patch 2>err && + grep \"a NUL byte in 'Subject' is not allowed\" err +" + test_done diff --git a/t/t4300-merge-tree.sh b/t/t4300-merge-tree.sh index d87cc7d9ef..e59601e5fe 100755 --- a/t/t4300-merge-tree.sh +++ b/t/t4300-merge-tree.sh @@ -11,16 +11,16 @@ test_expect_success setup ' ' test_expect_success 'file add A, !B' ' - cat >expected <<\EXPECTED && + git reset --hard initial && + test_commit "add-a-not-b" "ONE" "AAA" && + git merge-tree initial initial add-a-not-b >actual && + cat >expected <<EXPECTED && added in remote - their 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE + their 100644 $(git rev-parse HEAD:ONE) ONE @@ -0,0 +1 @@ +AAA EXPECTED - git reset --hard initial && - test_commit "add-a-not-b" "ONE" "AAA" && - git merge-tree initial initial add-a-not-b >actual && test_cmp expected actual ' @@ -41,10 +41,15 @@ test_expect_success 'file add A, B (same)' ' ' test_expect_success 'file add A, B (different)' ' - cat >expected <<\EXPECTED && + git reset --hard initial && + test_commit "add-a-b-diff-A" "ONE" "AAA" && + git reset --hard initial && + test_commit "add-a-b-diff-B" "ONE" "BBB" && + git merge-tree initial add-a-b-diff-A add-a-b-diff-B >actual && + cat >expected <<EXPECTED && added in both - our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE - their 100644 ba629238ca89489f2b350e196ca445e09d8bb834 ONE + our 100644 $(git rev-parse add-a-b-diff-A:ONE) ONE + their 100644 $(git rev-parse add-a-b-diff-B:ONE) ONE @@ -1 +1,5 @@ +<<<<<<< .our AAA @@ -53,11 +58,6 @@ added in both +>>>>>>> .their EXPECTED - git reset --hard initial && - test_commit "add-a-b-diff-A" "ONE" "AAA" && - git reset --hard initial && - test_commit "add-a-b-diff-B" "ONE" "BBB" && - git merge-tree initial add-a-b-diff-A add-a-b-diff-B >actual && test_cmp expected actual ' @@ -69,18 +69,18 @@ test_expect_success 'file change A, !B' ' ' test_expect_success 'file change !A, B' ' - cat >expected <<\EXPECTED && + git reset --hard initial && + test_commit "change-not-a-b" "initial-file" "BBB" && + git merge-tree initial initial change-not-a-b >actual && + cat >expected <<EXPECTED && merged - result 100644 ba629238ca89489f2b350e196ca445e09d8bb834 initial-file - our 100644 e79c5e8f964493290a409888d5413a737e8e5dd5 initial-file + result 100644 $(git rev-parse change-a-not-b:initial-file) initial-file + our 100644 $(git rev-parse initial:initial-file ) initial-file @@ -1 +1 @@ -initial +BBB EXPECTED - git reset --hard initial && - test_commit "change-not-a-b" "initial-file" "BBB" && - git merge-tree initial initial change-not-a-b >actual && test_cmp expected actual ' @@ -94,11 +94,16 @@ test_expect_success 'file change A, B (same)' ' ' test_expect_success 'file change A, B (different)' ' - cat >expected <<\EXPECTED && + git reset --hard initial && + test_commit "change-a-b-diff-A" "initial-file" "AAA" && + git reset --hard initial && + test_commit "change-a-b-diff-B" "initial-file" "BBB" && + git merge-tree initial change-a-b-diff-A change-a-b-diff-B >actual && + cat >expected <<EXPECTED && changed in both - base 100644 e79c5e8f964493290a409888d5413a737e8e5dd5 initial-file - our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d initial-file - their 100644 ba629238ca89489f2b350e196ca445e09d8bb834 initial-file + base 100644 $(git rev-parse initial:initial-file ) initial-file + our 100644 $(git rev-parse change-a-b-diff-A:initial-file) initial-file + their 100644 $(git rev-parse change-a-b-diff-B:initial-file) initial-file @@ -1 +1,5 @@ +<<<<<<< .our AAA @@ -107,34 +112,10 @@ changed in both +>>>>>>> .their EXPECTED - git reset --hard initial && - test_commit "change-a-b-diff-A" "initial-file" "AAA" && - git reset --hard initial && - test_commit "change-a-b-diff-B" "initial-file" "BBB" && - git merge-tree initial change-a-b-diff-A change-a-b-diff-B >actual && test_cmp expected actual ' test_expect_success 'file change A, B (mixed)' ' - cat >expected <<\EXPECTED && -changed in both - base 100644 f4f1f998c7776568c4ff38f516d77fef9399b5a7 ONE - our 100644 af14c2c3475337c73759d561ef70b59e5c731176 ONE - their 100644 372d761493f524d44d59bd24700c3bdf914c973c ONE -@@ -7,7 +7,11 @@ - AAA - AAA - AAA -+<<<<<<< .our - BBB -+======= -+CCC -+>>>>>>> .their - AAA - AAA - AAA -EXPECTED - git reset --hard initial && test_commit "change-a-b-mix-base" "ONE" " AAA @@ -159,6 +140,26 @@ AAA" && "$(sed -e "1{s/AAA/BBB/;}" -e "10{s/AAA/CCC/;}" <ONE)" && git merge-tree change-a-b-mix-base change-a-b-mix-A change-a-b-mix-B \ >actual && + + cat >expected <<EXPECTED && +changed in both + base 100644 $(git rev-parse change-a-b-mix-base:ONE) ONE + our 100644 $(git rev-parse change-a-b-mix-A:ONE ) ONE + their 100644 $(git rev-parse change-a-b-mix-B:ONE ) ONE +@@ -7,7 +7,11 @@ + AAA + AAA + AAA ++<<<<<<< .our + BBB ++======= ++CCC ++>>>>>>> .their + AAA + AAA + AAA +EXPECTED + test_cmp expected actual ' @@ -173,20 +174,20 @@ test_expect_success 'file remove A, !B' ' ' test_expect_success 'file remove !A, B' ' - cat >expected <<\EXPECTED && -removed in remote - base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE - our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE -@@ -1 +0,0 @@ --AAA -EXPECTED - git reset --hard initial && test_commit "rm-not-a-b-base" "ONE" "AAA" && git rm ONE && git commit -m "rm-not-a-b" && git tag "rm-not-a-b" && git merge-tree rm-a-not-b-base rm-a-not-b-base rm-a-not-b >actual && + cat >expected <<EXPECTED && +removed in remote + base 100644 $(git rev-parse rm-a-not-b-base:ONE) ONE + our 100644 $(git rev-parse rm-a-not-b-base:ONE) ONE +@@ -1 +0,0 @@ +-AAA +EXPECTED + test_cmp expected actual ' @@ -201,14 +202,6 @@ test_expect_success 'file remove A, B (same)' ' ' test_expect_success 'file change A, remove B' ' - cat >expected <<\EXPECTED && -removed in remote - base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE - our 100644 ba629238ca89489f2b350e196ca445e09d8bb834 ONE -@@ -1 +0,0 @@ --BBB -EXPECTED - git reset --hard initial && test_commit "change-a-rm-b-base" "ONE" "AAA" && test_commit "change-a-rm-b-A" "ONE" "BBB" && @@ -218,16 +211,18 @@ EXPECTED git tag "change-a-rm-b-B" && git merge-tree change-a-rm-b-base change-a-rm-b-A change-a-rm-b-B \ >actual && + cat >expected <<EXPECTED && +removed in remote + base 100644 $(git rev-parse change-a-rm-b-base:ONE) ONE + our 100644 $(git rev-parse change-a-rm-b-A:ONE ) ONE +@@ -1 +0,0 @@ +-BBB +EXPECTED + test_cmp expected actual ' test_expect_success 'file remove A, change B' ' - cat >expected <<\EXPECTED && -removed in local - base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d ONE - their 100644 ba629238ca89489f2b350e196ca445e09d8bb834 ONE -EXPECTED - git reset --hard initial && test_commit "rm-a-change-b-base" "ONE" "AAA" && @@ -238,6 +233,11 @@ EXPECTED test_commit "rm-a-change-b-B" "ONE" "BBB" && git merge-tree rm-a-change-b-base rm-a-change-b-A rm-a-change-b-B \ >actual && + cat >expected <<EXPECTED && +removed in local + base 100644 $(git rev-parse rm-a-change-b-base:ONE) ONE + their 100644 $(git rev-parse rm-a-change-b-B:ONE ) ONE +EXPECTED test_cmp expected actual ' @@ -250,10 +250,17 @@ test_expect_success 'tree add A, B (same)' ' ' test_expect_success 'tree add A, B (different)' ' - cat >expect <<-\EOF && + git reset --hard initial && + mkdir sub && + test_commit "add sub/file" "sub/file" "AAA" add-tree-a-b-A && + git reset --hard initial && + mkdir sub && + test_commit "add sub/file" "sub/file" "BBB" add-tree-a-b-B && + git merge-tree initial add-tree-a-b-A add-tree-a-b-B >actual && + cat >expect <<-EOF && added in both - our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d sub/file - their 100644 ba629238ca89489f2b350e196ca445e09d8bb834 sub/file + our 100644 $(git rev-parse add-tree-a-b-A:sub/file) sub/file + their 100644 $(git rev-parse add-tree-a-b-B:sub/file) sub/file @@ -1 +1,5 @@ +<<<<<<< .our AAA @@ -261,24 +268,10 @@ test_expect_success 'tree add A, B (different)' ' +BBB +>>>>>>> .their EOF - git reset --hard initial && - mkdir sub && - test_commit "add sub/file" "sub/file" "AAA" add-tree-a-b-A && - git reset --hard initial && - mkdir sub && - test_commit "add sub/file" "sub/file" "BBB" add-tree-a-b-B && - git merge-tree initial add-tree-a-b-A add-tree-a-b-B >actual && test_cmp expect actual ' test_expect_success 'tree unchanged A, removed B' ' - cat >expect <<-\EOF && - removed in remote - base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d sub/file - our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d sub/file - @@ -1 +0,0 @@ - -AAA - EOF git reset --hard initial && mkdir sub && test_commit "add sub/file" "sub/file" "AAA" tree-remove-b-initial && @@ -287,6 +280,13 @@ test_expect_success 'tree unchanged A, removed B' ' git commit -m "remove sub/file" && git tag tree-remove-b-B && git merge-tree tree-remove-b-initial tree-remove-b-initial tree-remove-b-B >actual && + cat >expect <<-EOF && + removed in remote + base 100644 $(git rev-parse tree-remove-b-initial:sub/file) sub/file + our 100644 $(git rev-parse tree-remove-b-initial:sub/file) sub/file + @@ -1 +0,0 @@ + -AAA + EOF test_cmp expect actual ' @@ -296,14 +296,14 @@ test_expect_success 'turn file to tree' ' mkdir initial-file && test_commit "turn-file-to-tree" "initial-file/ONE" "CCC" && git merge-tree initial initial turn-file-to-tree >actual && - cat >expect <<-\EOF && + cat >expect <<-EOF && added in remote - their 100644 43aa4fdec31eb92e1fdc2f0ce6ea9ddb7c32bcf7 initial-file/ONE + their 100644 $(git rev-parse turn-file-to-tree:initial-file/ONE) initial-file/ONE @@ -0,0 +1 @@ +CCC removed in remote - base 100644 e79c5e8f964493290a409888d5413a737e8e5dd5 initial-file - our 100644 e79c5e8f964493290a409888d5413a737e8e5dd5 initial-file + base 100644 $(git rev-parse initial:initial-file) initial-file + our 100644 $(git rev-parse initial:initial-file) initial-file @@ -1 +0,0 @@ -initial EOF @@ -318,14 +318,14 @@ test_expect_success 'turn tree to file' ' rm -fr dir && test_commit "make-file" "dir" "CCC" && git merge-tree add-tree add-another-tree make-file >actual && - cat >expect <<-\EOF && + cat >expect <<-EOF && removed in remote - base 100644 43d5a8ed6ef6c00ff775008633f95787d088285d dir/path - our 100644 43d5a8ed6ef6c00ff775008633f95787d088285d dir/path + base 100644 $(git rev-parse add-tree:dir/path) dir/path + our 100644 $(git rev-parse add-tree:dir/path) dir/path @@ -1 +0,0 @@ -AAA added in remote - their 100644 43aa4fdec31eb92e1fdc2f0ce6ea9ddb7c32bcf7 dir + their 100644 $(git rev-parse make-file:dir) dir @@ -0,0 +1 @@ +CCC EOF diff --git a/t/t5003-archive-zip.sh b/t/t5003-archive-zip.sh index 106eddbd85..3b76d2eb65 100755 --- a/t/t5003-archive-zip.sh +++ b/t/t5003-archive-zip.sh @@ -7,12 +7,12 @@ test_description='git archive --format=zip test' SUBSTFORMAT=%H%n test_lazy_prereq UNZIP_SYMLINKS ' - ( - mkdir unzip-symlinks && - cd unzip-symlinks && - "$GIT_UNZIP" "$TEST_DIRECTORY"/t5003/infozip-symlinks.zip && - test -h symlink - ) + "$GIT_UNZIP" "$TEST_DIRECTORY"/t5003/infozip-symlinks.zip && + test -h symlink +' + +test_lazy_prereq UNZIP_CONVERT ' + "$GIT_UNZIP" -a "$TEST_DIRECTORY"/t5003/infozip-symlinks.zip ' check_zip() { @@ -39,33 +39,33 @@ check_zip() { extracted=${dir_with_prefix}a original=a - test_expect_success UNZIP " extract ZIP archive with EOL conversion" ' + test_expect_success UNZIP_CONVERT " extract ZIP archive with EOL conversion" ' (mkdir $dir && cd $dir && "$GIT_UNZIP" -a ../$zipfile) ' - test_expect_success UNZIP " validate that text files are converted" " + test_expect_success UNZIP_CONVERT " validate that text files are converted" " test_cmp_bin $extracted/text.cr $extracted/text.crlf && test_cmp_bin $extracted/text.cr $extracted/text.lf " - test_expect_success UNZIP " validate that binary files are unchanged" " + test_expect_success UNZIP_CONVERT " validate that binary files are unchanged" " test_cmp_bin $original/binary.cr $extracted/binary.cr && test_cmp_bin $original/binary.crlf $extracted/binary.crlf && test_cmp_bin $original/binary.lf $extracted/binary.lf " - test_expect_success UNZIP " validate that diff files are converted" " + test_expect_success UNZIP_CONVERT " validate that diff files are converted" " test_cmp_bin $extracted/diff.cr $extracted/diff.crlf && test_cmp_bin $extracted/diff.cr $extracted/diff.lf " - test_expect_success UNZIP " validate that -diff files are unchanged" " + test_expect_success UNZIP_CONVERT " validate that -diff files are unchanged" " test_cmp_bin $original/nodiff.cr $extracted/nodiff.cr && test_cmp_bin $original/nodiff.crlf $extracted/nodiff.crlf && test_cmp_bin $original/nodiff.lf $extracted/nodiff.lf " - test_expect_success UNZIP " validate that custom diff is unchanged " " + test_expect_success UNZIP_CONVERT " validate that custom diff is unchanged " " test_cmp_bin $original/custom.cr $extracted/custom.cr && test_cmp_bin $original/custom.crlf $extracted/custom.crlf && test_cmp_bin $original/custom.lf $extracted/custom.lf diff --git a/t/t5100-mailinfo.sh b/t/t5100-mailinfo.sh index 9690dcad4f..147e616533 100755 --- a/t/t5100-mailinfo.sh +++ b/t/t5100-mailinfo.sh @@ -213,4 +213,19 @@ test_expect_failure 'mailinfo -b separated double [PATCH]' ' test z"$subj" = z"Subject: [other] message" ' +test_expect_success 'mailinfo handles unusual header whitespace' ' + git mailinfo /dev/null /dev/null >actual <<-\EOF && + From:Real Name <user@example.com> + Subject: extra spaces + EOF + + cat >expect <<-\EOF && + Author: Real Name + Email: user@example.com + Subject: extra spaces + + EOF + test_cmp expect actual +' + test_done diff --git a/t/t5150-request-pull.sh b/t/t5150-request-pull.sh index 1ad4ecc29a..c1811ea0f4 100755 --- a/t/t5150-request-pull.sh +++ b/t/t5150-request-pull.sh @@ -150,7 +150,6 @@ test_expect_success 'pull request after push' ' git request-pull initial origin master:for-upstream >../request ) && sed -nf read-request.sed <request >digest && - cat digest && { read task && read repository && @@ -179,7 +178,6 @@ test_expect_success 'request asks HEAD to be pulled' ' git request-pull initial "$downstream_url" >../request ) && sed -nf read-request.sed <request >digest && - cat digest && { read task && read repository && diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh index 91d51b35f9..ad07f2f7fc 100755 --- a/t/t5302-pack-index.sh +++ b/t/t5302-pack-index.sh @@ -6,9 +6,10 @@ test_description='pack index with 64-bit offsets and object CRC' . ./test-lib.sh -test_expect_success \ - 'setup' \ - 'rm -rf .git && +test_expect_success 'setup' ' + test_oid_init && + rawsz=$(test_oid rawsz) && + rm -rf .git && git init && git config pack.threads 1 && i=1 && @@ -32,7 +33,8 @@ test_expect_success \ echo $tree && git ls-tree $tree | sed -e "s/.* \\([0-9a-f]*\\) .*/\\1/" } >obj-list && - git update-ref HEAD $commit' + git update-ref HEAD $commit +' test_expect_success \ 'pack-objects with index version 1' \ @@ -157,10 +159,11 @@ test_expect_success \ offs_101=$(index_obj_offset 1.idx $sha1_101) && nr_099=$(index_obj_nr 1.idx $sha1_099) && chmod +w ".git/objects/pack/pack-${pack1}.pack" && + recordsz=$((rawsz + 4)) && dd of=".git/objects/pack/pack-${pack1}.pack" seek=$(($offs_101 + 1)) \ if=".git/objects/pack/pack-${pack1}.idx" \ - skip=$((4 + 256 * 4 + $nr_099 * 24)) \ - bs=1 count=20 conv=notrunc && + skip=$((4 + 256 * 4 + $nr_099 * recordsz)) \ + bs=1 count=$rawsz conv=notrunc && git cat-file blob $sha1_101 > file_101_foo1' test_expect_success \ @@ -200,8 +203,8 @@ test_expect_success \ chmod +w ".git/objects/pack/pack-${pack1}.pack" && dd of=".git/objects/pack/pack-${pack1}.pack" seek=$(($offs_101 + 1)) \ if=".git/objects/pack/pack-${pack1}.idx" \ - skip=$((8 + 256 * 4 + $nr_099 * 20)) \ - bs=1 count=20 conv=notrunc && + skip=$((8 + 256 * 4 + $nr_099 * rawsz)) \ + bs=1 count=$rawsz conv=notrunc && git cat-file blob $sha1_101 > file_101_foo2' test_expect_success \ @@ -226,7 +229,7 @@ test_expect_success \ nr=$(index_obj_nr ".git/objects/pack/pack-${pack1}.idx" $obj) && chmod +w ".git/objects/pack/pack-${pack1}.idx" && printf xxxx | dd of=".git/objects/pack/pack-${pack1}.idx" conv=notrunc \ - bs=1 count=4 seek=$((8 + 256 * 4 + $(wc -l <obj-list) * 20 + $nr * 4)) && + bs=1 count=4 seek=$((8 + 256 * 4 + $(wc -l <obj-list) * rawsz + $nr * 4)) && ( while read obj do git cat-file -p $obj >/dev/null || exit 1 done <obj-list ) && diff --git a/t/t5309-pack-delta-cycles.sh b/t/t5309-pack-delta-cycles.sh index 491556dad9..55b787630f 100755 --- a/t/t5309-pack-delta-cycles.sh +++ b/t/t5309-pack-delta-cycles.sh @@ -4,15 +4,9 @@ test_description='test index-pack handling of delta cycles in packfiles' . ./test-lib.sh . "$TEST_DIRECTORY"/lib-pack.sh -if ! test_have_prereq SHA1 -then - skip_all='not using SHA-1 for objects' - test_done -fi - # Two similar-ish objects that we have computed deltas between. -A=01d7713666f4de822776c7622c10f1b07de280dc -B=e68fe8129b546b101aee9510c5328e7f21ca1d18 +A=$(test_oid packlib_7_0) +B=$(test_oid packlib_7_76) # double-check our hand-constucted packs test_expect_success 'index-pack works with a single delta (A->B)' ' @@ -62,13 +56,13 @@ test_expect_success 'index-pack detects REF_DELTA cycles' ' test_must_fail git index-pack --fix-thin --stdin <cycle.pack ' -test_expect_failure 'failover to an object in another pack' ' +test_expect_success 'failover to an object in another pack' ' clear_packs && git index-pack --stdin <ab.pack && - git index-pack --stdin --fix-thin <cycle.pack + test_must_fail git index-pack --stdin --fix-thin <cycle.pack ' -test_expect_failure 'failover to a duplicate object in the same pack' ' +test_expect_success 'failover to a duplicate object in the same pack' ' clear_packs && { pack_header 3 && @@ -77,7 +71,7 @@ test_expect_failure 'failover to a duplicate object in the same pack' ' pack_obj $A } >recoverable.pack && pack_trailer recoverable.pack && - git index-pack --fix-thin --stdin <recoverable.pack + test_must_fail git index-pack --fix-thin --stdin <recoverable.pack ' test_done diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh index 6640329ebf..8318781d2b 100755 --- a/t/t5310-pack-bitmaps.sh +++ b/t/t5310-pack-bitmaps.sh @@ -74,16 +74,24 @@ rev_list_tests() { test_cmp expect actual ' - test_expect_success "enumerate --objects ($state)" ' - git rev-list --objects --use-bitmap-index HEAD >tmp && - cut -d" " -f1 <tmp >tmp2 && - sort <tmp2 >actual && - git rev-list --objects HEAD >tmp && - cut -d" " -f1 <tmp >tmp2 && - sort <tmp2 >expect && + test_expect_success "counting objects via bitmap ($state)" ' + git rev-list --count --objects HEAD >expect && + git rev-list --use-bitmap-index --count --objects HEAD >actual && test_cmp expect actual ' + test_expect_success "enumerate commits ($state)" ' + git rev-list --use-bitmap-index HEAD >actual && + git rev-list HEAD >expect && + test_bitmap_traversal --no-confirm-bitmaps expect actual + ' + + test_expect_success "enumerate --objects ($state)" ' + git rev-list --objects --use-bitmap-index HEAD >actual && + git rev-list --objects HEAD >expect && + test_bitmap_traversal expect actual + ' + test_expect_success "bitmap --objects handles non-commit objects ($state)" ' git rev-list --objects --use-bitmap-index HEAD tagged-blob >actual && grep $blob actual @@ -99,6 +107,20 @@ test_expect_success 'clone from bitmapped repository' ' test_cmp expect actual ' +test_expect_success 'partial clone from bitmapped repository' ' + test_config uploadpack.allowfilter true && + git clone --no-local --bare --filter=blob:none . partial-clone.git && + ( + cd partial-clone.git && + pack=$(echo objects/pack/*.pack) && + git verify-pack -v "$pack" >have && + awk "/blob/ { print \$1 }" <have >blobs && + # we expect this single blob because of the direct ref + git rev-parse refs/tags/tagged-blob >expect && + test_cmp expect blobs + ) +' + test_expect_success 'setup further non-bitmapped commits' ' test_commit_bulk --id=further 10 ' diff --git a/t/t5313-pack-bounds-checks.sh b/t/t5313-pack-bounds-checks.sh index f1708d415e..2a4557efc2 100755 --- a/t/t5313-pack-bounds-checks.sh +++ b/t/t5313-pack-bounds-checks.sh @@ -38,16 +38,27 @@ munge () { # for the initial, and another ofs(4*nr) past that for the extended. # ofs_table () { - echo $((4 + 4 + 4*256 + 20*$1 + 4*$1)) + echo $((4 + 4 + 4*256 + $(test_oid rawsz)*$1 + 4*$1)) } extended_table () { echo $(($(ofs_table "$1") + 4*$1)) } +test_expect_success 'setup' ' + test_oid_init && + test_oid_cache <<-EOF + oid000 sha1:1485 + oid000 sha256:4222 + + oidfff sha1:74 + oidfff sha256:1350 + EOF +' + test_expect_success 'set up base packfile and variables' ' # the hash of this content starts with ff, which # makes some later computations much simpler - echo 74 >file && + echo $(test_oid oidfff) >file && git add file && git commit -m base && git repack -ad && @@ -140,10 +151,10 @@ test_expect_success 'bogus offset inside v2 extended table' ' # an extended table (if the first object were larger than 2^31). # # Note that the value is important here. We want $object as - # the second entry in sorted-sha1 order. The sha1 of 1485 starts + # the second entry in sorted-hash order. The hash of this object starts # with "000", which sorts before that of $object (which starts # with "fff"). - second=$(echo 1485 | git hash-object -w --stdin) && + second=$(test_oid oid000 | git hash-object -w --stdin) && do_pack "$object $second" --index-version=2 && # We have to make extra room for the table, so we cannot diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh index 3f03de6018..424599959c 100755 --- a/t/t5318-commit-graph.sh +++ b/t/t5318-commit-graph.sh @@ -3,6 +3,8 @@ test_description='commit graph' . ./test-lib.sh +GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0 + test_expect_success 'setup full repo' ' mkdir full && cd "$TRASH_DIRECTORY/full" && @@ -12,6 +14,10 @@ test_expect_success 'setup full repo' ' test_oid_init ' +test_expect_success POSIXPERM 'tweak umask for modebit tests' ' + umask 022 +' + test_expect_success 'verify graph with no graph file' ' cd "$TRASH_DIRECTORY/full" && git commit-graph verify @@ -19,8 +25,8 @@ test_expect_success 'verify graph with no graph file' ' test_expect_success 'write graph with no packs' ' cd "$TRASH_DIRECTORY/full" && - git commit-graph write --object-dir . && - test_path_is_missing info/commit-graph + git commit-graph write --object-dir $objdir && + test_path_is_missing $objdir/info/commit-graph ' test_expect_success 'exit with correct error on bad input to --stdin-packs' ' @@ -43,7 +49,7 @@ test_expect_success 'create commits and repack' ' test_expect_success 'exit with correct error on bad input to --stdin-commits' ' cd "$TRASH_DIRECTORY/full" && echo HEAD | test_expect_code 1 git commit-graph write --stdin-commits 2>stderr && - test_i18ngrep "invalid commit object id" stderr && + test_i18ngrep "unexpected non-hex object ID: HEAD" stderr && # valid tree OID, but not a commit OID git rev-parse HEAD^{tree} | test_expect_code 1 git commit-graph write --stdin-commits 2>stderr && test_i18ngrep "invalid commit object id" stderr @@ -96,6 +102,13 @@ test_expect_success 'write graph' ' graph_read_expect "3" ' +test_expect_success POSIXPERM 'write graph has correct permissions' ' + test_path_is_file $objdir/info/commit-graph && + echo "-r--r--r--" >expect && + test_modebits $objdir/info/commit-graph >actual && + test_cmp expect actual +' + graph_git_behavior 'graph exists' full commits/3 commits/1 test_expect_success 'Add more commits' ' @@ -421,7 +434,8 @@ GRAPH_BYTE_FOOTER=$(($GRAPH_OCTOPUS_DATA_OFFSET + 4 * $NUM_OCTOPUS_EDGES)) corrupt_graph_setup() { cd "$TRASH_DIRECTORY/full" && test_when_finished mv commit-graph-backup $objdir/info/commit-graph && - cp $objdir/info/commit-graph commit-graph-backup + cp $objdir/info/commit-graph commit-graph-backup && + chmod u+w $objdir/info/commit-graph } corrupt_graph_verify() { @@ -435,6 +449,7 @@ corrupt_graph_verify() { fi && git status --short && GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD=true git commit-graph write && + chmod u+w $objdir/info/commit-graph && git commit-graph verify } @@ -481,7 +496,7 @@ test_expect_success 'detect bad version' ' ' test_expect_success 'detect bad hash version' ' - corrupt_graph_and_verify $GRAPH_BYTE_HASH "\02" \ + corrupt_graph_and_verify $GRAPH_BYTE_HASH "\03" \ "hash version" ' @@ -629,7 +644,7 @@ test_expect_success 'corrupt commit-graph write (broken parent)' ' empty="$(git mktree </dev/null)" && cat >broken <<-EOF && tree $empty - parent 0000000000000000000000000000000000000000 + parent $ZERO_OID author whatever <whatever@example.com> 1234 -0000 committer whatever <whatever@example.com> 1234 -0000 @@ -650,7 +665,7 @@ test_expect_success 'corrupt commit-graph write (missing tree)' ' cd repo && tree="$(git mktree </dev/null)" && cat >broken <<-EOF && - parent 0000000000000000000000000000000000000000 + parent $ZERO_OID author whatever <whatever@example.com> 1234 -0000 committer whatever <whatever@example.com> 1234 -0000 diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh index cd2f87be6a..030a7222b2 100755 --- a/t/t5319-multi-pack-index.sh +++ b/t/t5319-multi-pack-index.sh @@ -28,10 +28,29 @@ midx_read_expect () { test_cmp expect actual } -test_expect_success 'write midx with no packs' ' - test_when_finished rm -f pack/multi-pack-index && - git multi-pack-index --object-dir=. write && - midx_read_expect 0 0 4 . +test_expect_success 'setup' ' + test_oid_init && + test_oid_cache <<-EOF + idxoff sha1:2999 + idxoff sha256:3739 + + packnameoff sha1:652 + packnameoff sha256:940 + + fanoutoff sha1:1 + fanoutoff sha256:3 + EOF +' + +test_expect_success "don't write midx with no packs" ' + test_must_fail git multi-pack-index --object-dir=. write && + test_path_is_missing pack/multi-pack-index +' + +test_expect_success "Warn if a midx contains no oid" ' + cp "$TEST_DIRECTORY"/t5319/no-objects.midx $objdir/pack/multi-pack-index && + test_must_fail git multi-pack-index verify && + rm $objdir/pack/multi-pack-index ' generate_objects () { @@ -225,7 +244,7 @@ test_expect_success 'verify bad signature' ' "multi-pack-index signature" ' -HASH_LEN=20 +HASH_LEN=$(test_oid rawsz) NUM_OBJECTS=74 MIDX_BYTE_VERSION=4 MIDX_BYTE_OID_VERSION=5 @@ -238,9 +257,9 @@ MIDX_CHUNK_LOOKUP_WIDTH=12 MIDX_OFFSET_PACKNAMES=$(($MIDX_HEADER_SIZE + \ $MIDX_NUM_CHUNKS * $MIDX_CHUNK_LOOKUP_WIDTH)) MIDX_BYTE_PACKNAME_ORDER=$(($MIDX_OFFSET_PACKNAMES + 2)) -MIDX_OFFSET_OID_FANOUT=$(($MIDX_OFFSET_PACKNAMES + 652)) +MIDX_OFFSET_OID_FANOUT=$(($MIDX_OFFSET_PACKNAMES + $(test_oid packnameoff))) MIDX_OID_FANOUT_WIDTH=4 -MIDX_BYTE_OID_FANOUT_ORDER=$((MIDX_OFFSET_OID_FANOUT + 250 * $MIDX_OID_FANOUT_WIDTH + 1)) +MIDX_BYTE_OID_FANOUT_ORDER=$((MIDX_OFFSET_OID_FANOUT + 250 * $MIDX_OID_FANOUT_WIDTH + $(test_oid fanoutoff))) MIDX_OFFSET_OID_LOOKUP=$(($MIDX_OFFSET_OID_FANOUT + 256 * $MIDX_OID_FANOUT_WIDTH)) MIDX_BYTE_OID_LOOKUP=$(($MIDX_OFFSET_OID_LOOKUP + 16 * $HASH_LEN)) MIDX_OFFSET_OBJECT_OFFSETS=$(($MIDX_OFFSET_OID_LOOKUP + $NUM_OBJECTS * $HASH_LEN)) @@ -304,12 +323,12 @@ test_expect_success 'verify incorrect pack-int-id' ' ' test_expect_success 'verify incorrect offset' ' - corrupt_midx_and_verify $MIDX_BYTE_OFFSET "\07" $objdir \ + corrupt_midx_and_verify $MIDX_BYTE_OFFSET "\377" $objdir \ "incorrect object offset" ' test_expect_success 'git-fsck incorrect offset' ' - corrupt_midx_and_verify $MIDX_BYTE_OFFSET "\07" $objdir \ + corrupt_midx_and_verify $MIDX_BYTE_OFFSET "\377" $objdir \ "incorrect object offset" \ "git -c core.multipackindex=true fsck" ' @@ -387,7 +406,7 @@ test_expect_success 'force some 64-bit offsets with pack-objects' ' pack64=$(git pack-objects --index-version=2,0x40 objects64/pack/test-64 <obj-list) && idx64=objects64/pack/test-64-$pack64.idx && chmod u+w $idx64 && - corrupt_data $idx64 2999 "\02" && + corrupt_data $idx64 $(test_oid idxoff) "\02" && midx64=$(git multi-pack-index --object-dir=objects64 write) && midx_read_expect 1 63 5 objects64 " large-offsets" ' @@ -507,10 +526,10 @@ test_expect_success 'repack with minimum size does not alter existing packs' ' cd dup && rm -rf .git/objects/pack && mv .git/objects/pack-backup .git/objects/pack && - touch -m -t 201901010000 .git/objects/pack/pack-D* && - touch -m -t 201901010001 .git/objects/pack/pack-C* && - touch -m -t 201901010002 .git/objects/pack/pack-B* && - touch -m -t 201901010003 .git/objects/pack/pack-A* && + test-tool chmtime =-5 .git/objects/pack/pack-D* && + test-tool chmtime =-4 .git/objects/pack/pack-C* && + test-tool chmtime =-3 .git/objects/pack/pack-B* && + test-tool chmtime =-2 .git/objects/pack/pack-A* && ls .git/objects/pack >expect && MINSIZE=$(test-tool path-utils file-size .git/objects/pack/*pack | sort -n | head -n 1) && git multi-pack-index repack --batch-size=$MINSIZE && diff --git a/t/t5319/no-objects.midx b/t/t5319/no-objects.midx Binary files differnew file mode 100644 index 0000000000..e466b8e086 --- /dev/null +++ b/t/t5319/no-objects.midx diff --git a/t/t5321-pack-large-objects.sh b/t/t5321-pack-large-objects.sh index a75eab87d3..8a56d98a0e 100755 --- a/t/t5321-pack-large-objects.sh +++ b/t/t5321-pack-large-objects.sh @@ -10,8 +10,8 @@ test_description='git pack-object with "large" deltas . "$TEST_DIRECTORY"/lib-pack.sh # Two similar-ish objects that we have computed deltas between. -A=01d7713666f4de822776c7622c10f1b07de280dc -B=e68fe8129b546b101aee9510c5328e7f21ca1d18 +A=$(test_oid packlib_7_0) +B=$(test_oid packlib_7_76) test_expect_success 'setup' ' clear_packs && diff --git a/t/t5322-pack-objects-sparse.sh b/t/t5322-pack-objects-sparse.sh index 7124b5581a..a581eaf529 100755 --- a/t/t5322-pack-objects-sparse.sh +++ b/t/t5322-pack-objects-sparse.sh @@ -105,14 +105,16 @@ test_expect_success 'non-sparse pack-objects' ' test_cmp required_objects.txt nonsparse_required_objects.txt ' +# --sparse is enabled by default by pack.useSparse test_expect_success 'sparse pack-objects' ' + GIT_TEST_PACK_SPARSE=-1 && git rev-parse \ topic1 \ topic1^{tree} \ topic1:f3 \ topic1:f3/f4 \ topic1:f3/f4/data.txt | sort >expect_sparse_objects.txt && - git pack-objects --stdout --revs --sparse <packinput.txt >sparse.pack && + git pack-objects --stdout --revs <packinput.txt >sparse.pack && git index-pack -o sparse.idx sparse.pack && git show-index <sparse.idx | awk "{print \$2}" >sparse_objects.txt && test_cmp expect_sparse_objects.txt sparse_objects.txt diff --git a/t/t5324-split-commit-graph.sh b/t/t5324-split-commit-graph.sh index c24823431f..269d0964a3 100755 --- a/t/t5324-split-commit-graph.sh +++ b/t/t5324-split-commit-graph.sh @@ -4,6 +4,7 @@ test_description='split commit graph' . ./test-lib.sh GIT_TEST_COMMIT_GRAPH=0 +GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=0 test_expect_success 'setup repo' ' git init && @@ -11,7 +12,14 @@ test_expect_success 'setup repo' ' git config gc.writeCommitGraph false && infodir=".git/objects/info" && graphdir="$infodir/commit-graphs" && - test_oid_init + test_oid_init && + test_oid_cache <<-EOM + shallow sha1:1760 + shallow sha256:2064 + + base sha1:1376 + base sha256:1496 + EOM ' graph_read_expect() { @@ -29,6 +37,10 @@ graph_read_expect() { test_cmp expect output } +test_expect_success POSIXPERM 'tweak umask for modebit tests' ' + umask 022 +' + test_expect_success 'create commits and write commit-graph' ' for i in $(test_seq 3) do @@ -203,8 +215,14 @@ test_expect_success 'test merge stragety constants' ' git config core.commitGraph true && test_line_count = 2 $graphdir/commit-graph-chain && test_commit 15 && - git commit-graph write --reachable --split --size-multiple=10 --expire-time=1980-01-01 && + touch $graphdir/to-delete.graph $graphdir/to-keep.graph && + test-tool chmtime =1546362000 $graphdir/to-delete.graph && + test-tool chmtime =1546362001 $graphdir/to-keep.graph && + git commit-graph write --reachable --split --size-multiple=10 \ + --expire-time="2019-01-01 12:00 -05:00" && test_line_count = 1 $graphdir/commit-graph-chain && + test_path_is_missing $graphdir/to-delete.graph && + test_path_is_file $graphdir/to-keep.graph && ls $graphdir/graph-*.graph >graph-files && test_line_count = 3 graph-files ) && @@ -248,7 +266,7 @@ test_expect_success 'verify hashes along chain, even in shallow' ' cd verify && git commit-graph verify && base_file=$graphdir/graph-$(head -n 1 $graphdir/commit-graph-chain).graph && - corrupt_file "$base_file" 1760 "\01" && + corrupt_file "$base_file" $(test_oid shallow) "\01" && test_must_fail git commit-graph verify --shallow 2>test_err && grep -v "^+" test_err >err && test_i18ngrep "incorrect checksum" err @@ -275,7 +293,7 @@ test_expect_success 'warn on base graph chunk incorrect' ' cd base-chunk && git commit-graph verify && base_file=$graphdir/graph-$(tail -n 1 $graphdir/commit-graph-chain).graph && - corrupt_file "$base_file" 1376 "\01" && + corrupt_file "$base_file" $(test_oid base) "\01" && git commit-graph verify --shallow 2>test_err && grep -v "^+" test_err >err && test_i18ngrep "commit-graph chain does not match" err @@ -344,4 +362,67 @@ test_expect_success 'split across alternate where alternate is not split' ' test_cmp commit-graph .git/objects/info/commit-graph ' +test_expect_success '--split=no-merge always writes an incremental' ' + test_when_finished rm -rf a b && + rm -rf $graphdir $infodir/commit-graph && + git reset --hard commits/2 && + git rev-list HEAD~1 >a && + git rev-list HEAD >b && + git commit-graph write --split --stdin-commits <a && + git commit-graph write --split=no-merge --stdin-commits <b && + test_line_count = 2 $graphdir/commit-graph-chain +' + +test_expect_success '--split=replace replaces the chain' ' + rm -rf $graphdir $infodir/commit-graph && + git reset --hard commits/3 && + git rev-list -1 HEAD~2 >a && + git rev-list -1 HEAD~1 >b && + git rev-list -1 HEAD >c && + git commit-graph write --split=no-merge --stdin-commits <a && + git commit-graph write --split=no-merge --stdin-commits <b && + git commit-graph write --split=no-merge --stdin-commits <c && + test_line_count = 3 $graphdir/commit-graph-chain && + git commit-graph write --stdin-commits --split=replace <b && + test_path_is_missing $infodir/commit-graph && + test_path_is_file $graphdir/commit-graph-chain && + ls $graphdir/graph-*.graph >graph-files && + test_line_count = 1 graph-files && + verify_chain_files_exist $graphdir && + graph_read_expect 2 +' + +test_expect_success ULIMIT_FILE_DESCRIPTORS 'handles file descriptor exhaustion' ' + git init ulimit && + ( + cd ulimit && + for i in $(test_seq 64) + do + test_commit $i && + test_might_fail run_with_limited_open_files git commit-graph write \ + --split=no-merge --reachable || return 1 + done + ) +' + +while read mode modebits +do + test_expect_success POSIXPERM "split commit-graph respects core.sharedrepository $mode" ' + rm -rf $graphdir $infodir/commit-graph && + git reset --hard commits/1 && + test_config core.sharedrepository "$mode" && + git commit-graph write --split --reachable && + ls $graphdir/graph-*.graph >graph-files && + test_line_count = 1 graph-files && + echo "$modebits" >expect && + test_modebits $graphdir/graph-*.graph >actual && + test_cmp expect actual && + test_modebits $graphdir/commit-graph-chain >actual && + test_cmp expect actual + ' +done <<\EOF +0666 -r--r--r-- +0600 -r-------- +EOF + test_done diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh index 571d620aed..b84618c925 100755 --- a/t/t5400-send-pack.sh +++ b/t/t5400-send-pack.sh @@ -288,7 +288,7 @@ test_expect_success 'receive-pack de-dupes .have lines' ' $shared .have EOF - GIT_TRACE_PACKET=$(pwd)/trace GIT_TEST_PROTOCOL_VERSION= \ + GIT_TRACE_PACKET=$(pwd)/trace GIT_TEST_PROTOCOL_VERSION=0 \ git push \ --receive-pack="unset GIT_TRACE_PACKET; git-receive-pack" \ fork HEAD:foo && diff --git a/t/t5407-post-rewrite-hook.sh b/t/t5407-post-rewrite-hook.sh index 7344253bfb..80750a817e 100755 --- a/t/t5407-post-rewrite-hook.sh +++ b/t/t5407-post-rewrite-hook.sh @@ -53,10 +53,10 @@ test_expect_success 'git commit --amend --no-post-rewrite' ' test ! -f post-rewrite.data ' -test_expect_success 'git rebase' ' +test_expect_success 'git rebase --apply' ' git reset --hard D && clear_hook_input && - test_must_fail git rebase --onto A B && + test_must_fail git rebase --apply --onto A B && echo C > foo && git add foo && git rebase --continue && @@ -68,10 +68,10 @@ test_expect_success 'git rebase' ' verify_hook_input ' -test_expect_success 'git rebase --skip' ' +test_expect_success 'git rebase --apply --skip' ' git reset --hard D && clear_hook_input && - test_must_fail git rebase --onto A B && + test_must_fail git rebase --apply --onto A B && test_must_fail git rebase --skip && echo D > foo && git add foo && @@ -84,10 +84,10 @@ test_expect_success 'git rebase --skip' ' verify_hook_input ' -test_expect_success 'git rebase --skip the last one' ' +test_expect_success 'git rebase --apply --skip the last one' ' git reset --hard F && clear_hook_input && - test_must_fail git rebase --onto D A && + test_must_fail git rebase --apply --onto D A && git rebase --skip && echo rebase >expected.args && cat >expected.data <<-EOF && @@ -128,7 +128,7 @@ test_expect_success 'git rebase -m --skip' ' verify_hook_input ' -test_expect_success 'git rebase with implicit use of interactive backend' ' +test_expect_success 'git rebase with implicit use of merge backend' ' git reset --hard D && clear_hook_input && test_must_fail git rebase --keep-empty --onto A B && @@ -143,7 +143,7 @@ test_expect_success 'git rebase with implicit use of interactive backend' ' verify_hook_input ' -test_expect_success 'git rebase --skip with implicit use of interactive backend' ' +test_expect_success 'git rebase --skip with implicit use of merge backend' ' git reset --hard D && clear_hook_input && test_must_fail git rebase --keep-empty --onto A B && diff --git a/t/t5409-colorize-remote-messages.sh b/t/t5409-colorize-remote-messages.sh index 2a8c449661..5d8f401d8e 100755 --- a/t/t5409-colorize-remote-messages.sh +++ b/t/t5409-colorize-remote-messages.sh @@ -56,14 +56,13 @@ test_expect_success 'short line' ' test_expect_success 'case-insensitive' ' git --git-dir child/.git -c color.remote=always push -f origin HEAD:refs/heads/case-insensitive 2>output && - cat output && test_decode_color <output >decoded && grep "<BOLD;RED>error<RESET>: error" decoded && grep "<BOLD;RED>ERROR<RESET>: also highlighted" decoded ' test_expect_success 'leading space' ' - git --git-dir child/.git -c color.remote=always push -f origin HEAD:refs/heads/leading-space 2>output && cat output && + git --git-dir child/.git -c color.remote=always push -f origin HEAD:refs/heads/leading-space 2>output && test_decode_color <output >decoded && grep " <BOLD;RED>error<RESET>: leading space" decoded ' diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh index 6b97923964..52dd1a688c 100755 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@ -385,6 +385,54 @@ test_expect_success 'clone shallow with packed refs' ' test_cmp count8.expected count8.actual ' +test_expect_success 'in_vain not triggered before first ACK' ' + rm -rf myserver myclient trace && + git init myserver && + test_commit -C myserver foo && + git clone "file://$(pwd)/myserver" myclient && + + # MAX_IN_VAIN is 256. Because of batching, the client will send 496 + # (16+32+64+128+256) commits, not 256, before giving up. So create 496 + # irrelevant commits. + test_commit_bulk -C myclient 496 && + + # The new commit that the client wants to fetch. + test_commit -C myserver bar && + + GIT_TRACE_PACKET="$(pwd)/trace" git -C myclient fetch --progress origin && + test_i18ngrep "Total 3 " trace +' + +test_expect_success 'in_vain resetted upon ACK' ' + rm -rf myserver myclient trace && + git init myserver && + + # Linked list of commits on master. The first is common; the rest are + # not. + test_commit -C myserver first_master_commit && + git clone "file://$(pwd)/myserver" myclient && + test_commit_bulk -C myclient 255 && + + # Another linked list of commits on anotherbranch with no connection to + # master. The first is common; the rest are not. + git -C myserver checkout --orphan anotherbranch && + test_commit -C myserver first_anotherbranch_commit && + git -C myclient fetch origin anotherbranch:refs/heads/anotherbranch && + git -C myclient checkout anotherbranch && + test_commit_bulk -C myclient 255 && + + # The new commit that the client wants to fetch. + git -C myserver checkout master && + test_commit -C myserver to_fetch && + + # The client will send (as "have"s) all 256 commits in anotherbranch + # first. The 256th commit is common between the client and the server, + # and should reset in_vain. This allows negotiation to continue until + # the client reports that first_anotherbranch_commit is common. + GIT_TRACE_PACKET="$(pwd)/trace" git -C myclient fetch --progress origin master && + test_i18ngrep "Total 3 " trace +' + test_expect_success 'fetch in shallow repo unreachable shallow objects' ' ( git clone --bare --branch B --single-branch "file://$(pwd)/." no-reflog && @@ -440,11 +488,12 @@ test_expect_success 'setup tests for the --stdin parameter' ' ' test_expect_success 'setup fetch refs from cmdline v[12]' ' + cp -r client client0 && cp -r client client1 && cp -r client client2 ' -for version in '' 1 2 +for version in '' 0 1 2 do test_expect_success "protocol.version=$version fetch refs from cmdline" " ( @@ -638,7 +687,7 @@ test_expect_success 'fetch-pack cannot fetch a raw sha1 that is not advertised a git init client && # Some protocol versions (e.g. 2) support fetching # unadvertised objects, so restrict this test to v0. - test_must_fail env GIT_TEST_PROTOCOL_VERSION= git -C client fetch-pack ../server \ + test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 git -C client fetch-pack ../server \ $(git -C server rev-parse refs/heads/master^) 2>err && test_i18ngrep "Server does not allow request for unadvertised object" err ' @@ -917,7 +966,10 @@ test_expect_success 'filtering by size' ' git -C client fetch-pack --filter=blob:limit=0 ../server HEAD && # Ensure that object is not inadvertently fetched - test_must_fail git -C client cat-file -e $(git hash-object server/one.t) + commit=$(git -C server rev-parse HEAD) && + blob=$(git hash-object server/one.t) && + git -C client rev-list --objects --missing=allow-any "$commit" >oids && + ! grep "$blob" oids ' test_expect_success 'filtering by size has no effect if support for it is not advertised' ' @@ -929,7 +981,10 @@ test_expect_success 'filtering by size has no effect if support for it is not ad git -C client fetch-pack --filter=blob:limit=0 ../server HEAD 2> err && # Ensure that object is fetched - git -C client cat-file -e $(git hash-object server/one.t) && + commit=$(git -C server rev-parse HEAD) && + blob=$(git hash-object server/one.t) && + git -C client rev-list --objects --missing=allow-any "$commit" >oids && + grep "$blob" oids && test_i18ngrep "filtering not recognized by server" err ' @@ -951,9 +1006,11 @@ fetch_filter_blob_limit_zero () { git -C client fetch --filter=blob:limit=0 origin HEAD:somewhere && # Ensure that commit is fetched, but blob is not - test_config -C client extensions.partialclone "arbitrary string" && - git -C client cat-file -e $(git -C "$SERVER" rev-parse two) && - test_must_fail git -C client cat-file -e $(git hash-object "$SERVER/two.t") + commit=$(git -C "$SERVER" rev-parse two) && + blob=$(git hash-object server/two.t) && + git -C client rev-list --objects --missing=allow-any "$commit" >oids && + grep "$commit" oids && + ! grep "$blob" oids } test_expect_success 'fetch with --filter=blob:limit=0' ' diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh index fdfe179b11..a32efe2b6c 100755 --- a/t/t5504-fetch-receive-strict.sh +++ b/t/t5504-fetch-receive-strict.sh @@ -4,6 +4,7 @@ test_description='fetch/receive strict mode' . ./test-lib.sh test_expect_success 'setup and inject "corrupt or missing" object' ' + test_oid_init && echo hello >greetings && git add greetings && git commit -m greetings && @@ -64,6 +65,7 @@ test_expect_success 'fetch with transfer.fsckobjects' ' cat >exp <<EOF To dst ! refs/heads/master:refs/heads/test [remote rejected] (missing necessary objects) +Done EOF test_expect_success 'push without strict' ' @@ -144,11 +146,11 @@ test_expect_success 'fsck with no skipList input' ' test_expect_success 'setup sorted and unsorted skipLists' ' cat >SKIP.unsorted <<-EOF && - 0000000000000000000000000000000000000004 - 0000000000000000000000000000000000000002 + $(test_oid 004) + $(test_oid 002) $commit - 0000000000000000000000000000000000000001 - 0000000000000000000000000000000000000003 + $(test_oid 001) + $(test_oid 003) EOF sort SKIP.unsorted >SKIP.sorted ' @@ -172,14 +174,14 @@ test_expect_success 'fsck with invalid or bogus skipList input' ' test_expect_success 'fsck with other accepted skipList input (comments & empty lines)' ' cat >SKIP.with-comment <<-EOF && # Some bad commit - 0000000000000000000000000000000000000001 + $(test_oid 001) EOF test_must_fail git -c fsck.skipList=SKIP.with-comment fsck 2>err-with-comment && test_i18ngrep "missingEmail" err-with-comment && cat >SKIP.with-empty-line <<-EOF && - 0000000000000000000000000000000000000001 + $(test_oid 001) - 0000000000000000000000000000000000000002 + $(test_oid 002) EOF test_must_fail git -c fsck.skipList=SKIP.with-empty-line fsck 2>err-with-empty-line && test_i18ngrep "missingEmail" err-with-empty-line @@ -204,7 +206,7 @@ test_expect_success 'fsck with exhaustive accepted skipList input (various types echo " # Comment after whitespace" >>SKIP.exhaustive && echo "$commit # Our bad commit (with leading whitespace and trailing comment)" >>SKIP.exhaustive && echo "# Some bad commit (leading whitespace)" >>SKIP.exhaustive && - echo " 0000000000000000000000000000000000000001" >>SKIP.exhaustive && + echo " $(test_oid 001)" >>SKIP.exhaustive && git -c fsck.skipList=SKIP.exhaustive fsck 2>err && test_must_be_empty err ' diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index 883b32efa0..dda81b7d07 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -734,15 +734,53 @@ test_expect_success 'reject adding remote with an invalid name' ' # the last two ones check if the config is updated. test_expect_success 'rename a remote' ' + test_config_global remote.pushDefault origin && git clone one four && ( cd four && + git config branch.master.pushRemote origin && git remote rename origin upstream && test -z "$(git for-each-ref refs/remotes/origin)" && test "$(git symbolic-ref refs/remotes/upstream/HEAD)" = "refs/remotes/upstream/master" && test "$(git rev-parse upstream/master)" = "$(git rev-parse master)" && test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*" && - test "$(git config branch.master.remote)" = "upstream" + test "$(git config branch.master.remote)" = "upstream" && + test "$(git config branch.master.pushRemote)" = "upstream" && + test "$(git config --global remote.pushDefault)" = "origin" + ) +' + +test_expect_success 'rename a remote renames repo remote.pushDefault' ' + git clone one four.1 && + ( + cd four.1 && + git config remote.pushDefault origin && + git remote rename origin upstream && + test "$(git config --local remote.pushDefault)" = "upstream" + ) +' + +test_expect_success 'rename a remote renames repo remote.pushDefault but ignores global' ' + test_config_global remote.pushDefault other && + git clone one four.2 && + ( + cd four.2 && + git config remote.pushDefault origin && + git remote rename origin upstream && + test "$(git config --global remote.pushDefault)" = "other" && + test "$(git config --local remote.pushDefault)" = "upstream" + ) +' + +test_expect_success 'rename a remote renames repo remote.pushDefault but keeps global' ' + test_config_global remote.pushDefault origin && + git clone one four.3 && + ( + cd four.3 && + git config remote.pushDefault origin && + git remote rename origin upstream && + test "$(git config --global remote.pushDefault)" = "origin" && + test "$(git config --local remote.pushDefault)" = "upstream" ) ' @@ -784,6 +822,54 @@ test_expect_success 'rename succeeds with existing remote.<target>.prune' ' git -C four.four remote rename origin upstream ' +test_expect_success 'remove a remote' ' + test_config_global remote.pushDefault origin && + git clone one four.five && + ( + cd four.five && + git config branch.master.pushRemote origin && + git remote remove origin && + test -z "$(git for-each-ref refs/remotes/origin)" && + test_must_fail git config branch.master.remote && + test_must_fail git config branch.master.pushRemote && + test "$(git config --global remote.pushDefault)" = "origin" + ) +' + +test_expect_success 'remove a remote removes repo remote.pushDefault' ' + git clone one four.five.1 && + ( + cd four.five.1 && + git config remote.pushDefault origin && + git remote remove origin && + test_must_fail git config --local remote.pushDefault + ) +' + +test_expect_success 'remove a remote removes repo remote.pushDefault but ignores global' ' + test_config_global remote.pushDefault other && + git clone one four.five.2 && + ( + cd four.five.2 && + git config remote.pushDefault origin && + git remote remove origin && + test "$(git config --global remote.pushDefault)" = "other" && + test_must_fail git config --local remote.pushDefault + ) +' + +test_expect_success 'remove a remote removes repo remote.pushDefault but keeps global' ' + test_config_global remote.pushDefault origin && + git clone one four.five.3 && + ( + cd four.five.3 && + git config remote.pushDefault origin && + git remote remove origin && + test "$(git config --global remote.pushDefault)" = "origin" && + test_must_fail git config --local remote.pushDefault + ) +' + cat >remotes_origin <<EOF URL: $(pwd)/one Push: refs/heads/master:refs/heads/upstream diff --git a/t/t5509-fetch-push-namespaces.sh b/t/t5509-fetch-push-namespaces.sh index 75cbfcc392..a67f792adf 100755 --- a/t/t5509-fetch-push-namespaces.sh +++ b/t/t5509-fetch-push-namespaces.sh @@ -20,7 +20,7 @@ test_expect_success setup ' ) && commit0=$(cd original && git rev-parse HEAD^) && commit1=$(cd original && git rev-parse HEAD) && - git init pushee && + git init --bare pushee && git init puller ' @@ -152,4 +152,15 @@ test_expect_success 'clone chooses correct HEAD (v2)' ' test_cmp expect actual ' +test_expect_success 'denyCurrentBranch and unborn branch with ref namespace' ' + ( + cd original && + git init unborn && + git remote add unborn-namespaced "ext::git --namespace=namespace %s unborn" && + test_must_fail git push unborn-namespaced HEAD:master && + git -C unborn config receive.denyCurrentBranch updateInstead && + git push unborn-namespaced HEAD:master + ) +' + test_done diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 4b60282689..a66dbe0bde 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -11,7 +11,7 @@ D=$(pwd) test_bundle_object_count () { git verify-pack -v "$1" >verify.out && - test "$2" = $(grep '^[0-9a-f]\{40\} ' verify.out | wc -l) + test "$2" = $(grep "^$OID_REGEX " verify.out | wc -l) } convert_bundle_to_pack () { @@ -174,6 +174,30 @@ test_expect_success 'fetch --prune --tags with refspec prunes based on refspec' git rev-parse sometag ' +test_expect_success '--refmap="" ignores configured refspec' ' + cd "$TRASH_DIRECTORY" && + git clone "$D" remote-refs && + git -C remote-refs rev-parse remotes/origin/master >old && + git -C remote-refs update-ref refs/remotes/origin/master master~1 && + git -C remote-refs rev-parse remotes/origin/master >new && + git -C remote-refs fetch --refmap= origin "+refs/heads/*:refs/hidden/origin/*" && + git -C remote-refs rev-parse remotes/origin/master >actual && + test_cmp new actual && + git -C remote-refs fetch origin && + git -C remote-refs rev-parse remotes/origin/master >actual && + test_cmp old actual +' + +test_expect_success '--refmap="" and --prune' ' + git -C remote-refs update-ref refs/remotes/origin/foo/otherbranch master && + git -C remote-refs update-ref refs/hidden/foo/otherbranch master && + git -C remote-refs fetch --prune --refmap="" origin +refs/heads/*:refs/hidden/* && + git -C remote-refs rev-parse remotes/origin/foo/otherbranch && + test_must_fail git -C remote-refs rev-parse refs/hidden/foo/otherbranch && + git -C remote-refs fetch --prune origin && + test_must_fail git -C remote-refs rev-parse remotes/origin/foo/otherbranch +' + test_expect_success 'fetch tags when there is no tags' ' cd "$D" && @@ -261,9 +285,10 @@ test_expect_success 'create bundle 1' ' ' test_expect_success 'header of bundle looks right' ' + head -n 4 "$D"/bundle1 && head -n 1 "$D"/bundle1 | grep "^#" && - head -n 2 "$D"/bundle1 | grep "^-[0-9a-f]\{40\} " && - head -n 3 "$D"/bundle1 | grep "^[0-9a-f]\{40\} " && + head -n 2 "$D"/bundle1 | grep "^-$OID_REGEX " && + head -n 3 "$D"/bundle1 | grep "^$OID_REGEX " && head -n 4 "$D"/bundle1 | grep "^$" ' @@ -289,7 +314,7 @@ test_expect_success 'bundle 1 has only 3 files ' ' test_expect_success 'unbundle 2' ' cd "$D/bundle" && git fetch ../bundle2 master:master && - test "tip" = "$(git log -1 --pretty=oneline master | cut -b42-)" + test "tip" = "$(git log -1 --pretty=oneline master | cut -d" " -f2)" ' test_expect_success 'bundle does not prerequisite objects' ' @@ -354,7 +379,6 @@ test_expect_success 'fetch from GIT URL with a non-applying branch.<name>.merge # the strange name is: a\!'b test_expect_success 'quoting of a strangely named repo' ' test_must_fail git fetch "a\\!'\''b" > result 2>&1 && - cat result && grep "fatal: '\''a\\\\!'\''b'\''" result ' diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh index d7b9f9078f..e98c3a0174 100755 --- a/t/t5512-ls-remote.sh +++ b/t/t5512-ls-remote.sh @@ -4,6 +4,14 @@ test_description='git ls-remote' . ./test-lib.sh +generate_references () { + for ref + do + oid=$(git rev-parse "$ref") && + printf '%s\t%s\n' "$oid" "$ref" || return 1 + done +} + test_expect_success setup ' >file && git add file && @@ -13,11 +21,11 @@ test_expect_success setup ' git tag mark1.1 && git tag mark1.2 && git tag mark1.10 && - git show-ref --tags -d | sed -e "s/ / /" >expected.tag && - ( - echo "$(git rev-parse HEAD) HEAD" && - git show-ref -d | sed -e "s/ / /" - ) >expected.all && + git show-ref --tags -d >expected.tag.raw && + sed -e "s/ / /" expected.tag.raw >expected.tag && + generate_references HEAD >expected.all && + git show-ref -d >refs && + sed -e "s/ / /" refs >>expected.all && git remote add self "$(pwd)/.git" ' @@ -43,34 +51,31 @@ test_expect_success 'ls-remote self' ' ' test_expect_success 'ls-remote --sort="version:refname" --tags self' ' - cat >expect <<-EOF && - $(git rev-parse mark) refs/tags/mark - $(git rev-parse mark1.1) refs/tags/mark1.1 - $(git rev-parse mark1.2) refs/tags/mark1.2 - $(git rev-parse mark1.10) refs/tags/mark1.10 - EOF + generate_references \ + refs/tags/mark \ + refs/tags/mark1.1 \ + refs/tags/mark1.2 \ + refs/tags/mark1.10 >expect && git ls-remote --sort="version:refname" --tags self >actual && test_cmp expect actual ' test_expect_success 'ls-remote --sort="-version:refname" --tags self' ' - cat >expect <<-EOF && - $(git rev-parse mark1.10) refs/tags/mark1.10 - $(git rev-parse mark1.2) refs/tags/mark1.2 - $(git rev-parse mark1.1) refs/tags/mark1.1 - $(git rev-parse mark) refs/tags/mark - EOF + generate_references \ + refs/tags/mark1.10 \ + refs/tags/mark1.2 \ + refs/tags/mark1.1 \ + refs/tags/mark >expect && git ls-remote --sort="-version:refname" --tags self >actual && test_cmp expect actual ' test_expect_success 'ls-remote --sort="-refname" --tags self' ' - cat >expect <<-EOF && - $(git rev-parse mark1.2) refs/tags/mark1.2 - $(git rev-parse mark1.10) refs/tags/mark1.10 - $(git rev-parse mark1.1) refs/tags/mark1.1 - $(git rev-parse mark) refs/tags/mark - EOF + generate_references \ + refs/tags/mark1.2 \ + refs/tags/mark1.10 \ + refs/tags/mark1.1 \ + refs/tags/mark >expect && git ls-remote --sort="-refname" --tags self >actual && test_cmp expect actual ' @@ -92,7 +97,7 @@ test_expect_success 'use "origin" when no remote specified' ' test_expect_success 'suppress "From <url>" with -q' ' git ls-remote -q 2>actual_err && - test_must_fail test_cmp exp_err actual_err + ! test_cmp exp_err actual_err ' test_expect_success 'use branch.<name>.remote if possible' ' @@ -180,8 +185,8 @@ do test_config $configsection.hiderefs refs/tags && git ls-remote . >actual && test_unconfig $configsection.hiderefs && - git ls-remote . | - sed -e "/ refs\/tags\//d" >expect && + git ls-remote . >expect.raw && + sed -e "/ refs\/tags\//d" expect.raw >expect && test_cmp expect actual ' @@ -212,57 +217,59 @@ test_expect_success 'protocol v2 supports hiderefs' ' test_expect_success 'ls-remote --symref' ' git fetch origin && - cat >expect <<-EOF && - ref: refs/heads/master HEAD - $(git rev-parse HEAD) HEAD - $(git rev-parse refs/heads/master) refs/heads/master - $(git rev-parse HEAD) refs/remotes/origin/HEAD - $(git rev-parse refs/remotes/origin/master) refs/remotes/origin/master - $(git rev-parse refs/tags/mark) refs/tags/mark - $(git rev-parse refs/tags/mark1.1) refs/tags/mark1.1 - $(git rev-parse refs/tags/mark1.10) refs/tags/mark1.10 - $(git rev-parse refs/tags/mark1.2) refs/tags/mark1.2 - EOF + echo "ref: refs/heads/master HEAD" >expect && + generate_references \ + HEAD \ + refs/heads/master >>expect && + oid=$(git rev-parse HEAD) && + echo "$oid refs/remotes/origin/HEAD" >>expect && + generate_references \ + refs/remotes/origin/master \ + refs/tags/mark \ + refs/tags/mark1.1 \ + refs/tags/mark1.10 \ + refs/tags/mark1.2 >>expect && # Protocol v2 supports sending symrefs for refs other than HEAD, so use # protocol v0 here. - GIT_TEST_PROTOCOL_VERSION= git ls-remote --symref >actual && + GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref >actual && test_cmp expect actual ' test_expect_success 'ls-remote with filtered symref (refname)' ' - cat >expect <<-\EOF && + rev=$(git rev-parse HEAD) && + cat >expect <<-EOF && ref: refs/heads/master HEAD - 1bd44cb9d13204b0fe1958db0082f5028a16eb3a HEAD + $rev HEAD EOF # Protocol v2 supports sending symrefs for refs other than HEAD, so use # protocol v0 here. - GIT_TEST_PROTOCOL_VERSION= git ls-remote --symref . HEAD >actual && + GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref . HEAD >actual && test_cmp expect actual ' test_expect_failure 'ls-remote with filtered symref (--heads)' ' git symbolic-ref refs/heads/foo refs/tags/mark && - cat >expect <<-\EOF && + cat >expect <<-EOF && ref: refs/tags/mark refs/heads/foo - 1bd44cb9d13204b0fe1958db0082f5028a16eb3a refs/heads/foo - 1bd44cb9d13204b0fe1958db0082f5028a16eb3a refs/heads/master + $rev refs/heads/foo + $rev refs/heads/master EOF # Protocol v2 supports sending symrefs for refs other than HEAD, so use # protocol v0 here. - GIT_TEST_PROTOCOL_VERSION= git ls-remote --symref --heads . >actual && + GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref --heads . >actual && test_cmp expect actual ' test_expect_success 'ls-remote --symref omits filtered-out matches' ' - cat >expect <<-\EOF && - 1bd44cb9d13204b0fe1958db0082f5028a16eb3a refs/heads/foo - 1bd44cb9d13204b0fe1958db0082f5028a16eb3a refs/heads/master + cat >expect <<-EOF && + $rev refs/heads/foo + $rev refs/heads/master EOF # Protocol v2 supports sending symrefs for refs other than HEAD, so use # protocol v0 here. - GIT_TEST_PROTOCOL_VERSION= git ls-remote --symref --heads . >actual && + GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref --heads . >actual && test_cmp expect actual && - GIT_TEST_PROTOCOL_VERSION= git ls-remote --symref . "refs/heads/*" >actual && + GIT_TEST_PROTOCOL_VERSION=0 git ls-remote --symref . "refs/heads/*" >actual && test_cmp expect actual ' diff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh index 961eb35c99..9d6a46ff56 100755 --- a/t/t5515-fetch-merge-logic.sh +++ b/t/t5515-fetch-merge-logic.sh @@ -8,15 +8,60 @@ test_description='Merge logic in fetch' # NEEDSWORK: If the overspecification of the expected result is reduced, we # might be able to run this test in all protocol versions. -GIT_TEST_PROTOCOL_VERSION= +GIT_TEST_PROTOCOL_VERSION=0 +export GIT_TEST_PROTOCOL_VERSION . ./test-lib.sh +build_script () { + script="$1" && + for i in one three_file master master2 one_tree three two two2 three2 + do + echo "s/$(test_oid --hash=sha1 "$i")/$(test_oid "$i")/g" >>"$script" + done +} + +convert_expected () { + file="$1" && + script="$2" && + sed -f "$script" "$file" >"$file.tmp" && + mv "$file.tmp" "$file" +} + test_expect_success setup ' GIT_AUTHOR_DATE="2006-06-26 00:00:00 +0000" && GIT_COMMITTER_DATE="2006-06-26 00:00:00 +0000" && export GIT_AUTHOR_DATE GIT_COMMITTER_DATE && + test_oid_cache <<-EOF && + one sha1:8e32a6d901327a23ef831511badce7bf3bf46689 + one sha256:8739546433ab1ac72ee93088dce611210effee072b2b586ceac6dde43ebec9ce + + three_file sha1:0e3b14047d3ee365f4f2a1b673db059c3972589c + three_file sha256:bc4447d50c07497a8bfe6eef817f2364ecca9d471452e43b52756cc1a908bd32 + + master sha1:6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 + master sha256:8521c3072461fcfe8f32d67f95cc6e6b832a2db2fa29769ffc788bce85ebcd75 + + one_tree sha1:22feea448b023a2d864ef94b013735af34d238ba + one_tree sha256:6e4743f4ef2356b881dda5e91f5c7cdffe870faf350bf7b312f80a20935f5d83 + + three sha1:c61a82b60967180544e3c19f819ddbd0c9f89899 + three sha256:0cc6d1eda617ded715170786e31ba4e2d0185404ec5a3508dd0d73b324860c6a + + two sha1:525b7fb068d59950d185a8779dc957c77eed73ba + two sha256:3b21de3440cd38c2a9e9b464adb923f7054949ed4c918e1a0ac4c95cd52774db + + master2 sha1:754b754407bf032e9a2f9d5a9ad05ca79a6b228f + master2 sha256:6c7abaea8a6d8ef4d89877e68462758dc6774690fbbbb0e6d7dd57415c9abde0 + + two2 sha1:6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 + two2 sha256:87a2d3ee29c83a3dc7afd41c0606b11f67603120b910a7be7840accdc18344d4 + + three2 sha1:0567da4d5edd2ff4bb292a465ba9e64dcad9536b + three2 sha256:cceb3e8eca364fa9a0a39a1efbebecacc664af86cbbd8070571f5faeb5f0e8c3 + EOF + echo >file original && git add file && git commit -a -m One && @@ -86,7 +131,8 @@ test_expect_success setup ' git config branch.br-$remote-octopus.remote $remote && git config branch.br-$remote-octopus.merge refs/heads/one && git config --add branch.br-$remote-octopus.merge two - done + done && + build_script sed_script ' # Merge logic depends on branch properties and Pull: or .fetch lines @@ -137,6 +183,10 @@ do actual_r="$pfx-refs.$test" test_expect_success "$cmd" ' + cp "$expect_f" expect_f && + convert_expected expect_f sed_script && + cp "$expect_r" expect_r && + convert_expected expect_r sed_script && { echo "# $cmd" set x $cmd; shift @@ -152,18 +202,18 @@ do cat .git/FETCH_HEAD } >"$actual_f" && git show-ref >"$actual_r" && - if test -f "$expect_f" + if test -f "expect_f" then - test_cmp "$expect_f" "$actual_f" && + test_cmp "expect_f" "$actual_f" && rm -f "$actual_f" else # this is to help developing new tests. cp "$actual_f" "$expect_f" false fi && - if test -f "$expect_r" + if test -f "expect_r" then - test_cmp "$expect_r" "$actual_r" && + test_cmp "expect_r" "$actual_r" && rm -f "$actual_r" else # this is to help developing new tests. diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index c81ca360ac..9c6218f568 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -1066,6 +1066,7 @@ test_expect_success 'push --porcelain rejected' ' echo >.git/foo "To testrepo" && echo >>.git/foo "! refs/heads/master:refs/heads/master [remote rejected] (branch is currently checked out)" && + echo >>.git/foo "Done" && test_must_fail git push >.git/bar --porcelain testrepo refs/heads/master:refs/heads/master && test_cmp .git/foo .git/bar @@ -1151,7 +1152,7 @@ test_expect_success 'fetch exact SHA1' ' # unadvertised objects, so restrict this test to v0. # fetching the hidden object should fail by default - test_must_fail env GIT_TEST_PROTOCOL_VERSION= \ + test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \ git fetch -v ../testrepo $the_commit:refs/heads/copy 2>err && test_i18ngrep "Server does not allow request for unadvertised object" err && test_must_fail git rev-parse --verify refs/heads/copy && @@ -1210,7 +1211,7 @@ do cd shallow && # Some protocol versions (e.g. 2) support fetching # unadvertised objects, so restrict this test to v0. - test_must_fail env GIT_TEST_PROTOCOL_VERSION= \ + test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \ git fetch --depth=1 ../testrepo/.git $SHA1 && git --git-dir=../testrepo/.git config uploadpack.allowreachablesha1inwant true && git fetch --depth=1 ../testrepo/.git $SHA1 && @@ -1241,9 +1242,9 @@ do cd shallow && # Some protocol versions (e.g. 2) support fetching # unadvertised objects, so restrict this test to v0. - test_must_fail env GIT_TEST_PROTOCOL_VERSION= \ + test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \ git fetch ../testrepo/.git $SHA1_3 && - test_must_fail env GIT_TEST_PROTOCOL_VERSION= \ + test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \ git fetch ../testrepo/.git $SHA1_1 && git --git-dir=../testrepo/.git config uploadpack.allowreachablesha1inwant true && git fetch ../testrepo/.git $SHA1_1 && @@ -1251,7 +1252,7 @@ do test_must_fail git cat-file commit $SHA1_2 && git fetch ../testrepo/.git $SHA1_2 && git cat-file commit $SHA1_2 && - test_must_fail env GIT_TEST_PROTOCOL_VERSION= \ + test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \ git fetch ../testrepo/.git $SHA1_3 2>err && test_i18ngrep "remote error:.*not our ref.*$SHA1_3\$" err ) @@ -1291,7 +1292,7 @@ test_expect_success 'peeled advertisements are not considered ref tips' ' git -C testrepo commit --allow-empty -m two && git -C testrepo tag -m foo mytag HEAD^ && oid=$(git -C testrepo rev-parse mytag^{commit}) && - test_must_fail env GIT_TEST_PROTOCOL_VERSION= \ + test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \ git fetch testrepo $oid 2>err && test_i18ngrep "Server does not allow request for unadvertised object" err ' @@ -1712,4 +1713,15 @@ test_expect_success 'updateInstead with push-to-checkout hook' ' ) ' +test_expect_success 'denyCurrentBranch and worktrees' ' + git worktree add new-wt && + git clone . cloned && + test_commit -C cloned first && + test_config receive.denyCurrentBranch refuse && + test_must_fail git -C cloned push origin HEAD:new-wt && + test_config receive.denyCurrentBranch updateInstead && + git -C cloned push origin HEAD:new-wt && + test_must_fail git -C cloned push --delete origin new-wt +' + test_done diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh index 602d996a33..37535d63a9 100755 --- a/t/t5520-pull.sh +++ b/t/t5520-pull.sh @@ -10,11 +10,13 @@ modify () { } test_pull_autostash () { + expect_parent_num="$1" && + shift && git reset --hard before-rebase && echo dirty >new_file && git add new_file && git pull "$@" . copy && - test_cmp_rev HEAD^ copy && + test_cmp_rev HEAD^"$expect_parent_num" copy && echo dirty >expect && test_cmp expect new_file && echo "modified again" >expect && @@ -26,7 +28,7 @@ test_pull_autostash_fail () { echo dirty >new_file && git add new_file && test_must_fail git pull "$@" . copy 2>err && - test_i18ngrep "uncommitted changes." err + test_i18ngrep "\(uncommitted changes.\)\|\(overwritten by merge:\)" err } test_expect_success setup ' @@ -277,14 +279,27 @@ test_expect_success '--rebase' ' test_cmp expect actual ' -test_expect_success '--rebase fast forward' ' +test_expect_success '--rebase (merge) fast forward' ' git reset --hard before-rebase && git checkout -b ff && echo another modification >file && git commit -m third file && git checkout to-rebase && - git pull --rebase . ff && + git -c rebase.backend=merge pull --rebase . ff && + test_cmp_rev HEAD ff && + + # The above only validates the result. Did we actually bypass rebase? + git reflog -1 >reflog.actual && + sed "s/^[0-9a-f][0-9a-f]*/OBJID/" reflog.actual >reflog.fuzzy && + echo "OBJID HEAD@{0}: pull --rebase . ff: Fast-forward" >reflog.expected && + test_cmp reflog.expected reflog.fuzzy +' + +test_expect_success '--rebase (am) fast forward' ' + git reset --hard before-rebase && + + git -c rebase.backend=apply pull --rebase . ff && test_cmp_rev HEAD ff && # The above only validates the result. Did we actually bypass rebase? @@ -327,7 +342,7 @@ test_expect_success '--rebase with conflicts shows advice' ' test_tick && git commit -m "Create conflict" seq.txt && test_must_fail git pull --rebase . seq 2>err >out && - test_i18ngrep "Resolve all conflicts manually" out + test_i18ngrep "Resolve all conflicts manually" err ' test_expect_success 'failed --rebase shows advice' ' @@ -341,7 +356,7 @@ test_expect_success 'failed --rebase shows advice' ' git checkout -f -b fails-to-rebase HEAD^ && test_commit v2-without-cr file "2" file2-lf && test_must_fail git pull --rebase . diverging 2>err >out && - test_i18ngrep "Resolve all conflicts manually" out + test_i18ngrep "Resolve all conflicts manually" err ' test_expect_success '--rebase fails with multiple branches' ' @@ -356,22 +371,22 @@ test_expect_success '--rebase fails with multiple branches' ' test_expect_success 'pull --rebase succeeds with dirty working directory and rebase.autostash set' ' test_config rebase.autostash true && - test_pull_autostash --rebase + test_pull_autostash 1 --rebase ' test_expect_success 'pull --rebase --autostash & rebase.autostash=true' ' test_config rebase.autostash true && - test_pull_autostash --rebase --autostash + test_pull_autostash 1 --rebase --autostash ' test_expect_success 'pull --rebase --autostash & rebase.autostash=false' ' test_config rebase.autostash false && - test_pull_autostash --rebase --autostash + test_pull_autostash 1 --rebase --autostash ' test_expect_success 'pull --rebase --autostash & rebase.autostash unset' ' test_unconfig rebase.autostash && - test_pull_autostash --rebase --autostash + test_pull_autostash 1 --rebase --autostash ' test_expect_success 'pull --rebase --no-autostash & rebase.autostash=true' ' @@ -389,13 +404,40 @@ test_expect_success 'pull --rebase --no-autostash & rebase.autostash unset' ' test_pull_autostash_fail --rebase --no-autostash ' -for i in --autostash --no-autostash -do - test_expect_success "pull $i (without --rebase) is illegal" ' - test_must_fail git pull $i . copy 2>err && - test_i18ngrep "only valid with --rebase" err - ' -done +test_expect_success 'pull succeeds with dirty working directory and merge.autostash set' ' + test_config merge.autostash true && + test_pull_autostash 2 +' + +test_expect_success 'pull --autostash & merge.autostash=true' ' + test_config merge.autostash true && + test_pull_autostash 2 --autostash +' + +test_expect_success 'pull --autostash & merge.autostash=false' ' + test_config merge.autostash false && + test_pull_autostash 2 --autostash +' + +test_expect_success 'pull --autostash & merge.autostash unset' ' + test_unconfig merge.autostash && + test_pull_autostash 2 --autostash +' + +test_expect_success 'pull --no-autostash & merge.autostash=true' ' + test_config merge.autostash true && + test_pull_autostash_fail --no-autostash +' + +test_expect_success 'pull --no-autostash & merge.autostash=false' ' + test_config merge.autostash false && + test_pull_autostash_fail --no-autostash +' + +test_expect_success 'pull --no-autostash & merge.autostash unset' ' + test_unconfig merge.autostash && + test_pull_autostash_fail --no-autostash +' test_expect_success 'pull.rebase' ' git reset --hard before-rebase && @@ -409,7 +451,7 @@ test_expect_success 'pull.rebase' ' test_expect_success 'pull --autostash & pull.rebase=true' ' test_config pull.rebase true && - test_pull_autostash --autostash + test_pull_autostash 1 --autostash ' test_expect_success 'pull --no-autostash & pull.rebase=true' ' @@ -761,8 +803,10 @@ test_expect_success 'git pull --rebase does not reapply old patches' ' ( cd dst && test_must_fail git pull --rebase && - find .git/rebase-apply -name "000*" >patches && - test_line_count = 1 patches + cat .git/rebase-merge/done .git/rebase-merge/git-rebase-todo >work && + grep -v -e \# -e ^$ work >patches && + test_line_count = 1 patches && + rm -f work ) ' diff --git a/t/t5521-pull-options.sh b/t/t5521-pull-options.sh index ccde8ba491..159afa7ac8 100755 --- a/t/t5521-pull-options.sh +++ b/t/t5521-pull-options.sh @@ -11,10 +11,10 @@ test_expect_success 'setup' ' git commit -m one) ' -test_expect_success 'git pull -q' ' +test_expect_success 'git pull -q --no-rebase' ' mkdir clonedq && (cd clonedq && git init && - git pull -q "../parent" >out 2>err && + git pull -q --no-rebase "../parent" >out 2>err && test_must_be_empty err && test_must_be_empty out) ' @@ -30,10 +30,10 @@ test_expect_success 'git pull -q --rebase' ' test_must_be_empty out) ' -test_expect_success 'git pull' ' +test_expect_success 'git pull --no-rebase' ' mkdir cloned && (cd cloned && git init && - git pull "../parent" >out 2>err && + git pull --no-rebase "../parent" >out 2>err && test -s err && test_must_be_empty out) ' @@ -46,10 +46,10 @@ test_expect_success 'git pull --rebase' ' test_must_be_empty out) ' -test_expect_success 'git pull -v' ' +test_expect_success 'git pull -v --no-rebase' ' mkdir clonedv && (cd clonedv && git init && - git pull -v "../parent" >out 2>err && + git pull -v --no-rebase "../parent" >out 2>err && test -s err && test_must_be_empty out) ' @@ -62,25 +62,25 @@ test_expect_success 'git pull -v --rebase' ' test_must_be_empty out) ' -test_expect_success 'git pull -v -q' ' +test_expect_success 'git pull -v -q --no-rebase' ' mkdir clonedvq && (cd clonedvq && git init && - git pull -v -q "../parent" >out 2>err && + git pull -v -q --no-rebase "../parent" >out 2>err && test_must_be_empty out && test_must_be_empty err) ' -test_expect_success 'git pull -q -v' ' +test_expect_success 'git pull -q -v --no-rebase' ' mkdir clonedqv && (cd clonedqv && git init && - git pull -q -v "../parent" >out 2>err && + git pull -q -v --no-rebase "../parent" >out 2>err && test_must_be_empty out && test -s err) ' test_expect_success 'git pull --cleanup errors early on invalid argument' ' mkdir clonedcleanup && (cd clonedcleanup && git init && - test_must_fail git pull --cleanup invalid "../parent" >out 2>err && + test_must_fail git pull --no-rebase --cleanup invalid "../parent" >out 2>err && test_must_be_empty out && test -s err) ' diff --git a/t/t5530-upload-pack-error.sh b/t/t5530-upload-pack-error.sh index a1d3031d40..4ce9a9f704 100755 --- a/t/t5530-upload-pack-error.sh +++ b/t/t5530-upload-pack-error.sh @@ -14,7 +14,7 @@ corrupt_repo () { } test_expect_success 'setup and corrupt repository' ' - + test_oid_init && echo file >file && git add file && git rev-parse :file && @@ -31,9 +31,10 @@ test_expect_success 'fsck fails' ' ' test_expect_success 'upload-pack fails due to error in pack-objects packing' ' - - printf "0032want %s\n00000009done\n0000" \ - $(git rev-parse HEAD) >input && + head=$(git rev-parse HEAD) && + hexsz=$(test_oid hexsz) && + printf "%04xwant %s\n00000009done\n0000" \ + $(($hexsz + 10)) $head >input && test_must_fail git upload-pack . <input >/dev/null 2>output.err && test_i18ngrep "unable to read" output.err && test_i18ngrep "pack-objects died" output.err @@ -51,16 +52,17 @@ test_expect_success 'fsck fails' ' ' test_expect_success 'upload-pack fails due to error in rev-list' ' - printf "0032want %s\n0034shallow %s00000009done\n0000" \ - $(git rev-parse HEAD) $(git rev-parse HEAD^) >input && + printf "%04xwant %s\n%04xshallow %s00000009done\n0000" \ + $(($hexsz + 10)) $(git rev-parse HEAD) \ + $(($hexsz + 12)) $(git rev-parse HEAD^) >input && test_must_fail git upload-pack . <input >/dev/null 2>output.err && grep "bad tree object" output.err ' test_expect_success 'upload-pack fails due to bad want (no object)' ' - printf "0045want %s multi_ack_detailed\n00000009done\n0000" \ - "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef" >input && + printf "%04xwant %s multi_ack_detailed\n00000009done\n0000" \ + $(($hexsz + 29)) $(test_oid deadbeef) >input && test_must_fail git upload-pack . <input >output 2>output.err && grep "not our ref" output.err && grep "ERR" output && @@ -70,8 +72,8 @@ test_expect_success 'upload-pack fails due to bad want (no object)' ' test_expect_success 'upload-pack fails due to bad want (not tip)' ' oid=$(echo an object we have | git hash-object -w --stdin) && - printf "0045want %s multi_ack_detailed\n00000009done\n0000" \ - "$oid" >input && + printf "%04xwant %s multi_ack_detailed\n00000009done\n0000" \ + $(($hexsz + 29)) "$oid" >input && test_must_fail git upload-pack . <input >output 2>output.err && grep "not our ref" output.err && grep "ERR" output && @@ -80,8 +82,8 @@ test_expect_success 'upload-pack fails due to bad want (not tip)' ' test_expect_success 'upload-pack fails due to error in pack-objects enumeration' ' - printf "0032want %s\n00000009done\n0000" \ - $(git rev-parse HEAD) >input && + printf "%04xwant %s\n00000009done\n0000" \ + $((hexsz + 10)) $(git rev-parse HEAD) >input && test_must_fail git upload-pack . <input >/dev/null 2>output.err && grep "bad tree object" output.err && grep "pack-objects died" output.err diff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh index 97a67728ca..d427a2d7f7 100755 --- a/t/t5537-fetch-shallow.sh +++ b/t/t5537-fetch-shallow.sh @@ -15,16 +15,17 @@ test_expect_success 'setup' ' commit 2 && commit 3 && commit 4 && - git config --global transfer.fsckObjects true + git config --global transfer.fsckObjects true && + test_oid_cache <<-\EOF + perl sha1:s/0034shallow %s/0036unshallow %s/ + perl sha256:s/004cshallow %s/004eunshallow %s/ + EOF ' test_expect_success 'setup shallow clone' ' git clone --no-local --depth=2 .git shallow && git --git-dir=shallow/.git log --format=%s >actual && - cat <<EOF >expect && -4 -3 -EOF + test_write_lines 4 3 >expect && test_cmp expect actual ' @@ -34,10 +35,7 @@ test_expect_success 'clone from shallow clone' ' cd shallow2 && git fsck && git log --format=%s >actual && - cat <<EOF >expect && -4 -3 -EOF + test_write_lines 4 3 >expect && test_cmp expect actual ) ' @@ -52,11 +50,7 @@ test_expect_success 'fetch from shallow clone' ' git fetch && git fsck && git log --format=%s origin/master >actual && - cat <<EOF >expect && -5 -4 -3 -EOF + test_write_lines 5 4 3 >expect && test_cmp expect actual ) ' @@ -71,10 +65,7 @@ test_expect_success 'fetch --depth from shallow clone' ' git fetch --depth=2 && git fsck && git log --format=%s origin/master >actual && - cat <<EOF >expect && -6 -5 -EOF + test_write_lines 6 5 >expect && test_cmp expect actual ) ' @@ -85,12 +76,7 @@ test_expect_success 'fetch --unshallow from shallow clone' ' git fetch --unshallow && git fsck && git log --format=%s origin/master >actual && - cat <<EOF >expect && -6 -5 -4 -3 -EOF + test_write_lines 6 5 4 3 >expect && test_cmp expect actual ) ' @@ -107,15 +93,10 @@ test_expect_success 'fetch something upstream has but hidden by clients shallow git fetch ../.git +refs/heads/master:refs/remotes/top/master && git fsck && git log --format=%s top/master >actual && - cat <<EOF >expect && -add-1-back -4 -3 -EOF + test_write_lines add-1-back 4 3 >expect && test_cmp expect actual ) && git --git-dir=shallow2/.git cat-file blob $(echo 1|git hash-object --stdin) >/dev/null - ' test_expect_success 'fetch that requires changes in .git/shallow is filtered' ' @@ -127,16 +108,12 @@ test_expect_success 'fetch that requires changes in .git/shallow is filtered' ' git init notshallow && ( cd notshallow && - git fetch ../shallow/.git refs/heads/*:refs/remotes/shallow/*&& + git fetch ../shallow/.git refs/heads/*:refs/remotes/shallow/* && git for-each-ref --format="%(refname)" >actual.refs && - cat <<EOF >expect.refs && -refs/remotes/shallow/no-shallow -EOF + echo refs/remotes/shallow/no-shallow >expect.refs && test_cmp expect.refs actual.refs && git log --format=%s shallow/no-shallow >actual && - cat <<EOF >expect && -no-shallow -EOF + echo no-shallow >expect && test_cmp expect actual ) ' @@ -154,21 +131,44 @@ test_expect_success 'fetch --update-shallow' ' git fetch --update-shallow ../shallow/.git refs/heads/*:refs/remotes/shallow/* && git fsck && git for-each-ref --sort=refname --format="%(refname)" >actual.refs && - cat <<EOF >expect.refs && -refs/remotes/shallow/master -refs/remotes/shallow/no-shallow -refs/tags/heavy-tag -refs/tags/light-tag -EOF + cat <<-\EOF >expect.refs && + refs/remotes/shallow/master + refs/remotes/shallow/no-shallow + refs/tags/heavy-tag + refs/tags/light-tag + EOF + test_cmp expect.refs actual.refs && + git log --format=%s shallow/master >actual && + test_write_lines 7 6 5 4 3 >expect && + test_cmp expect actual + ) +' + +test_expect_success 'fetch --update-shallow (with fetch.writeCommitGraph)' ' + ( + cd shallow && + git checkout master && + commit 8 && + git tag -m foo heavy-tag-for-graph HEAD^ && + git tag light-tag-for-graph HEAD^:tracked + ) && + test_config -C notshallow fetch.writeCommitGraph true && + ( + cd notshallow && + git fetch --update-shallow ../shallow/.git refs/heads/*:refs/remotes/shallow/* && + git fsck && + git for-each-ref --sort=refname --format="%(refname)" >actual.refs && + cat <<-EOF >expect.refs && + refs/remotes/shallow/master + refs/remotes/shallow/no-shallow + refs/tags/heavy-tag + refs/tags/heavy-tag-for-graph + refs/tags/light-tag + refs/tags/light-tag-for-graph + EOF test_cmp expect.refs actual.refs && git log --format=%s shallow/master >actual && - cat <<EOF >expect && -7 -6 -5 -4 -3 -EOF + test_write_lines 8 7 6 5 4 3 >expect && test_cmp expect actual ) ' @@ -179,10 +179,7 @@ test_expect_success POSIXPERM,SANITY 'shallow fetch from a read-only repo' ' find read-only.git -print | xargs chmod -w && git clone --no-local --depth=2 read-only.git from-read-only && git --git-dir=from-read-only/.git log --format=%s >actual && - cat >expect <<EOF && -add-1-back -4 -EOF + test_write_lines add-1-back 4 >expect && test_cmp expect actual ' @@ -233,22 +230,22 @@ test_expect_success 'shallow fetches check connectivity before writing shallow f git -C "$REPO" config protocol.version 2 && git -C client config protocol.version 2 && - git -C client fetch --depth=2 "$HTTPD_URL/one_time_sed/repo" master:a_branch && + git -C client fetch --depth=2 "$HTTPD_URL/one_time_perl/repo" master:a_branch && # Craft a situation in which the server sends back an unshallow request # with an empty packfile. This is done by refetching with a shorter # depth (to ensure that the packfile is empty), and overwriting the # shallow line in the response with the unshallow line we want. - printf "s/0034shallow %s/0036unshallow %s/" \ + printf "$(test_oid perl)" \ "$(git -C "$REPO" rev-parse HEAD)" \ "$(git -C "$REPO" rev-parse HEAD^)" \ - >"$HTTPD_ROOT_PATH/one-time-sed" && + >"$HTTPD_ROOT_PATH/one-time-perl" && test_must_fail env GIT_TEST_SIDEBAND_ALL=0 git -C client \ - fetch --depth=1 "$HTTPD_URL/one_time_sed/repo" \ + fetch --depth=1 "$HTTPD_URL/one_time_perl/repo" \ master:a_branch && - # Ensure that the one-time-sed script was used. - ! test -e "$HTTPD_ROOT_PATH/one-time-sed" && + # Ensure that the one-time-perl script was used. + ! test -e "$HTTPD_ROOT_PATH/one-time-perl" && # Ensure that the resulting repo is consistent, despite our failure to # fetch. diff --git a/t/t5539-fetch-http-shallow.sh b/t/t5539-fetch-http-shallow.sh index b4ad81f006..c0d02dee89 100755 --- a/t/t5539-fetch-http-shallow.sh +++ b/t/t5539-fetch-http-shallow.sh @@ -69,7 +69,7 @@ test_expect_success 'no shallow lines after receiving ACK ready' ' test_commit new-too && # NEEDSWORK: If the overspecification of the expected result is reduced, we # might be able to run this test in all protocol versions. - GIT_TRACE_PACKET="$TRASH_DIRECTORY/trace" GIT_TEST_PROTOCOL_VERSION= \ + GIT_TRACE_PACKET="$TRASH_DIRECTORY/trace" GIT_TEST_PROTOCOL_VERSION=0 \ git fetch --depth=2 && grep "fetch-pack< ACK .* ready" ../trace && ! grep "fetch-pack> done" ../trace diff --git a/t/t5540-http-push-webdav.sh b/t/t5540-http-push-webdav.sh index a094fd5e71..d476c33509 100755 --- a/t/t5540-http-push-webdav.sh +++ b/t/t5540-http-push-webdav.sh @@ -134,15 +134,13 @@ test_expect_success 'MKCOL sends directory names with trailing slashes' ' x1="[0-9a-f]" x2="$x1$x1" -x5="$x1$x1$x1$x1$x1" -x38="$x5$x5$x5$x5$x5$x5$x5$x1$x1$x1" -x40="$x38$x2" +xtrunc=$(echo $OID_REGEX | sed -e "s/\[0-9a-f\]\[0-9a-f\]//") test_expect_success 'PUT and MOVE sends object to URLs with SHA-1 hash suffix' ' sed \ -e "s/PUT /OP /" \ -e "s/MOVE /OP /" \ - -e "s|/objects/$x2/${x38}_$x40|WANTED_PATH_REQUEST|" \ + -e "s|/objects/$x2/${xtrunc}_$OID_REGEX|WANTED_PATH_REQUEST|" \ "$HTTPD_ROOT_PATH"/access.log | grep -e "\"OP .*WANTED_PATH_REQUEST HTTP/[.0-9]*\" 20[0-9] " diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh index 4c970787b0..afc680d5e3 100755 --- a/t/t5541-http-push-smart.sh +++ b/t/t5541-http-push-smart.sh @@ -49,7 +49,7 @@ test_expect_success 'no empty path components' ' # NEEDSWORK: If the overspecification of the expected result is reduced, we # might be able to run this test in all protocol versions. - if test -z "$GIT_TEST_PROTOCOL_VERSION" + if test "$GIT_TEST_PROTOCOL_VERSION" = 0 then check_access_log exp fi @@ -135,7 +135,7 @@ EOF test_expect_success 'used receive-pack service' ' # NEEDSWORK: If the overspecification of the expected result is reduced, we # might be able to run this test in all protocol versions. - if test -z "$GIT_TEST_PROTOCOL_VERSION" + if test "$GIT_TEST_PROTOCOL_VERSION" = 0 then check_access_log exp fi @@ -177,6 +177,9 @@ test_expect_success 'push (chunked)' ' test $HEAD = $(git rev-parse --verify HEAD)) ' +## References of remote: atomic1(1) master(2) collateral(2) other(2) +## References of local : atomic2(2) master(1) collateral(3) other(2) collateral1(3) atomic(1) +## Atomic push : master(1) collateral(3) atomic(1) test_expect_success 'push --atomic also prevents branch creation, reports collateral' ' # Setup upstream repo - empty for now d=$HTTPD_DOCUMENT_ROOT_PATH/atomic-branches.git && @@ -189,7 +192,8 @@ test_expect_success 'push --atomic also prevents branch creation, reports collat test_commit atomic2 && git branch collateral && git branch other && - git push "$up" master collateral other && + git push "$up" atomic1 master collateral other && + git tag -d atomic1 && # collateral is a valid push, but should be failed by atomic push git checkout collateral && @@ -224,7 +228,11 @@ test_expect_success 'push --atomic also prevents branch creation, reports collat # the collateral failure refs should be indicated to the user grep "^ ! .*rejected.* atomic -> atomic .*atomic push failed" output && - grep "^ ! .*rejected.* collateral -> collateral .*atomic push failed" output + grep "^ ! .*rejected.* collateral -> collateral .*atomic push failed" output && + + # never report what we do not push + ! grep "^ ! .*rejected.* atomic1 " output && + ! grep "^ ! .*rejected.* other " output ' test_expect_success 'push --atomic fails on server-side errors' ' diff --git a/t/t5543-atomic-push.sh b/t/t5543-atomic-push.sh index 7079bcf9a0..620c30d58f 100755 --- a/t/t5543-atomic-push.sh +++ b/t/t5543-atomic-push.sh @@ -27,6 +27,12 @@ test_refs () { test_cmp expect actual } +fmt_status_report () { + sed -n \ + -e "/^To / { s/ */ /g; p; }" \ + -e "/^ ! / { s/ */ /g; p; }" +} + test_expect_success 'atomic push works for a single branch' ' mk_repo_pair && ( @@ -191,4 +197,87 @@ test_expect_success 'atomic push is not advertised if configured' ' test_refs master HEAD@{1} ' +# References in upstream : master(1) one(1) foo(1) +# References in workbench: master(2) foo(1) two(2) bar(2) +# Atomic push : master(2) two(2) bar(2) +test_expect_success 'atomic push reports (reject by update hook)' ' + mk_repo_pair && + ( + cd workbench && + test_commit one && + git branch foo && + git push up master one foo && + git tag -d one + ) && + ( + mkdir -p upstream/.git/hooks && + cat >upstream/.git/hooks/update <<-EOF && + #!/bin/sh + + if test "\$1" = "refs/heads/bar" + then + echo >&2 "Pusing to branch bar is prohibited" + exit 1 + fi + EOF + chmod a+x upstream/.git/hooks/update + ) && + ( + cd workbench && + test_commit two && + git branch bar + ) && + test_must_fail git -C workbench \ + push --atomic up master two bar >out 2>&1 && + fmt_status_report <out >actual && + cat >expect <<-EOF && + To ../upstream + ! [remote rejected] master -> master (atomic push failure) + ! [remote rejected] two -> two (atomic push failure) + ! [remote rejected] bar -> bar (hook declined) + EOF + test_cmp expect actual +' + +# References in upstream : master(1) one(1) foo(1) +# References in workbench: master(2) foo(1) two(2) bar(2) +test_expect_success 'atomic push reports (mirror, but reject by update hook)' ' + ( + cd workbench && + git remote remove up && + git remote add up ../upstream + ) && + test_must_fail git -C workbench \ + push --atomic --mirror up >out 2>&1 && + fmt_status_report <out >actual && + cat >expect <<-EOF && + To ../upstream + ! [remote rejected] master -> master (atomic push failure) + ! [remote rejected] one (atomic push failure) + ! [remote rejected] bar -> bar (hook declined) + ! [remote rejected] two -> two (atomic push failure) + EOF + test_cmp expect actual +' + +# References in upstream : master(2) one(1) foo(1) +# References in workbench: master(1) foo(1) two(2) bar(2) +test_expect_success 'atomic push reports (reject by non-ff)' ' + rm upstream/.git/hooks/update && + ( + cd workbench && + git push up master && + git reset --hard HEAD^ + ) && + test_must_fail git -C workbench \ + push --atomic up master foo bar >out 2>&1 && + fmt_status_report <out >actual && + cat >expect <<-EOF && + To ../upstream + ! [rejected] master -> master (non-fast-forward) + ! [rejected] bar -> bar (atomic push failed) + EOF + test_cmp expect actual +' + test_done diff --git a/t/t5548-push-porcelain.sh b/t/t5548-push-porcelain.sh new file mode 100755 index 0000000000..1b19b3ef55 --- /dev/null +++ b/t/t5548-push-porcelain.sh @@ -0,0 +1,279 @@ +#!/bin/sh +# +# Copyright (c) 2020 Jiang Xin +# +test_description='Test git push porcelain output' + +. ./test-lib.sh + +# Create commits in <repo> and assign each commit's oid to shell variables +# given in the arguments (A, B, and C). E.g.: +# +# create_commits_in <repo> A B C +# +# NOTE: Never calling this function from a subshell since variable +# assignments will disappear when subshell exits. +create_commits_in () { + repo="$1" && + if ! parent=$(git -C "$repo" rev-parse HEAD^{} --) + then + parent= + fi && + T=$(git -C "$repo" write-tree) && + shift && + while test $# -gt 0 + do + name=$1 && + test_tick && + if test -z "$parent" + then + oid=$(echo $name | git -C "$repo" commit-tree $T) + else + oid=$(echo $name | git -C "$repo" commit-tree -p $parent $T) + fi && + eval $name=$oid && + parent=$oid && + shift || + return 1 + done && + git -C "$repo" update-ref refs/heads/master $oid +} + +# Format the output of git-push, git-show-ref and other commands to make a +# user-friendly and stable text. We can easily prepare the expect text +# without having to worry about future changes of the commit ID and spaces +# of the output. +make_user_friendly_and_stable_output () { + sed \ + -e "s/ *\$//" \ + -e "s/ */ /g" \ + -e "s/ / /g" \ + -e "s/$A/<COMMIT-A>/g" \ + -e "s/$B/<COMMIT-B>/g" \ + -e "s/$ZERO_OID/<ZERO-OID>/g" \ + -e "s/$(echo $A | cut -c1-7)[0-9a-f]*/<OID-A>/g" \ + -e "s/$(echo $B | cut -c1-7)[0-9a-f]*/<OID-B>/g" \ + -e "s#To $URL_PREFIX/upstream.git#To <URL/of/upstream.git>#" +} + +setup_upstream_and_workbench () { + # Upstream after setup : master(B) foo(A) bar(A) baz(A) + # Workbench after setup : master(A) + test_expect_success "setup upstream repository and workbench" ' + rm -rf upstream.git workbench && + git init --bare upstream.git && + git init workbench && + create_commits_in workbench A B && + ( + cd workbench && + # Try to make a stable fixed width for abbreviated commit ID, + # this fixed-width oid will be replaced with "<OID>". + git config core.abbrev 7 && + git remote add origin ../upstream.git && + git update-ref refs/heads/master $A && + git push origin \ + $B:refs/heads/master \ + $A:refs/heads/foo \ + $A:refs/heads/bar \ + $A:refs/heads/baz + ) && + git -C "workbench" config advice.pushUpdateRejected false && + upstream=upstream.git + ' +} + +run_git_push_porcelain_output_test() { + case $1 in + http) + PROTOCOL="HTTP protocol" + URL_PREFIX="http://.*" + ;; + file) + PROTOCOL="builtin protocol" + URL_PREFIX="\.\." + ;; + esac + + # Refs of upstream : master(B) foo(A) bar(A) baz(A) + # Refs of workbench: master(A) baz(A) next(A) + # git-push : master(A) NULL (B) baz(A) next(A) + test_expect_success "porcelain output of successful git-push ($PROTOCOL)" ' + ( + cd workbench && + git update-ref refs/heads/master $A && + git update-ref refs/heads/baz $A && + git update-ref refs/heads/next $A && + git push --porcelain --force origin \ + master \ + :refs/heads/foo \ + $B:bar \ + baz \ + next + ) >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + To <URL/of/upstream.git> + = refs/heads/baz:refs/heads/baz [up to date] + <COMMIT-B>:refs/heads/bar <OID-A>..<OID-B> + - :refs/heads/foo [deleted] + + refs/heads/master:refs/heads/master <OID-B>...<OID-A> (forced update) + * refs/heads/next:refs/heads/next [new branch] + Done + EOF + test_cmp expect actual && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + <COMMIT-B> refs/heads/bar + <COMMIT-A> refs/heads/baz + <COMMIT-A> refs/heads/master + <COMMIT-A> refs/heads/next + EOF + test_cmp expect actual + ' + + # Refs of upstream : master(A) bar(B) baz(A) next(A) + # Refs of workbench: master(B) bar(A) baz(A) next(A) + # git-push : master(B) bar(A) NULL next(A) + test_expect_success "atomic push failed ($PROTOCOL)" ' + ( + cd workbench && + git update-ref refs/heads/master $B && + git update-ref refs/heads/bar $A && + test_must_fail git push --atomic --porcelain origin \ + master \ + bar \ + :baz \ + next + ) >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + To <URL/of/upstream.git> + = refs/heads/next:refs/heads/next [up to date] + ! refs/heads/bar:refs/heads/bar [rejected] (non-fast-forward) + ! (delete):refs/heads/baz [rejected] (atomic push failed) + ! refs/heads/master:refs/heads/master [rejected] (atomic push failed) + Done + EOF + test_cmp expect actual && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + <COMMIT-B> refs/heads/bar + <COMMIT-A> refs/heads/baz + <COMMIT-A> refs/heads/master + <COMMIT-A> refs/heads/next + EOF + test_cmp expect actual + ' + test_expect_success "prepare pre-receive hook ($PROTOCOL)" ' + write_script "$upstream/hooks/pre-receive" <<-EOF + exit 1 + EOF + ' + + # Refs of upstream : master(A) bar(B) baz(A) next(A) + # Refs of workbench: master(B) bar(A) baz(A) next(A) + # git-push : master(B) bar(A) NULL next(A) + test_expect_success "pre-receive hook declined ($PROTOCOL)" ' + ( + cd workbench && + git update-ref refs/heads/master $B && + git update-ref refs/heads/bar $A && + test_must_fail git push --porcelain --force origin \ + master \ + bar \ + :baz \ + next + ) >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + To <URL/of/upstream.git> + = refs/heads/next:refs/heads/next [up to date] + ! refs/heads/bar:refs/heads/bar [remote rejected] (pre-receive hook declined) + ! :refs/heads/baz [remote rejected] (pre-receive hook declined) + ! refs/heads/master:refs/heads/master [remote rejected] (pre-receive hook declined) + Done + EOF + test_cmp expect actual && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + <COMMIT-B> refs/heads/bar + <COMMIT-A> refs/heads/baz + <COMMIT-A> refs/heads/master + <COMMIT-A> refs/heads/next + EOF + test_cmp expect actual + ' + + test_expect_success "remove pre-receive hook ($PROTOCOL)" ' + rm "$upstream/hooks/pre-receive" + ' + + # Refs of upstream : master(A) bar(B) baz(A) next(A) + # Refs of workbench: master(B) bar(A) baz(A) next(A) + # git-push : master(B) bar(A) NULL next(A) + test_expect_success "non-fastforward push ($PROTOCOL)" ' + ( + cd workbench && + test_must_fail git push --porcelain origin \ + master \ + bar \ + :baz \ + next + ) >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + To <URL/of/upstream.git> + = refs/heads/next:refs/heads/next [up to date] + - :refs/heads/baz [deleted] + refs/heads/master:refs/heads/master <OID-A>..<OID-B> + ! refs/heads/bar:refs/heads/bar [rejected] (non-fast-forward) + Done + EOF + test_cmp expect actual && + + git -C "$upstream" show-ref >out && + make_user_friendly_and_stable_output <out >actual && + cat >expect <<-EOF && + <COMMIT-B> refs/heads/bar + <COMMIT-B> refs/heads/master + <COMMIT-A> refs/heads/next + EOF + test_cmp expect actual + ' +} + +# Initialize the upstream repository and local workbench. +setup_upstream_and_workbench + +# Run git-push porcelain test on builtin protocol +run_git_push_porcelain_output_test file + +ROOT_PATH="$PWD" +. "$TEST_DIRECTORY"/lib-gpg.sh +. "$TEST_DIRECTORY"/lib-httpd.sh +. "$TEST_DIRECTORY"/lib-terminal.sh +start_httpd + +# Re-initialize the upstream repository and local workbench. +setup_upstream_and_workbench + +test_expect_success "setup for http" ' + git -C upstream.git config http.receivepack true && + upstream="$HTTPD_DOCUMENT_ROOT_PATH/upstream.git" && + mv upstream.git "$upstream" && + + git -C workbench remote set-url origin $HTTPD_URL/smart/upstream.git +' + +setup_askpass_helper + +# Run git-push porcelain test on HTTP protocol +run_git_push_porcelain_output_test http + +test_done diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh index b811d89cfd..50485300eb 100755 --- a/t/t5550-http-fetch-dumb.sh +++ b/t/t5550-http-fetch-dumb.sh @@ -248,9 +248,7 @@ test_expect_success 'fetch can handle previously-fetched .idx files' ' ' test_expect_success 'did not use upload-pack service' ' - test_might_fail grep '/git-upload-pack' <"$HTTPD_ROOT_PATH"/access.log >act && - : >exp && - test_cmp exp act + ! grep "/git-upload-pack" "$HTTPD_ROOT_PATH/access.log" ' test_expect_success 'git client shows text/plain errors' ' @@ -321,11 +319,17 @@ test_expect_success 'git client does not send an empty Accept-Language' ' ' 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 + test_must_fail git remote-http http::/example.com/repo.git 2>stderr && + test_i18ngrep "url has no scheme" stderr +' + +# NEEDSWORK: Writing commands to git-remote-curl can race against the latter +# erroring out, producing SIGPIPE. Remove "ok=sigpipe" once transport-helper has +# learned to handle early remote helper failures more cleanly. +test_expect_success 'remote-http complains cleanly about empty scheme' ' + test_must_fail ok=sigpipe git ls-remote \ + http::${HTTPD_URL#http}/dumb/repo.git 2>stderr && + test_i18ngrep "url has no scheme" stderr ' test_expect_success 'redirects can be forbidden/allowed' ' diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh index e38e543867..6788aeface 100755 --- a/t/t5551-http-fetch-smart.sh +++ b/t/t5551-http-fetch-smart.sh @@ -43,7 +43,7 @@ test_expect_success 'clone http repository' ' < Cache-Control: no-cache, max-age=0, must-revalidate < Content-Type: application/x-git-upload-pack-result EOF - GIT_TRACE_CURL=true GIT_TEST_PROTOCOL_VERSION= \ + GIT_TRACE_CURL=true GIT_TEST_PROTOCOL_VERSION=0 \ git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err && test_cmp file clone/file && tr '\''\015'\'' Q <err | @@ -84,7 +84,7 @@ test_expect_success 'clone http repository' ' # NEEDSWORK: If the overspecification of the expected result is reduced, we # might be able to run this test in all protocol versions. - if test -z "$GIT_TEST_PROTOCOL_VERSION" + if test "$GIT_TEST_PROTOCOL_VERSION" = 0 then sed -e "s/^> Accept-Encoding: .*/> Accept-Encoding: ENCODINGS/" \ actual >actual.smudged && @@ -113,7 +113,7 @@ test_expect_success 'used upload-pack service' ' # NEEDSWORK: If the overspecification of the expected result is reduced, we # might be able to run this test in all protocol versions. - if test -z "$GIT_TEST_PROTOCOL_VERSION" + if test "$GIT_TEST_PROTOCOL_VERSION" = 0 then check_access_log exp fi @@ -241,7 +241,7 @@ test_expect_success 'cookies stored in http.cookiefile when http.savecookies set # NEEDSWORK: If the overspecification of the expected result is reduced, we # might be able to run this test in all protocol versions. - if test -z "$GIT_TEST_PROTOCOL_VERSION" + if test "$GIT_TEST_PROTOCOL_VERSION" = 0 then tail -3 cookies.txt | sort >cookies_tail.txt && test_cmp expect_cookies.txt cookies_tail.txt @@ -336,7 +336,7 @@ test_expect_success 'test allowreachablesha1inwant with unreachable' ' git -C test_reachable.git remote add origin "$HTTPD_URL/smart/repo.git" && # Some protocol versions (e.g. 2) support fetching # unadvertised objects, so restrict this test to v0. - test_must_fail env GIT_TEST_PROTOCOL_VERSION= \ + test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \ git -C test_reachable.git fetch origin "$(git rev-parse HEAD)" ' @@ -358,7 +358,7 @@ test_expect_success 'test allowanysha1inwant with unreachable' ' git -C test_reachable.git remote add origin "$HTTPD_URL/smart/repo.git" && # Some protocol versions (e.g. 2) support fetching # unadvertised objects, so restrict this test to v0. - test_must_fail env GIT_TEST_PROTOCOL_VERSION= \ + test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \ git -C test_reachable.git fetch origin "$(git rev-parse HEAD)" && git -C "$server" config uploadpack.allowanysha1inwant 1 && diff --git a/t/t5552-skipping-fetch-negotiator.sh b/t/t5552-skipping-fetch-negotiator.sh index f70cbcc9ca..156c704040 100755 --- a/t/t5552-skipping-fetch-negotiator.sh +++ b/t/t5552-skipping-fetch-negotiator.sh @@ -107,7 +107,11 @@ test_expect_success 'use ref advertisement to filter out commits' ' # The ref advertisement itself is filtered when protocol v2 is used, so # use v0. - GIT_TEST_PROTOCOL_VERSION= trace_fetch client origin to_fetch && + ( + GIT_TEST_PROTOCOL_VERSION=0 && + export GIT_TEST_PROTOCOL_VERSION && + trace_fetch client origin to_fetch + ) && have_sent c5 c4^ c2side && have_not_sent c4 c4^^ c4^^^ ' @@ -169,7 +173,17 @@ test_expect_success 'do not send "have" with ancestors of commits that server AC test_commit -C server commit-on-b1 && test_config -C client fetch.negotiationalgorithm skipping && - trace_fetch client "$(pwd)/server" to_fetch && + + # NEEDSWORK: The number of "have"s sent depends on whether the transport + # is stateful. If the overspecification of the result were reduced, this + # test could be used for both stateful and stateless transports. + ( + # Force protocol v0, in which local transport is stateful (in + # protocol v2 it is stateless). + GIT_TEST_PROTOCOL_VERSION=0 && + export GIT_TEST_PROTOCOL_VERSION && + trace_fetch client "$(pwd)/server" to_fetch + ) && grep " fetch" trace && # fetch-pack sends 2 requests each containing 16 "have" lines before diff --git a/t/t5562-http-backend-content-length.sh b/t/t5562-http-backend-content-length.sh index f0f425b2cf..3f4ac71f83 100755 --- a/t/t5562-http-backend-content-length.sh +++ b/t/t5562-http-backend-content-length.sh @@ -53,15 +53,20 @@ test_expect_success 'setup' ' test_commit c1 && hash_head=$(git rev-parse HEAD) && hash_prev=$(git rev-parse HEAD~1) && - printf "want %s" "$hash_head" | packetize >fetch_body && - printf 0000 >>fetch_body && - printf "have %s" "$hash_prev" | packetize >>fetch_body && - printf done | packetize >>fetch_body && + { + packetize "want $hash_head" && + printf 0000 && + packetize "have $hash_prev" && + packetize "done" + } >fetch_body && test_copy_bytes 10 <fetch_body >fetch_body.trunc && hash_next=$(git commit-tree -p HEAD -m next HEAD^{tree}) && - printf "%s %s refs/heads/newbranch\\0report-status\\n" "$_z40" "$hash_next" | packetize >push_body && - printf 0000 >>push_body && - echo "$hash_next" | git pack-objects --stdout >>push_body && + { + printf "%s %s refs/heads/newbranch\\0report-status\\n" \ + "$ZERO_OID" "$hash_next" | packetize && + printf 0000 && + echo "$hash_next" | git pack-objects --stdout + } >push_body && test_copy_bytes 10 <push_body >push_body.trunc && : >empty_body ' diff --git a/t/t5573-pull-verify-signatures.sh b/t/t5573-pull-verify-signatures.sh index 3e9876e197..a53dd8550d 100755 --- a/t/t5573-pull-verify-signatures.sh +++ b/t/t5573-pull-verify-signatures.sh @@ -60,6 +60,27 @@ test_expect_success GPG 'pull commit with untrusted signature with --verify-sign test_i18ngrep "has an untrusted GPG signature" pullerror ' +test_expect_success GPG 'pull commit with untrusted signature with --verify-signatures and minTrustLevel=ultimate' ' + test_when_finished "git reset --hard && git checkout initial" && + test_config gpg.minTrustLevel ultimate && + test_must_fail git pull --ff-only --verify-signatures untrusted 2>pullerror && + test_i18ngrep "has an untrusted GPG signature" pullerror +' + +test_expect_success GPG 'pull commit with untrusted signature with --verify-signatures and minTrustLevel=marginal' ' + test_when_finished "git reset --hard && git checkout initial" && + test_config gpg.minTrustLevel marginal && + test_must_fail git pull --ff-only --verify-signatures untrusted 2>pullerror && + test_i18ngrep "has an untrusted GPG signature" pullerror +' + +test_expect_success GPG 'pull commit with untrusted signature with --verify-signatures and minTrustLevel=undefined' ' + test_when_finished "git reset --hard && git checkout initial" && + test_config gpg.minTrustLevel undefined && + git pull --ff-only --verify-signatures untrusted >pulloutput && + test_i18ngrep "has a good GPG signature" pulloutput +' + test_expect_success GPG 'pull signed commit with --verify-signatures' ' test_when_finished "git reset --hard && git checkout initial" && git pull --verify-signatures signed >pulloutput && @@ -79,10 +100,53 @@ test_expect_success GPG 'pull commit with bad signature with --no-verify-signatu ' test_expect_success GPG 'pull unsigned commit into unborn branch' ' + test_when_finished "rm -rf empty-repo" && git init empty-repo && test_must_fail \ git -C empty-repo pull --verify-signatures .. 2>pullerror && test_i18ngrep "does not have a GPG signature" pullerror ' +test_expect_success GPG 'pull commit into unborn branch with bad signature and --verify-signatures' ' + test_when_finished "rm -rf empty-repo" && + git init empty-repo && + test_must_fail \ + git -C empty-repo pull --ff-only --verify-signatures ../bad 2>pullerror && + test_i18ngrep "has a bad GPG signature" pullerror +' + +test_expect_success GPG 'pull commit into unborn branch with untrusted signature and --verify-signatures' ' + test_when_finished "rm -rf empty-repo" && + git init empty-repo && + test_must_fail \ + git -C empty-repo pull --ff-only --verify-signatures ../untrusted 2>pullerror && + test_i18ngrep "has an untrusted GPG signature" pullerror +' + +test_expect_success GPG 'pull commit into unborn branch with untrusted signature and --verify-signatures and minTrustLevel=ultimate' ' + test_when_finished "rm -rf empty-repo" && + git init empty-repo && + test_config_global gpg.minTrustLevel ultimate && + test_must_fail \ + git -C empty-repo pull --ff-only --verify-signatures ../untrusted 2>pullerror && + test_i18ngrep "has an untrusted GPG signature" pullerror +' + +test_expect_success GPG 'pull commit into unborn branch with untrusted signature and --verify-signatures and minTrustLevel=marginal' ' + test_when_finished "rm -rf empty-repo" && + git init empty-repo && + test_config_global gpg.minTrustLevel marginal && + test_must_fail \ + git -C empty-repo pull --ff-only --verify-signatures ../untrusted 2>pullerror && + test_i18ngrep "has an untrusted GPG signature" pullerror +' + +test_expect_success GPG 'pull commit into unborn branch with untrusted signature and --verify-signatures and minTrustLevel=undefined' ' + test_when_finished "rm -rf empty-repo" && + git init empty-repo && + test_config_global gpg.minTrustLevel undefined && + git -C empty-repo pull --ff-only --verify-signatures ../untrusted >pulloutput && + test_i18ngrep "has a good GPG signature" pulloutput +' + test_done diff --git a/t/t5580-clone-push-unc.sh b/t/t5580-unc-paths.sh index 01b52c195a..cf768b3a27 100755 --- a/t/t5580-clone-push-unc.sh +++ b/t/t5580-unc-paths.sh @@ -40,11 +40,23 @@ test_expect_success clone ' git clone "file://$UNCPATH" clone ' +test_expect_success 'clone without file://' ' + git clone "$UNCPATH" clone-without-file +' + test_expect_success 'clone with backslashed path' ' BACKSLASHED="$(echo "$UNCPATH" | tr / \\\\)" && git clone "$BACKSLASHED" backslashed ' +test_expect_success fetch ' + git init to-fetch && + ( + cd to-fetch && + git fetch "$UNCPATH" master + ) +' + test_expect_success push ' ( cd clone && diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index ad8c41176e..84ea2a3eb7 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -635,10 +635,10 @@ partial_clone_server () { rm -rf "$SERVER" client && test_create_repo "$SERVER" && test_commit -C "$SERVER" one && - HASH1=$(git hash-object "$SERVER/one.t") && + HASH1=$(git -C "$SERVER" hash-object one.t) && git -C "$SERVER" revert HEAD && test_commit -C "$SERVER" two && - HASH2=$(git hash-object "$SERVER/two.t") && + HASH2=$(git -C "$SERVER" hash-object two.t) && test_config -C "$SERVER" uploadpack.allowfilter 1 && test_config -C "$SERVER" uploadpack.allowanysha1inwant 1 } diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh index 4894237ab8..2f7be23044 100755 --- a/t/t5604-clone-reference.sh +++ b/t/t5604-clone-reference.sh @@ -175,7 +175,7 @@ test_expect_success 'clone using repo pointed at by gitfile as reference' ' test_expect_success 'clone and dissociate from reference' ' git init P && ( - cd P && test_commit one + cd P && test_commit one ) && git clone P Q && ( @@ -326,15 +326,16 @@ test_expect_success SYMLINKS 'clone repo with symlinked or unknown files at obje for raw in $(ls T*.raw) do sed -e "s!/../!/Y/!; s![0-9a-f]\{38,\}!Z!" -e "/commit-graph/d" \ - -e "/multi-pack-index/d" <$raw >$raw.de-sha || return 1 + -e "/multi-pack-index/d" <$raw >$raw.de-sha-1 && + sort $raw.de-sha-1 >$raw.de-sha || return 1 done && cat >expected-files <<-EOF && ./Y/Z ./Y/Z + ./Y/Z ./a-loose-dir/Z ./an-object - ./Y/Z ./info/packs ./pack/pack-Z.idx ./pack/pack-Z.pack diff --git a/t/t5607-clone-bundle.sh b/t/t5607-clone-bundle.sh index b7a3fdf02d..6d5a977fcb 100755 --- a/t/t5607-clone-bundle.sh +++ b/t/t5607-clone-bundle.sh @@ -16,7 +16,7 @@ test_expect_success 'setup' ' test_expect_success '"verify" needs a worktree' ' git bundle create tip.bundle -1 master && - test_must_fail nongit git bundle verify ../tip.bundle 2>err && + nongit test_must_fail git bundle verify ../tip.bundle 2>err && test_i18ngrep "need a repository" err ' @@ -64,7 +64,7 @@ test_expect_success 'ridiculously long subject in boundary' ' test -s heads && git fetch long-subject-bundle.bdl && sed -n "/^-/{p;q;}" long-subject-bundle.bdl >boundary && - grep "^-[0-9a-f]\\{40\\} " boundary + grep "^-$OID_REGEX " boundary ' test_expect_success 'prerequisites with an empty commit message' ' diff --git a/t/t5611-clone-config.sh b/t/t5611-clone-config.sh index 60c1ba951b..8e0fd39823 100755 --- a/t/t5611-clone-config.sh +++ b/t/t5611-clone-config.sh @@ -92,24 +92,17 @@ test_expect_success 'clone -c remote.<remote>.fetch=<refspec> --origin=<name>' ' test_cmp expect actual ' -# Tests for the hidden file attribute on windows -is_hidden () { - # Use the output of `attrib`, ignore the absolute path - case "$(attrib "$1")" in *H*?:*) return 0;; esac - return 1 -} - test_expect_success MINGW 'clone -c core.hideDotFiles' ' test_commit attributes .gitattributes "" && rm -rf child && git clone -c core.hideDotFiles=false . child && - ! is_hidden child/.gitattributes && + ! test_path_is_hidden child/.gitattributes && rm -rf child && git clone -c core.hideDotFiles=dotGitOnly . child && - ! is_hidden child/.gitattributes && + ! test_path_is_hidden child/.gitattributes && rm -rf child && git clone -c core.hideDotFiles=true . child && - is_hidden child/.gitattributes + test_path_is_hidden child/.gitattributes ' test_done diff --git a/t/t5612-clone-refspec.sh b/t/t5612-clone-refspec.sh index e36ac01661..e3b436d8ae 100755 --- a/t/t5612-clone-refspec.sh +++ b/t/t5612-clone-refspec.sh @@ -71,9 +71,9 @@ test_expect_success 'by default all branches will be kept updated' ' ( cd dir_all && git fetch && - git for-each-ref refs/remotes/origin | + git for-each-ref refs/remotes/origin >refs && sed -e "/HEAD$/d" \ - -e "s|/remotes/origin/|/heads/|" >../actual + -e "s|/remotes/origin/|/heads/|" refs >../actual ) && # follow both master and side git for-each-ref refs/heads >expect && @@ -87,7 +87,7 @@ test_expect_success 'by default no tags will be kept updated' ' git for-each-ref refs/tags >../actual ) && git for-each-ref refs/tags >expect && - test_must_fail test_cmp expect actual && + ! test_cmp expect actual && test_line_count = 2 actual ' @@ -104,9 +104,9 @@ test_expect_success '--single-branch while HEAD pointing at master' ' ( cd dir_master && git fetch --force && - git for-each-ref refs/remotes/origin | + git for-each-ref refs/remotes/origin >refs && sed -e "/HEAD$/d" \ - -e "s|/remotes/origin/|/heads/|" >../actual + -e "s|/remotes/origin/|/heads/|" refs >../actual ) && # only follow master git for-each-ref refs/heads/master >expect && @@ -126,9 +126,9 @@ test_expect_success '--single-branch while HEAD pointing at master and --no-tags ( cd dir_master_no_tags && git fetch && - git for-each-ref refs/remotes/origin | + git for-each-ref refs/remotes/origin >refs && sed -e "/HEAD$/d" \ - -e "s|/remotes/origin/|/heads/|" >../actual + -e "s|/remotes/origin/|/heads/|" refs >../actual ) && # only follow master git for-each-ref refs/heads/master >expect && @@ -156,9 +156,9 @@ test_expect_success '--single-branch while HEAD pointing at side' ' ( cd dir_side && git fetch && - git for-each-ref refs/remotes/origin | + git for-each-ref refs/remotes/origin >refs && sed -e "/HEAD$/d" \ - -e "s|/remotes/origin/|/heads/|" >../actual + -e "s|/remotes/origin/|/heads/|" refs >../actual ) && # only follow side git for-each-ref refs/heads/side >expect && @@ -169,9 +169,9 @@ test_expect_success '--single-branch with explicit --branch side' ' ( cd dir_side2 && git fetch && - git for-each-ref refs/remotes/origin | + git for-each-ref refs/remotes/origin >refs && sed -e "/HEAD$/d" \ - -e "s|/remotes/origin/|/heads/|" >../actual + -e "s|/remotes/origin/|/heads/|" refs >../actual ) && # only follow side git for-each-ref refs/heads/side >expect && @@ -223,9 +223,9 @@ test_expect_success '--single-branch with detached' ' ( cd dir_detached && git fetch && - git for-each-ref refs/remotes/origin | + git for-each-ref refs/remotes/origin >refs && sed -e "/HEAD$/d" \ - -e "s|/remotes/origin/|/heads/|" >../actual + -e "s|/remotes/origin/|/heads/|" refs >../actual ) && # nothing test_must_be_empty actual diff --git a/t/t5616-partial-clone.sh b/t/t5616-partial-clone.sh index fea56cda6d..8a27452a51 100755 --- a/t/t5616-partial-clone.sh +++ b/t/t5616-partial-clone.sh @@ -49,7 +49,7 @@ test_expect_success 'do partial clone 1' ' test_expect_success 'verify that .promisor file contains refs fetched' ' ls pc1/.git/objects/pack/pack-*.promisor >promisorlist && test_line_count = 1 promisorlist && - git -C srv.bare rev-list HEAD >headhash && + git -C srv.bare rev-parse --verify HEAD >headhash && grep "$(cat headhash) HEAD" $(cat promisorlist) && grep "$(cat headhash) refs/heads/master" $(cat promisorlist) ' @@ -309,26 +309,36 @@ setup_triangle () { printf "line %d\n" $(test_seq 1 100) >big-blob.txt && - # Create a server with 2 commits: a commit with a big blob and a child + # Create a server with 2 commits: a commit with a big tree and a child # commit with an incremental change. Also, create a partial clone # client that only contains the first commit. git init server && git -C server config --local uploadpack.allowfilter 1 && - cp big-blob.txt server && - git -C server add big-blob.txt && + for i in $(test_seq 1 100) + do + echo "make the tree big" >server/file$i && + git -C server add file$i + done && git -C server commit -m "initial" && git clone --bare --filter=tree:0 "file://$(pwd)/server" client && - echo another line >>server/big-blob.txt && - git -C server commit -am "append line to big blob" && + echo another line >>server/file1 && + git -C server commit -am "incremental change" && - # Create a promisor remote that only contains the blob from the first - # commit, and set it as the promisor remote of client. Thus, whenever - # the client lazy fetches, the lazy fetch will succeed only if it is - # for this blob. + # Create a promisor remote that only contains the tree and blob from + # the first commit. git init promisor-remote && + git -C server config --local uploadpack.allowanysha1inwant 1 && + TREE_HASH=$(git -C server rev-parse HEAD~1^{tree}) && + git -C promisor-remote fetch --keep "file://$(pwd)/server" "$TREE_HASH" && + git -C promisor-remote count-objects -v >object-count && + test_i18ngrep "count: 0" object-count && + test_i18ngrep "in-pack: 2" object-count && + + # Set it as the promisor remote of client. Thus, whenever + # the client lazy fetches, the lazy fetch will succeed only if it is + # for this tree or blob. test_commit -C promisor-remote one && # so that ref advertisement is not empty git -C promisor-remote config --local uploadpack.allowanysha1inwant 1 && - git -C promisor-remote hash-object -w --stdin <big-blob.txt && git -C client remote set-url origin "file://$(pwd)/promisor-remote" } @@ -341,14 +351,14 @@ test_expect_success 'fetch lazy-fetches only to resolve deltas' ' setup_triangle && # Exercise to make sure it works. Git will not fetch anything from the - # promisor remote other than for the big blob (because it needs to + # promisor remote other than for the big tree (because it needs to # resolve the delta). GIT_TRACE_PACKET="$(pwd)/trace" git -C client \ fetch "file://$(pwd)/server" master && # Verify the assumption that the client needed to fetch the delta base # to resolve the delta. - git hash-object big-blob.txt >hash && + git -C server rev-parse HEAD~1^{tree} >hash && grep "want $(cat hash)" trace ' @@ -370,10 +380,48 @@ test_expect_success 'fetch lazy-fetches only to resolve deltas, protocol v2' ' # Verify the assumption that the client needed to fetch the delta base # to resolve the delta. - git hash-object big-blob.txt >hash && + git -C server rev-parse HEAD~1^{tree} >hash && grep "want $(cat hash)" trace ' +# The following two tests must be in this order. It is important that +# the srv.bare repository did not have tags during clone, but has tags +# in the fetch. + +test_expect_success 'verify fetch succeeds when asking for new tags' ' + git clone --filter=blob:none "file://$(pwd)/srv.bare" tag-test && + for i in I J K + do + test_commit -C src $i && + git -C src branch $i || return 1 + done && + git -C srv.bare fetch --tags origin +refs/heads/*:refs/heads/* && + git -C tag-test -c protocol.version=2 fetch --tags origin +' + +test_expect_success 'verify fetch downloads only one pack when updating refs' ' + git clone --filter=blob:none "file://$(pwd)/srv.bare" pack-test && + ls pack-test/.git/objects/pack/*pack >pack-list && + test_line_count = 2 pack-list && + for i in A B C + do + test_commit -C src $i && + git -C src branch $i || return 1 + done && + git -C srv.bare fetch origin +refs/heads/*:refs/heads/* && + git -C pack-test fetch origin && + ls pack-test/.git/objects/pack/*pack >pack-list && + test_line_count = 3 pack-list +' + +test_expect_success 'single-branch tag following respects partial clone' ' + git clone --single-branch -b B --filter=blob:none \ + "file://$(pwd)/srv.bare" single && + git -C single rev-parse --verify refs/tags/B && + git -C single rev-parse --verify refs/tags/A && + test_must_fail git -C single rev-parse --verify refs/tags/C +' + . "$TEST_DIRECTORY"/lib-httpd.sh start_httpd @@ -388,14 +436,18 @@ intersperse () { sed 's/\(..\)/'$1'\1/g' } -# Create a one-time-sed command to replace the existing packfile with $1. +# Create a one-time-perl command to replace the existing packfile with $1. replace_packfile () { # The protocol requires that the packfile be sent in sideband 1, hence # the extra \x01 byte at the beginning. - printf "1,/packfile/!c %04x\\\\x01%s0000" \ - "$(($(wc -c <$1) + 5))" \ - "$(hex_unpack <$1 | intersperse '\\x')" \ - >"$HTTPD_ROOT_PATH/one-time-sed" + cp $1 "$HTTPD_ROOT_PATH/one-time-pack" && + echo 'if (/packfile/) { + print; + my $length = -s "one-time-pack"; + printf "%04x\x01", $length + 5; + print `cat one-time-pack` . "0000"; + last + }' >"$HTTPD_ROOT_PATH/one-time-perl" } test_expect_success 'upon cloning, check that all refs point to objects' ' @@ -419,16 +471,16 @@ test_expect_success 'upon cloning, check that all refs point to objects' ' # \x01 byte at the beginning. replace_packfile incomplete.pack && - # Use protocol v2 because the sed command looks for the "packfile" + # Use protocol v2 because the perl command looks for the "packfile" # section header. test_config -C "$SERVER" protocol.version 2 && test_must_fail git -c protocol.version=2 clone \ - --filter=blob:none $HTTPD_URL/one_time_sed/server repo 2>err && + --filter=blob:none $HTTPD_URL/one_time_perl/server repo 2>err && test_i18ngrep "did not send all necessary objects" err && - # Ensure that the one-time-sed script was used. - ! test -e "$HTTPD_ROOT_PATH/one-time-sed" + # Ensure that the one-time-perl script was used. + ! test -e "$HTTPD_ROOT_PATH/one-time-perl" ' test_expect_success 'when partial cloning, tolerate server not sending target of tag' ' @@ -459,17 +511,17 @@ test_expect_success 'when partial cloning, tolerate server not sending target of # \x01 byte at the beginning. replace_packfile incomplete.pack && - # Use protocol v2 because the sed command looks for the "packfile" + # Use protocol v2 because the perl command looks for the "packfile" # section header. test_config -C "$SERVER" protocol.version 2 && # Exercise to make sure it works. git -c protocol.version=2 clone \ - --filter=blob:none $HTTPD_URL/one_time_sed/server repo 2> err && + --filter=blob:none $HTTPD_URL/one_time_perl/server repo 2> err && ! grep "missing object referenced by" err && - # Ensure that the one-time-sed script was used. - ! test -e "$HTTPD_ROOT_PATH/one-time-sed" + # Ensure that the one-time-perl script was used. + ! test -e "$HTTPD_ROOT_PATH/one-time-perl" ' test_expect_success 'tolerate server sending REF_DELTA against missing promisor objects' ' @@ -492,7 +544,7 @@ test_expect_success 'tolerate server sending REF_DELTA against missing promisor # Clone. The client has deltabase_have but not deltabase_missing. git -c protocol.version=2 clone --no-checkout \ - --filter=blob:none $HTTPD_URL/one_time_sed/server repo && + --filter=blob:none $HTTPD_URL/one_time_perl/server repo && git -C repo hash-object -w -- "$SERVER/have.txt" && # Sanity check to ensure that the client does not have @@ -533,7 +585,7 @@ test_expect_success 'tolerate server sending REF_DELTA against missing promisor replace_packfile thin.pack && - # Use protocol v2 because the sed command looks for the "packfile" + # Use protocol v2 because the perl command looks for the "packfile" # section header. test_config -C "$SERVER" protocol.version 2 && @@ -546,8 +598,8 @@ test_expect_success 'tolerate server sending REF_DELTA against missing promisor grep "want $(cat deltabase_missing)" trace && ! grep "want $(cat deltabase_have)" trace && - # Ensure that the one-time-sed script was used. - ! test -e "$HTTPD_ROOT_PATH/one-time-sed" + # Ensure that the one-time-perl script was used. + ! test -e "$HTTPD_ROOT_PATH/one-time-perl" ' # DO NOT add non-httpd-specific tests here, because the last part of this diff --git a/t/t5617-clone-submodules-remote.sh b/t/t5617-clone-submodules-remote.sh index 37fcce9c40..1a041df10b 100755 --- a/t/t5617-clone-submodules-remote.sh +++ b/t/t5617-clone-submodules-remote.sh @@ -14,7 +14,8 @@ test_expect_success 'setup' ' cd sub && git init && test_commit subcommit1 && - git tag sub_when_added_to_super + git tag sub_when_added_to_super && + git branch other ) && git submodule add "file://$pwd/sub" sub && git commit -m "add submodule" && @@ -51,4 +52,14 @@ test_expect_success 'check the default is --no-remote-submodules' ' ) ' +test_expect_success 'clone with --single-branch' ' + test_when_finished "rm -rf super_clone" && + git clone --recurse-submodules --single-branch "file://$pwd/." super_clone && + ( + cd super_clone/sub && + git rev-parse --verify origin/master && + test_must_fail git rev-parse --verify origin/other + ) +' + test_done diff --git a/t/t5700-protocol-v1.sh b/t/t5700-protocol-v1.sh index 2571eb90b7..022901b9eb 100755 --- a/t/t5700-protocol-v1.sh +++ b/t/t5700-protocol-v1.sh @@ -5,7 +5,8 @@ test_description='test git wire-protocol transition' TEST_NO_CREATE_REPO=1 # This is a protocol-specific test. -GIT_TEST_PROTOCOL_VERSION= +GIT_TEST_PROTOCOL_VERSION=0 +export GIT_TEST_PROTOCOL_VERSION . ./test-lib.sh diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index e73067d23f..5039e66dc4 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -665,6 +665,18 @@ test_expect_success 'fetch from namespaced repo respects namespaces' ' test_cmp expect actual ' +test_expect_success 'ls-remote with v2 http sends only one POST' ' + test_when_finished "rm -f log" && + + git ls-remote "$HTTPD_DOCUMENT_ROOT_PATH/http_parent" >expect && + GIT_TRACE_CURL="$(pwd)/log" git -c protocol.version=2 \ + ls-remote "$HTTPD_URL/smart/http_parent" >actual && + test_cmp expect actual && + + grep "Send header: POST" log >posts && + test_line_count = 1 posts +' + test_expect_success 'push with http:// and a config of v2 does not request v2' ' test_when_finished "rm -f log" && # Till v2 for push is designed, make sure that if a client has @@ -700,11 +712,11 @@ test_expect_success 'when server sends "ready", expect DELIM' ' # After "ready" in the acknowledgments section, pretend that a FLUSH # (0000) was sent instead of a DELIM (0001). - printf "/ready/,$ s/0001/0000/" \ - >"$HTTPD_ROOT_PATH/one-time-sed" && + printf "\$ready = 1 if /ready/; \$ready && s/0001/0000/" \ + >"$HTTPD_ROOT_PATH/one-time-perl" && test_must_fail git -C http_child -c protocol.version=2 \ - fetch "$HTTPD_URL/one_time_sed/http_parent" 2> err && + fetch "$HTTPD_URL/one_time_perl/http_parent" 2> err && test_i18ngrep "expected packfile to be sent after .ready." err ' @@ -725,12 +737,12 @@ test_expect_success 'when server does not send "ready", expect FLUSH' ' # After the acknowledgments section, pretend that a DELIM # (0001) was sent instead of a FLUSH (0000). - printf "/acknowledgments/,$ s/0000/0001/" \ - >"$HTTPD_ROOT_PATH/one-time-sed" && + printf "\$ack = 1 if /acknowledgments/; \$ack && s/0000/0001/" \ + >"$HTTPD_ROOT_PATH/one-time-perl" && test_must_fail env GIT_TRACE_PACKET="$(pwd)/log" git -C http_child \ -c protocol.version=2 \ - fetch "$HTTPD_URL/one_time_sed/http_parent" 2> err && + fetch "$HTTPD_URL/one_time_perl/http_parent" 2> err && grep "fetch< .*acknowledgments" log && ! grep "fetch< .*ready" log && test_i18ngrep "expected no other sections to be sent after no .ready." err diff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh index 1424fabd4a..a34460f7d8 100755 --- a/t/t5703-upload-pack-ref-in-want.sh +++ b/t/t5703-upload-pack-ref-in-want.sh @@ -13,13 +13,10 @@ get_actual_refs () { } get_actual_commits () { - sed -n -e '/packfile/,/0000/{ - /packfile/d - p - }' <out | test-tool pkt-line unpack-sideband >o.pack && + test-tool pkt-line unpack-sideband <out >o.pack && git index-pack o.pack && git verify-pack -v o.idx >objs && - grep commit objs | cut -c-40 | sort >actual_commits + grep commit objs | cut -d" " -f1 | sort >actual_commits } check_output () { @@ -37,6 +34,7 @@ check_output () { # \ | / # a test_expect_success 'setup repository' ' + test_oid_init && test_commit a && git checkout -b o/foo && test_commit b && @@ -313,7 +311,7 @@ test_expect_success 'setup repos for change-while-negotiating test' ' test_commit m3 && git tag -d m2 m3 ) && - git -C "$LOCAL_PRISTINE" remote set-url origin "http://127.0.0.1:$LIB_HTTPD_PORT/one_time_sed/repo" && + git -C "$LOCAL_PRISTINE" remote set-url origin "http://127.0.0.1:$LIB_HTTPD_PORT/one_time_perl/repo" && git -C "$LOCAL_PRISTINE" config protocol.version 2 ' @@ -326,14 +324,14 @@ inconsistency () { # RPCs during a single negotiation. oid1=$(git -C "$REPO" rev-parse $1) && oid2=$(git -C "$REPO" rev-parse $2) && - echo "s/$oid1/$oid2/" >"$HTTPD_ROOT_PATH/one-time-sed" + echo "s/$oid1/$oid2/" >"$HTTPD_ROOT_PATH/one-time-perl" } test_expect_success 'server is initially ahead - no ref in want' ' git -C "$REPO" config uploadpack.allowRefInWant false && rm -rf local && cp -r "$LOCAL_PRISTINE" local && - inconsistency master 1234567890123456789012345678901234567890 && + inconsistency master $(test_oid numeric) && test_must_fail git -C local fetch 2>err && test_i18ngrep "fatal: remote error: upload-pack: not our ref" err ' @@ -342,7 +340,7 @@ test_expect_success 'server is initially ahead - ref in want' ' git -C "$REPO" config uploadpack.allowRefInWant true && rm -rf local && cp -r "$LOCAL_PRISTINE" local && - inconsistency master 1234567890123456789012345678901234567890 && + inconsistency master $(test_oid numeric) && git -C local fetch && git -C "$REPO" rev-parse --verify master >expected && @@ -378,7 +376,7 @@ test_expect_success 'server loses a ref - ref in want' ' git -C "$REPO" config uploadpack.allowRefInWant true && rm -rf local && cp -r "$LOCAL_PRISTINE" local && - echo "s/master/raster/" >"$HTTPD_ROOT_PATH/one-time-sed" && + echo "s/master/raster/" >"$HTTPD_ROOT_PATH/one-time-perl" && test_must_fail git -C local fetch 2>err && test_i18ngrep "fatal: remote error: unknown ref refs/heads/raster" err diff --git a/t/t5704-protocol-violations.sh b/t/t5704-protocol-violations.sh new file mode 100755 index 0000000000..950cfb21fe --- /dev/null +++ b/t/t5704-protocol-violations.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +test_description='Test responses to violations of the network protocol. In most +of these cases it will generally be acceptable for one side to break off +communications if the other side says something unexpected. We are mostly +making sure that we do not segfault or otherwise behave badly.' +. ./test-lib.sh + +test_expect_success 'extra delim packet in v2 ls-refs args' ' + { + packetize command=ls-refs && + printf 0001 && + # protocol expects 0000 flush here + printf 0001 + } >input && + test_must_fail env GIT_PROTOCOL=version=2 \ + git upload-pack . <input 2>err && + test_i18ngrep "expected flush after ls-refs arguments" err +' + +test_expect_success 'extra delim packet in v2 fetch args' ' + { + packetize command=fetch && + printf 0001 && + # protocol expects 0000 flush here + printf 0001 + } >input && + test_must_fail env GIT_PROTOCOL=version=2 \ + git upload-pack . <input 2>err && + test_i18ngrep "expected flush after fetch arguments" err +' + +test_done diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh index 121e5c6edb..0f04b6cddb 100755 --- a/t/t5801-remote-helpers.sh +++ b/t/t5801-remote-helpers.sh @@ -11,9 +11,15 @@ test_description='Test remote-helper import and export commands' PATH="$TEST_DIRECTORY/t5801:$PATH" compare_refs() { + fail= && + if test "x$1" = 'x!' + then + fail='!' && + shift + fi && git --git-dir="$1/.git" rev-parse --verify $2 >expect && git --git-dir="$3/.git" rev-parse --verify $4 >actual && - test_cmp expect actual + eval $fail test_cmp expect actual } test_expect_success 'setup repository' ' @@ -189,7 +195,7 @@ test_expect_success GPG 'push signed tag' ' git push origin signed-tag ) && compare_refs local signed-tag^{} server signed-tag^{} && - test_must_fail compare_refs local signed-tag server signed-tag + compare_refs ! local signed-tag server signed-tag ' test_expect_success GPG 'push signed tag with signed-tags capability' ' diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh index b8cf82349b..3dc1ad8f71 100755 --- a/t/t6000-rev-list-misc.sh +++ b/t/t6000-rev-list-misc.sh @@ -104,13 +104,16 @@ test_expect_success 'rev-list can show index objects' ' # - we do not show the root tree; since we updated the index, it # does not have a valid cache tree # - cat >expect <<-\EOF && - 8e4020bb5a8d8c873b25de15933e75cc0fc275df one - d9d3a7417b9605cfd88ee6306b28dadc29e6ab08 only-in-index - 9200b628cf9dc883a85a7abc8d6e6730baee589c two - EOF echo only-in-index >only-in-index && test_when_finished "git reset --hard" && + rev1=$(git rev-parse HEAD:one) && + rev2=$(git rev-parse HEAD:two) && + revi=$(git hash-object only-in-index) && + cat >expect <<-EOF && + $rev1 one + $revi only-in-index + $rev2 two + EOF git add only-in-index && git rev-list --objects --indexed-objects >actual && test_cmp expect actual @@ -148,4 +151,16 @@ test_expect_success 'rev-list --end-of-options' ' test_cmp expect actual ' +test_expect_success 'rev-list --count' ' + count=$(git rev-list --count HEAD) && + git rev-list HEAD >actual && + test_line_count = $count actual +' + +test_expect_success 'rev-list --count --objects' ' + count=$(git rev-list --count --objects HEAD) && + git rev-list --objects HEAD >actual && + test_line_count = $count actual +' + test_done diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh index ebdc49c496..7e82e43a63 100755 --- a/t/t6006-rev-list-format.sh +++ b/t/t6006-rev-list-format.sh @@ -32,6 +32,7 @@ changed_iso88591=$(echo "$changed" | iconv -f utf-8 -t $test_encoding) truncate_count=20 test_expect_success 'setup' ' + test_oid_init && : >foo && git add foo && git config i18n.commitEncoding $test_encoding && @@ -463,9 +464,10 @@ test_expect_success '--abbrev' ' ' test_expect_success '%H is not affected by --abbrev-commit' ' + expected=$(($(test_oid hexsz) + 1)) && git log -1 --format=%H --abbrev-commit --abbrev=20 HEAD >actual && len=$(wc -c <actual) && - test $len = 41 + test $len = $expected ' test_expect_success '%h is not affected by --abbrev-commit' ' diff --git a/t/t6012-rev-list-simplify.sh b/t/t6012-rev-list-simplify.sh index a10f0df02b..b6fa43ace0 100755 --- a/t/t6012-rev-list-simplify.sh +++ b/t/t6012-rev-list-simplify.sh @@ -154,4 +154,124 @@ test_expect_success '--full-diff is not affected by --parents' ' test_cmp expected actual ' +# +# Create a new history to demonstrate the value of --show-pulls +# with respect to the subtleties of simplified history, --full-history, +# and --simplify-merges. +# +# .-A---M-----C--N---O---P +# / / \ \ \/ / / +# I B \ R-'`-Z' / +# \ / \/ / +# \ / /\ / +# `---X--' `---Y--' +# +# This example is explained in Documentation/rev-list-options.txt + +test_expect_success 'rebuild repo' ' + rm -rf .git * && + git init && + git switch -c main && + + echo base >file && + git add file && + test_commit I && + + echo A >file && + git add file && + test_commit A && + + git switch -c branchB I && + echo B >file && + git add file && + test_commit B && + + git switch main && + test_must_fail git merge -m "M" B && + echo A >file && + echo B >>file && + git add file && + git merge --continue && + note M && + + echo C >other && + git add other && + test_commit C && + + git switch -c branchX I && + echo X >file && + git add file && + test_commit X && + + git switch -c branchR M && + git merge -m R -Xtheirs X && + note R && + + git switch main && + git merge -m N R && + note N && + + git switch -c branchY M && + echo Y >y && + git add y && + test_commit Y && + + git switch -c branchZ C && + echo Z >z && + git add z && + test_commit Z && + + git switch main && + git merge -m O Z && + note O && + + git merge -m P Y && + note P +' + +check_result 'X I' -- file +check_result 'N R X I' --show-pulls -- file + +check_result 'P O N R X M B A I' --full-history --topo-order -- file +check_result 'N R X M B A I' --simplify-merges --topo-order --show-pulls -- file +check_result 'R X M B A I' --simplify-merges --topo-order -- file +check_result 'N M A I' --first-parent -- file +check_result 'N M A I' --first-parent --show-pulls -- file + +# --ancestry-path implies --full-history +check_result 'P O N R M' --topo-order \ + --ancestry-path A..HEAD -- file +check_result 'P O N R M' --topo-order \ + --show-pulls \ + --ancestry-path A..HEAD -- file +check_result 'P O N R M' --topo-order \ + --full-history \ + --ancestry-path A..HEAD -- file +check_result 'R M' --topo-order \ + --simplify-merges \ + --ancestry-path A..HEAD -- file +check_result 'N R M' --topo-order \ + --simplify-merges --show-pulls \ + --ancestry-path A..HEAD -- file + +test_expect_success 'log --graph --simplify-merges --show-pulls' ' + cat >expect <<-\EOF && + * N + * R + |\ + | * X + * | M + |\ \ + | * | B + | |/ + * / A + |/ + * I + EOF + git log --graph --pretty="%s" \ + --simplify-merges --show-pulls \ + -- file >actual && + test_cmp expect actual +' + test_done diff --git a/t/t6020-merge-df.sh b/t/t6020-merge-df.sh index 46b506b3b7..400a4cd139 100755 --- a/t/t6020-merge-df.sh +++ b/t/t6020-merge-df.sh @@ -83,9 +83,9 @@ test_expect_success 'modify/delete + directory/file conflict' ' test 4 -eq $(git ls-files -u | wc -l) && test 1 -eq $(git ls-files -o | wc -l) && - test -f letters/file && - test -f letters.txt && - test -f letters~modify + test_path_is_file letters/file && + test_path_is_file letters.txt && + test_path_is_file letters~modify ' test_expect_success 'modify/delete + directory/file conflict; other way' ' @@ -99,9 +99,52 @@ test_expect_success 'modify/delete + directory/file conflict; other way' ' test 4 -eq $(git ls-files -u | wc -l) && test 1 -eq $(git ls-files -o | wc -l) && - test -f letters/file && - test -f letters.txt && - test -f letters~HEAD + test_path_is_file letters/file && + test_path_is_file letters.txt && + test_path_is_file letters~HEAD +' + +test_expect_success 'Simple merge in repo with interesting pathnames' ' + # Simple lexicographic ordering of files and directories would be: + # foo + # foo/bar + # foo/bar-2 + # foo/bar/baz + # foo/bar-2/baz + # The fact that foo/bar-2 appears between foo/bar and foo/bar/baz + # can trip up some codepaths, and is the point of this test. + test_create_repo name-ordering && + ( + cd name-ordering && + + mkdir -p foo/bar && + mkdir -p foo/bar-2 && + >foo/bar/baz && + >foo/bar-2/baz && + git add . && + git commit -m initial && + + git branch main && + git branch other && + + git checkout other && + echo other >foo/bar-2/baz && + git add -u && + git commit -m other && + + git checkout main && + echo main >foo/bar/baz && + git add -u && + git commit -m main && + + git merge other && + git ls-files -s >out && + test_line_count = 2 out && + git rev-parse :0:foo/bar/baz :0:foo/bar-2/baz >actual && + git rev-parse HEAD~1:foo/bar/baz other:foo/bar-2/baz >expect && + test_cmp expect actual + ) + ' test_done diff --git a/t/t6021-merge-criss-cross.sh b/t/t6021-merge-criss-cross.sh index d254e020b6..9d5e992878 100755 --- a/t/t6021-merge-criss-cross.sh +++ b/t/t6021-merge-criss-cross.sh @@ -10,87 +10,58 @@ test_description='Test criss-cross merge' . ./test-lib.sh -test_expect_success 'prepare repository' \ -'echo "1 -2 -3 -4 -5 -6 -7 -8 -9" > file && -git add file && -git commit -m "Initial commit" file && -git branch A && -git branch B && -git checkout A && -echo "1 -2 -3 -4 -5 -6 -7 -8 changed in B8, branch A -9" > file && -git commit -m "B8" file && -git checkout B && -echo "1 -2 -3 changed in C3, branch B -4 -5 -6 -7 -8 -9 -" > file && -git commit -m "C3" file && -git branch C3 && -git merge -m "pre E3 merge" A && -echo "1 -2 -3 changed in E3, branch B. New file size -4 -5 -6 -7 -8 changed in B8, branch A -9 -" > file && -git commit -m "E3" file && -git checkout A && -git merge -m "pre D8 merge" C3 && -echo "1 -2 -3 changed in C3, branch B -4 -5 -6 -7 -8 changed in D8, branch A. New file size 2 -9" > file && -git commit -m D8 file' - -test_expect_success 'Criss-cross merge' 'git merge -m "final merge" B' - -cat > file-expect <<EOF -1 -2 -3 changed in E3, branch B. New file size -4 -5 -6 -7 -8 changed in D8, branch A. New file size 2 -9 -EOF - -test_expect_success 'Criss-cross merge result' 'cmp file file-expect' - -test_expect_success 'Criss-cross merge fails (-s resolve)' \ -'git reset --hard A^ && -test_must_fail git merge -s resolve -m "final merge" B' +test_expect_success 'prepare repository' ' + test_write_lines 1 2 3 4 5 6 7 8 9 >file && + git add file && + git commit -m "Initial commit" file && + + git branch A && + git branch B && + git checkout A && + + test_write_lines 1 2 3 4 5 6 7 "8 changed in B8, branch A" 9 >file && + git commit -m "B8" file && + git checkout B && + + test_write_lines 1 2 "3 changed in C3, branch B" 4 5 6 7 8 9 >file && + git commit -m "C3" file && + git branch C3 && + + git merge -m "pre E3 merge" A && + + test_write_lines 1 2 "3 changed in E3, branch B. New file size" 4 5 6 7 "8 changed in B8, branch A" 9 >file && + git commit -m "E3" file && + + git checkout A && + git merge -m "pre D8 merge" C3 && + test_write_lines 1 2 "3 changed in C3, branch B" 4 5 6 7 "8 changed in D8, branch A. New file size 2" 9 >file && + + git commit -m D8 file +' + +test_expect_success 'Criss-cross merge' ' + git merge -m "final merge" B +' + +test_expect_success 'Criss-cross merge result' ' + cat <<-\EOF >file-expect && + 1 + 2 + 3 changed in E3, branch B. New file size + 4 + 5 + 6 + 7 + 8 changed in D8, branch A. New file size 2 + 9 + EOF + + test_cmp file-expect file +' + +test_expect_success 'Criss-cross merge fails (-s resolve)' ' + git reset --hard A^ && + test_must_fail git merge -s resolve -m "final merge" B +' test_done diff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh index 53cc9b2ffb..bbbba3dcbf 100755 --- a/t/t6022-merge-rename.sh +++ b/t/t6022-merge-rename.sh @@ -8,94 +8,94 @@ modify () { mv "$2.x" "$2" } -test_expect_success setup \ -' -cat >A <<\EOF && -a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -b bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb -c cccccccccccccccccccccccccccccccccccccccccccccccc -d dddddddddddddddddddddddddddddddddddddddddddddddd -e eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee -f ffffffffffffffffffffffffffffffffffffffffffffffff -g gggggggggggggggggggggggggggggggggggggggggggggggg -h hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh -i iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii -j jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj -k kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk -l llllllllllllllllllllllllllllllllllllllllllllllll -m mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm -n nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn -o oooooooooooooooooooooooooooooooooooooooooooooooo -EOF - -cat >M <<\EOF && -A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -B BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB -C CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC -D DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD -E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE -F FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -G GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG -H HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH -I IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII -J JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ -K KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK -L LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL -M MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM -N NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN -O OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO -EOF - -git add A M && -git commit -m "initial has A and M" && -git branch white && -git branch red && -git branch blue && -git branch yellow && -git branch change && -git branch change+rename && - -sed -e "/^g /s/.*/g : master changes a line/" <A >A+ && -mv A+ A && -git commit -a -m "master updates A" && - -git checkout yellow && -rm -f M && -git commit -a -m "yellow removes M" && - -git checkout white && -sed -e "/^g /s/.*/g : white changes a line/" <A >B && -sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N && -rm -f A M && -git update-index --add --remove A B M N && -git commit -m "white renames A->B, M->N" && - -git checkout red && -sed -e "/^g /s/.*/g : red changes a line/" <A >B && -sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N && -rm -f A M && -git update-index --add --remove A B M N && -git commit -m "red renames A->B, M->N" && - -git checkout blue && -sed -e "/^g /s/.*/g : blue changes a line/" <A >C && -sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N && -rm -f A M && -git update-index --add --remove A C M N && -git commit -m "blue renames A->C, M->N" && - -git checkout change && -sed -e "/^g /s/.*/g : changed line/" <A >A+ && -mv A+ A && -git commit -q -a -m "changed" && - -git checkout change+rename && -sed -e "/^g /s/.*/g : changed line/" <A >B && -rm A && -git update-index --add B && -git commit -q -a -m "changed and renamed" && - -git checkout master' +test_expect_success 'setup' ' + cat >A <<-\EOF && + a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + b bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + c cccccccccccccccccccccccccccccccccccccccccccccccc + d dddddddddddddddddddddddddddddddddddddddddddddddd + e eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + f ffffffffffffffffffffffffffffffffffffffffffffffff + g gggggggggggggggggggggggggggggggggggggggggggggggg + h hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh + i iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii + j jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj + k kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk + l llllllllllllllllllllllllllllllllllllllllllllllll + m mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm + n nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn + o oooooooooooooooooooooooooooooooooooooooooooooooo + EOF + + cat >M <<-\EOF && + A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + B BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + C CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC + D DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD + E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE + F FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + G GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG + H HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH + I IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + J JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ + K KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK + L LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL + M MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM + N NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN + O OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO + EOF + + git add A M && + git commit -m "initial has A and M" && + git branch white && + git branch red && + git branch blue && + git branch yellow && + git branch change && + git branch change+rename && + + sed -e "/^g /s/.*/g : master changes a line/" <A >A+ && + mv A+ A && + git commit -a -m "master updates A" && + + git checkout yellow && + rm -f M && + git commit -a -m "yellow removes M" && + + git checkout white && + sed -e "/^g /s/.*/g : white changes a line/" <A >B && + sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N && + rm -f A M && + git update-index --add --remove A B M N && + git commit -m "white renames A->B, M->N" && + + git checkout red && + sed -e "/^g /s/.*/g : red changes a line/" <A >B && + sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N && + rm -f A M && + git update-index --add --remove A B M N && + git commit -m "red renames A->B, M->N" && + + git checkout blue && + sed -e "/^g /s/.*/g : blue changes a line/" <A >C && + sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N && + rm -f A M && + git update-index --add --remove A C M N && + git commit -m "blue renames A->C, M->N" && + + git checkout change && + sed -e "/^g /s/.*/g : changed line/" <A >A+ && + mv A+ A && + git commit -q -a -m "changed" && + + git checkout change+rename && + sed -e "/^g /s/.*/g : changed line/" <A >B && + rm A && + git update-index --add B && + git commit -q -a -m "changed and renamed" && + + git checkout master +' test_expect_success 'pull renaming branch into unrenaming one' \ ' @@ -242,12 +242,24 @@ test_expect_success 'merge of identical changes in a renamed file' ' rm -f A M N && git reset --hard && git checkout change+rename && + + test-tool chmtime --get -3600 B >old-mtime && GIT_MERGE_VERBOSITY=3 git merge change >out && - test_i18ngrep "^Skipped B" out && + + test-tool chmtime --get B >new-mtime && + test_cmp old-mtime new-mtime && + git reset --hard HEAD^ && git checkout change && + + # A will be renamed to B; we check mtimes and file presence + test_path_is_missing B && + test-tool chmtime --get -3600 A >old-mtime && GIT_MERGE_VERBOSITY=3 git merge change+rename >out && - test_i18ngrep ! "^Skipped B" out + + test_path_is_missing A && + test-tool chmtime --get B >new-mtime && + test $(cat old-mtime) -lt $(cat new-mtime) ' test_expect_success 'setup for rename + d/f conflicts' ' @@ -288,14 +300,15 @@ test_expect_success 'setup for rename + d/f conflicts' ' git commit -m "Conflicting change" ' -printf "1\n2\n3\n4\n5555\n6\n7\n8\n9\n10\n11\n" >expected - test_expect_success 'Rename+D/F conflict; renamed file merges + dir not in way' ' git reset --hard && git checkout -q renamed-file-has-no-conflicts^0 && + git merge --strategy=recursive dir-not-in-way && + git diff --quiet && - test -f dir && + test_path_is_file dir && + test_write_lines 1 2 3 4 5555 6 7 8 9 10 11 >expected && test_cmp expected dir ' @@ -315,8 +328,8 @@ test_expect_success 'Rename+D/F conflict; renamed file merges but dir in way' ' test_must_fail git diff --quiet && test_must_fail git diff --cached --quiet && - test -f dir/file-in-the-way && - test -f dir~HEAD && + test_path_is_file dir/file-in-the-way && + test_path_is_file dir~HEAD && test_cmp expected dir~HEAD ' @@ -337,29 +350,11 @@ test_expect_success 'Same as previous, but merged other way' ' test_must_fail git diff --quiet && test_must_fail git diff --cached --quiet && - test -f dir/file-in-the-way && - test -f dir~renamed-file-has-no-conflicts && + test_path_is_file dir/file-in-the-way && + test_path_is_file dir~renamed-file-has-no-conflicts && test_cmp expected dir~renamed-file-has-no-conflicts ' -cat >expected <<\EOF && -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -<<<<<<< HEAD:dir -12 -======= -11 ->>>>>>> dir-not-in-way:sub/file -EOF - test_expect_success 'Rename+D/F conflict; renamed file cannot merge, dir not in way' ' git reset --hard && rm -rf dir~* && @@ -372,7 +367,24 @@ test_expect_success 'Rename+D/F conflict; renamed file cannot merge, dir not in test_must_fail git diff --quiet && test_must_fail git diff --cached --quiet && - test -f dir && + test_path_is_file dir && + cat >expected <<-\EOF && + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + <<<<<<< HEAD:dir + 12 + ======= + 11 + >>>>>>> dir-not-in-way:sub/file + EOF test_cmp expected dir ' @@ -391,29 +403,11 @@ test_expect_success 'Rename+D/F conflict; renamed file cannot merge and dir in t test_must_fail git diff --quiet && test_must_fail git diff --cached --quiet && - test -f dir/file-in-the-way && - test -f dir~HEAD && + test_path_is_file dir/file-in-the-way && + test_path_is_file dir~HEAD && test_cmp expected dir~HEAD ' -cat >expected <<\EOF && -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -<<<<<<< HEAD:sub/file -11 -======= -12 ->>>>>>> renamed-file-has-conflicts:dir -EOF - test_expect_success 'Same as previous, but merged other way' ' git reset --hard && rm -rf dir~* && @@ -427,8 +421,25 @@ test_expect_success 'Same as previous, but merged other way' ' test_must_fail git diff --quiet && test_must_fail git diff --cached --quiet && - test -f dir/file-in-the-way && - test -f dir~renamed-file-has-conflicts && + test_path_is_file dir/file-in-the-way && + test_path_is_file dir~renamed-file-has-conflicts && + cat >expected <<-\EOF && + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + <<<<<<< HEAD:sub/file + 11 + ======= + 12 + >>>>>>> renamed-file-has-conflicts:dir + EOF test_cmp expected dir~renamed-file-has-conflicts ' @@ -464,9 +475,9 @@ test_expect_success 'both rename source and destination involved in D/F conflict test_must_fail git diff --quiet && - test -f destdir/foo && - test -f one && - test -f destdir~HEAD && + test_path_is_file destdir/foo && + test_path_is_file one && + test_path_is_file destdir~HEAD && test "stuff" = "$(cat destdir~HEAD)" ' @@ -507,9 +518,9 @@ test_expect_success 'pair rename to parent of other (D/F conflicts) w/ untracked test 4 -eq $(find . | grep -v .git | wc -l) && - test -d one && - test -f one~rename-two && - test -f two && + test_path_is_dir one && + test_path_is_file one~rename-two && + test_path_is_file two && test "other" = $(cat one~rename-two) && test "stuff" = $(cat two) ' @@ -527,8 +538,8 @@ test_expect_success 'pair rename to parent of other (D/F conflicts) w/ clean sta test 3 -eq $(find . | grep -v .git | wc -l) && - test -f one && - test -f two && + test_path_is_file one && + test_path_is_file two && test "other" = $(cat one) && test "stuff" = $(cat two) ' @@ -568,11 +579,11 @@ test_expect_success 'check handling of differently renamed file with D/F conflic test 1 -eq "$(git ls-files -u original | wc -l)" && test 2 -eq "$(git ls-files -o | wc -l)" && - test -f one/file && - test -f two/file && - test -f one~HEAD && - test -f two~second-rename && - ! test -f original + test_path_is_file one/file && + test_path_is_file two/file && + test_path_is_file one~HEAD && + test_path_is_file two~second-rename && + test_path_is_missing original ' test_expect_success 'setup rename one file to two; directories moving out of the way' ' @@ -607,9 +618,9 @@ test_expect_success 'check handling of differently renamed file with D/F conflic test 1 -eq "$(git ls-files -u original | wc -l)" && test 0 -eq "$(git ls-files -o | wc -l)" && - test -f one && - test -f two && - ! test -f original + test_path_is_file one && + test_path_is_file two && + test_path_is_missing original ' test_expect_success 'setup avoid unnecessary update, normal rename' ' @@ -635,7 +646,7 @@ test_expect_success 'setup avoid unnecessary update, normal rename' ' test_expect_success 'avoid unnecessary update, normal rename' ' git checkout -q avoid-unnecessary-update-1^0 && - test-tool chmtime --get =1000000000 rename >expect && + test-tool chmtime --get -3600 rename >expect && git merge merge-branch-1 && test-tool chmtime --get rename >actual && test_cmp expect actual # "rename" should have stayed intact @@ -667,7 +678,7 @@ test_expect_success 'setup to test avoiding unnecessary update, with D/F conflic test_expect_success 'avoid unnecessary update, with D/F conflict' ' git checkout -q avoid-unnecessary-update-2^0 && - test-tool chmtime --get =1000000000 df >expect && + test-tool chmtime --get -3600 df >expect && git merge merge-branch-2 && test-tool chmtime --get df >actual && test_cmp expect actual # "df" should have stayed intact @@ -698,7 +709,7 @@ test_expect_success 'setup avoid unnecessary update, dir->(file,nothing)' ' test_expect_success 'avoid unnecessary update, dir->(file,nothing)' ' git checkout -q master^0 && - test-tool chmtime --get =1000000000 df >expect && + test-tool chmtime --get -3600 df >expect && git merge side && test-tool chmtime --get df >actual && test_cmp expect actual # "df" should have stayed intact @@ -727,7 +738,7 @@ test_expect_success 'setup avoid unnecessary update, modify/delete' ' test_expect_success 'avoid unnecessary update, modify/delete' ' git checkout -q master^0 && - test-tool chmtime --get =1000000000 file >expect && + test-tool chmtime --get -3600 file >expect && test_must_fail git merge side && test-tool chmtime --get file >actual && test_cmp expect actual # "file" should have stayed intact @@ -755,7 +766,7 @@ test_expect_success 'setup avoid unnecessary update, rename/add-dest' ' test_expect_success 'avoid unnecessary update, rename/add-dest' ' git checkout -q master^0 && - test-tool chmtime --get =1000000000 newfile >expect && + test-tool chmtime --get -3600 newfile >expect && git merge side && test-tool chmtime --get newfile >actual && test_cmp expect actual # "file" should have stayed intact @@ -810,48 +821,48 @@ test_expect_success 'setup for use of extended merge markers' ' git commit -mC ' -cat >expected <<\EOF && -1 -2 -3 -4 -5 -6 -7 -8 -<<<<<<< HEAD:renamed_file -9 -======= -8.5 ->>>>>>> master^0:original_file -EOF - test_expect_success 'merge master into rename has correct extended markers' ' git checkout rename^0 && test_must_fail git merge -s recursive master^0 && + + cat >expected <<-\EOF && + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + <<<<<<< HEAD:renamed_file + 9 + ======= + 8.5 + >>>>>>> master^0:original_file + EOF test_cmp expected renamed_file ' -cat >expected <<\EOF && -1 -2 -3 -4 -5 -6 -7 -8 -<<<<<<< HEAD:original_file -8.5 -======= -9 ->>>>>>> rename^0:renamed_file -EOF - test_expect_success 'merge rename into master has correct extended markers' ' git reset --hard && git checkout master^0 && test_must_fail git merge -s recursive rename^0 && + + cat >expected <<-\EOF && + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + <<<<<<< HEAD:original_file + 8.5 + ======= + 9 + >>>>>>> rename^0:renamed_file + EOF test_cmp expected renamed_file ' diff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh index 51ee887a77..2f421d967a 100755 --- a/t/t6023-merge-file.sh +++ b/t/t6023-merge-file.sh @@ -3,56 +3,59 @@ test_description='RCS merge replacement: merge-file' . ./test-lib.sh -cat > orig.txt << EOF -Dominus regit me, -et nihil mihi deerit. -In loco pascuae ibi me collocavit, -super aquam refectionis educavit me; -animam meam convertit, -deduxit me super semitas jusitiae, -propter nomen suum. -EOF - -cat > new1.txt << EOF -Dominus regit me, -et nihil mihi deerit. -In loco pascuae ibi me collocavit, -super aquam refectionis educavit me; -animam meam convertit, -deduxit me super semitas jusitiae, -propter nomen suum. -Nam et si ambulavero in medio umbrae mortis, -non timebo mala, quoniam tu mecum es: -virga tua et baculus tuus ipsa me consolata sunt. -EOF - -cat > new2.txt << EOF -Dominus regit me, et nihil mihi deerit. -In loco pascuae ibi me collocavit, -super aquam refectionis educavit me; -animam meam convertit, -deduxit me super semitas jusitiae, -propter nomen suum. -EOF - -cat > new3.txt << EOF -DOMINUS regit me, -et nihil mihi deerit. -In loco pascuae ibi me collocavit, -super aquam refectionis educavit me; -animam meam convertit, -deduxit me super semitas jusitiae, -propter nomen suum. -EOF - -cat > new4.txt << EOF -Dominus regit me, et nihil mihi deerit. -In loco pascuae ibi me collocavit, -super aquam refectionis educavit me; -animam meam convertit, -deduxit me super semitas jusitiae, -EOF -printf "propter nomen suum." >> new4.txt +test_expect_success 'setup' ' + cat >orig.txt <<-\EOF && + Dominus regit me, + et nihil mihi deerit. + In loco pascuae ibi me collocavit, + super aquam refectionis educavit me; + animam meam convertit, + deduxit me super semitas jusitiae, + propter nomen suum. + EOF + + cat >new1.txt <<-\EOF && + Dominus regit me, + et nihil mihi deerit. + In loco pascuae ibi me collocavit, + super aquam refectionis educavit me; + animam meam convertit, + deduxit me super semitas jusitiae, + propter nomen suum. + Nam et si ambulavero in medio umbrae mortis, + non timebo mala, quoniam tu mecum es: + virga tua et baculus tuus ipsa me consolata sunt. + EOF + + cat >new2.txt <<-\EOF && + Dominus regit me, et nihil mihi deerit. + In loco pascuae ibi me collocavit, + super aquam refectionis educavit me; + animam meam convertit, + deduxit me super semitas jusitiae, + propter nomen suum. + EOF + + cat >new3.txt <<-\EOF && + DOMINUS regit me, + et nihil mihi deerit. + In loco pascuae ibi me collocavit, + super aquam refectionis educavit me; + animam meam convertit, + deduxit me super semitas jusitiae, + propter nomen suum. + EOF + + cat >new4.txt <<-\EOF && + Dominus regit me, et nihil mihi deerit. + In loco pascuae ibi me collocavit, + super aquam refectionis educavit me; + animam meam convertit, + deduxit me super semitas jusitiae, + EOF + + printf "propter nomen suum." >>new4.txt +' test_expect_success 'merge with no changes' ' cp orig.txt test.txt && @@ -60,9 +63,10 @@ test_expect_success 'merge with no changes' ' test_cmp test.txt orig.txt ' -cp new1.txt test.txt -test_expect_success "merge without conflict" \ - "git merge-file test.txt orig.txt new2.txt" +test_expect_success "merge without conflict" ' + cp new1.txt test.txt && + git merge-file test.txt orig.txt new2.txt +' test_expect_success 'works in subdirectory' ' mkdir dir && @@ -73,151 +77,176 @@ test_expect_success 'works in subdirectory' ' test_path_is_missing a.txt ' -cp new1.txt test.txt -test_expect_success "merge without conflict (--quiet)" \ - "git merge-file --quiet test.txt orig.txt new2.txt" - -cp new1.txt test2.txt -test_expect_failure "merge without conflict (missing LF at EOF)" \ - "git merge-file test2.txt orig.txt new4.txt" - -test_expect_failure "merge result added missing LF" \ - "test_cmp test.txt test2.txt" - -cp new4.txt test3.txt -test_expect_success "merge without conflict (missing LF at EOF, away from change in the other file)" \ - "git merge-file --quiet test3.txt new2.txt new3.txt" - -cat > expect.txt << EOF -DOMINUS regit me, -et nihil mihi deerit. -In loco pascuae ibi me collocavit, -super aquam refectionis educavit me; -animam meam convertit, -deduxit me super semitas jusitiae, -EOF -printf "propter nomen suum." >> expect.txt - -test_expect_success "merge does not add LF away of change" \ - "test_cmp expect.txt test3.txt" - -cp test.txt backup.txt -test_expect_success "merge with conflicts" \ - "test_must_fail git merge-file test.txt orig.txt new3.txt" - -cat > expect.txt << EOF -<<<<<<< test.txt -Dominus regit me, et nihil mihi deerit. -======= -DOMINUS regit me, -et nihil mihi deerit. ->>>>>>> new3.txt -In loco pascuae ibi me collocavit, -super aquam refectionis educavit me; -animam meam convertit, -deduxit me super semitas jusitiae, -propter nomen suum. -Nam et si ambulavero in medio umbrae mortis, -non timebo mala, quoniam tu mecum es: -virga tua et baculus tuus ipsa me consolata sunt. -EOF - -test_expect_success "expected conflict markers" "test_cmp expect.txt test.txt" - -cp backup.txt test.txt - -cat > expect.txt << EOF -Dominus regit me, et nihil mihi deerit. -In loco pascuae ibi me collocavit, -super aquam refectionis educavit me; -animam meam convertit, -deduxit me super semitas jusitiae, -propter nomen suum. -Nam et si ambulavero in medio umbrae mortis, -non timebo mala, quoniam tu mecum es: -virga tua et baculus tuus ipsa me consolata sunt. -EOF -test_expect_success "merge conflicting with --ours" \ - "git merge-file --ours test.txt orig.txt new3.txt && test_cmp expect.txt test.txt" -cp backup.txt test.txt - -cat > expect.txt << EOF -DOMINUS regit me, -et nihil mihi deerit. -In loco pascuae ibi me collocavit, -super aquam refectionis educavit me; -animam meam convertit, -deduxit me super semitas jusitiae, -propter nomen suum. -Nam et si ambulavero in medio umbrae mortis, -non timebo mala, quoniam tu mecum es: -virga tua et baculus tuus ipsa me consolata sunt. -EOF -test_expect_success "merge conflicting with --theirs" \ - "git merge-file --theirs test.txt orig.txt new3.txt && test_cmp expect.txt test.txt" -cp backup.txt test.txt - -cat > expect.txt << EOF -Dominus regit me, et nihil mihi deerit. -DOMINUS regit me, -et nihil mihi deerit. -In loco pascuae ibi me collocavit, -super aquam refectionis educavit me; -animam meam convertit, -deduxit me super semitas jusitiae, -propter nomen suum. -Nam et si ambulavero in medio umbrae mortis, -non timebo mala, quoniam tu mecum es: -virga tua et baculus tuus ipsa me consolata sunt. -EOF -test_expect_success "merge conflicting with --union" \ - "git merge-file --union test.txt orig.txt new3.txt && test_cmp expect.txt test.txt" -cp backup.txt test.txt - -test_expect_success "merge with conflicts, using -L" \ - "test_must_fail git merge-file -L 1 -L 2 test.txt orig.txt new3.txt" - -cat > expect.txt << EOF -<<<<<<< 1 -Dominus regit me, et nihil mihi deerit. -======= -DOMINUS regit me, -et nihil mihi deerit. ->>>>>>> new3.txt -In loco pascuae ibi me collocavit, -super aquam refectionis educavit me; -animam meam convertit, -deduxit me super semitas jusitiae, -propter nomen suum. -Nam et si ambulavero in medio umbrae mortis, -non timebo mala, quoniam tu mecum es: -virga tua et baculus tuus ipsa me consolata sunt. -EOF - -test_expect_success "expected conflict markers, with -L" \ - "test_cmp expect.txt test.txt" - -sed "s/ tu / TU /" < new1.txt > new5.txt -test_expect_success "conflict in removed tail" \ - "test_must_fail git merge-file -p orig.txt new1.txt new5.txt > out" - -cat > expect << EOF -Dominus regit me, -et nihil mihi deerit. -In loco pascuae ibi me collocavit, -super aquam refectionis educavit me; -animam meam convertit, -deduxit me super semitas jusitiae, -propter nomen suum. -<<<<<<< orig.txt -======= -Nam et si ambulavero in medio umbrae mortis, -non timebo mala, quoniam TU mecum es: -virga tua et baculus tuus ipsa me consolata sunt. ->>>>>>> new5.txt -EOF - -test_expect_success "expected conflict markers" "test_cmp expect out" +test_expect_success "merge without conflict (--quiet)" ' + cp new1.txt test.txt && + git merge-file --quiet test.txt orig.txt new2.txt +' + +test_expect_failure "merge without conflict (missing LF at EOF)" ' + cp new1.txt test2.txt && + git merge-file test2.txt orig.txt new4.txt +' + +test_expect_failure "merge result added missing LF" ' + test_cmp test.txt test2.txt +' + +test_expect_success "merge without conflict (missing LF at EOF, away from change in the other file)" ' + cp new4.txt test3.txt && + git merge-file --quiet test3.txt new2.txt new3.txt +' + +test_expect_success "merge does not add LF away of change" ' + cat >expect.txt <<-\EOF && + DOMINUS regit me, + et nihil mihi deerit. + In loco pascuae ibi me collocavit, + super aquam refectionis educavit me; + animam meam convertit, + deduxit me super semitas jusitiae, + EOF + printf "propter nomen suum." >>expect.txt && + + test_cmp expect.txt test3.txt +' + +test_expect_success "merge with conflicts" ' + cp test.txt backup.txt && + test_must_fail git merge-file test.txt orig.txt new3.txt +' + +test_expect_success "expected conflict markers" ' + cat >expect.txt <<-\EOF && + <<<<<<< test.txt + Dominus regit me, et nihil mihi deerit. + ======= + DOMINUS regit me, + et nihil mihi deerit. + >>>>>>> new3.txt + In loco pascuae ibi me collocavit, + super aquam refectionis educavit me; + animam meam convertit, + deduxit me super semitas jusitiae, + propter nomen suum. + Nam et si ambulavero in medio umbrae mortis, + non timebo mala, quoniam tu mecum es: + virga tua et baculus tuus ipsa me consolata sunt. + EOF + + test_cmp expect.txt test.txt +' + +test_expect_success "merge conflicting with --ours" ' + cp backup.txt test.txt && + + cat >expect.txt <<-\EOF && + Dominus regit me, et nihil mihi deerit. + In loco pascuae ibi me collocavit, + super aquam refectionis educavit me; + animam meam convertit, + deduxit me super semitas jusitiae, + propter nomen suum. + Nam et si ambulavero in medio umbrae mortis, + non timebo mala, quoniam tu mecum es: + virga tua et baculus tuus ipsa me consolata sunt. + EOF + + git merge-file --ours test.txt orig.txt new3.txt && + test_cmp expect.txt test.txt +' + +test_expect_success "merge conflicting with --theirs" ' + cp backup.txt test.txt && + + cat >expect.txt <<-\EOF && + DOMINUS regit me, + et nihil mihi deerit. + In loco pascuae ibi me collocavit, + super aquam refectionis educavit me; + animam meam convertit, + deduxit me super semitas jusitiae, + propter nomen suum. + Nam et si ambulavero in medio umbrae mortis, + non timebo mala, quoniam tu mecum es: + virga tua et baculus tuus ipsa me consolata sunt. + EOF + + git merge-file --theirs test.txt orig.txt new3.txt && + test_cmp expect.txt test.txt +' + +test_expect_success "merge conflicting with --union" ' + cp backup.txt test.txt && + + cat >expect.txt <<-\EOF && + Dominus regit me, et nihil mihi deerit. + DOMINUS regit me, + et nihil mihi deerit. + In loco pascuae ibi me collocavit, + super aquam refectionis educavit me; + animam meam convertit, + deduxit me super semitas jusitiae, + propter nomen suum. + Nam et si ambulavero in medio umbrae mortis, + non timebo mala, quoniam tu mecum es: + virga tua et baculus tuus ipsa me consolata sunt. + EOF + + git merge-file --union test.txt orig.txt new3.txt && + test_cmp expect.txt test.txt +' + +test_expect_success "merge with conflicts, using -L" ' + cp backup.txt test.txt && + + test_must_fail git merge-file -L 1 -L 2 test.txt orig.txt new3.txt +' + +test_expect_success "expected conflict markers, with -L" ' + cat >expect.txt <<-\EOF && + <<<<<<< 1 + Dominus regit me, et nihil mihi deerit. + ======= + DOMINUS regit me, + et nihil mihi deerit. + >>>>>>> new3.txt + In loco pascuae ibi me collocavit, + super aquam refectionis educavit me; + animam meam convertit, + deduxit me super semitas jusitiae, + propter nomen suum. + Nam et si ambulavero in medio umbrae mortis, + non timebo mala, quoniam tu mecum es: + virga tua et baculus tuus ipsa me consolata sunt. + EOF + + test_cmp expect.txt test.txt +' + +test_expect_success "conflict in removed tail" ' + sed "s/ tu / TU /" <new1.txt >new5.txt && + test_must_fail git merge-file -p orig.txt new1.txt new5.txt >out +' + +test_expect_success "expected conflict markers" ' + cat >expect <<-\EOF && + Dominus regit me, + et nihil mihi deerit. + In loco pascuae ibi me collocavit, + super aquam refectionis educavit me; + animam meam convertit, + deduxit me super semitas jusitiae, + propter nomen suum. + <<<<<<< orig.txt + ======= + Nam et si ambulavero in medio umbrae mortis, + non timebo mala, quoniam TU mecum es: + virga tua et baculus tuus ipsa me consolata sunt. + >>>>>>> new5.txt + EOF + + test_cmp expect out +' test_expect_success 'binary files cannot be merged' ' test_must_fail git merge-file -p \ @@ -225,59 +254,55 @@ test_expect_success 'binary files cannot be merged' ' grep "Cannot merge binary files" merge.err ' -sed -e "s/deerit.\$/deerit;/" -e "s/me;\$/me./" < new5.txt > new6.txt -sed -e "s/deerit.\$/deerit,/" -e "s/me;\$/me,/" < new5.txt > new7.txt - test_expect_success 'MERGE_ZEALOUS simplifies non-conflicts' ' + sed -e "s/deerit.\$/deerit;/" -e "s/me;\$/me./" <new5.txt >new6.txt && + sed -e "s/deerit.\$/deerit,/" -e "s/me;\$/me,/" <new5.txt >new7.txt && test_must_fail git merge-file -p new6.txt new5.txt new7.txt > output && - test 1 = $(grep ======= < output | wc -l) - + test 1 = $(grep ======= <output | wc -l) ' -sed -e 's/deerit./&%%%%/' -e "s/locavit,/locavit;/"< new6.txt | tr '%' '\012' > new8.txt -sed -e 's/deerit./&%%%%/' -e "s/locavit,/locavit --/" < new7.txt | tr '%' '\012' > new9.txt - test_expect_success 'ZEALOUS_ALNUM' ' + sed -e "s/deerit./&%%%%/" -e "s/locavit,/locavit;/" <new6.txt | tr % "\012" >new8.txt && + sed -e "s/deerit./&%%%%/" -e "s/locavit,/locavit --/" <new7.txt | tr % "\012" >new9.txt && test_must_fail git merge-file -p \ - new8.txt new5.txt new9.txt > merge.out && - test 1 = $(grep ======= < merge.out | wc -l) - + new8.txt new5.txt new9.txt >merge.out && + test 1 = $(grep ======= <merge.out | wc -l) ' -cat >expect <<\EOF -Dominus regit me, -<<<<<<< new8.txt -et nihil mihi deerit; +test_expect_success '"diff3 -m" style output (1)' ' + cat >expect <<-\EOF && + Dominus regit me, + <<<<<<< new8.txt + et nihil mihi deerit; -In loco pascuae ibi me collocavit; -super aquam refectionis educavit me. -||||||| new5.txt -et nihil mihi deerit. -In loco pascuae ibi me collocavit, -super aquam refectionis educavit me; -======= -et nihil mihi deerit, + In loco pascuae ibi me collocavit; + super aquam refectionis educavit me. + ||||||| new5.txt + et nihil mihi deerit. + In loco pascuae ibi me collocavit, + super aquam refectionis educavit me; + ======= + et nihil mihi deerit, -In loco pascuae ibi me collocavit -- -super aquam refectionis educavit me, ->>>>>>> new9.txt -animam meam convertit, -deduxit me super semitas jusitiae, -propter nomen suum. -Nam et si ambulavero in medio umbrae mortis, -non timebo mala, quoniam TU mecum es: -virga tua et baculus tuus ipsa me consolata sunt. -EOF + In loco pascuae ibi me collocavit -- + super aquam refectionis educavit me, + >>>>>>> new9.txt + animam meam convertit, + deduxit me super semitas jusitiae, + propter nomen suum. + Nam et si ambulavero in medio umbrae mortis, + non timebo mala, quoniam TU mecum es: + virga tua et baculus tuus ipsa me consolata sunt. + EOF -test_expect_success '"diff3 -m" style output (1)' ' test_must_fail git merge-file -p --diff3 \ new8.txt new5.txt new9.txt >actual && test_cmp expect actual @@ -290,61 +315,64 @@ test_expect_success '"diff3 -m" style output (2)' ' test_cmp expect actual ' -cat >expect <<\EOF -Dominus regit me, -<<<<<<<<<< new8.txt -et nihil mihi deerit; +test_expect_success 'marker size' ' + cat >expect <<-\EOF && + Dominus regit me, + <<<<<<<<<< new8.txt + et nihil mihi deerit; -In loco pascuae ibi me collocavit; -super aquam refectionis educavit me. -|||||||||| new5.txt -et nihil mihi deerit. -In loco pascuae ibi me collocavit, -super aquam refectionis educavit me; -========== -et nihil mihi deerit, + In loco pascuae ibi me collocavit; + super aquam refectionis educavit me. + |||||||||| new5.txt + et nihil mihi deerit. + In loco pascuae ibi me collocavit, + super aquam refectionis educavit me; + ========== + et nihil mihi deerit, -In loco pascuae ibi me collocavit -- -super aquam refectionis educavit me, ->>>>>>>>>> new9.txt -animam meam convertit, -deduxit me super semitas jusitiae, -propter nomen suum. -Nam et si ambulavero in medio umbrae mortis, -non timebo mala, quoniam TU mecum es: -virga tua et baculus tuus ipsa me consolata sunt. -EOF + In loco pascuae ibi me collocavit -- + super aquam refectionis educavit me, + >>>>>>>>>> new9.txt + animam meam convertit, + deduxit me super semitas jusitiae, + propter nomen suum. + Nam et si ambulavero in medio umbrae mortis, + non timebo mala, quoniam TU mecum es: + virga tua et baculus tuus ipsa me consolata sunt. + EOF -test_expect_success 'marker size' ' test_must_fail git merge-file -p --marker-size=10 \ new8.txt new5.txt new9.txt >actual && test_cmp expect actual ' -printf "line1\nline2\nline3" >nolf-orig.txt -printf "line1\nline2\nline3x" >nolf-diff1.txt -printf "line1\nline2\nline3y" >nolf-diff2.txt +test_expect_success 'conflict at EOF without LF resolved by --ours' ' + printf "line1\nline2\nline3" >nolf-orig.txt && + printf "line1\nline2\nline3x" >nolf-diff1.txt && + printf "line1\nline2\nline3y" >nolf-diff2.txt && -test_expect_success 'conflict at EOF without LF resolved by --ours' \ - 'git merge-file -p --ours nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt && - printf "line1\nline2\nline3x" >expect.txt && - test_cmp expect.txt output.txt' + git merge-file -p --ours nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt && + printf "line1\nline2\nline3x" >expect.txt && + test_cmp expect.txt output.txt +' -test_expect_success 'conflict at EOF without LF resolved by --theirs' \ - 'git merge-file -p --theirs nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt && - printf "line1\nline2\nline3y" >expect.txt && - test_cmp expect.txt output.txt' +test_expect_success 'conflict at EOF without LF resolved by --theirs' ' + git merge-file -p --theirs nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt && + printf "line1\nline2\nline3y" >expect.txt && + test_cmp expect.txt output.txt +' -test_expect_success 'conflict at EOF without LF resolved by --union' \ - 'git merge-file -p --union nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt && - printf "line1\nline2\nline3x\nline3y" >expect.txt && - test_cmp expect.txt output.txt' +test_expect_success 'conflict at EOF without LF resolved by --union' ' + git merge-file -p --union nolf-diff1.txt nolf-orig.txt nolf-diff2.txt >output.txt && + printf "line1\nline2\nline3x\nline3y" >expect.txt && + test_cmp expect.txt output.txt +' test_expect_success 'conflict sections match existing line endings' ' printf "1\\r\\n2\\r\\n3" >crlf-orig.txt && diff --git a/t/t6024-recursive-merge.sh b/t/t6024-recursive-merge.sh index 0c9e3c20e8..332cfc53fd 100755 --- a/t/t6024-recursive-merge.sh +++ b/t/t6024-recursive-merge.sh @@ -57,7 +57,12 @@ test_expect_success 'setup tests' ' git rev-parse C >.git/MERGE_HEAD && echo F >a1 && git update-index a1 && - GIT_AUTHOR_DATE="2006-12-12 23:00:08" git commit -m F + GIT_AUTHOR_DATE="2006-12-12 23:00:08" git commit -m F && + + test_oid_cache <<-EOF + idxstage1 sha1:ec3fe2a791706733f2d8fa7ad45d9a9672031f5e + idxstage1 sha256:b3c8488929903aaebdeb22270cb6d36e5b8724b01ae0d4da24632f158c99676f + EOF ' test_expect_success 'combined merge conflicts' ' @@ -79,10 +84,10 @@ test_expect_success 'result contains a conflict' ' test_expect_success 'virtual trees were processed' ' git ls-files --stage >out && - cat >expect <<-\EOF && - 100644 ec3fe2a791706733f2d8fa7ad45d9a9672031f5e 1 a1 - 100644 cf84443e49e1b366fac938711ddf4be2d4d1d9e9 2 a1 - 100644 fd7923529855d0b274795ae3349c5e0438333979 3 a1 + cat >expect <<-EOF && + 100644 $(test_oid idxstage1) 1 a1 + 100644 $(git rev-parse F:a1) 2 a1 + 100644 $(git rev-parse G:a1) 3 a1 EOF test_cmp expect out diff --git a/t/t6025-merge-symlinks.sh b/t/t6025-merge-symlinks.sh index 433c4de08f..6c0a90d044 100755 --- a/t/t6025-merge-symlinks.sh +++ b/t/t6025-merge-symlinks.sh @@ -10,52 +10,53 @@ if core.symlinks is false.' . ./test-lib.sh -test_expect_success \ -'setup' ' -git config core.symlinks false && -> file && -git add file && -git commit -m initial && -git branch b-symlink && -git branch b-file && -l=$(printf file | git hash-object -t blob -w --stdin) && -echo "120000 $l symlink" | git update-index --index-info && -git commit -m master && -git checkout b-symlink && -l=$(printf file-different | git hash-object -t blob -w --stdin) && -echo "120000 $l symlink" | git update-index --index-info && -git commit -m b-symlink && -git checkout b-file && -echo plain-file > symlink && -git add symlink && -git commit -m b-file' - -test_expect_success \ -'merge master into b-symlink, which has a different symbolic link' ' -git checkout b-symlink && -test_must_fail git merge master' - -test_expect_success \ -'the merge result must be a file' ' -test -f symlink' - -test_expect_success \ -'merge master into b-file, which has a file instead of a symbolic link' ' -git reset --hard && git checkout b-file && -test_must_fail git merge master' - -test_expect_success \ -'the merge result must be a file' ' -test -f symlink' - -test_expect_success \ -'merge b-file, which has a file instead of a symbolic link, into master' ' -git reset --hard && -git checkout master && -test_must_fail git merge b-file' - -test_expect_success \ -'the merge result must be a file' ' -test -f symlink' +test_expect_success 'setup' ' + git config core.symlinks false && + >file && + git add file && + git commit -m initial && + git branch b-symlink && + git branch b-file && + l=$(printf file | git hash-object -t blob -w --stdin) && + echo "120000 $l symlink" | git update-index --index-info && + git commit -m master && + git checkout b-symlink && + l=$(printf file-different | git hash-object -t blob -w --stdin) && + echo "120000 $l symlink" | git update-index --index-info && + git commit -m b-symlink && + git checkout b-file && + echo plain-file >symlink && + git add symlink && + git commit -m b-file +' + +test_expect_success 'merge master into b-symlink, which has a different symbolic link' ' + git checkout b-symlink && + test_must_fail git merge master +' + +test_expect_success 'the merge result must be a file' ' + test_path_is_file symlink +' + +test_expect_success 'merge master into b-file, which has a file instead of a symbolic link' ' + git reset --hard && + git checkout b-file && + test_must_fail git merge master +' + +test_expect_success 'the merge result must be a file' ' + test_path_is_file symlink +' + +test_expect_success 'merge b-file, which has a file instead of a symbolic link, into master' ' + git reset --hard && + git checkout master && + test_must_fail git merge b-file +' + +test_expect_success 'the merge result must be a file' ' + test_path_is_file symlink +' test_done diff --git a/t/t6026-merge-attr.sh b/t/t6026-merge-attr.sh index 8f9b48a493..5900358ce9 100755 --- a/t/t6026-merge-attr.sh +++ b/t/t6026-merge-attr.sh @@ -32,7 +32,29 @@ test_expect_success setup ' test_tick && git commit -m Side && - git tag anchor + git tag anchor && + + cat >./custom-merge <<-\EOF && + #!/bin/sh + + orig="$1" ours="$2" theirs="$3" exit="$4" path=$5 + ( + echo "orig is $orig" + echo "ours is $ours" + echo "theirs is $theirs" + echo "path is $path" + echo "=== orig ===" + cat "$orig" + echo "=== ours ===" + cat "$ours" + echo "=== theirs ===" + cat "$theirs" + ) >"$ours+" + cat "$ours+" >"$ours" + rm -f "$ours+" + exit "$exit" + EOF + chmod +x ./custom-merge ' test_expect_success merge ' @@ -82,28 +104,6 @@ test_expect_success 'retry the merge with longer context' ' grep "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" actual ' -cat >./custom-merge <<\EOF -#!/bin/sh - -orig="$1" ours="$2" theirs="$3" exit="$4" path=$5 -( - echo "orig is $orig" - echo "ours is $ours" - echo "theirs is $theirs" - echo "path is $path" - echo "=== orig ===" - cat "$orig" - echo "=== ours ===" - cat "$ours" - echo "=== theirs ===" - cat "$theirs" -) >"$ours+" -cat "$ours+" >"$ours" -rm -f "$ours+" -exit "$exit" -EOF -chmod +x ./custom-merge - test_expect_success 'custom merge backend' ' echo "* merge=union" >.gitattributes && diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh index 821a0c88cf..1313142564 100755 --- a/t/t6030-bisect-porcelain.sh +++ b/t/t6030-bisect-porcelain.sh @@ -148,7 +148,7 @@ test_expect_success 'bisect start: no ".git/BISECT_START" created if junk rev' ' test_must_fail git bisect start $HASH4 foo -- && git branch > branch.output && grep "* other" branch.output > /dev/null && - test_must_fail test -e .git/BISECT_START + test_path_is_missing .git/BISECT_START ' test_expect_success 'bisect start: existing ".git/BISECT_START" not modified if junk rev' ' @@ -166,7 +166,7 @@ test_expect_success 'bisect start: no ".git/BISECT_START" if mistaken rev' ' test_must_fail git bisect start $HASH1 $HASH4 -- && git branch > branch.output && grep "* other" branch.output > /dev/null && - test_must_fail test -e .git/BISECT_START + test_path_is_missing .git/BISECT_START ' test_expect_success 'bisect start: no ".git/BISECT_START" if checkout error' ' @@ -175,7 +175,7 @@ test_expect_success 'bisect start: no ".git/BISECT_START" if checkout error' ' git branch && git branch > branch.output && grep "* other" branch.output > /dev/null && - test_must_fail test -e .git/BISECT_START && + test_path_is_missing .git/BISECT_START && test -z "$(git for-each-ref "refs/bisect/*")" && git checkout HEAD hello ' @@ -485,7 +485,7 @@ test_expect_success 'optimized merge base checks' ' git bisect bad && git bisect good "$A_HASH" > my_bisect_log4.txt && test_i18ngrep "merge base must be tested" my_bisect_log4.txt && - test_must_fail test -f ".git/BISECT_ANCESTORS_OK" + test_path_is_missing ".git/BISECT_ANCESTORS_OK" ' # This creates another side branch called "parallel" with some files diff --git a/t/t6034-merge-rename-nocruft.sh b/t/t6034-merge-rename-nocruft.sh index 89871aa5b0..a25e730460 100755 --- a/t/t6034-merge-rename-nocruft.sh +++ b/t/t6034-merge-rename-nocruft.sh @@ -3,74 +3,73 @@ test_description='Merge-recursive merging renames' . ./test-lib.sh -test_expect_success setup \ -' -cat >A <<\EOF && -a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -b bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb -c cccccccccccccccccccccccccccccccccccccccccccccccc -d dddddddddddddddddddddddddddddddddddddddddddddddd -e eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee -f ffffffffffffffffffffffffffffffffffffffffffffffff -g gggggggggggggggggggggggggggggggggggggggggggggggg -h hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh -i iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii -j jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj -k kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk -l llllllllllllllllllllllllllllllllllllllllllllllll -m mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm -n nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn -o oooooooooooooooooooooooooooooooooooooooooooooooo -EOF +test_expect_success 'setup' ' + cat >A <<-\EOF && + a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + b bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb + c cccccccccccccccccccccccccccccccccccccccccccccccc + d dddddddddddddddddddddddddddddddddddddddddddddddd + e eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee + f ffffffffffffffffffffffffffffffffffffffffffffffff + g gggggggggggggggggggggggggggggggggggggggggggggggg + h hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh + i iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii + j jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj + k kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk + l llllllllllllllllllllllllllllllllllllllllllllllll + m mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm + n nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn + o oooooooooooooooooooooooooooooooooooooooooooooooo + EOF -cat >M <<\EOF && -A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -B BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB -C CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC -D DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD -E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE -F FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -G GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG -H HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH -I IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII -J JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ -K KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK -L LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL -M MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM -N NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN -O OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO -EOF + cat >M <<-\EOF && + A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + B BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + C CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC + D DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD + E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE + F FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + G GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG + H HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH + I IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + J JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ + K KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK + L LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL + M MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM + N NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN + O OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO + EOF -git add A M && -git commit -m "initial has A and M" && -git branch white && -git branch red && -git branch blue && + git add A M && + git commit -m "initial has A and M" && + git branch white && + git branch red && + git branch blue && -git checkout white && -sed -e "/^g /s/.*/g : white changes a line/" <A >B && -sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N && -rm -f A M && -git update-index --add --remove A B M N && -git commit -m "white renames A->B, M->N" && + git checkout white && + sed -e "/^g /s/.*/g : white changes a line/" <A >B && + sed -e "/^G /s/.*/G : colored branch changes a line/" <M >N && + rm -f A M && + git update-index --add --remove A B M N && + git commit -m "white renames A->B, M->N" && -git checkout red && -echo created by red >R && -git update-index --add R && -git commit -m "red creates R" && + git checkout red && + echo created by red >R && + git update-index --add R && + git commit -m "red creates R" && -git checkout blue && -sed -e "/^o /s/.*/g : blue changes a line/" <A >B && -rm -f A && -mv B A && -git update-index A && -git commit -m "blue modify A" && + git checkout blue && + sed -e "/^o /s/.*/g : blue changes a line/" <A >B && + rm -f A && + mv B A && + git update-index A && + git commit -m "blue modify A" && -git checkout master' + git checkout master +' # This test broke in 65ac6e9c3f47807cb603af07a6a9e1a43bc119ae -test_expect_success 'merge white into red (A->B,M->N)' \ -' +test_expect_success 'merge white into red (A->B,M->N)' ' git checkout -b red-white red && git merge white && git write-tree && @@ -82,8 +81,7 @@ test_expect_success 'merge white into red (A->B,M->N)' \ ' # This test broke in 8371234ecaaf6e14fe3f2082a855eff1bbd79ae9 -test_expect_success 'merge blue into white (A->B, mod A, A untracked)' \ -' +test_expect_success 'merge blue into white (A->B, mod A, A untracked)' ' git checkout -b white-blue white && echo dirty >A && git merge blue && diff --git a/t/t6035-merge-dir-to-symlink.sh b/t/t6035-merge-dir-to-symlink.sh index 9324ea4416..2eddcc7664 100755 --- a/t/t6035-merge-dir-to-symlink.sh +++ b/t/t6035-merge-dir-to-symlink.sh @@ -31,19 +31,19 @@ test_expect_success 'a/b-2/c/d is kept when clobbering symlink b' ' git rm --cached a/b && git commit -m "untracked symlink remains" && git checkout -f start^0 && - test -f a/b-2/c/d + test_path_is_file a/b-2/c/d ' test_expect_success 'checkout should not have deleted a/b-2/c/d' ' git checkout HEAD^0 && git reset --hard master && git checkout start^0 && - test -f a/b-2/c/d + test_path_is_file a/b-2/c/d ' test_expect_success 'setup for merge test' ' git reset --hard && - test -f a/b-2/c/d && + test_path_is_file a/b-2/c/d && echo x > a/x && git add a/x && git commit -m x && @@ -54,7 +54,7 @@ test_expect_success 'Handle D/F conflict, do not lose a/b-2/c/d in merge (resolv git reset --hard && git checkout baseline^0 && git merge -s resolve master && - test -f a/b-2/c/d + test_path_is_file a/b-2/c/d ' test_expect_success SYMLINKS 'a/b was resolved as symlink' ' @@ -65,7 +65,7 @@ test_expect_success 'Handle D/F conflict, do not lose a/b-2/c/d in merge (recurs git reset --hard && git checkout baseline^0 && git merge -s recursive master && - test -f a/b-2/c/d + test_path_is_file a/b-2/c/d ' test_expect_success SYMLINKS 'a/b was resolved as symlink' ' @@ -76,7 +76,7 @@ test_expect_success 'Handle F/D conflict, do not lose a/b-2/c/d in merge (resolv git reset --hard && git checkout master^0 && git merge -s resolve baseline^0 && - test -f a/b-2/c/d + test_path_is_file a/b-2/c/d ' test_expect_success SYMLINKS 'a/b was resolved as symlink' ' @@ -87,7 +87,7 @@ test_expect_success 'Handle F/D conflict, do not lose a/b-2/c/d in merge (recurs git reset --hard && git checkout master^0 && git merge -s recursive baseline^0 && - test -f a/b-2/c/d + test_path_is_file a/b-2/c/d ' test_expect_success SYMLINKS 'a/b was resolved as symlink' ' @@ -99,8 +99,8 @@ test_expect_failure 'do not lose untracked in merge (resolve)' ' git checkout baseline^0 && >a/b/c/e && test_must_fail git merge -s resolve master && - test -f a/b/c/e && - test -f a/b-2/c/d + test_path_is_file a/b/c/e && + test_path_is_file a/b-2/c/d ' test_expect_success 'do not lose untracked in merge (recursive)' ' @@ -108,8 +108,8 @@ test_expect_success 'do not lose untracked in merge (recursive)' ' git checkout baseline^0 && >a/b/c/e && test_must_fail git merge -s recursive master && - test -f a/b/c/e && - test -f a/b-2/c/d + test_path_is_file a/b/c/e && + test_path_is_file a/b-2/c/d ' test_expect_success 'do not lose modifications in merge (resolve)' ' @@ -140,7 +140,7 @@ test_expect_success 'merge should not have D/F conflicts (resolve)' ' git reset --hard && git checkout baseline^0 && git merge -s resolve test2 && - test -f a/b/c/d + test_path_is_file a/b/c/d ' test_expect_success SYMLINKS 'a/b-2 was resolved as symlink' ' @@ -151,7 +151,7 @@ test_expect_success 'merge should not have D/F conflicts (recursive)' ' git reset --hard && git checkout baseline^0 && git merge -s recursive test2 && - test -f a/b/c/d + test_path_is_file a/b/c/d ' test_expect_success SYMLINKS 'a/b-2 was resolved as symlink' ' @@ -162,7 +162,7 @@ test_expect_success 'merge should not have F/D conflicts (recursive)' ' git reset --hard && git checkout -b foo test2 && git merge -s recursive baseline^0 && - test -f a/b/c/d + test_path_is_file a/b/c/d ' test_expect_success SYMLINKS 'a/b-2 was resolved as symlink' ' diff --git a/t/t6036-recursive-corner-cases.sh b/t/t6036-recursive-corner-cases.sh index 7d73afdcda..b3bf462617 100755 --- a/t/t6036-recursive-corner-cases.sh +++ b/t/t6036-recursive-corner-cases.sh @@ -60,9 +60,9 @@ test_expect_success 'merge simple rename+criss-cross with no modifications' ' test_must_fail git merge -s recursive R2^0 && git ls-files -s >out && - test_line_count = 2 out && + test_line_count = 5 out && git ls-files -u >out && - test_line_count = 2 out && + test_line_count = 3 out && git ls-files -o >out && test_line_count = 1 out && @@ -133,9 +133,9 @@ test_expect_success 'merge criss-cross + rename merges with basic modification' test_must_fail git merge -s recursive R2^0 && git ls-files -s >out && - test_line_count = 2 out && + test_line_count = 5 out && git ls-files -u >out && - test_line_count = 2 out && + test_line_count = 3 out && git ls-files -o >out && test_line_count = 1 out && @@ -218,8 +218,18 @@ test_expect_success 'git detects differently handled merges conflict' ' git ls-files -o >out && test_line_count = 1 out && - git rev-parse >expect \ - C:new_a D:new_a E:new_a && + git cat-file -p C:new_a >ours && + git cat-file -p C:a >theirs && + >empty && + test_must_fail git merge-file \ + -L "Temporary merge branch 1" \ + -L "" \ + -L "Temporary merge branch 2" \ + ours empty theirs && + sed -e "s/^\([<=>]\)/\1\1\1/" ours >ours-tweaked && + git hash-object ours-tweaked >expect && + git rev-parse >>expect \ + D:new_a E:new_a && git rev-parse >actual \ :1:new_a :2:new_a :3:new_a && test_cmp expect actual && @@ -257,7 +267,8 @@ test_expect_success 'git detects differently handled merges conflict, swapped' ' ctime=$(git log --no-walk --date=raw --format=%cd C | awk "{print \$1}") && newctime=$(($btime+1)) && git fast-export --no-data --all | sed -e s/$ctime/$newctime/ | git fast-import --force --quiet && - # End of differences; rest is copy-paste of last test + # End of most differences; rest is copy-paste of last test, + # other than swapping C:a and C:new_a due to order switch git checkout D^0 && test_must_fail git merge -s recursive E^0 && @@ -269,8 +280,18 @@ test_expect_success 'git detects differently handled merges conflict, swapped' ' git ls-files -o >out && test_line_count = 1 out && - git rev-parse >expect \ - C:new_a D:new_a E:new_a && + git cat-file -p C:a >ours && + git cat-file -p C:new_a >theirs && + >empty && + test_must_fail git merge-file \ + -L "Temporary merge branch 1" \ + -L "" \ + -L "Temporary merge branch 2" \ + ours empty theirs && + sed -e "s/^\([<=>]\)/\1\1\1/" ours >ours-tweaked && + git hash-object ours-tweaked >expect && + git rev-parse >>expect \ + D:new_a E:new_a && git rev-parse >actual \ :1:new_a :2:new_a :3:new_a && test_cmp expect actual && diff --git a/t/t6046-merge-skip-unneeded-updates.sh b/t/t6046-merge-skip-unneeded-updates.sh index b7e4669832..1ddc9e6626 100755 --- a/t/t6046-merge-skip-unneeded-updates.sh +++ b/t/t6046-merge-skip-unneeded-updates.sh @@ -71,16 +71,15 @@ test_expect_success '1a-L: Modify(A)/Modify(B), change on B subset of A' ' git checkout A^0 && - test-tool chmtime =31337 b && - test-tool chmtime -v +0 b >expected-mtime && + test-tool chmtime --get -3600 b >old-mtime && GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err && - test_i18ngrep "Skipped b" out && test_must_be_empty err && - test-tool chmtime -v +0 b >actual-mtime && - test_cmp expected-mtime actual-mtime && + # Make sure b was NOT updated + test-tool chmtime --get b >new-mtime && + test_cmp old-mtime new-mtime && git ls-files -s >index_files && test_line_count = 1 index_files && @@ -102,9 +101,13 @@ test_expect_success '1a-R: Modify(A)/Modify(B), change on B subset of A' ' git checkout B^0 && + test-tool chmtime --get -3600 b >old-mtime && GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err && - test_i18ngrep "Auto-merging b" out && + # Make sure b WAS updated + test-tool chmtime --get b >new-mtime && + test $(cat old-mtime) -lt $(cat new-mtime) && + test_must_be_empty err && git ls-files -s >index_files && @@ -165,10 +168,10 @@ test_expect_success '2a-L: Modify/rename, merge into modify side' ' git checkout A^0 && + test_path_is_missing c && GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err && - test_i18ngrep ! "Skipped c" out && - test_must_be_empty err && + test_path_is_file c && git ls-files -s >index_files && test_line_count = 1 index_files && @@ -193,9 +196,13 @@ test_expect_success '2a-R: Modify/rename, merge into rename side' ' git checkout B^0 && + test-tool chmtime --get -3600 c >old-mtime && GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err && - test_i18ngrep ! "Skipped c" out && + # Make sure c WAS updated + test-tool chmtime --get c >new-mtime && + test $(cat old-mtime) -lt $(cat new-mtime) && + test_must_be_empty err && git ls-files -s >index_files && @@ -256,16 +263,14 @@ test_expect_success '2b-L: Rename+Mod(A)/Mod(B), B mods subset of A' ' git checkout A^0 && - test-tool chmtime =31337 c && - test-tool chmtime -v +0 c >expected-mtime && - + test-tool chmtime --get -3600 c >old-mtime && GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err && - test_i18ngrep "Skipped c" out && test_must_be_empty err && - test-tool chmtime -v +0 c >actual-mtime && - test_cmp expected-mtime actual-mtime && + # Make sure c WAS updated + test-tool chmtime --get c >new-mtime && + test_cmp old-mtime new-mtime && git ls-files -s >index_files && test_line_count = 1 index_files && @@ -290,9 +295,12 @@ test_expect_success '2b-R: Rename+Mod(A)/Mod(B), B mods subset of A' ' git checkout B^0 && + test_path_is_missing c && GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err && - test_i18ngrep "Auto-merging c" out && + # Make sure c now present (and thus was updated) + test_path_is_file c && + test_must_be_empty err && git ls-files -s >index_files && @@ -361,13 +369,17 @@ test_expect_success '2c: Modify b & add c VS rename b->c' ' git checkout A^0 && + test-tool chmtime --get -3600 c >old-mtime && GIT_MERGE_VERBOSITY=3 && export GIT_MERGE_VERBOSITY && test_must_fail git merge -s recursive B^0 >out 2>err && test_i18ngrep "CONFLICT (rename/add): Rename b->c" out && - test_i18ngrep ! "Skipped c" out && - test_must_be_empty err + test_must_be_empty err && + + # Make sure c WAS updated + test-tool chmtime --get c >new-mtime && + test $(cat old-mtime) -lt $(cat new-mtime) # FIXME: rename/add conflicts are horribly broken right now; # when I get back to my patch series fixing it and @@ -460,11 +472,13 @@ test_expect_success '3a-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' git checkout A^0 && + test_path_is_missing bar/bq && GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && - test_i18ngrep ! "Skipped bar/bq" out && test_must_be_empty err && + test_path_is_file bar/bq && + git ls-files -s >index_files && test_line_count = 2 index_files && @@ -488,11 +502,13 @@ test_expect_success '3a-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' git checkout B^0 && + test_path_is_missing bar/bq && GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err && - test_i18ngrep ! "Skipped bar/bq" out && test_must_be_empty err && + test_path_is_file bar/bq && + git ls-files -s >index_files && test_line_count = 2 index_files && @@ -552,11 +568,13 @@ test_expect_success '3b-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' git checkout A^0 && + test_path_is_missing bar/bq && GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && - test_i18ngrep ! "Skipped bar/bq" out && test_must_be_empty err && + test_path_is_file bar/bq && + git ls-files -s >index_files && test_line_count = 2 index_files && @@ -580,11 +598,13 @@ test_expect_success '3b-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' git checkout B^0 && + test_path_is_missing bar/bq && GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err && - test_i18ngrep ! "Skipped bar/bq" out && test_must_be_empty err && + test_path_is_file bar/bq && + git ls-files -s >index_files && test_line_count = 2 index_files && @@ -654,16 +674,15 @@ test_expect_failure '4a: Change on A, change on B subset of A, dirty mods presen git checkout A^0 && echo "File rewritten" >b && - test-tool chmtime =31337 b && - test-tool chmtime -v +0 b >expected-mtime && + test-tool chmtime --get -3600 b >old-mtime && GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err && - test_i18ngrep "Skipped b" out && test_must_be_empty err && - test-tool chmtime -v +0 b >actual-mtime && - test_cmp expected-mtime actual-mtime && + # Make sure b was NOT updated + test-tool chmtime --get b >new-mtime && + test_cmp old-mtime new-mtime && git ls-files -s >index_files && test_line_count = 1 index_files && @@ -722,16 +741,15 @@ test_expect_success '4b: Rename+Mod(A)/Mod(B), change on B subset of A, dirty mo git checkout A^0 && echo "File rewritten" >c && - test-tool chmtime =31337 c && - test-tool chmtime -v +0 c >expected-mtime && + test-tool chmtime --get -3600 c >old-mtime && GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err && - test_i18ngrep "Skipped c" out && test_must_be_empty err && - test-tool chmtime -v +0 c >actual-mtime && - test_cmp expected-mtime actual-mtime && + # Make sure c was NOT updated + test-tool chmtime --get c >new-mtime && + test_cmp old-mtime new-mtime && git ls-files -s >index_files && test_line_count = 1 index_files && diff --git a/t/t6047-diff3-conflict-markers.sh b/t/t6047-diff3-conflict-markers.sh index 860542aad0..f4655bb358 100755 --- a/t/t6047-diff3-conflict-markers.sh +++ b/t/t6047-diff3-conflict-markers.sh @@ -186,7 +186,7 @@ test_expect_success 'check multiple merge bases' ' ) ' -test_expect_success 'rebase describes fake ancestor base' ' +test_expect_success 'rebase --merge describes parent of commit being picked' ' test_create_repo rebase && ( cd rebase && @@ -194,7 +194,16 @@ test_expect_success 'rebase describes fake ancestor base' ' test_commit master file && git checkout -b side HEAD^ && test_commit side file && - test_must_fail git -c merge.conflictstyle=diff3 rebase master && + test_must_fail git -c merge.conflictstyle=diff3 rebase --merge master && + grep "||||||| parent of" file + ) +' + +test_expect_success 'rebase --apply describes fake ancestor base' ' + ( + cd rebase && + git rebase --abort && + test_must_fail git -c merge.conflictstyle=diff3 rebase --apply master && grep "||||||| constructed merge base" file ) ' diff --git a/t/t6113-rev-list-bitmap-filters.sh b/t/t6113-rev-list-bitmap-filters.sh new file mode 100755 index 0000000000..2b551e6fd0 --- /dev/null +++ b/t/t6113-rev-list-bitmap-filters.sh @@ -0,0 +1,77 @@ +#!/bin/sh + +test_description='rev-list combining bitmaps and filters' +. ./test-lib.sh + +test_expect_success 'set up bitmapped repo' ' + # one commit will have bitmaps, the other will not + test_commit one && + test_commit much-larger-blob-one && + git repack -adb && + test_commit two && + test_commit much-larger-blob-two +' + +test_expect_success 'filters fallback to non-bitmap traversal' ' + # use a path-based filter, since they are inherently incompatible with + # bitmaps (i.e., this test will never get confused by later code to + # combine the features) + filter=$(echo "!one" | git hash-object -w --stdin) && + git rev-list --objects --filter=sparse:oid=$filter HEAD >expect && + git rev-list --use-bitmap-index \ + --objects --filter=sparse:oid=$filter HEAD >actual && + test_cmp expect actual +' + +test_expect_success 'blob:none filter' ' + git rev-list --objects --filter=blob:none HEAD >expect && + git rev-list --use-bitmap-index \ + --objects --filter=blob:none HEAD >actual && + test_bitmap_traversal expect actual +' + +test_expect_success 'blob:none filter with specified blob' ' + git rev-list --objects --filter=blob:none HEAD HEAD:two.t >expect && + git rev-list --use-bitmap-index \ + --objects --filter=blob:none HEAD HEAD:two.t >actual && + test_bitmap_traversal expect actual +' + +test_expect_success 'blob:limit filter' ' + git rev-list --objects --filter=blob:limit=5 HEAD >expect && + git rev-list --use-bitmap-index \ + --objects --filter=blob:limit=5 HEAD >actual && + test_bitmap_traversal expect actual +' + +test_expect_success 'blob:limit filter with specified blob' ' + git rev-list --objects --filter=blob:limit=5 \ + HEAD HEAD:much-larger-blob-two.t >expect && + git rev-list --use-bitmap-index \ + --objects --filter=blob:limit=5 \ + HEAD HEAD:much-larger-blob-two.t >actual && + test_bitmap_traversal expect actual +' + +test_expect_success 'tree:0 filter' ' + git rev-list --objects --filter=tree:0 HEAD >expect && + git rev-list --use-bitmap-index \ + --objects --filter=tree:0 HEAD >actual && + test_bitmap_traversal expect actual +' + +test_expect_success 'tree:0 filter with specified blob, tree' ' + git rev-list --objects --filter=tree:0 HEAD HEAD:two.t >expect && + git rev-list --use-bitmap-index \ + --objects --filter=tree:0 HEAD HEAD:two.t >actual && + test_bitmap_traversal expect actual +' + +test_expect_success 'tree:1 filter' ' + git rev-list --objects --filter=tree:1 HEAD >expect && + git rev-list --use-bitmap-index \ + --objects --filter=tree:1 HEAD >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh index 09c50f3f04..f822d5d328 100755 --- a/t/t6120-describe.sh +++ b/t/t6120-describe.sh @@ -129,12 +129,30 @@ test_expect_success 'rename tag A to Q locally' ' mv .git/refs/tags/A .git/refs/tags/Q ' cat - >err.expect <<EOF -warning: tag 'A' is really 'Q' here +warning: tag 'Q' is externally known as 'A' EOF check_describe A-* HEAD test_expect_success 'warning was displayed for Q' ' test_i18ncmp err.expect err.actual ' +test_expect_success 'misnamed annotated tag forces long output' ' + description=$(git describe --no-long Q^0) && + expr "$description" : "A-0-g[0-9a-f]*$" && + git rev-parse --verify "$description" >actual && + git rev-parse --verify Q^0 >expect && + test_cmp expect actual +' + +test_expect_success 'abbrev=0 will not break misplaced tag (1)' ' + description=$(git describe --abbrev=0 Q^0) && + expr "$description" : "A-0-g[0-9a-f]*$" +' + +test_expect_success 'abbrev=0 will not break misplaced tag (2)' ' + description=$(git describe --abbrev=0 c^0) && + expr "$description" : "A-1-g[0-9a-f]*$" +' + test_expect_success 'rename tag Q back to A' ' mv .git/refs/tags/Q .git/refs/tags/A ' @@ -479,4 +497,55 @@ test_expect_success 'name-rev covers all conditions while looking at parents' ' ) ' +# B +# o +# \ +# o-----o---o----x +# A +# +test_expect_success 'describe commits with disjoint bases' ' + git init disjoint1 && + ( + cd disjoint1 && + + echo o >> file && git add file && git commit -m o && + echo A >> file && git add file && git commit -m A && + git tag A -a -m A && + echo o >> file && git add file && git commit -m o && + + git checkout --orphan branch && rm file && + echo B > file2 && git add file2 && git commit -m B && + git tag B -a -m B && + git merge --no-ff --allow-unrelated-histories master -m x && + + check_describe "A-3-*" HEAD + ) +' + +# B +# o---o---o------------. +# \ +# o---o---x +# A +# +test_expect_success 'describe commits with disjoint bases 2' ' + git init disjoint2 && + ( + cd disjoint2 && + + echo A >> file && git add file && GIT_COMMITTER_DATE="2020-01-01 18:00" git commit -m A && + git tag A -a -m A && + echo o >> file && git add file && GIT_COMMITTER_DATE="2020-01-01 18:01" git commit -m o && + + git checkout --orphan branch && + echo o >> file2 && git add file2 && GIT_COMMITTER_DATE="2020-01-01 15:00" git commit -m o && + echo o >> file2 && git add file2 && GIT_COMMITTER_DATE="2020-01-01 15:01" git commit -m o && + echo B >> file2 && git add file2 && GIT_COMMITTER_DATE="2020-01-01 15:02" git commit -m B && + git tag B -a -m B && + git merge --no-ff --allow-unrelated-histories master -m x && + + check_describe "B-3-*" HEAD + ) +' + test_done diff --git a/t/t6136-pathspec-in-bare.sh b/t/t6136-pathspec-in-bare.sh new file mode 100755 index 0000000000..b117251366 --- /dev/null +++ b/t/t6136-pathspec-in-bare.sh @@ -0,0 +1,38 @@ +#!/bin/sh + +test_description='diagnosing out-of-scope pathspec' + +. ./test-lib.sh + +test_expect_success 'setup a bare and non-bare repository' ' + test_commit file1 && + git clone --bare . bare +' + +test_expect_success 'log and ls-files in a bare repository' ' + ( + cd bare && + test_must_fail git log -- .. >out 2>err && + test_must_be_empty out && + test_i18ngrep "outside repository" err && + + test_must_fail git ls-files -- .. >out 2>err && + test_must_be_empty out && + test_i18ngrep "outside repository" err + ) +' + +test_expect_success 'log and ls-files in .git directory' ' + ( + cd .git && + test_must_fail git log -- .. >out 2>err && + test_must_be_empty out && + test_i18ngrep "outside repository" err && + + test_must_fail git ls-files -- .. >out 2>err && + test_must_be_empty out && + test_i18ngrep "outside repository" err + ) +' + +test_done diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh index 8a72b4c43a..b15582a7a2 100755 --- a/t/t6200-fmt-merge-msg.sh +++ b/t/t6200-fmt-merge-msg.sh @@ -6,6 +6,7 @@ test_description='fmt-merge-msg test' . ./test-lib.sh +. "$TEST_DIRECTORY/lib-gpg.sh" test_expect_success setup ' echo one >one && @@ -73,6 +74,10 @@ test_expect_success setup ' apos="'\''" ' +test_expect_success GPG 'set up a signed tag' ' + git tag -s -m signed-tag-msg signed-good-tag left +' + test_expect_success 'message for merging local branch' ' echo "Merge branch ${apos}left${apos}" >expected && @@ -83,6 +88,24 @@ test_expect_success 'message for merging local branch' ' test_cmp expected actual ' +test_expect_success GPG 'message for merging local tag signed by good key' ' + git checkout master && + git fetch . signed-good-tag && + git fmt-merge-msg <.git/FETCH_HEAD >actual 2>&1 && + grep "^Merge tag ${apos}signed-good-tag${apos}" actual && + grep "^# gpg: Signature made" actual && + grep "^# gpg: Good signature from" actual +' + +test_expect_success GPG 'message for merging local tag signed by unknown key' ' + git checkout master && + git fetch . signed-good-tag && + GNUPGHOME=. git fmt-merge-msg <.git/FETCH_HEAD >actual 2>&1 && + grep "^Merge tag ${apos}signed-good-tag${apos}" actual && + grep "^# gpg: Signature made" actual && + grep "^# gpg: Can${apos}t check signature: \(public key not found\|No public key\)" actual +' + test_expect_success 'message for merging external branch' ' echo "Merge branch ${apos}left${apos} of $(pwd)" >expected && diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index 9c910ce746..da59fadc5d 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -20,6 +20,10 @@ setdate_and_increment () { } test_expect_success setup ' + test_oid_cache <<-EOF && + disklen sha1:138 + disklen sha256:154 + EOF setdate_and_increment && echo "Using $datestamp" > one && git add one && @@ -50,6 +54,9 @@ test_atom() { " } +hexlen=$(test_oid hexsz) +disklen=$(test_oid disklen) + test_atom head refname refs/heads/master test_atom head refname: refs/heads/master test_atom head refname:short master @@ -82,9 +89,9 @@ test_atom head push:rstrip=-1 refs test_atom head push:strip=1 remotes/myfork/master test_atom head push:strip=-1 master test_atom head objecttype commit -test_atom head objectsize 171 -test_atom head objectsize:disk 138 -test_atom head deltabase 0000000000000000000000000000000000000000 +test_atom head objectsize $((131 + hexlen)) +test_atom head objectsize:disk $disklen +test_atom head deltabase $ZERO_OID test_atom head objectname $(git rev-parse refs/heads/master) test_atom head objectname:short $(git rev-parse --short refs/heads/master) test_atom head objectname:short=1 $(git rev-parse --short=1 refs/heads/master) @@ -125,11 +132,11 @@ test_atom tag refname:short testtag test_atom tag upstream '' test_atom tag push '' test_atom tag objecttype tag -test_atom tag objectsize 154 -test_atom tag objectsize:disk 138 -test_atom tag '*objectsize:disk' 138 -test_atom tag deltabase 0000000000000000000000000000000000000000 -test_atom tag '*deltabase' 0000000000000000000000000000000000000000 +test_atom tag objectsize $((114 + hexlen)) +test_atom tag objectsize:disk $disklen +test_atom tag '*objectsize:disk' $disklen +test_atom tag deltabase $ZERO_OID +test_atom tag '*deltabase' $ZERO_OID test_atom tag objectname $(git rev-parse refs/tags/testtag) test_atom tag objectname:short $(git rev-parse --short refs/tags/testtag) test_atom head objectname:short=1 $(git rev-parse --short=1 refs/heads/master) @@ -139,7 +146,7 @@ test_atom tag parent '' test_atom tag numparent '' test_atom tag object $(git rev-parse refs/tags/testtag^0) test_atom tag type 'commit' -test_atom tag '*objectname' 'ea122842f48be4afb2d1fc6a4b96c05885ab7463' +test_atom tag '*objectname' $(git rev-parse refs/tags/testtag^{}) test_atom tag '*objecttype' 'commit' test_atom tag author '' test_atom tag authorname '' @@ -643,17 +650,59 @@ test_atom refs/tags/signed-long contents "subject line body contents $sig" -cat >expected <<EOF -$(git rev-parse refs/tags/bogo) <committer@example.com> refs/tags/bogo -$(git rev-parse refs/tags/master) <committer@example.com> refs/tags/master -EOF +test_expect_success 'set up multiple-sort tags' ' + for when in 100000 200000 + do + for email in user1 user2 + do + for ref in ref1 ref2 + do + GIT_COMMITTER_DATE="@$when +0000" \ + GIT_COMMITTER_EMAIL="$email@example.com" \ + git tag -m "tag $ref-$when-$email" \ + multi-$ref-$when-$email || return 1 + done + done + done +' test_expect_success 'Verify sort with multiple keys' ' - git for-each-ref --format="%(objectname) %(taggeremail) %(refname)" --sort=objectname --sort=taggeremail \ - refs/tags/bogo refs/tags/master > actual && + cat >expected <<-\EOF && + 100000 <user1@example.com> refs/tags/multi-ref2-100000-user1 + 100000 <user1@example.com> refs/tags/multi-ref1-100000-user1 + 100000 <user2@example.com> refs/tags/multi-ref2-100000-user2 + 100000 <user2@example.com> refs/tags/multi-ref1-100000-user2 + 200000 <user1@example.com> refs/tags/multi-ref2-200000-user1 + 200000 <user1@example.com> refs/tags/multi-ref1-200000-user1 + 200000 <user2@example.com> refs/tags/multi-ref2-200000-user2 + 200000 <user2@example.com> refs/tags/multi-ref1-200000-user2 + EOF + git for-each-ref \ + --format="%(taggerdate:unix) %(taggeremail) %(refname)" \ + --sort=-refname \ + --sort=taggeremail \ + --sort=taggerdate \ + "refs/tags/multi-*" >actual && test_cmp expected actual ' +test_expect_success 'equivalent sorts fall back on refname' ' + cat >expected <<-\EOF && + 100000 <user1@example.com> refs/tags/multi-ref1-100000-user1 + 100000 <user2@example.com> refs/tags/multi-ref1-100000-user2 + 100000 <user1@example.com> refs/tags/multi-ref2-100000-user1 + 100000 <user2@example.com> refs/tags/multi-ref2-100000-user2 + 200000 <user1@example.com> refs/tags/multi-ref1-200000-user1 + 200000 <user2@example.com> refs/tags/multi-ref1-200000-user2 + 200000 <user1@example.com> refs/tags/multi-ref2-200000-user1 + 200000 <user2@example.com> refs/tags/multi-ref2-200000-user2 + EOF + git for-each-ref \ + --format="%(taggerdate:unix) %(taggeremail) %(refname)" \ + --sort=taggerdate \ + "refs/tags/multi-*" >actual && + test_cmp expected actual +' test_expect_success 'do not dereference NULL upon %(HEAD) on unborn branch' ' test_when_finished "git checkout master" && @@ -888,4 +937,44 @@ test_expect_success 'for-each-ref --ignore-case ignores case' ' test_cmp expect actual ' +test_expect_success 'for-each-ref --ignore-case works on multiple sort keys' ' + # name refs numerically to avoid case-insensitive filesystem conflicts + nr=0 && + for email in a A b B + do + for subject in a A b B + do + GIT_COMMITTER_EMAIL="$email@example.com" \ + git tag -m "tag $subject" icase-$(printf %02d $nr) && + nr=$((nr+1))|| + return 1 + done + done && + git for-each-ref --ignore-case \ + --format="%(taggeremail) %(subject) %(refname)" \ + --sort=refname \ + --sort=subject \ + --sort=taggeremail \ + refs/tags/icase-* >actual && + cat >expect <<-\EOF && + <a@example.com> tag a refs/tags/icase-00 + <a@example.com> tag A refs/tags/icase-01 + <A@example.com> tag a refs/tags/icase-04 + <A@example.com> tag A refs/tags/icase-05 + <a@example.com> tag b refs/tags/icase-02 + <a@example.com> tag B refs/tags/icase-03 + <A@example.com> tag b refs/tags/icase-06 + <A@example.com> tag B refs/tags/icase-07 + <b@example.com> tag a refs/tags/icase-08 + <b@example.com> tag A refs/tags/icase-09 + <B@example.com> tag a refs/tags/icase-12 + <B@example.com> tag A refs/tags/icase-13 + <b@example.com> tag b refs/tags/icase-10 + <b@example.com> tag B refs/tags/icase-11 + <B@example.com> tag b refs/tags/icase-14 + <B@example.com> tag B refs/tags/icase-15 + EOF + test_cmp expect actual +' + test_done diff --git a/t/t6600-test-reach.sh b/t/t6600-test-reach.sh index b24d850036..475564bee7 100755 --- a/t/t6600-test-reach.sh +++ b/t/t6600-test-reach.sh @@ -51,8 +51,10 @@ test_expect_success 'setup' ' done && git commit-graph write --reachable && mv .git/objects/info/commit-graph commit-graph-full && + chmod u+w commit-graph-full && git show-ref -s commit-5-5 | git commit-graph write --stdin-commits && mv .git/objects/info/commit-graph commit-graph-half && + chmod u+w commit-graph-half && git config core.commitGraph true ' diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index 6db92bd3ba..74b637deb2 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -1726,6 +1726,7 @@ test_expect_success 'recursive tagging should give advice' ' hint: already a tag. If you meant to tag the object that it points to, use: hint: | hint: git tag -f nested annotated-v4.0^{} + hint: Disable this message with "git config advice.nestedTag false" EOF git tag -m nested nested annotated-v4.0 2>actual && test_i18ncmp expect actual diff --git a/t/t7030-verify-tag.sh b/t/t7030-verify-tag.sh index 8f077bea60..5c5bc32ccb 100755 --- a/t/t7030-verify-tag.sh +++ b/t/t7030-verify-tag.sh @@ -86,6 +86,30 @@ test_expect_success GPGSM 'verify and show signatures x509' ' echo ninth-signed-x509 OK ' +test_expect_success GPGSM 'verify and show signatures x509 with low minTrustLevel' ' + test_config gpg.minTrustLevel undefined && + git verify-tag ninth-signed-x509 2>actual && + grep "Good signature from" actual && + ! grep "BAD signature from" actual && + echo ninth-signed-x509 OK +' + +test_expect_success GPGSM 'verify and show signatures x509 with matching minTrustLevel' ' + test_config gpg.minTrustLevel fully && + git verify-tag ninth-signed-x509 2>actual && + grep "Good signature from" actual && + ! grep "BAD signature from" actual && + echo ninth-signed-x509 OK +' + +test_expect_success GPGSM 'verify and show signatures x509 with high minTrustLevel' ' + test_config gpg.minTrustLevel ultimate && + test_must_fail git verify-tag ninth-signed-x509 2>actual && + grep "Good signature from" actual && + ! grep "BAD signature from" actual && + echo ninth-signed-x509 OK +' + test_expect_success GPG 'detect fudged signature' ' git cat-file tag seventh-signed >raw && sed -e "/^tag / s/seventh/7th forged/" raw >forged1 && diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh index 190ae149cf..428cff9cf3 100755 --- a/t/t7063-status-untracked-cache.sh +++ b/t/t7063-status-untracked-cache.sh @@ -18,7 +18,7 @@ GIT_FORCE_UNTRACKED_CACHE=true export GIT_FORCE_UNTRACKED_CACHE sync_mtime () { - find . -type d -ls >/dev/null + find . -type d -exec ls -ld {} + >/dev/null } avoid_racy() { @@ -30,6 +30,30 @@ status_is_clean() { test_must_be_empty ../status.actual } +# Ignore_Untracked_Cache, abbreviated to 3 letters because then people can +# compare commands side-by-side, e.g. +# iuc status --porcelain >expect && +# git status --porcelain >actual && +# test_cmp expect actual +iuc () { + git ls-files -s >../current-index-entries + git ls-files -t | sed -ne s/^S.//p >../current-sparse-entries + + GIT_INDEX_FILE=.git/tmp_index + export GIT_INDEX_FILE + git update-index --index-info <../current-index-entries + git update-index --skip-worktree $(cat ../current-sparse-entries) + + git -c core.untrackedCache=false "$@" + ret=$? + + rm ../current-index-entries + rm $GIT_INDEX_FILE + unset GIT_INDEX_FILE + + return $ret +} + test_lazy_prereq UNTRACKED_CACHE ' { git update-index --test-untracked-cache; ret=$?; } && test $ret -ne 1 @@ -95,6 +119,8 @@ test_expect_success 'status first time (empty cache)' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../actual && + iuc status --porcelain >../status.iuc && + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../actual && cat >../trace.expect <<EOF && node creation: 3 @@ -115,6 +141,8 @@ test_expect_success 'status second time (fully populated cache)' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../actual && + iuc status --porcelain >../status.iuc && + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../actual && cat >../trace.expect <<EOF && node creation: 0 @@ -136,6 +164,7 @@ test_expect_success 'modify in root directory, one dir invalidation' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && A done/one A one @@ -145,6 +174,7 @@ A two ?? four ?? three EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../actual && cat >../trace.expect <<EOF && node creation: 0 @@ -183,6 +213,7 @@ test_expect_success 'new .gitignore invalidates recursively' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && A done/one A one @@ -192,6 +223,7 @@ A two ?? dtwo/ ?? three EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../actual && cat >../trace.expect <<EOF && node creation: 0 @@ -230,6 +262,7 @@ test_expect_success 'new info/exclude invalidates everything' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && A done/one A one @@ -237,6 +270,7 @@ A two ?? .gitignore ?? dtwo/ EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../actual && cat >../trace.expect <<EOF && node creation: 0 @@ -286,6 +320,7 @@ test_expect_success 'status after the move' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && A done/one A one @@ -293,6 +328,7 @@ A one ?? dtwo/ ?? two EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../actual && cat >../trace.expect <<EOF && node creation: 0 @@ -343,6 +379,7 @@ test_expect_success 'status after the move' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && A done/one A one @@ -350,6 +387,7 @@ A two ?? .gitignore ?? dtwo/ EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../actual && cat >../trace.expect <<EOF && node creation: 0 @@ -390,10 +428,12 @@ test_expect_success 'status after commit' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && ?? .gitignore ?? dtwo/ EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../actual && cat >../trace.expect <<EOF && node creation: 0 @@ -447,12 +487,14 @@ test_expect_success 'test sparse status with untracked cache' ' avoid_racy && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../status.actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && M done/two ?? .gitignore ?? done/five ?? dtwo/ EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../status.actual && cat >../trace.expect <<EOF && node creation: 0 @@ -487,12 +529,14 @@ test_expect_success 'test sparse status again with untracked cache' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../status.actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && M done/two ?? .gitignore ?? done/five ?? dtwo/ EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../status.actual && cat >../trace.expect <<EOF && node creation: 0 @@ -514,6 +558,7 @@ test_expect_success 'test sparse status with untracked cache and subdir' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../status.actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && M done/two ?? .gitignore @@ -521,6 +566,7 @@ test_expect_success 'test sparse status with untracked cache and subdir' ' ?? done/sub/ ?? dtwo/ EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../status.actual && cat >../trace.expect <<EOF && node creation: 2 @@ -560,6 +606,8 @@ test_expect_success 'test sparse status again with untracked cache and subdir' ' : >../trace && GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \ git status --porcelain >../status.actual && + iuc status --porcelain >../status.iuc && + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../status.actual && cat >../trace.expect <<EOF && node creation: 0 @@ -573,6 +621,7 @@ EOF test_expect_success 'move entry in subdir from untracked to cached' ' git add dtwo/two && git status --porcelain >../status.actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && M done/two A dtwo/two @@ -580,12 +629,14 @@ A dtwo/two ?? done/five ?? done/sub/ EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../status.actual ' test_expect_success 'move entry in subdir from cached to untracked' ' git rm --cached dtwo/two && git status --porcelain >../status.actual && + iuc status --porcelain >../status.iuc && cat >../status.expect <<EOF && M done/two ?? .gitignore @@ -593,6 +644,7 @@ test_expect_success 'move entry in subdir from cached to untracked' ' ?? done/sub/ ?? dtwo/ EOF + test_cmp ../status.expect ../status.iuc && test_cmp ../status.expect ../status.actual ' diff --git a/t/t7107-reset-pathspec-file.sh b/t/t7107-reset-pathspec-file.sh index 6b1a731fff..cad3a9de9e 100755 --- a/t/t7107-reset-pathspec-file.sh +++ b/t/t7107-reset-pathspec-file.sh @@ -105,8 +105,12 @@ test_expect_success 'CRLF delimiters' ' test_expect_success 'quotes' ' restore_checkpoint && + cat >list <<-\EOF && + "file\101.t" + EOF + git rm fileA.t && - printf "\"file\\101.t\"" | git reset --pathspec-from-file=- && + git reset --pathspec-from-file=list && cat >expect <<-\EOF && D fileA.t @@ -117,8 +121,10 @@ test_expect_success 'quotes' ' test_expect_success 'quotes not compatible with --pathspec-file-nul' ' restore_checkpoint && - git rm fileA.t && - printf "\"file\\101.t\"" >list && + cat >list <<-\EOF && + "file\101.t" + EOF + # Note: "git reset" has not yet learned to fail on wrong pathspecs git reset --pathspec-from-file=list --pathspec-file-nul && @@ -128,15 +134,6 @@ test_expect_success 'quotes not compatible with --pathspec-file-nul' ' test_must_fail verify_expect ' -test_expect_success '--pathspec-from-file is not compatible with --soft or --hard' ' - restore_checkpoint && - - git rm fileA.t && - echo fileA.t >list && - test_must_fail git reset --soft --pathspec-from-file=list && - test_must_fail git reset --hard --pathspec-from-file=list -' - test_expect_success 'only touches what was listed' ' restore_checkpoint && @@ -152,4 +149,25 @@ test_expect_success 'only touches what was listed' ' verify_expect ' +test_expect_success 'error conditions' ' + restore_checkpoint && + echo fileA.t >list && + git rm fileA.t && + + test_must_fail git reset --pathspec-from-file=list --patch 2>err && + test_i18ngrep -e "--pathspec-from-file is incompatible with --patch" err && + + test_must_fail git reset --pathspec-from-file=list -- fileA.t 2>err && + test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err && + + test_must_fail git reset --pathspec-file-nul 2>err && + test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err && + + test_must_fail git reset --soft --pathspec-from-file=list 2>err && + test_i18ngrep -e "fatal: Cannot do soft reset with paths" err && + + test_must_fail git reset --hard --pathspec-from-file=list 2>err && + test_i18ngrep -e "fatal: Cannot do hard reset with paths" err +' + test_done diff --git a/t/t7112-reset-submodule.sh b/t/t7112-reset-submodule.sh index a1cb9ff858..67346424a5 100755 --- a/t/t7112-reset-submodule.sh +++ b/t/t7112-reset-submodule.sh @@ -5,7 +5,6 @@ test_description='reset can handle submodules' . ./test-lib.sh . "$TEST_DIRECTORY"/lib-submodule-update.sh -KNOWN_FAILURE_SUBMODULE_RECURSIVE_NESTED=1 KNOWN_FAILURE_DIRECTORY_SUBMODULE_CONFLICTS=1 KNOWN_FAILURE_SUBMODULE_OVERWRITE_IGNORED_UNTRACKED=1 diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh index 6e6d24c1c3..cb5e34d94c 100755 --- a/t/t7300-clean.sh +++ b/t/t7300-clean.sh @@ -737,4 +737,13 @@ test_expect_success MINGW 'handle clean & core.longpaths = false nicely' ' test_i18ngrep "too long" .git/err ' +test_expect_success 'clean untracked paths by pathspec' ' + git init untracked && + mkdir untracked/dir && + echo >untracked/dir/file.txt && + git -C untracked clean -f dir/file.txt && + ls untracked/dir >actual && + test_must_be_empty actual +' + test_done diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index 7f75bb1be6..956e17abb3 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -55,6 +55,21 @@ test_expect_success 'add aborts on repository with no commits' ' test_i18ncmp expect actual ' +test_expect_success 'status should ignore inner git repo when not added' ' + rm -fr inner && + mkdir inner && + ( + cd inner && + git init && + >t && + git add t && + git commit -m "initial" + ) && + test_must_fail git submodule status inner 2>output.err && + rm -fr inner && + test_i18ngrep "^error: .*did not match any file(s) known to git" output.err +' + test_expect_success 'setup - repository in init subdirectory' ' mkdir init && ( @@ -156,9 +171,11 @@ test_expect_success 'submodule add to .gitignored path fails' ' ( cd addtest-ignore && cat <<-\EOF >expect && - The following path is ignored by one of your .gitignore files: + The following paths are ignored by one of your .gitignore files: submod - Use -f if you really want to add it. + hint: Use -f if you really want to add them. + hint: Turn this message off by running + hint: "git config advice.addIgnoredFile false" EOF # Does not use test_commit due to the ignore echo "*" > .gitignore && @@ -191,6 +208,17 @@ test_expect_success 'submodule add to reconfigure existing submodule with --forc ) ' +test_expect_success 'submodule add relays add --dry-run stderr' ' + test_when_finished "rm -rf addtest/.git/index.lock" && + ( + cd addtest && + : >.git/index.lock && + ! git submodule add "$submodurl" sub-while-locked 2>output.err && + test_i18ngrep "^fatal: .*index\.lock" output.err && + test_path_is_missing sub-while-locked + ) +' + test_expect_success 'submodule add --branch' ' echo "refs/heads/initial" >expect-head && cat <<-\EOF >expect-heads && @@ -399,6 +427,14 @@ test_expect_success 'init should register submodule url in .git/config' ' test_cmp expect url ' +test_expect_success 'status should still be "missing" after initializing' ' + rm -fr init && + mkdir init && + git submodule status >lines && + rm -fr init && + grep "^-$rev1" lines +' + test_failure_with_unknown_submodule () { test_must_fail git submodule $1 no-such-submodule 2>output.err && test_i18ngrep "^error: .*no-such-submodule" output.err @@ -902,7 +938,7 @@ test_expect_success 'submodule add --name allows to replace a submodule with ano echo "repo" >expect && test_must_fail git config -f .gitmodules submodule.repo.path && git config -f .gitmodules submodule.repo_new.path >actual && - test_cmp expect actual&& + test_cmp expect actual && echo "$submodurl/repo" >expect && test_must_fail git config -f .gitmodules submodule.repo.url && echo "$submodurl/bare.git" >expect && @@ -974,7 +1010,7 @@ test_expect_success 'submodule add with an existing name fails unless forced' ' test -d repo && echo "repo" >expect && git config -f .gitmodules submodule.repo_new.path >actual && - test_cmp expect actual&& + test_cmp expect actual && echo "$submodurl/repo.git" >expect && git config -f .gitmodules submodule.repo_new.url >actual && test_cmp expect actual && diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh index 7478f7ab7e..4fb447a143 100755 --- a/t/t7406-submodule-update.sh +++ b/t/t7406-submodule-update.sh @@ -960,7 +960,7 @@ test_expect_success 'submodule update clone shallow submodule outside of depth' mv -f .gitmodules.tmp .gitmodules && # Some protocol versions (e.g. 2) support fetching # unadvertised objects, so restrict this test to v0. - test_must_fail env GIT_TEST_PROTOCOL_VERSION= \ + test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 \ git submodule update --init --depth=1 2>actual && test_i18ngrep "Direct fetching of that commit failed." actual && git -C ../submodule config uploadpack.allowReachableSHA1InWant true && diff --git a/t/t7408-submodule-reference.sh b/t/t7408-submodule-reference.sh index 34ac28c056..a3892f494b 100755 --- a/t/t7408-submodule-reference.sh +++ b/t/t7408-submodule-reference.sh @@ -122,8 +122,8 @@ test_expect_success 'missing submodule alternate fails clone and submodule updat # 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_path_is_missing .git/modules/sub/objects/info/alternates && + test_path_is_missing sub/file1 ) ' @@ -137,7 +137,7 @@ test_expect_success 'ignoring missing submodule alternates passes clone and subm # 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_missing .git/modules/sub/objects/info/alternates && test_path_is_file sub/file1 ) ' @@ -182,7 +182,7 @@ check_that_two_of_three_alternates_are_used() { # immediate submodule has alternate: test_alternate_is_used .git/modules/subwithsub/objects/info/alternates subwithsub && # but nested submodule has no alternate: - test_must_fail test_alternate_is_used .git/modules/subwithsub/modules/sub/objects/info/alternates subwithsub/sub + test_path_is_missing .git/modules/subwithsub/modules/sub/objects/info/alternates } diff --git a/t/t7410-submodule-checkout-to.sh b/t/t7410-submodule-checkout-to.sh deleted file mode 100755 index f1b492ebc4..0000000000 --- a/t/t7410-submodule-checkout-to.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/bin/sh - -test_description='Combination of submodules and multiple workdirs' - -. ./test-lib.sh - -base_path=$(pwd -P) - -test_expect_success 'setup: make origin' ' - mkdir -p origin/sub && - ( - cd origin/sub && git init && - echo file1 >file1 && - git add file1 && - git commit -m file1 - ) && - mkdir -p origin/main && - ( - cd origin/main && git init && - git submodule add ../sub && - git commit -m "add sub" - ) && - ( - cd origin/sub && - echo file1updated >file1 && - git add file1 && - git commit -m "file1 updated" - ) && - git -C origin/main/sub pull && - ( - cd origin/main && - git add sub && - git commit -m "sub updated" - ) -' - -test_expect_success 'setup: clone' ' - mkdir clone && - git -C clone clone --recursive "$base_path/origin/main" -' - -rev1_hash_main=$(git --git-dir=origin/main/.git show --pretty=format:%h -q "HEAD~1") -rev1_hash_sub=$(git --git-dir=origin/sub/.git show --pretty=format:%h -q "HEAD~1") - -test_expect_success 'checkout main' ' - mkdir default_checkout && - git -C clone/main worktree add "$base_path/default_checkout/main" "$rev1_hash_main" -' - -test_expect_failure 'can see submodule diffs just after checkout' ' - git -C default_checkout/main diff --submodule master"^!" >out && - grep "file1 updated" out -' - -test_expect_success 'checkout main and initialize independent clones' ' - mkdir fully_cloned_submodule && - git -C clone/main worktree add "$base_path/fully_cloned_submodule/main" "$rev1_hash_main" && - git -C fully_cloned_submodule/main submodule update -' - -test_expect_success 'can see submodule diffs after independent cloning' ' - git -C fully_cloned_submodule/main diff --submodule master"^!" >out && - grep "file1 updated" out -' - -test_expect_success 'checkout sub manually' ' - mkdir linked_submodule && - git -C clone/main worktree add "$base_path/linked_submodule/main" "$rev1_hash_main" && - git -C clone/main/sub worktree add "$base_path/linked_submodule/main/sub" "$rev1_hash_sub" -' - -test_expect_success 'can see submodule diffs after manual checkout of linked submodule' ' - git -C linked_submodule/main diff --submodule master"^!" >out && - grep "file1 updated" out -' - -test_done diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh index 5ba041f537..eec96e0ba9 100755 --- a/t/t7416-submodule-dash-url.sh +++ b/t/t7416-submodule-dash-url.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='check handling of .gitmodule url with dash' +test_description='check handling of disallowed .gitmodule urls' . ./test-lib.sh test_expect_success 'create submodule with protected dash in url' ' @@ -60,4 +60,145 @@ test_expect_success 'trailing backslash is handled correctly' ' test_i18ngrep ! "unknown option" err ' +test_expect_success 'fsck rejects missing URL scheme' ' + git checkout --orphan missing-scheme && + cat >.gitmodules <<-\EOF && + [submodule "foo"] + url = http::one.example.com/foo.git + EOF + git add .gitmodules && + test_tick && + git commit -m "gitmodules with missing URL scheme" && + test_when_finished "rm -rf dst" && + git init --bare dst && + git -C dst config transfer.fsckObjects true && + test_must_fail git push dst HEAD 2>err && + grep gitmodulesUrl err +' + +test_expect_success 'fsck rejects relative URL resolving to missing scheme' ' + git checkout --orphan relative-missing-scheme && + cat >.gitmodules <<-\EOF && + [submodule "foo"] + url = "..\\../.\\../:one.example.com/foo.git" + EOF + git add .gitmodules && + test_tick && + git commit -m "gitmodules with relative URL that strips off scheme" && + test_when_finished "rm -rf dst" && + git init --bare dst && + git -C dst config transfer.fsckObjects true && + test_must_fail git push dst HEAD 2>err && + grep gitmodulesUrl err +' + +test_expect_success 'fsck rejects empty URL scheme' ' + git checkout --orphan empty-scheme && + cat >.gitmodules <<-\EOF && + [submodule "foo"] + url = http::://one.example.com/foo.git + EOF + git add .gitmodules && + test_tick && + git commit -m "gitmodules with empty URL scheme" && + test_when_finished "rm -rf dst" && + git init --bare dst && + git -C dst config transfer.fsckObjects true && + test_must_fail git push dst HEAD 2>err && + grep gitmodulesUrl err +' + +test_expect_success 'fsck rejects relative URL resolving to empty scheme' ' + git checkout --orphan relative-empty-scheme && + cat >.gitmodules <<-\EOF && + [submodule "foo"] + url = ../../../:://one.example.com/foo.git + EOF + git add .gitmodules && + test_tick && + git commit -m "relative gitmodules URL resolving to empty scheme" && + test_when_finished "rm -rf dst" && + git init --bare dst && + git -C dst config transfer.fsckObjects true && + test_must_fail git push dst HEAD 2>err && + grep gitmodulesUrl err +' + +test_expect_success 'fsck rejects empty hostname' ' + git checkout --orphan empty-host && + cat >.gitmodules <<-\EOF && + [submodule "foo"] + url = http:///one.example.com/foo.git + EOF + git add .gitmodules && + test_tick && + git commit -m "gitmodules with extra slashes" && + test_when_finished "rm -rf dst" && + git init --bare dst && + git -C dst config transfer.fsckObjects true && + test_must_fail git push dst HEAD 2>err && + grep gitmodulesUrl err +' + +test_expect_success 'fsck rejects relative url that produced empty hostname' ' + git checkout --orphan messy-relative && + cat >.gitmodules <<-\EOF && + [submodule "foo"] + url = ../../..//one.example.com/foo.git + EOF + git add .gitmodules && + test_tick && + git commit -m "gitmodules abusing relative_path" && + test_when_finished "rm -rf dst" && + git init --bare dst && + git -C dst config transfer.fsckObjects true && + test_must_fail git push dst HEAD 2>err && + grep gitmodulesUrl err +' + +test_expect_success 'fsck permits embedded newline with unrecognized scheme' ' + git checkout --orphan newscheme && + cat >.gitmodules <<-\EOF && + [submodule "foo"] + url = "data://acjbkd%0akajfdickajkd" + EOF + git add .gitmodules && + git commit -m "gitmodules with unrecognized scheme" && + test_when_finished "rm -rf dst" && + git init --bare dst && + git -C dst config transfer.fsckObjects true && + git push dst HEAD +' + +test_expect_success 'fsck rejects embedded newline in url' ' + # create an orphan branch to avoid existing .gitmodules objects + git checkout --orphan newline && + cat >.gitmodules <<-\EOF && + [submodule "foo"] + url = "https://one.example.com?%0ahost=two.example.com/foo.git" + EOF + git add .gitmodules && + git commit -m "gitmodules with newline" && + test_when_finished "rm -rf dst" && + git init --bare dst && + git -C dst config transfer.fsckObjects true && + test_must_fail git push dst HEAD 2>err && + grep gitmodulesUrl err +' + +test_expect_success 'fsck rejects embedded newline in relative url' ' + git checkout --orphan relative-newline && + cat >.gitmodules <<-\EOF && + [submodule "foo"] + url = "./%0ahost=two.example.com/foo.git" + EOF + git add .gitmodules && + git commit -m "relative url with newline" && + test_when_finished "rm -rf dst" && + git init --bare dst && + git -C dst config transfer.fsckObjects true && + test_must_fail git push dst HEAD 2>err && + grep gitmodulesUrl err +' + test_done diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh index 46a5cd4b73..6d19ece05d 100755 --- a/t/t7500-commit-template-squash-signoff.sh +++ b/t/t7500-commit-template-squash-signoff.sh @@ -382,4 +382,13 @@ test_expect_success 'check commit with unstaged rename and copy' ' ) ' +test_expect_success 'commit without staging files fails and displays hints' ' + echo "initial" >file && + git add file && + git commit -m initial && + echo "changes" >>file && + test_must_fail git commit -m update >actual && + test_i18ngrep "no changes added to commit (use \"git add\" and/or \"git commit -a\")" actual +' + test_done diff --git a/t/t7508-status.sh b/t/t7508-status.sh index 482ce3510e..8e969f3e36 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -1471,7 +1471,7 @@ test_expect_success '"status.branch=true" same as "-b"' ' test_expect_success '"status.branch=true" different from "--no-branch"' ' git status -s --no-branch >expected_nobranch && git -c status.branch=true status -s >actual && - test_must_fail test_cmp expected_nobranch actual + ! test_cmp expected_nobranch actual ' test_expect_success '"status.branch=true" weaker than "--no-branch"' ' diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh index 682b23a068..6baaa1ad91 100755 --- a/t/t7510-signed-commit.sh +++ b/t/t7510-signed-commit.sh @@ -6,6 +6,11 @@ GNUPGHOME_NOT_USED=$GNUPGHOME . "$TEST_DIRECTORY/lib-gpg.sh" test_expect_success GPG 'create signed commits' ' + test_oid_cache <<-\EOF && + header sha1:gpgsig + header sha256:gpgsig-sha256 + EOF + test_when_finished "test_unconfig commit.gpgsign" && echo 1 >file && git add file && @@ -109,6 +114,21 @@ test_expect_success GPG 'verify-commit exits success on untrusted signature' ' grep "not certified" actual ' +test_expect_success GPG 'verify-commit exits success with matching minTrustLevel' ' + test_config gpg.minTrustLevel ultimate && + git verify-commit sixth-signed +' + +test_expect_success GPG 'verify-commit exits success with low minTrustLevel' ' + test_config gpg.minTrustLevel fully && + git verify-commit sixth-signed +' + +test_expect_success GPG 'verify-commit exits failure with high minTrustLevel' ' + test_config gpg.minTrustLevel ultimate && + test_must_fail git verify-commit eighth-signed-alt +' + test_expect_success GPG 'verify signatures with --raw' ' ( for commit in initial second merge fourth-signed fifth-signed sixth-signed seventh-signed @@ -140,6 +160,11 @@ test_expect_success GPG 'verify signatures with --raw' ' ) ' +test_expect_success GPG 'proper header is used for hash algorithm' ' + git cat-file commit fourth-signed >output && + grep "^$(test_oid header) -----BEGIN PGP SIGNATURE-----" output +' + test_expect_success GPG 'show signed commit with signature' ' git show -s initial >commit && git show -s --show-signature initial >show && @@ -147,7 +172,7 @@ test_expect_success GPG 'show signed commit with signature' ' git cat-file commit initial >cat && grep -v -e "gpg: " -e "Warning: " show >show.commit && grep -e "gpg: " -e "Warning: " show >show.gpg && - grep -v "^ " cat | grep -v "^gpgsig " >cat.commit && + grep -v "^ " cat | grep -v "^$(test_oid header) " >cat.commit && test_cmp show.commit commit && test_cmp show.gpg verify.2 && test_cmp cat.commit verify.1 @@ -219,6 +244,30 @@ test_expect_success GPG 'show untrusted signature with custom format' ' test_cmp expect actual ' +test_expect_success GPG 'show untrusted signature with undefined trust level' ' + cat >expect <<-\EOF && + undefined + 65A0EEA02E30CAD7 + Eris Discordia <discord@example.net> + F8364A59E07FFE9F4D63005A65A0EEA02E30CAD7 + D4BE22311AD3131E5EDA29A461092E85B7227189 + EOF + git log -1 --format="%GT%n%GK%n%GS%n%GF%n%GP" eighth-signed-alt >actual && + test_cmp expect actual +' + +test_expect_success GPG 'show untrusted signature with ultimate trust level' ' + cat >expect <<-\EOF && + ultimate + 13B6F51ECDDE430D + C O Mitter <committer@example.com> + 73D758744BE721698EC54E8713B6F51ECDDE430D + 73D758744BE721698EC54E8713B6F51ECDDE430D + EOF + git log -1 --format="%GT%n%GK%n%GS%n%GF%n%GP" sixth-signed >actual && + test_cmp expect actual +' + test_expect_success GPG 'show unknown signature with custom format' ' cat >expect <<-\EOF && E @@ -260,10 +309,10 @@ test_expect_success GPG 'check config gpg.format values' ' test_expect_success GPG 'detect fudged commit with double signature' ' sed -e "/gpgsig/,/END PGP/d" forged1 >double-base && sed -n -e "/gpgsig/,/END PGP/p" forged1 | \ - sed -e "s/^gpgsig//;s/^ //" | gpg --dearmor >double-sig1.sig && + sed -e "s/^$(test_oid header)//;s/^ //" | gpg --dearmor >double-sig1.sig && gpg -o double-sig2.sig -u 29472784 --detach-sign double-base && cat double-sig1.sig double-sig2.sig | gpg --enarmor >double-combined.asc && - sed -e "s/^\(-.*\)ARMORED FILE/\1SIGNATURE/;1s/^/gpgsig /;2,\$s/^/ /" \ + sed -e "s/^\(-.*\)ARMORED FILE/\1SIGNATURE/;1s/^/$(test_oid header) /;2,\$s/^/ /" \ double-combined.asc > double-gpgsig && sed -e "/committer/r double-gpgsig" double-base >double-commit && git hash-object -w -t commit double-commit >double-commit.commit && diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh index 66d7a62797..29518e0949 100755 --- a/t/t7512-status-help.sh +++ b/t/t7512-status-help.sh @@ -71,10 +71,10 @@ test_expect_success 'prepare for rebase conflicts' ' ' -test_expect_success 'status when rebase in progress before resolving conflicts' ' +test_expect_success 'status when rebase --apply in progress before resolving conflicts' ' test_when_finished "git rebase --abort" && ONTO=$(git rev-parse --short HEAD^^) && - test_must_fail git rebase HEAD^ --onto HEAD^^ && + test_must_fail git rebase --apply HEAD^ --onto HEAD^^ && cat >expected <<EOF && rebase in progress; onto $ONTO You are currently rebasing branch '\''rebase_conflicts'\'' on '\''$ONTO'\''. @@ -94,11 +94,11 @@ EOF ' -test_expect_success 'status when rebase in progress before rebase --continue' ' +test_expect_success 'status when rebase --apply in progress before rebase --continue' ' git reset --hard rebase_conflicts && test_when_finished "git rebase --abort" && ONTO=$(git rev-parse --short HEAD^^) && - test_must_fail git rebase HEAD^ --onto HEAD^^ && + test_must_fail git rebase --apply HEAD^ --onto HEAD^^ && echo three >main.txt && git add main.txt && cat >expected <<EOF && @@ -688,7 +688,7 @@ EOF ' -test_expect_success 'status when rebase conflicts with statushints disabled' ' +test_expect_success 'status when rebase --apply conflicts with statushints disabled' ' git reset --hard master && git checkout -b statushints_disabled && test_when_finished "git config --local advice.statushints true" && @@ -698,7 +698,7 @@ test_expect_success 'status when rebase conflicts with statushints disabled' ' test_commit three_statushints main.txt three && test_when_finished "git rebase --abort" && ONTO=$(git rev-parse --short HEAD^^) && - test_must_fail git rebase HEAD^ --onto HEAD^^ && + test_must_fail git rebase --apply HEAD^ --onto HEAD^^ && cat >expected <<EOF && rebase in progress; onto $ONTO You are currently rebasing branch '\''statushints_disabled'\'' on '\''$ONTO'\''. diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh index cf0fda2d5a..fbfdcca000 100755 --- a/t/t7519-status-fsmonitor.sh +++ b/t/t7519-status-fsmonitor.sh @@ -32,11 +32,12 @@ write_integration_script () { echo "$0: exactly 2 arguments expected" exit 2 fi - if test "$1" != 1 + if test "$1" != 2 then echo "Unsupported core.fsmonitor hook version." >&2 exit 1 fi + printf "last_update_token\0" printf "untracked\0" printf "dir1/untracked\0" printf "dir2/untracked\0" @@ -107,6 +108,7 @@ EOF # test that "update-index --fsmonitor-valid" sets the fsmonitor valid bit test_expect_success 'update-index --fsmonitor-valid" sets the fsmonitor valid bit' ' write_script .git/hooks/fsmonitor-test<<-\EOF && + printf "last_update_token\0" EOF git update-index --fsmonitor && git update-index --fsmonitor-valid dir1/modified && @@ -167,6 +169,7 @@ EOF # test that newly added files are marked valid test_expect_success 'newly added files are marked valid' ' write_script .git/hooks/fsmonitor-test<<-\EOF && + printf "last_update_token\0" EOF git add new && git add dir1/new && @@ -207,6 +210,7 @@ EOF # test that *only* files returned by the integration script get flagged as invalid test_expect_success '*only* files returned by the integration script get flagged as invalid' ' write_script .git/hooks/fsmonitor-test<<-\EOF && + printf "last_update_token\0" printf "dir1/modified\0" EOF clean_repo && @@ -276,6 +280,7 @@ do # (if enabled) files unless it is told about them. test_expect_success "status doesn't detect unreported modifications" ' write_script .git/hooks/fsmonitor-test<<-\EOF && + printf "last_update_token\0" :>marker EOF clean_repo && diff --git a/t/t7519/fsmonitor-all b/t/t7519/fsmonitor-all index 691bc94dc2..94ab66bd3d 100755 --- a/t/t7519/fsmonitor-all +++ b/t/t7519/fsmonitor-all @@ -17,7 +17,6 @@ fi if test "$1" != 1 then - echo "Unsupported core.fsmonitor hook version." >&2 exit 1 fi diff --git a/t/t7519/fsmonitor-all-v2 b/t/t7519/fsmonitor-all-v2 new file mode 100755 index 0000000000..061907e88b --- /dev/null +++ b/t/t7519/fsmonitor-all-v2 @@ -0,0 +1,21 @@ +#!/usr/bin/perl + +use strict; +use warnings; +# +# An test hook script to integrate with git to test fsmonitor. +# +# The hook is passed a version (currently 2) and since token +# formatted as a string and outputs to stdout all files that have been +# modified since the given time. Paths must be relative to the root of +# the working tree and separated by a single NUL. +# +#echo "$0 $*" >&2 +my ($version, $last_update_token) = @ARGV; + +if ($version ne 2) { + print "Unsupported query-fsmonitor hook version '$version'.\n"; + exit 1; +} + +print "last_update_token\0/\0" diff --git a/t/t7519/fsmonitor-watchman b/t/t7519/fsmonitor-watchman index d8e7a1e5ba..264b9daf83 100755 --- a/t/t7519/fsmonitor-watchman +++ b/t/t7519/fsmonitor-watchman @@ -26,8 +26,7 @@ if ($version == 1) { # subtract one second to make sure watchman will return all changes $time = int ($time / 1000000000) - 1; } else { - die "Unsupported query-fsmonitor hook version '$version'.\n" . - "Falling back to scanning...\n"; + exit 1; } my $git_work_tree; diff --git a/t/t7519/fsmonitor-watchman-v2 b/t/t7519/fsmonitor-watchman-v2 new file mode 100755 index 0000000000..14ed0aa42d --- /dev/null +++ b/t/t7519/fsmonitor-watchman-v2 @@ -0,0 +1,173 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IPC::Open2; + +# An example hook script to integrate Watchman +# (https://facebook.github.io/watchman/) with git to speed up detecting +# new and modified files. +# +# The hook is passed a version (currently 2) and last update token +# formatted as a string and outputs to stdout a new update token and +# all files that have been modified since the update token. Paths must +# be relative to the root of the working tree and separated by a single NUL. +# +# To enable this hook, rename this file to "query-watchman" and set +# 'git config core.fsmonitor .git/hooks/query-watchman' +# +my ($version, $last_update_token) = @ARGV; + +# Uncomment for debugging +# print STDERR "$0 $version $last_update_token\n"; + +# Check the hook interface version +if ($version ne 2) { + die "Unsupported query-fsmonitor hook version '$version'.\n" . + "Falling back to scanning...\n"; +} + +my $git_work_tree = get_working_dir(); + +my $retry = 1; + +my $json_pkg; +eval { + require JSON::XS; + $json_pkg = "JSON::XS"; + 1; +} or do { + require JSON::PP; + $json_pkg = "JSON::PP"; +}; + +launch_watchman(); + +sub launch_watchman { + my $o = watchman_query(); + if (is_work_tree_watched($o)) { + output_result($o->{clock}, @{$o->{files}}); + } +} + +sub output_result { + my ($clockid, @files) = @_; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # binmode $fh, ":utf8"; + # print $fh "$clockid\n@files\n"; + # close $fh; + + binmode STDOUT, ":utf8"; + print $clockid; + print "\0"; + local $, = "\0"; + print @files; +} + +sub watchman_clock { + my $response = qx/watchman clock "$git_work_tree"/; + die "Failed to get clock id on '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + + return $json_pkg->new->utf8->decode($response); +} + +sub watchman_query { + my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') + or die "open2() failed: $!\n" . + "Falling back to scanning...\n"; + + # In the query expression below we're asking for names of files that + # changed since $last_update_token but not from the .git folder. + # + # To accomplish this, we're using the "since" generator to use the + # recency index to select candidate nodes and "fields" to limit the + # output to file names only. Then we're using the "expression" term to + # further constrain the results. + if (substr($last_update_token, 0, 1) eq "c") { + $last_update_token = "\"$last_update_token\""; + } + my $query = <<" END"; + ["query", "$git_work_tree", { + "since": $last_update_token, + "fields": ["name"], + "expression": ["not", ["dirname", ".git"]] + }] + END + + # Uncomment for debugging the watchman query + # open (my $fh, ">", ".git/watchman-query.json"); + # print $fh $query; + # close $fh; + + print CHLD_IN $query; + close CHLD_IN; + my $response = do {local $/; <CHLD_OUT>}; + + # Uncomment for debugging the watch response + # open ($fh, ">", ".git/watchman-response.json"); + # print $fh $response; + # close $fh; + + die "Watchman: command returned no output.\n" . + "Falling back to scanning...\n" if $response eq ""; + die "Watchman: command returned invalid output: $response\n" . + "Falling back to scanning...\n" unless $response =~ /^\{/; + + return $json_pkg->new->utf8->decode($response); +} + +sub is_work_tree_watched { + my ($output) = @_; + my $error = $output->{error}; + if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) { + $retry--; + my $response = qx/watchman watch "$git_work_tree"/; + die "Failed to make watchman watch '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + $output = $json_pkg->new->utf8->decode($response); + $error = $output->{error}; + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # close $fh; + + # Watchman will always return all files on the first query so + # return the fast "everything is dirty" flag to git and do the + # Watchman query just to get it over with now so we won't pay + # the cost in git to look up each individual file. + my $o = watchman_clock(); + $error = $output->{error}; + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + output_result($o->{clock}, ("/")); + $last_update_token = $o->{clock}; + + eval { launch_watchman() }; + return 0; + } + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + return 1; +} + +sub get_working_dir { + my $working_dir; + if ($^O =~ 'msys' || $^O =~ 'cygwin') { + $working_dir = Win32::GetCwd(); + $working_dir =~ tr/\\/\//; + } else { + require Cwd; + $working_dir = Cwd::cwd(); + } + + return $working_dir; +} diff --git a/t/t7526-commit-pathspec-file.sh b/t/t7526-commit-pathspec-file.sh index 4b58901ed6..5fbe47ebcd 100755 --- a/t/t7526-commit-pathspec-file.sh +++ b/t/t7526-commit-pathspec-file.sh @@ -100,7 +100,11 @@ test_expect_success 'CRLF delimiters' ' test_expect_success 'quotes' ' restore_checkpoint && - printf "\"file\\101.t\"" | git commit --pathspec-from-file=- -m "Commit" && + cat >list <<-\EOF && + "file\101.t" + EOF + + git commit --pathspec-from-file=list -m "Commit" && cat >expect <<-\EOF && A fileA.t @@ -111,7 +115,10 @@ test_expect_success 'quotes' ' test_expect_success 'quotes not compatible with --pathspec-file-nul' ' restore_checkpoint && - printf "\"file\\101.t\"" >list && + cat >list <<-\EOF && + "file\101.t" + EOF + test_must_fail git commit --pathspec-from-file=list --pathspec-file-nul -m "Commit" ' @@ -127,10 +134,31 @@ test_expect_success 'only touches what was listed' ' verify_expect ' -test_expect_success '--pathspec-from-file and --all cannot be used together' ' +test_expect_success 'error conditions' ' restore_checkpoint && - test_must_fail git commit --pathspec-from-file=- --all -m "Commit" 2>err && - test_i18ngrep "[-]-pathspec-from-file with -a does not make sense" err + echo fileA.t >list && + >empty_list && + + test_must_fail git commit --pathspec-from-file=list --interactive -m "Commit" 2>err && + test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err && + + test_must_fail git commit --pathspec-from-file=list --patch -m "Commit" 2>err && + test_i18ngrep -e "--pathspec-from-file is incompatible with --interactive/--patch" err && + + test_must_fail git commit --pathspec-from-file=list --all -m "Commit" 2>err && + test_i18ngrep -e "--pathspec-from-file with -a does not make sense" err && + + test_must_fail git commit --pathspec-from-file=list -m "Commit" -- fileA.t 2>err && + test_i18ngrep -e "--pathspec-from-file is incompatible with pathspec arguments" err && + + test_must_fail git commit --pathspec-file-nul -m "Commit" 2>err && + test_i18ngrep -e "--pathspec-file-nul requires --pathspec-from-file" err && + + test_must_fail git commit --pathspec-from-file=empty_list --include -m "Commit" 2>err && + test_i18ngrep -e "No paths with --include/--only does not make sense." err && + + test_must_fail git commit --pathspec-from-file=empty_list --only -m "Commit" 2>err && + test_i18ngrep -e "No paths with --include/--only does not make sense." err ' test_done diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh index 132608879a..5883a6adc3 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -29,15 +29,19 @@ Testing basic merge operations/option parsing. . ./test-lib.sh . "$TEST_DIRECTORY"/lib-gpg.sh -printf '%s\n' 1 2 3 4 5 6 7 8 9 >file -printf '%s\n' '1 X' 2 3 4 5 6 7 8 9 >file.1 -printf '%s\n' 1 2 3 4 '5 X' 6 7 8 9 >file.5 -printf '%s\n' 1 2 3 4 5 6 7 8 '9 X' >file.9 -printf '%s\n' 1 2 3 4 5 6 7 8 '9 Y' >file.9y -printf '%s\n' '1 X' 2 3 4 5 6 7 8 9 >result.1 -printf '%s\n' '1 X' 2 3 4 '5 X' 6 7 8 9 >result.1-5 -printf '%s\n' '1 X' 2 3 4 '5 X' 6 7 8 '9 X' >result.1-5-9 -printf '%s\n' 1 2 3 4 5 6 7 8 '9 Z' >result.9z +test_write_lines 1 2 3 4 5 6 7 8 9 >file +cp file file.orig +test_write_lines '1 X' 2 3 4 5 6 7 8 9 >file.1 +test_write_lines 1 2 '3 X' 4 5 6 7 8 9 >file.3 +test_write_lines 1 2 3 4 '5 X' 6 7 8 9 >file.5 +test_write_lines 1 2 3 4 5 6 7 8 '9 X' >file.9 +test_write_lines 1 2 3 4 5 6 7 8 '9 Y' >file.9y +test_write_lines '1 X' 2 3 4 5 6 7 8 9 >result.1 +test_write_lines '1 X' 2 3 4 '5 X' 6 7 8 9 >result.1-5 +test_write_lines '1 X' 2 3 4 5 6 7 8 '9 X' >result.1-9 +test_write_lines '1 X' 2 3 4 '5 X' 6 7 8 '9 X' >result.1-5-9 +test_write_lines '1 X' 2 '3 X' 4 '5 X' 6 7 8 '9 X' >result.1-3-5-9 +test_write_lines 1 2 3 4 5 6 7 8 '9 Z' >result.9z create_merge_msgs () { echo "Merge tag 'c2'" >msg.1-5 && @@ -81,7 +85,7 @@ verify_head () { } verify_parents () { - printf '%s\n' "$@" >parents.expected && + test_write_lines "$@" >parents.expected && >parents.actual && i=1 && while test $i -le $# @@ -95,7 +99,7 @@ verify_parents () { } verify_mergeheads () { - printf '%s\n' "$@" >mergehead.expected && + test_write_lines "$@" >mergehead.expected && while read sha1 rest do git rev-parse $sha1 @@ -675,6 +679,134 @@ test_expect_success 'refresh the index before merging' ' git merge c3 ' +test_expect_success 'merge with --autostash' ' + git reset --hard c1 && + git merge-file file file.orig file.9 && + git merge --autostash c2 2>err && + test_i18ngrep "Applied autostash." err && + git show HEAD:file >merge-result && + test_cmp result.1-5 merge-result && + test_cmp result.1-5-9 file +' + +test_expect_success 'merge with merge.autoStash' ' + test_config merge.autoStash true && + git reset --hard c1 && + git merge-file file file.orig file.9 && + git merge c2 2>err && + test_i18ngrep "Applied autostash." err && + git show HEAD:file >merge-result && + test_cmp result.1-5 merge-result && + test_cmp result.1-5-9 file +' + +test_expect_success 'fast-forward merge with --autostash' ' + git reset --hard c0 && + git merge-file file file.orig file.5 && + git merge --autostash c1 2>err && + test_i18ngrep "Applied autostash." err && + test_cmp result.1-5 file +' + +test_expect_success 'octopus merge with --autostash' ' + git reset --hard c1 && + git merge-file file file.orig file.3 && + git merge --autostash c2 c3 2>err && + test_i18ngrep "Applied autostash." err && + git show HEAD:file >merge-result && + test_cmp result.1-5-9 merge-result && + test_cmp result.1-3-5-9 file +' + +test_expect_success 'conflicted merge with --autostash, --abort restores stash' ' + git reset --hard c3 && + cp file.1 file && + test_must_fail git merge --autostash c7 && + git merge --abort 2>err && + test_i18ngrep "Applied autostash." err && + test_cmp file.1 file +' + +test_expect_success 'completed merge (git commit) with --no-commit and --autostash' ' + git reset --hard c1 && + git merge-file file file.orig file.9 && + git diff >expect && + git merge --no-commit --autostash c2 && + git stash show -p MERGE_AUTOSTASH >actual && + test_cmp expect actual && + git commit 2>err && + test_i18ngrep "Applied autostash." err && + git show HEAD:file >merge-result && + test_cmp result.1-5 merge-result && + test_cmp result.1-5-9 file +' + +test_expect_success 'completed merge (git merge --continue) with --no-commit and --autostash' ' + git reset --hard c1 && + git merge-file file file.orig file.9 && + git diff >expect && + git merge --no-commit --autostash c2 && + git stash show -p MERGE_AUTOSTASH >actual && + test_cmp expect actual && + git merge --continue 2>err && + test_i18ngrep "Applied autostash." err && + git show HEAD:file >merge-result && + test_cmp result.1-5 merge-result && + test_cmp result.1-5-9 file +' + +test_expect_success 'aborted merge (merge --abort) with --no-commit and --autostash' ' + git reset --hard c1 && + git merge-file file file.orig file.9 && + git diff >expect && + git merge --no-commit --autostash c2 && + git stash show -p MERGE_AUTOSTASH >actual && + test_cmp expect actual && + git merge --abort 2>err && + test_i18ngrep "Applied autostash." err && + git diff >actual && + test_cmp expect actual +' + +test_expect_success 'aborted merge (reset --hard) with --no-commit and --autostash' ' + git reset --hard c1 && + git merge-file file file.orig file.9 && + git diff >expect && + git merge --no-commit --autostash c2 && + git stash show -p MERGE_AUTOSTASH >actual && + test_cmp expect actual && + git reset --hard 2>err && + test_i18ngrep "Autostash exists; creating a new stash entry." err && + git diff --exit-code +' + +test_expect_success 'quit merge with --no-commit and --autostash' ' + git reset --hard c1 && + git merge-file file file.orig file.9 && + git diff >expect && + git merge --no-commit --autostash c2 && + git stash show -p MERGE_AUTOSTASH >actual && + test_cmp expect actual && + git diff HEAD >expect && + git merge --quit 2>err && + test_i18ngrep "Autostash exists; creating a new stash entry." err && + git diff HEAD >actual && + test_cmp expect actual +' + +test_expect_success 'merge with conflicted --autostash changes' ' + git reset --hard c1 && + git merge-file file file.orig file.9y && + git diff >expect && + test_when_finished "test_might_fail git stash drop" && + git merge --autostash c3 2>err && + test_i18ngrep "Applying autostash resulted in conflicts." err && + git show HEAD:file >merge-result && + test_cmp result.1-9 merge-result && + git stash show -p >actual && + test_cmp expect actual +' + cat >expected.branch <<\EOF Merge branch 'c5-branch' (early part) EOF diff --git a/t/t7601-merge-pull-config.sh b/t/t7601-merge-pull-config.sh index c6c44ec570..0f97828cd0 100755 --- a/t/t7601-merge-pull-config.sh +++ b/t/t7601-merge-pull-config.sh @@ -27,6 +27,44 @@ test_expect_success 'setup' ' git tag c3 ' +test_expect_success 'pull.rebase not set' ' + git reset --hard c0 && + git pull . c1 2>err && + test_i18ngrep "Pulling without specifying how to reconcile" err +' + +test_expect_success 'pull.rebase not set and pull.ff=false' ' + git reset --hard c0 && + test_config pull.ff false && + git pull . c1 2>err && + test_i18ngrep "Pulling without specifying how to reconcile" err +' + +test_expect_success 'pull.rebase not set and pull.ff=only' ' + git reset --hard c0 && + test_config pull.ff only && + git pull . c1 2>err && + test_i18ngrep ! "Pulling without specifying how to reconcile" err +' + +test_expect_success 'pull.rebase not set and --rebase given' ' + git reset --hard c0 && + git pull --rebase . c1 2>err && + test_i18ngrep ! "Pulling without specifying how to reconcile" err +' + +test_expect_success 'pull.rebase not set and --no-rebase given' ' + git reset --hard c0 && + git pull --no-rebase . c1 2>err && + test_i18ngrep ! "Pulling without specifying how to reconcile" err +' + +test_expect_success 'pull.rebase not set and --ff-only given' ' + git reset --hard c0 && + git pull --ff-only . c1 2>err && + test_i18ngrep ! "Pulling without specifying how to reconcile" err +' + test_expect_success 'merge c1 with c2' ' git reset --hard c1 && test -f c0.c && diff --git a/t/t7609-merge-co-error-msgs.sh b/t/t7609-merge-co-error-msgs.sh index e90413204e..5c8894d94f 100755 --- a/t/t7609-merge-co-error-msgs.sh +++ b/t/t7609-merge-co-error-msgs.sh @@ -126,7 +126,7 @@ test_expect_success 'not_uptodate_dir porcelain checkout error' ' git rm rep2 -r && >rep && >rep2 && - git add rep rep2&& + git add rep rep2 && git commit -m "added test as a file" && git checkout master && >rep/untracked-file && diff --git a/t/t7612-merge-verify-signatures.sh b/t/t7612-merge-verify-signatures.sh index d99218a725..a426f3a89a 100755 --- a/t/t7612-merge-verify-signatures.sh +++ b/t/t7612-merge-verify-signatures.sh @@ -66,6 +66,20 @@ test_expect_success GPG 'merge commit with untrusted signature with verification test_i18ngrep "has an untrusted GPG signature" mergeerror ' +test_expect_success GPG 'merge commit with untrusted signature with verification and high minTrustLevel' ' + test_when_finished "git reset --hard && git checkout initial" && + test_config gpg.minTrustLevel marginal && + test_must_fail git merge --ff-only --verify-signatures side-untrusted 2>mergeerror && + test_i18ngrep "has an untrusted GPG signature" mergeerror +' + +test_expect_success GPG 'merge commit with untrusted signature with verification and low minTrustLevel' ' + test_when_finished "git reset --hard && git checkout initial" && + test_config gpg.minTrustLevel undefined && + git merge --ff-only --verify-signatures side-untrusted >mergeoutput && + test_i18ngrep "has a good GPG signature" mergeoutput +' + test_expect_success GPG 'merge commit with untrusted signature with merge.verifySignatures=true' ' test_when_finished "git reset --hard && git checkout initial" && test_config merge.verifySignatures true && @@ -73,6 +87,14 @@ test_expect_success GPG 'merge commit with untrusted signature with merge.verify test_i18ngrep "has an untrusted GPG signature" mergeerror ' +test_expect_success GPG 'merge commit with untrusted signature with merge.verifySignatures=true and minTrustLevel' ' + test_when_finished "git reset --hard && git checkout initial" && + test_config merge.verifySignatures true && + test_config gpg.minTrustLevel marginal && + test_must_fail git merge --ff-only side-untrusted 2>mergeerror && + test_i18ngrep "has an untrusted GPG signature" mergeerror +' + test_expect_success GPG 'merge signed commit with verification' ' test_when_finished "git reset --hard && git checkout initial" && git merge --verbose --ff-only --verify-signatures side-signed >mergeoutput && diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh index 6bac9ed180..29b92907e2 100755 --- a/t/t7800-difftool.sh +++ b/t/t7800-difftool.sh @@ -125,15 +125,14 @@ test_expect_success 'difftool stops on error with --trust-exit-code' ' test_when_finished "rm -f for-diff .git/fail-right-file" && test_when_finished "git reset -- for-diff" && write_script .git/fail-right-file <<-\EOF && - echo "$2" + echo failed exit 1 EOF >for-diff && git add for-diff && - echo file >expect && test_must_fail git difftool -y --trust-exit-code \ --extcmd .git/fail-right-file branch >actual && - test_cmp expect actual + test_line_count = 1 actual ' test_expect_success 'difftool honors exit status if command not found' ' diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index 7d7b396c23..991d5bd9c0 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -72,6 +72,11 @@ test_expect_success setup ' # Still a no-op. function dummy() {} EOF + if test_have_prereq FUNNYNAMES + then + echo unusual >"\"unusual\" pathname" && + echo unusual >"t/nested \"unusual\" pathname" + fi && git add . && test_tick && git commit -m initial @@ -481,6 +486,48 @@ do git grep --count -h -e b $H -- ab >actual && test_cmp expected actual ' + + test_expect_success FUNNYNAMES "grep $L should quote unusual pathnames" ' + cat >expected <<-EOF && + ${HC}"\"unusual\" pathname":unusual + ${HC}"t/nested \"unusual\" pathname":unusual + EOF + git grep unusual $H >actual && + test_cmp expected actual + ' + + test_expect_success FUNNYNAMES "grep $L in subdir should quote unusual relative pathnames" ' + cat >expected <<-EOF && + ${HC}"nested \"unusual\" pathname":unusual + EOF + ( + cd t && + git grep unusual $H + ) >actual && + test_cmp expected actual + ' + + test_expect_success FUNNYNAMES "grep -z $L with unusual pathnames" ' + cat >expected <<-EOF && + ${HC}"unusual" pathname:unusual + ${HC}t/nested "unusual" pathname:unusual + EOF + git grep -z unusual $H >actual && + tr "\0" ":" <actual >actual-replace-null && + test_cmp expected actual-replace-null + ' + + test_expect_success FUNNYNAMES "grep -z $L in subdir with unusual relative pathnames" ' + cat >expected <<-EOF && + ${HC}nested "unusual" pathname:unusual + EOF + ( + cd t && + git grep -z unusual $H + ) >actual && + tr "\0" ":" <actual >actual-replace-null && + test_cmp expected actual-replace-null + ' done cat >expected <<EOF diff --git a/t/t7814-grep-recurse-submodules.sh b/t/t7814-grep-recurse-submodules.sh index 946f91fa57..828cb3ba58 100755 --- a/t/t7814-grep-recurse-submodules.sh +++ b/t/t7814-grep-recurse-submodules.sh @@ -345,7 +345,16 @@ test_incompatible_with_recurse_submodules () } test_incompatible_with_recurse_submodules --untracked -test_incompatible_with_recurse_submodules --no-index + +test_expect_success 'grep --recurse-submodules --no-index ignores --recurse-submodules' ' + git grep --recurse-submodules --no-index -e "^(.|.)[\d]" >actual && + cat >expect <<-\EOF && + a:(1|2)d(3|4) + submodule/a:(1|2)d(3|4) + submodule/sub/a:(1|2)d(3|4) + EOF + test_cmp expect actual +' test_expect_success 'grep --recurse-submodules should pass the pattern type along' ' # Fixed diff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh index 1c5fb1d1f8..9130b887d2 100755 --- a/t/t8003-blame-corner-cases.sh +++ b/t/t8003-blame-corner-cases.sh @@ -173,7 +173,6 @@ test_expect_success 'blame during cherry-pick with file rename conflict' ' 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 diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index a834afab4d..90f61c3400 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -1194,8 +1194,8 @@ test_expect_success $PREREQ 'in-reply-to but no threading' ' --to=nobody@example.com \ --in-reply-to="<in-reply-id@example.com>" \ --no-thread \ - $patches | - grep "In-Reply-To: <in-reply-id@example.com>" + $patches >out && + grep "In-Reply-To: <in-reply-id@example.com>" out ' test_expect_success $PREREQ 'no in-reply-to and no threading' ' diff --git a/t/t9010-svn-fe.sh b/t/t9010-svn-fe.sh index c90fdc5c89..83f8f5cacb 100755 --- a/t/t9010-svn-fe.sh +++ b/t/t9010-svn-fe.sh @@ -486,7 +486,7 @@ test_expect_success 'NUL in property value' ' { properties \ unimportant "something with a NUL (Q)" \ - svn:log "commit message"&& + svn:log "commit message" && echo PROPS-END } | q_to_nul >props && diff --git a/t/t9106-git-svn-commit-diff-clobber.sh b/t/t9106-git-svn-commit-diff-clobber.sh index dbe8deac0d..aec45bca3b 100755 --- a/t/t9106-git-svn-commit-diff-clobber.sh +++ b/t/t9106-git-svn-commit-diff-clobber.sh @@ -92,7 +92,8 @@ test_expect_success 'multiple dcommit from git svn will not clobber svn' " test_expect_success 'check that rebase really failed' ' - test -d .git/rebase-apply + git status >output && + grep currently.rebasing output ' test_expect_success 'resolve, continue the rebase and dcommit' " diff --git a/t/t9116-git-svn-log.sh b/t/t9116-git-svn-log.sh index 45773ee560..0a9f1ef366 100755 --- a/t/t9116-git-svn-log.sh +++ b/t/t9116-git-svn-log.sh @@ -43,14 +43,18 @@ test_expect_success 'setup repository and import' ' test_expect_success 'run log' " git reset --hard origin/a && - git svn log -r2 origin/trunk | grep ^r2 && - git svn log -r4 origin/trunk | grep ^r4 && - git svn log -r3 | grep ^r3 + git svn log -r2 origin/trunk >out && + grep ^r2 out && + git svn log -r4 origin/trunk >out && + grep ^r4 out && + git svn log -r3 >out && + grep ^r3 out " test_expect_success 'run log against a from trunk' " git reset --hard origin/trunk && - git svn log -r3 origin/a | grep ^r3 + git svn log -r3 origin/a >out && + grep ^r3 out " printf 'r1 \nr2 \nr4 \n' > expected-range-r1-r2-r4 diff --git a/t/t9141-git-svn-multiple-branches.sh b/t/t9141-git-svn-multiple-branches.sh index 8e7f7d68b7..bf168a3645 100755 --- a/t/t9141-git-svn-multiple-branches.sh +++ b/t/t9141-git-svn-multiple-branches.sh @@ -90,10 +90,10 @@ test_expect_success 'Multiple branch or tag paths require -d' ' ) && ( cd svn_project && svn_cmd up && - test_must_fail test -d b_one/Nope && - test_must_fail test -d b_two/Nope && - test_must_fail test -d tags_A/Tagless && - test_must_fail test -d tags_B/Tagless + test_path_is_missing b_one/Nope && + test_path_is_missing b_two/Nope && + test_path_is_missing tags_A/Tagless && + test_path_is_missing tags_B/Tagless ) ' diff --git a/t/t9160-git-svn-preserve-empty-dirs.sh b/t/t9160-git-svn-preserve-empty-dirs.sh index 0ede3cfedb..36c6b1a12f 100755 --- a/t/t9160-git-svn-preserve-empty-dirs.sh +++ b/t/t9160-git-svn-preserve-empty-dirs.sh @@ -86,8 +86,8 @@ test_expect_success 'remove non-last entry from directory' ' cd "$GIT_REPO" && git checkout HEAD~2 ) && - test_must_fail test -f "$GIT_REPO"/2/.gitignore && - test_must_fail test -f "$GIT_REPO"/3/.gitignore + test_path_is_missing "$GIT_REPO"/2/.gitignore && + test_path_is_missing "$GIT_REPO"/3/.gitignore ' # After re-cloning the repository with --placeholder-file specified, there diff --git a/t/t9164-git-svn-dcommit-concurrent.sh b/t/t9164-git-svn-dcommit-concurrent.sh index 90346ff4e9..8466269bf5 100755 --- a/t/t9164-git-svn-dcommit-concurrent.sh +++ b/t/t9164-git-svn-dcommit-concurrent.sh @@ -92,7 +92,7 @@ test_expect_success 'check if post-commit hook creates a concurrent commit' ' echo 1 >> file && svn_cmd commit -m "changing file" && svn_cmd up && - test_must_fail test_cmp auto_updated_file au_file_saved + ! test_cmp auto_updated_file au_file_saved ) ' @@ -103,7 +103,7 @@ test_expect_success 'check if pre-commit hook fails' ' echo 2 >> file && svn_cmd commit -m "changing file once again" && echo 3 >> file && - test_must_fail svn_cmd commit -m "this commit should fail" && + ! svn_cmd commit -m "this commit should fail" && svn_cmd revert file ) ' diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index ae9950a9c2..768257b29e 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -1047,7 +1047,6 @@ test_expect_success 'M: rename root to subdirectory' ' EOF git fast-import <input && git diff-tree -M -r M4^ M4 >actual && - cat actual && compare_diff_raw expect actual ' @@ -3382,4 +3381,113 @@ test_expect_success 'X: handling encoding' ' git log -1 --format=%B encoding | grep $(printf "\317\200") ' +### +### series Y (submodules and hash algorithms) +### + +cat >Y-sub-input <<\Y_INPUT_END +blob +mark :1 +data 4 +foo + +reset refs/heads/master +commit refs/heads/master +mark :2 +author Full Name <user@company.tld> 1000000000 +0100 +committer Full Name <user@company.tld> 1000000000 +0100 +data 24 +Test submodule commit 1 +M 100644 :1 file + +blob +mark :3 +data 8 +foo +bar + +commit refs/heads/master +mark :4 +author Full Name <user@company.tld> 1000000001 +0100 +committer Full Name <user@company.tld> 1000000001 +0100 +data 24 +Test submodule commit 2 +from :2 +M 100644 :3 file +Y_INPUT_END + +# Note that the submodule object IDs are intentionally not translated. +cat >Y-main-input <<\Y_INPUT_END +blob +mark :1 +data 4 +foo + +reset refs/heads/master +commit refs/heads/master +mark :2 +author Full Name <user@company.tld> 2000000000 +0100 +committer Full Name <user@company.tld> 2000000000 +0100 +data 14 +Test commit 1 +M 100644 :1 file + +blob +mark :3 +data 73 +[submodule "sub1"] + path = sub1 + url = https://void.example.com/main.git + +commit refs/heads/master +mark :4 +author Full Name <user@company.tld> 2000000001 +0100 +committer Full Name <user@company.tld> 2000000001 +0100 +data 14 +Test commit 2 +from :2 +M 100644 :3 .gitmodules +M 160000 0712c5be7cf681388e355ef47525aaf23aee1a6d sub1 + +blob +mark :5 +data 8 +foo +bar + +commit refs/heads/master +mark :6 +author Full Name <user@company.tld> 2000000002 +0100 +committer Full Name <user@company.tld> 2000000002 +0100 +data 14 +Test commit 3 +from :4 +M 100644 :5 file +M 160000 ff729f5e62f72c0c3978207d9a80e5f3a65f14d7 sub1 +Y_INPUT_END + +cat >Y-marks <<\Y_INPUT_END +:2 0712c5be7cf681388e355ef47525aaf23aee1a6d +:4 ff729f5e62f72c0c3978207d9a80e5f3a65f14d7 +Y_INPUT_END + +test_expect_success 'Y: setup' ' + test_oid_cache <<-EOF + Ymaster sha1:9afed2f9161ddf416c0a1863b8b0725b00070504 + Ymaster sha256:c0a1010da1df187b2e287654793df01b464bd6f8e3f17fc1481a7dadf84caee3 + EOF +' + +test_expect_success 'Y: rewrite submodules' ' + git init main1 && + ( + cd main1 && + git init sub2 && + git -C sub2 fast-import --export-marks=../sub2-marks <../Y-sub-input && + git fast-import --rewrite-submodules-from=sub:../Y-marks \ + --rewrite-submodules-to=sub:sub2-marks <../Y-main-input && + test "$(git rev-parse master)" = "$(test_oid Ymaster)" + ) +' + test_done diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh index cc8d463e01..267ddc997d 100755 --- a/t/t9500-gitweb-standalone-no-errors.sh +++ b/t/t9500-gitweb-standalone-no-errors.sh @@ -53,7 +53,7 @@ test_expect_success \ test_expect_success \ 'Make initial commit' \ - 'echo "Not an empty file." > file && + 'echo "Not an empty file." >file && git add file && git commit -a -m "Initial commit." && git branch b' @@ -139,7 +139,7 @@ test_expect_success \ test_expect_success \ 'commitdiff(0): file added' \ - 'echo "New file" > new_file && + 'echo "New file" >new_file && git add new_file && git commit -a -m "File added." && gitweb_run "p=.git;a=commitdiff"' @@ -179,7 +179,7 @@ test_expect_success \ test_expect_success \ 'commitdiff(0): mode change and modified' \ - 'echo "New line" >> file2 && + 'echo "New line" >>file2 && test_chmod +x file2 && git commit -a -m "Mode change and modification." && gitweb_run "p=.git;a=commitdiff"' @@ -197,14 +197,14 @@ propter nomen suum. EOF git commit -a -m "File added." && git mv file2 file3 && - echo "Propter nomen suum." >> file3 && + echo "Propter nomen suum." >>file3 && git commit -a -m "File rename and modification." && gitweb_run "p=.git;a=commitdiff"' test_expect_success \ 'commitdiff(0): renamed, mode change and modified' \ 'git mv file3 file2 && - echo "Propter nomen suum." >> file2 && + echo "Propter nomen suum." >>file2 && test_chmod +x file2 && git commit -a -m "File rename, mode change and modification." && gitweb_run "p=.git;a=commitdiff"' @@ -213,8 +213,8 @@ test_expect_success \ # commitdiff testing (taken from t4114-apply-typechange.sh) test_expect_success 'setup typechange commits' ' - echo "hello world" > foo && - echo "hi planet" > bar && + echo "hello world" >foo && + echo "hi planet" >bar && git update-index --add foo bar && git commit -m initial && git branch initial && @@ -223,18 +223,18 @@ test_expect_success 'setup typechange commits' ' git commit -m "foo symlinked to bar" && git branch foo-symlinked-to-bar && rm -f foo && - echo "how far is the sun?" > foo && + echo "how far is the sun?" >foo && git update-index foo && git commit -m "foo back to file" && git branch foo-back-to-file && rm -f foo && git update-index --remove foo && mkdir foo && - echo "if only I knew" > foo/baz && + echo "if only I knew" >foo/baz && git update-index --add foo/baz && git commit -m "foo becomes a directory" && git branch "foo-becomes-a-directory" && - echo "hello world" > foo/baz && + echo "hello world" >foo/baz && git update-index foo/baz && git commit -m "foo/baz is the original foo" && git branch foo-baz-renamed-from-foo @@ -324,7 +324,7 @@ test_expect_success 'commitdiff(1): removal of incomplete line' ' test_expect_success \ 'Create a merge' \ 'git checkout b && - echo "Branch" >> b && + echo "Branch" >>b && git add b && git commit -a -m "On branch" && git checkout master && @@ -342,26 +342,26 @@ test_expect_success \ test_expect_success \ 'Prepare large commit' \ 'git checkout b && - echo "To be changed" > 01-change && - echo "To be renamed" > 02-pure-rename-from && - echo "To be deleted" > 03-delete && - echo "To be renamed and changed" > 04-rename-from && - echo "To have mode changed" > 05-mode-change && - echo "File to symlink" > 06-file-or-symlink && - echo "To be changed and have mode changed" > 07-change-mode-change && + echo "To be changed" >01-change && + echo "To be renamed" >02-pure-rename-from && + echo "To be deleted" >03-delete && + echo "To be renamed and changed" >04-rename-from && + echo "To have mode changed" >05-mode-change && + echo "File to symlink" >06-file-or-symlink && + echo "To be changed and have mode changed" >07-change-mode-change && git add 0* && git commit -a -m "Prepare large commit" && - echo "Changed" > 01-change && + echo "Changed" >01-change && git mv 02-pure-rename-from 02-pure-rename-to && git rm 03-delete && rm -f 03-delete && - echo "A new file" > 03-new && + echo "A new file" >03-new && git add 03-new && git mv 04-rename-from 04-rename-to && - echo "Changed" >> 04-rename-to && + echo "Changed" >>04-rename-to && test_chmod +x 05-mode-change && rm -f 06-file-or-symlink && test_ln_s_add 01-change 06-file-or-symlink && - echo "Changed and have mode changed" > 07-change-mode-change && + echo "Changed and have mode changed" >07-change-mode-change && test_chmod +x 07-change-mode-change && git commit -a -m "Large commit" && git checkout master' @@ -444,7 +444,7 @@ test_expect_success \ test_expect_success \ 'logs: history (implicit HEAD, deleted file)' \ 'git checkout master && - echo "to be deleted" > deleted_file && + echo "to be deleted" >deleted_file && git add deleted_file && git commit -m "Add file to be deleted" && git rm deleted_file && @@ -522,7 +522,7 @@ test_expect_success \ '. "$TEST_DIRECTORY"/t3901/utf8.txt && test_when_finished "GIT_AUTHOR_NAME=\"A U Thor\"" && test_when_finished "GIT_COMMITTER_NAME=\"C O Mitter\"" && - echo "UTF-8" >> file && + echo "UTF-8" >>file && git add file && git commit -F "$TEST_DIRECTORY"/t3900/1-UTF-8.txt && gitweb_run "p=.git;a=commit"' @@ -532,7 +532,7 @@ test_expect_success \ '. "$TEST_DIRECTORY"/t3901/8859-1.txt && test_when_finished "GIT_AUTHOR_NAME=\"A U Thor\"" && test_when_finished "GIT_COMMITTER_NAME=\"C O Mitter\"" && - echo "ISO-8859-1" >> file && + echo "ISO-8859-1" >>file && git add file && test_config i18n.commitencoding ISO-8859-1 && git commit -F "$TEST_DIRECTORY"/t3900/ISO8859-1.txt && @@ -675,8 +675,8 @@ test_expect_success \ test_expect_success \ 'README.html with non-ASCII characters (utf-8)' \ - 'echo "<b>UTF-8 example:</b><br />" > .git/README.html && - cat "$TEST_DIRECTORY"/t3900/1-UTF-8.txt >> .git/README.html && + 'echo "<b>UTF-8 example:</b><br />" >.git/README.html && + cat "$TEST_DIRECTORY"/t3900/1-UTF-8.txt >>.git/README.html && gitweb_run "p=.git;a=summary"' # ---------------------------------------------------------------------- @@ -704,7 +704,7 @@ test_expect_success HIGHLIGHT \ test_expect_success HIGHLIGHT \ 'syntax highlighting (highlighted, shell script)' \ 'git config gitweb.highlight yes && - echo "#!/usr/bin/sh" > test.sh && + echo "#!/usr/bin/sh" >test.sh && git add test.sh && git commit -m "Add test.sh" && gitweb_run "p=.git;a=blob;f=test.sh"' @@ -712,7 +712,7 @@ test_expect_success HIGHLIGHT \ test_expect_success HIGHLIGHT \ 'syntax highlighting (highlighter language autodetection)' \ 'git config gitweb.highlight yes && - echo "#!/usr/bin/perl" > test && + echo "#!/usr/bin/perl" >test && git add test && git commit -m "Add test" && gitweb_run "p=.git;a=blob;f=test"' @@ -729,11 +729,11 @@ test_expect_success \ 'git init --bare foo.git && git --git-dir=foo.git --work-tree=. add file && git --git-dir=foo.git --work-tree=. commit -m "Initial commit" && - echo "foo" > foo.git/description && + echo "foo" >foo.git/description && mkdir -p foo && (cd foo && git clone --shared --bare ../foo.git foo-forked.git && - echo "fork of foo" > foo-forked.git/description)' + echo "fork of foo" >foo-forked.git/description)' test_expect_success \ 'forks: projects list' \ @@ -754,8 +754,8 @@ EOF test_expect_success \ 'ctags: tag cloud in projects list' \ 'mkdir .git/ctags && - echo "2" > .git/ctags/foo && - echo "1" > .git/ctags/bar && + echo "2" >.git/ctags/foo && + echo "1" >.git/ctags/bar && gitweb_run' test_expect_success \ @@ -769,8 +769,8 @@ test_expect_success \ test_expect_success \ 'ctags: malformed tag weights' \ 'mkdir -p .git/ctags && - echo "not-a-number" > .git/ctags/nan && - echo "not-a-number-2" > .git/ctags/nan2 && + echo "not-a-number" >.git/ctags/nan && + echo "not-a-number-2" >.git/ctags/nan2 && echo "0.1" >.git/ctags/floating-point && gitweb_run' diff --git a/t/t9800-git-p4-basic.sh b/t/t9800-git-p4-basic.sh index 5856563068..c98c1dfc23 100755 --- a/t/t9800-git-p4-basic.sh +++ b/t/t9800-git-p4-basic.sh @@ -202,7 +202,6 @@ test_expect_success 'exit when p4 fails to produce marshaled output' ' export PATH && test_expect_code 1 git p4 clone --dest="$git" //depot >errs 2>&1 ) && - cat errs && test_i18ngrep ! Traceback errs ' diff --git a/t/t9810-git-p4-rcs.sh b/t/t9810-git-p4-rcs.sh index 57b533dc6f..e3836888ec 100755 --- a/t/t9810-git-p4-rcs.sh +++ b/t/t9810-git-p4-rcs.sh @@ -294,7 +294,6 @@ test_expect_success 'cope with rcs keyword file deletion' ' echo "\$Revision\$" >kwdelfile.c && p4 add -t ktext kwdelfile.c && p4 submit -d "Add file to be deleted" && - cat kwdelfile.c && grep 1 kwdelfile.c ) && git p4 clone --dest="$git" //depot && diff --git a/t/t9819-git-p4-case-folding.sh b/t/t9819-git-p4-case-folding.sh index 600ce1e0b0..b4d93f0c17 100755 --- a/t/t9819-git-p4-case-folding.sh +++ b/t/t9819-git-p4-case-folding.sh @@ -30,7 +30,7 @@ test_expect_success 'Check p4 is in case-folding mode' ' cd "$cli" && >lc/FILE.TXT && p4 add lc/FILE.TXT && - test_must_fail p4 submit -d "Cannot add file differing only in case" lc/FILE.TXT + ! p4 submit -d "Cannot add file differing only in case" lc/FILE.TXT ) ' diff --git a/t/t9831-git-p4-triggers.sh b/t/t9831-git-p4-triggers.sh index d743ca33ee..ff6c0352e6 100755 --- a/t/t9831-git-p4-triggers.sh +++ b/t/t9831-git-p4-triggers.sh @@ -58,7 +58,7 @@ test_expect_success 'import with extra info lines from verbose p4 trigger' ' ( cd "$git" && git p4 sync - )&& + ) && ( p4 triggers -i <<-EOF Triggers: diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh index 93877ba9cd..3c44af6940 100755 --- a/t/t9902-completion.sh +++ b/t/t9902-completion.sh @@ -1363,6 +1363,63 @@ test_expect_success 'teardown after path completion tests' ' BS\\dir '$'separators\034in\035dir'' ' +test_expect_success '__git_find_on_cmdline - single match' ' + echo list >expect && + ( + words=(git command --opt list) && + cword=${#words[@]} && + __git_find_on_cmdline "add list remove" >actual + ) && + test_cmp expect actual +' + +test_expect_success '__git_find_on_cmdline - multiple matches' ' + echo remove >expect && + ( + words=(git command -o --opt remove list add) && + cword=${#words[@]} && + __git_find_on_cmdline "add list remove" >actual + ) && + test_cmp expect actual +' + +test_expect_success '__git_find_on_cmdline - no match' ' + ( + words=(git command --opt branch) && + cword=${#words[@]} && + __git_find_on_cmdline "add list remove" >actual + ) && + test_must_be_empty actual +' + +test_expect_success '__git_find_on_cmdline - single match with index' ' + echo "3 list" >expect && + ( + words=(git command --opt list) && + cword=${#words[@]} && + __git_find_on_cmdline --show-idx "add list remove" >actual + ) && + test_cmp expect actual +' + +test_expect_success '__git_find_on_cmdline - multiple matches with index' ' + echo "4 remove" >expect && + ( + words=(git command -o --opt remove list add) && + cword=${#words[@]} && + __git_find_on_cmdline --show-idx "add list remove" >actual + ) && + test_cmp expect actual +' + +test_expect_success '__git_find_on_cmdline - no match with index' ' + ( + words=(git command --opt branch) && + cword=${#words[@]} && + __git_find_on_cmdline --show-idx "add list remove" >actual + ) && + test_must_be_empty actual +' test_expect_success '__git_get_config_variables' ' cat >expect <<-EOF && @@ -1581,6 +1638,11 @@ test_expect_success 'complete files' ' echo modify > modified && test_completion "git add " "modified" && + mkdir -p some/deep && + touch some/deep/path && + test_completion "git add some/" "some/deep" && + git clean -f some && + touch untracked && : TODO .gitignore should not be here && diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh index 88bc733ad6..ab5da2cabc 100755 --- a/t/t9903-bash-prompt.sh +++ b/t/t9903-bash-prompt.sh @@ -163,7 +163,7 @@ test_expect_success 'prompt - inside bare repository' ' ' test_expect_success 'prompt - interactive rebase' ' - printf " (b1|REBASE-i 2/3)" >expected && + printf " (b1|REBASE 2/3)" >expected && write_script fake_editor.sh <<-\EOF && echo "exec echo" >"$1" echo "edit $(git log -1 --format="%h")" >>"$1" @@ -180,7 +180,7 @@ test_expect_success 'prompt - interactive rebase' ' ' test_expect_success 'prompt - rebase merge' ' - printf " (b2|REBASE-i 1/3)" >expected && + printf " (b2|REBASE 1/3)" >expected && git checkout b2 && test_when_finished "git checkout master" && test_must_fail git rebase --merge b1 b2 && @@ -189,11 +189,11 @@ test_expect_success 'prompt - rebase merge' ' test_cmp expected "$actual" ' -test_expect_success 'prompt - rebase' ' +test_expect_success 'prompt - rebase am' ' printf " (b2|REBASE 1/3)" >expected && git checkout b2 && test_when_finished "git checkout master" && - test_must_fail git rebase b1 b2 && + test_must_fail git rebase --apply b1 b2 && 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 284c52d076..3103be8a32 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -905,7 +905,7 @@ test_expect_code () { # - not all diff versions understand "-u" test_cmp() { - $GIT_TEST_CMP "$@" + eval "$GIT_TEST_CMP" '"$@"' } # Check that the given config key has the expected value. @@ -1362,14 +1362,22 @@ nongit () { ) } 7>&2 2>&4 -# convert stdin to pktline representation; note that empty input becomes an -# empty packet, not a flush packet (for that you can just print 0000 yourself). +# convert function arguments or stdin (if not arguments given) to pktline +# representation. If multiple arguments are given, they are separated by +# whitespace and put in a single packet. Note that data containing NULs must be +# given on stdin, and that empty input becomes an empty packet, not a flush +# packet (for that you can just print 0000 yourself). packetize() { - cat >packetize.tmp && - len=$(wc -c <packetize.tmp) && - printf '%04x%s' "$(($len + 4))" && - cat packetize.tmp && - rm -f packetize.tmp + if test $# -gt 0 + then + packet="$*" + printf '%04x%s' "$((4 + ${#packet}))" "$packet" + else + perl -e ' + my $packet = do { local $/; <STDIN> }; + printf "%04x%s", 4 + length($packet), $packet; + ' + fi } # Parse the input as a series of pktlines, writing the result to stdout. @@ -1516,3 +1524,40 @@ test_set_port () { port=$(($port + ${GIT_TEST_STRESS_JOB_NR:-0})) eval $var=$port } + +# Compare a file containing rev-list bitmap traversal output to its non-bitmap +# counterpart. You can't just use test_cmp for this, because the two produce +# subtly different output: +# +# - regular output is in traversal order, whereas bitmap is split by type, +# with non-packed objects at the end +# +# - regular output has a space and the pathname appended to non-commit +# objects; bitmap output omits this +# +# This function normalizes and compares the two. The second file should +# always be the bitmap output. +test_bitmap_traversal () { + if test "$1" = "--no-confirm-bitmaps" + then + shift + elif cmp "$1" "$2" + then + echo >&2 "identical raw outputs; are you sure bitmaps were used?" + return 1 + fi && + cut -d' ' -f1 "$1" | sort >"$1.normalized" && + sort "$2" >"$2.normalized" && + test_cmp "$1.normalized" "$2.normalized" && + rm -f "$1.normalized" "$2.normalized" +} + +# Tests for the hidden file attribute on Windows +test_path_is_hidden () { + test_have_prereq MINGW || + BUG "test_path_is_hidden can only be used on Windows" + + # Use the output of `attrib`, ignore the absolute path + case "$("$SYSTEMROOT"/system32/attrib "$1")" in *H*?:*) return 0;; esac + return 1 +} diff --git a/t/test-lib.sh b/t/test-lib.sh index 44df51be8f..baf94546da 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -78,20 +78,23 @@ then exit 1 fi -# Parse options while taking care to leave $@ intact, so we will still -# have all the original command line options when executing the test -# script again for '--tee' and '--verbose-log' below. store_arg_to= -prev_opt= -for opt -do - if test -n "$store_arg_to" +opt_required_arg= +# $1: option string +# $2: name of the var where the arg will be stored +mark_option_requires_arg () { + if test -n "$opt_required_arg" then - eval $store_arg_to=\$opt - store_arg_to= - prev_opt= - continue + echo "error: options that require args cannot be bundled" \ + "together: '$opt_required_arg' and '$1'" >&2 + exit 1 fi + opt_required_arg=$1 + store_arg_to=$2 +} + +parse_option () { + local opt="$1" case "$opt" in -d|--d|--de|--deb|--debu|--debug) @@ -101,7 +104,7 @@ do -l|--l|--lo|--lon|--long|--long-|--long-t|--long-te|--long-tes|--long-test|--long-tests) GIT_TEST_LONG=t; export GIT_TEST_LONG ;; -r) - store_arg_to=run_list + mark_option_requires_arg "$opt" run_list ;; --run=*) run_list=${opt#--*=} ;; @@ -185,12 +188,42 @@ do *) echo "error: unknown test option '$opt'" >&2; exit 1 ;; esac +} - prev_opt=$opt +# Parse options while taking care to leave $@ intact, so we will still +# have all the original command line options when executing the test +# script again for '--tee' and '--verbose-log' later. +for opt +do + if test -n "$store_arg_to" + then + eval $store_arg_to=\$opt + store_arg_to= + opt_required_arg= + continue + fi + + case "$opt" in + --*|-?) + parse_option "$opt" ;; + -?*) + # bundled short options must be fed separately to parse_option + opt=${opt#-} + while test -n "$opt" + do + extra=${opt#?} + this=${opt%$extra} + opt=$extra + parse_option "-$this" + done + ;; + *) + echo "error: unknown test option '$opt'" >&2; exit 1 ;; + esac done if test -n "$store_arg_to" then - echo "error: $prev_opt requires an argument" >&2 + echo "error: $opt_required_arg requires an argument" >&2 exit 1 fi @@ -494,21 +527,6 @@ case $(echo $GIT_TRACE |tr "[A-Z]" "[a-z]") in ;; esac -# Convenience -# -# A regexp to match 5, 35 and 40 hexdigits -_x05='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' -_x35="$_x05$_x05$_x05$_x05$_x05$_x05$_x05" -_x40="$_x35$_x05" - -# Zero SHA-1 -_z40=0000000000000000000000000000000000000000 - -OID_REGEX="$_x40" -ZERO_OID=$_z40 -EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904 -EMPTY_BLOB=e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 - # Line feed LF=' ' @@ -657,6 +675,20 @@ die () { fi } +file_lineno () { + test -z "$GIT_TEST_FRAMEWORK_SELFTEST" && test -n "$BASH" || return 0 + eval ' + local i + for i in ${!BASH_SOURCE[*]} + do + case $i,"${BASH_SOURCE[$i]##*/}" in + 0,t[0-9]*.sh) echo "t/${BASH_SOURCE[$i]}:$LINENO: ${1+$1: }"; return;; + *,t[0-9]*.sh) echo "t/${BASH_SOURCE[$i]}:${BASH_LINENO[$(($i-1))]}: ${1+$1: }"; return;; + esac + done + ' +} + GIT_EXIT_OK= trap 'die' EXIT # Disable '-x' tracing, because with some shells, notably dash, it @@ -702,7 +734,7 @@ test_failure_ () { write_junit_xml_testcase "$1" " $junit_insert" fi test_failure=$(($test_failure + 1)) - say_color error "not ok $test_count - $1" + say_color error "$(file_lineno error)not ok $test_count - $1" shift printf '%s\n' "$*" | sed -e 's/^/# /' test "$immediate" = "" || { finalize_junit_xml; GIT_EXIT_OK=t; exit 1; } @@ -882,6 +914,7 @@ maybe_setup_valgrind () { fi } +trace_level_=0 want_trace () { test "$trace" = t && { test "$verbose" = t || test "$verbose_log" = t @@ -895,7 +928,7 @@ want_trace () { test_eval_inner_ () { # Do not add anything extra (including LF) after '$*' eval " - want_trace && set -x + want_trace && trace_level_=$(($trace_level_+1)) && set -x $*" } @@ -926,7 +959,8 @@ test_eval_ () { test_eval_ret_=$? if want_trace then - set +x + test 1 = $trace_level_ && set +x + trace_level_=$(($trace_level_-1)) fi } 2>/dev/null 4>&2 @@ -1083,7 +1117,9 @@ finalize_junit_xml () { # adjust the overall time junit_time=$(test-tool date getnanos $junit_suite_start) - sed "s/<testsuite [^>]*/& time=\"$junit_time\"/" \ + sed -e "s/\(<testsuite.*\) time=\"[^\"]*\"/\1/" \ + -e "s/<testsuite [^>]*/& time=\"$junit_time\"/" \ + -e '/^ *<\/testsuite/d' \ <"$junit_xml_path" >"$junit_xml_path.new" mv "$junit_xml_path.new" "$junit_xml_path" @@ -1382,6 +1418,20 @@ then fi fi +# Convenience +# A regexp to match 5, 35 and 40 hexdigits +_x05='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' +_x35="$_x05$_x05$_x05$_x05$_x05$_x05$_x05" +_x40="$_x35$_x05" + +test_oid_init + +ZERO_OID=$(test_oid zero) +OID_REGEX=$(echo $ZERO_OID | sed -e 's/0/[0-9a-f]/g') +EMPTY_TREE=$(test_oid empty_tree) +EMPTY_BLOB=$(test_oid empty_blob) +_z40=$ZERO_OID + # Provide an implementation of the 'yes' utility; the upper bound # limit is there to help Windows that cannot stop this loop from # wasting cycles when the downstream stops reading, so do not be @@ -1618,6 +1668,15 @@ test_lazy_prereq ULIMIT_STACK_SIZE ' run_with_limited_stack true ' +run_with_limited_open_files () { + (ulimit -n 32 && "$@") +} + +test_lazy_prereq ULIMIT_FILE_DESCRIPTORS ' + test_have_prereq !MINGW,!CYGWIN && + run_with_limited_open_files true +' + build_option () { git version --build-options | sed -ne "s/^$1: //p" |