diff options
Diffstat (limited to 't')
205 files changed, 4945 insertions, 1119 deletions
@@ -334,6 +334,15 @@ that cannot be easily covered by a few specific test cases. These could be enabled by running the test suite with correct GIT_TEST_ environment set. +GIT_TEST_FAIL_PREREQS<non-empty?> fails all prerequisites. This is +useful for discovering issues with the tests where say a later test +implicitly depends on an optional earlier test. + +There's a "FAIL_PREREQS" prerequisite that can be used to test for +whether this mode is active, and e.g. skip some tests that are hard to +refactor to deal with it. The "SYMLINKS" prerequisite is currently +excluded as so much relies on it, but this might change in the future. + GIT_TEST_GETTEXT_POISON=<non-empty?> turns all strings marked for translation into gibberish if non-empty (think "test -n"). Used for spotting those tests that need to be marked with a C_LOCALE_OUTPUT @@ -384,6 +393,10 @@ the --no-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_INDEX_THREADS=<n> enables exercising the multi-threaded loading of the index for the whole test suite by bypassing the default number of cache entries and thread minimums. Setting this to 1 will make the @@ -398,6 +411,10 @@ GIT_TEST_SIDEBAND_ALL=<boolean>, when true, overrides the fetch-pack to not request sideband-all (even if the server advertises sideband-all). +GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=<boolean>, when true (which is +the default when running tests), errors out when an abbreviated option +is used. + Naming Tests ------------ @@ -863,6 +880,26 @@ library for your script to use. ... ' + - test_atexit <script> + + Prepend <script> to a list of commands to run unconditionally to + clean up before the test script exits, e.g. to stop a daemon: + + test_expect_success 'test git daemon' ' + git daemon & + daemon_pid=$! && + test_atexit 'kill $daemon_pid' && + hello world + ' + + The commands will be executed before the trash directory is removed, + i.e. the atexit commands will still be able to access any pidfiles or + socket files. + + Note that these commands will be run even when a test script run + with '--immediate' fails. Be careful with your atexit commands to + minimize any changes to the failed state. + - test_write_lines <lines> Write <lines> on standard output, one line per argument. diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh index 6da48a2e0a..d933af5714 100644 --- a/t/annotate-tests.sh +++ b/t/annotate-tests.sh @@ -68,6 +68,14 @@ test_expect_success 'blame 1 author' ' check_count A 2 ' +test_expect_success 'blame in a bare repo without starting commit' ' + git clone --bare . bare.git && + ( + cd bare.git && + check_count A 2 + ) +' + test_expect_success 'blame by tag objects' ' git tag -m "test tag" testTag && git tag -m "test tag #2" testTag2 testTag && diff --git a/t/check-non-portable-shell.pl b/t/check-non-portable-shell.pl index 166d64d4a2..38bfeebd88 100755 --- a/t/check-non-portable-shell.pl +++ b/t/check-non-portable-shell.pl @@ -27,14 +27,14 @@ for my $i (@ARGV) { close $f; } +my $line = ''; while (<>) { chomp; + $line .= $_; # stitch together incomplete lines (those ending with "\") - while (s/\\$//) { - $_ .= readline; - chomp; - } + next if $line =~ s/\\$//; + $_ = $line; /\bcp\s+-a/ and err 'cp -a is not portable'; /\bsed\s+-[^efn]\s+/ and err 'sed option not portable (use only -n, -e, -f)'; /\becho\s+-[neE]/ and err 'echo with option is not portable (use printf)'; @@ -48,6 +48,7 @@ while (<>) { /\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 err '"FOO=bar shell_func" assignment extends beyond "shell_func"'; + $line = ''; # this resets our $. for each file close ARGV if eof; } diff --git a/t/helper/test-date.c b/t/helper/test-date.c index b3253803ac..585347ea48 100644 --- a/t/helper/test-date.c +++ b/t/helper/test-date.c @@ -55,7 +55,7 @@ static void show_dates(const char **argv, const char *format) } } -static void parse_dates(const char **argv, struct timeval *now) +static void parse_dates(const char **argv) { struct strbuf result = STRBUF_INIT; @@ -124,7 +124,7 @@ int cmd__date(int argc, const char **argv) else if (skip_prefix(*argv, "show:", &x)) show_dates(argv+1, x); else if (!strcmp(*argv, "parse")) - parse_dates(argv+1, &now); + parse_dates(argv+1); else if (!strcmp(*argv, "approxidate")) parse_approxidate(argv+1, &now); else if (!strcmp(*argv, "timestamp")) diff --git a/t/helper/test-example-decorate.c b/t/helper/test-example-decorate.c index a20a6161e4..c8a1cde7d2 100644 --- a/t/helper/test-example-decorate.c +++ b/t/helper/test-example-decorate.c @@ -26,8 +26,8 @@ int cmd__example_decorate(int argc, const char **argv) * Add 2 objects, one with a non-NULL decoration and one with a NULL * decoration. */ - one = lookup_unknown_object(one_oid.hash); - two = lookup_unknown_object(two_oid.hash); + one = lookup_unknown_object(&one_oid); + two = lookup_unknown_object(&two_oid); ret = add_decoration(&n, one, &decoration_a); if (ret) BUG("when adding a brand-new object, NULL should be returned"); @@ -56,7 +56,7 @@ int cmd__example_decorate(int argc, const char **argv) ret = lookup_decoration(&n, two); if (ret != &decoration_b) BUG("lookup should return added declaration"); - three = lookup_unknown_object(three_oid.hash); + three = lookup_unknown_object(&three_oid); ret = lookup_decoration(&n, three); if (ret) BUG("lookup for unknown object should return NULL"); diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c index cc88fba057..af82db06ac 100644 --- a/t/helper/test-parse-options.c +++ b/t/helper/test-parse-options.c @@ -132,7 +132,7 @@ int cmd__parse_options(int argc, const char **argv) OPT_NOOP_NOARG(0, "obsolete"), OPT_STRING_LIST(0, "list", &list, "str", "add str to list"), OPT_GROUP("Magic arguments"), - OPT_ARGUMENT("quux", "means --quux"), + OPT_ARGUMENT("quux", NULL, "means --quux"), OPT_NUMBER_CALLBACK(&integer, "set integer to NUM", number_callback), { OPTION_COUNTUP, '+', NULL, &boolean, NULL, "same as -b", @@ -149,6 +149,9 @@ int cmd__parse_options(int argc, const char **argv) OPT_CALLBACK(0, "expect", &expect, "string", "expected output in the variable dump", collect_expect), + OPT_GROUP("Alias"), + OPT_STRING('A', "alias-source", &string, "string", "get a string"), + OPT_ALIAS('Z', "alias-target", "alias-source"), OPT_END(), }; int i; diff --git a/t/helper/test-prio-queue.c b/t/helper/test-prio-queue.c index 5bc9c46ea5..f4028442e3 100644 --- a/t/helper/test-prio-queue.c +++ b/t/helper/test-prio-queue.c @@ -40,7 +40,7 @@ int cmd__prio_queue(int argc, const char **argv) } else if (!strcmp(*argv, "stack")) { pq.compare = NULL; } else { - int *v = malloc(sizeof(*v)); + int *v = xmalloc(sizeof(*v)); *v = atoi(*argv); prio_queue_put(&pq, v); } diff --git a/t/helper/test-read-cache.c b/t/helper/test-read-cache.c index d674c88ba0..7e79b555de 100644 --- a/t/helper/test-read-cache.c +++ b/t/helper/test-read-cache.c @@ -1,14 +1,36 @@ #include "test-tool.h" #include "cache.h" +#include "config.h" int cmd__read_cache(int argc, const char **argv) { - int i, cnt = 1; + int i, cnt = 1, namelen; + const char *name = NULL; + + if (argc > 1 && skip_prefix(argv[1], "--print-and-refresh=", &name)) { + namelen = strlen(name); + argc--; + argv++; + } + if (argc == 2) cnt = strtol(argv[1], NULL, 0); setup_git_directory(); + git_config(git_default_config, NULL); for (i = 0; i < cnt; i++) { read_cache(); + if (name) { + int pos; + + refresh_index(&the_index, REFRESH_QUIET, + NULL, NULL, NULL); + pos = index_name_pos(&the_index, name, namelen); + if (pos < 0) + die("%s not in index", name); + printf("%s is%s up to date\n", name, + ce_uptodate(the_index.cache[pos]) ? "" : " not"); + write_file(name, "%d\n", i); + } discard_cache(); } return 0; diff --git a/t/helper/test-serve-v2.c b/t/helper/test-serve-v2.c new file mode 100644 index 0000000000..aee35e5aef --- /dev/null +++ b/t/helper/test-serve-v2.c @@ -0,0 +1,31 @@ +#include "test-tool.h" +#include "cache.h" +#include "parse-options.h" +#include "serve.h" + +static char const * const serve_usage[] = { + N_("test-tool serve-v2 [<options>]"), + NULL +}; + +int cmd__serve_v2(int argc, const char **argv) +{ + struct serve_options opts = SERVE_OPTIONS_INIT; + + struct option options[] = { + OPT_BOOL(0, "stateless-rpc", &opts.stateless_rpc, + N_("quit after a single request/response exchange")), + OPT_BOOL(0, "advertise-capabilities", &opts.advertise_capabilities, + N_("exit immediately after advertising capabilities")), + OPT_END() + }; + const char *prefix = setup_git_directory(); + + /* ignore all unknown cmdline switches for now */ + argc = parse_options(argc, argv, prefix, options, serve_usage, + PARSE_OPT_KEEP_DASHDASH | + PARSE_OPT_KEEP_UNKNOWN); + serve(&opts); + + return 0; +} diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c index 53c06932c4..087a8c0cc9 100644 --- a/t/helper/test-tool.c +++ b/t/helper/test-tool.c @@ -1,6 +1,12 @@ #include "git-compat-util.h" #include "test-tool.h" #include "trace2.h" +#include "parse-options.h" + +static const char * const test_tool_usage[] = { + "test-tool [-C <directory>] <command [<arguments>...]]", + NULL +}; struct test_cmd { const char *name; @@ -43,6 +49,7 @@ static struct test_cmd cmds[] = { { "revision-walking", cmd__revision_walking }, { "run-command", cmd__run_command }, { "scrap-cache-tree", cmd__scrap_cache_tree }, + { "serve-v2", cmd__serve_v2 }, { "sha1", cmd__sha1 }, { "sha1-array", cmd__sha1_array }, { "sha256", cmd__sha256 }, @@ -75,11 +82,24 @@ static NORETURN void die_usage(void) int cmd_main(int argc, const char **argv) { int i; + const char *working_directory = NULL; + struct option options[] = { + OPT_STRING('C', NULL, &working_directory, "directory", + "change the working directory"), + OPT_END() + }; BUG_exit_code = 99; + argc = parse_options(argc, argv, NULL, options, test_tool_usage, + PARSE_OPT_STOP_AT_NON_OPTION | + PARSE_OPT_KEEP_ARGV0); + if (argc < 2) die_usage(); + if (working_directory && chdir(working_directory) < 0) + die("Could not cd to '%s'", working_directory); + for (i = 0; i < ARRAY_SIZE(cmds); i++) { if (!strcmp(cmds[i].name, argv[1])) { argv++; diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h index ffab4d19d7..7e703f3038 100644 --- a/t/helper/test-tool.h +++ b/t/helper/test-tool.h @@ -39,6 +39,7 @@ int cmd__repository(int argc, const char **argv); int cmd__revision_walking(int argc, const char **argv); 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__sha256(int argc, const char **argv); diff --git a/t/interop/i5500-git-daemon.sh b/t/interop/i5500-git-daemon.sh index 1daf69420b..4d22e42f84 100755 --- a/t/interop/i5500-git-daemon.sh +++ b/t/interop/i5500-git-daemon.sh @@ -37,5 +37,4 @@ test_expect_success "fetch with $VERSION_B" ' test_cmp expect actual ' -stop_git_daemon test_done diff --git a/t/lib-git-daemon.sh b/t/lib-git-daemon.sh index 79db3b7ae5..7b3407134e 100644 --- a/t/lib-git-daemon.sh +++ b/t/lib-git-daemon.sh @@ -13,7 +13,6 @@ # # test_expect_success ... # -# stop_git_daemon # test_done test_tristate GIT_TEST_GIT_DAEMON @@ -31,10 +30,12 @@ fi test_set_port LIB_GIT_DAEMON_PORT GIT_DAEMON_PID= +GIT_DAEMON_PIDFILE="$PWD"/daemon.pid GIT_DAEMON_DOCUMENT_ROOT_PATH="$PWD"/repo GIT_DAEMON_HOST_PORT=127.0.0.1:$LIB_GIT_DAEMON_PORT GIT_DAEMON_URL=git://$GIT_DAEMON_HOST_PORT +registered_stop_git_daemon_atexit_handler= start_git_daemon() { if test -n "$GIT_DAEMON_PID" then @@ -43,13 +44,19 @@ start_git_daemon() { mkdir -p "$GIT_DAEMON_DOCUMENT_ROOT_PATH" - trap 'code=$?; stop_git_daemon; (exit $code); die' EXIT + # One of the test scripts stops and then re-starts 'git daemon'. + # Don't register and then run the same atexit handlers several times. + if test -z "$registered_stop_git_daemon_atexit_handler" + then + test_atexit 'stop_git_daemon' + registered_stop_git_daemon_atexit_handler=AlreadyDone + fi say >&3 "Starting git daemon ..." mkfifo git_daemon_output ${LIB_GIT_DAEMON_COMMAND:-git daemon} \ --listen=127.0.0.1 --port="$LIB_GIT_DAEMON_PORT" \ - --reuseaddr --verbose \ + --reuseaddr --verbose --pid-file="$GIT_DAEMON_PIDFILE" \ --base-path="$GIT_DAEMON_DOCUMENT_ROOT_PATH" \ "$@" "$GIT_DAEMON_DOCUMENT_ROOT_PATH" \ >&3 2>git_daemon_output & @@ -65,7 +72,7 @@ start_git_daemon() { then kill "$GIT_DAEMON_PID" wait "$GIT_DAEMON_PID" - trap 'die' EXIT + unset GIT_DAEMON_PID test_skip_or_die $GIT_TEST_GIT_DAEMON \ "git daemon failed to start" fi @@ -77,8 +84,6 @@ stop_git_daemon() { return fi - trap 'die' EXIT - # kill git-daemon child of git say >&3 "Stopping git daemon ..." kill "$GIT_DAEMON_PID" @@ -88,8 +93,9 @@ stop_git_daemon() { then error "git daemon exited with status: $ret" fi + kill "$(cat "$GIT_DAEMON_PIDFILE")" 2>/dev/null GIT_DAEMON_PID= - rm -f git_daemon_output + rm -f git_daemon_output "$GIT_DAEMON_PIDFILE" } # A stripped-down version of a netcat client, that connects to a "host:port" diff --git a/t/lib-git-p4.sh b/t/lib-git-p4.sh index b3be3ba011..547b9f88e1 100644 --- a/t/lib-git-p4.sh +++ b/t/lib-git-p4.sh @@ -44,15 +44,6 @@ native_path () { echo "$path" } -# On Solaris the 'date +%s' function is not supported and therefore we -# need this replacement. -# Attention: This function is not safe again against time offset updates -# at runtime (e.g. via NTP). The 'clock_gettime(CLOCK_MONOTONIC)' -# function could fix that but it is not in Python until 3.3. -time_in_seconds () { - (cd / && "$PYTHON_PATH" -c 'import time; print(int(time.time()))') -} - test_set_port P4DPORT P4PORT=localhost:$P4DPORT @@ -67,14 +58,9 @@ cli="$TRASH_DIRECTORY/cli" git="$TRASH_DIRECTORY/git" pidfile="$TRASH_DIRECTORY/p4d.pid" -# Sometimes "prove" seems to hang on exit because p4d is still running -cleanup () { - if test -f "$pidfile" - then - kill -9 $(cat "$pidfile") 2>/dev/null && exit 255 - fi +stop_p4d_and_watchdog () { + kill -9 $p4d_pid $watchdog_pid } -trap cleanup EXIT # git p4 submit generates a temp file, which will # not get cleaned up if the submission fails. Don't @@ -82,7 +68,16 @@ trap cleanup EXIT TMPDIR="$TRASH_DIRECTORY" export TMPDIR +registered_stop_p4d_atexit_handler= start_p4d () { + # One of the test scripts stops and then re-starts p4d. + # Don't register and then run the same atexit handlers several times. + if test -z "$registered_stop_p4d_atexit_handler" + then + test_atexit 'stop_p4d_and_watchdog' + registered_stop_p4d_atexit_handler=AlreadyDone + fi + mkdir -p "$db" "$cli" "$git" && rm -f "$pidfile" && ( @@ -92,6 +87,7 @@ start_p4d () { echo $! >"$pidfile" } ) && + p4d_pid=$(cat "$pidfile") # This gives p4d a long time to start up, as it can be # quite slow depending on the machine. Set this environment @@ -99,18 +95,18 @@ start_p4d () { # an automated test setup. If the p4d process dies, that # will be caught with the "kill -0" check below. i=${P4D_START_PATIENCE:-300} - pid=$(cat "$pidfile") - timeout=$(($(time_in_seconds) + $P4D_TIMEOUT)) + nr_tries_left=$P4D_TIMEOUT while true do - if test $(time_in_seconds) -gt $timeout + if test $nr_tries_left -eq 0 then - kill -9 $pid + kill -9 $p4d_pid exit 1 fi sleep 1 - done & + nr_tries_left=$(($nr_tries_left - 1)) + done 2>/dev/null 4>&2 & watchdog_pid=$! ready= @@ -123,7 +119,7 @@ start_p4d () { break fi # fail if p4d died - kill -0 $pid 2>/dev/null || break + kill -0 $p4d_pid 2>/dev/null || break echo waiting for p4d to start sleep 1 i=$(( $i - 1 )) @@ -163,29 +159,18 @@ p4_add_job () { } retry_until_success () { - timeout=$(($(time_in_seconds) + $RETRY_TIMEOUT)) - until "$@" 2>/dev/null || test $(time_in_seconds) -gt $timeout - do - sleep 1 - done -} - -retry_until_fail () { - timeout=$(($(time_in_seconds) + $RETRY_TIMEOUT)) - until ! "$@" 2>/dev/null || test $(time_in_seconds) -gt $timeout + nr_tries_left=$RETRY_TIMEOUT + until "$@" 2>/dev/null || test $nr_tries_left -eq 0 do sleep 1 + nr_tries_left=$(($nr_tries_left - 1)) done } -kill_p4d () { - pid=$(cat "$pidfile") - retry_until_fail kill $pid - retry_until_fail kill -9 $pid - # complain if it would not die - test_must_fail kill $pid >/dev/null 2>&1 && - rm -rf "$db" "$cli" "$pidfile" && - retry_until_fail kill -9 $watchdog_pid +stop_and_cleanup_p4d () { + kill -9 $p4d_pid $watchdog_pid + wait $p4d_pid + rm -rf "$db" "$cli" "$pidfile" } cleanup_git () { diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh index f3b478c307..c1271d6863 100644 --- a/t/lib-git-svn.sh +++ b/t/lib-git-svn.sh @@ -76,11 +76,6 @@ maybe_start_httpd () { LIB_HTTPD_SVN="$loc" start_httpd ;; - *) - stop_httpd () { - : noop - } - ;; esac } diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh index 0dfb48c2f6..b3cc62bd36 100644 --- a/t/lib-httpd.sh +++ b/t/lib-httpd.sh @@ -14,7 +14,6 @@ # # test_expect_success ... # -# stop_httpd # test_done # # Can be configured using the following variables. @@ -176,7 +175,7 @@ prepare_httpd() { start_httpd() { prepare_httpd >&3 2>&4 - trap 'code=$?; stop_httpd; (exit $code); die' EXIT + test_atexit stop_httpd "$LIB_HTTPD_PATH" -d "$HTTPD_ROOT_PATH" \ -f "$TEST_PATH/apache.conf" $HTTPD_PARA \ @@ -184,15 +183,12 @@ start_httpd() { >&3 2>&4 if test $? -ne 0 then - trap 'die' EXIT cat "$HTTPD_ROOT_PATH"/error.log >&4 2>/dev/null test_skip_or_die $GIT_TEST_HTTPD "web server setup failed" fi } stop_httpd() { - trap 'die' EXIT - "$LIB_HTTPD_PATH" -d "$HTTPD_ROOT_PATH" \ -f "$TEST_PATH/apache.conf" $HTTPD_PARA -k stop } diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf index 06a81b54c7..5c1c86c193 100644 --- a/t/lib-httpd/apache.conf +++ b/t/lib-httpd/apache.conf @@ -76,6 +76,7 @@ PassEnv GIT_VALGRIND PassEnv GIT_VALGRIND_OPTIONS PassEnv GNUPGHOME PassEnv ASAN_OPTIONS +PassEnv LSAN_OPTIONS PassEnv GIT_TRACE PassEnv GIT_CONFIG_NOSYSTEM PassEnv GIT_TEST_SIDEBAND_ALL diff --git a/t/lib-patch-mode.sh b/t/lib-patch-mode.sh index 06c3c91762..cfd76bf987 100644 --- a/t/lib-patch-mode.sh +++ b/t/lib-patch-mode.sh @@ -2,28 +2,40 @@ . ./test-lib.sh +# set_state <path> <worktree-content> <index-content> +# +# Prepare the content for path in worktree and the index as specified. set_state () { echo "$3" > "$1" && git add "$1" && echo "$2" > "$1" } +# save_state <path> +# +# Save index/worktree content of <path> in the files _worktree_<path> +# and _index_<path> save_state () { noslash="$(echo "$1" | tr / _)" && cat "$1" > _worktree_"$noslash" && git show :"$1" > _index_"$noslash" } +# set_and_save_state <path> <worktree-content> <index-content> set_and_save_state () { set_state "$@" && save_state "$1" } +# verify_state <path> <expected-worktree-content> <expected-index-content> verify_state () { test "$(cat "$1")" = "$2" && test "$(git show :"$1")" = "$3" } +# verify_saved_state <path> +# +# Call verify_state with expected contents from the last save_state verify_saved_state () { noslash="$(echo "$1" | tr / _)" && verify_state "$1" "$(cat _worktree_"$noslash")" "$(cat _index_"$noslash")" diff --git a/t/lib-submodule-update.sh b/t/lib-submodule-update.sh index 5b56b23166..1dd17fc03e 100755 --- a/t/lib-submodule-update.sh +++ b/t/lib-submodule-update.sh @@ -139,7 +139,7 @@ create_lib_submodule_repo () { git revert HEAD && git checkout -b invalid_sub1 add_sub1 && - git update-index --cacheinfo 160000 0123456789012345678901234567890123456789 sub1 && + git update-index --cacheinfo 160000 $(test_oid numeric) sub1 && git commit -m "Invalid sub1 commit" && git checkout -b valid_sub1 && git revert HEAD && @@ -196,6 +196,7 @@ test_git_directory_exists() { # the submodule repo if it doesn't exist and configures the most problematic # settings for diff.ignoreSubmodules. prolog () { + test_oid_init && (test -d submodule_update_repo || create_lib_submodule_repo) && test_config_global diff.ignoreSubmodules all && test_config diff.ignoreSubmodules all diff --git a/t/perf/README b/t/perf/README index be12090c38..c7b70e2d28 100644 --- a/t/perf/README +++ b/t/perf/README @@ -45,7 +45,7 @@ call the aggregation script to summarize the results: $ ./p0001-rev-list.sh [...] - $ GIT_BUILD_DIR=/path/to/other/git ./p0001-rev-list.sh + $ ./run /path/to/other/git -- ./p0001-rev-list.sh [...] $ ./aggregate.perl . /path/to/other/git ./p0001-rev-list.sh diff --git a/t/perf/aggregate.perl b/t/perf/aggregate.perl index 494907a892..66554d2161 100755 --- a/t/perf/aggregate.perl +++ b/t/perf/aggregate.perl @@ -3,9 +3,9 @@ use lib '../../perl/build/lib'; use strict; use warnings; -use JSON; use Getopt::Long; use Git; +use Cwd qw(realpath); sub get_times { my $name = shift; @@ -99,18 +99,21 @@ usage() unless $rc; while (scalar @ARGV) { my $arg = $ARGV[0]; my $dir; + my $prefix = ''; last if -f $arg or $arg eq "--"; if (! -d $arg) { my $rev = Git::command_oneline(qw(rev-parse --verify), $arg); $dir = "build/".$rev; + } elsif ($arg eq '.') { + $dir = '.'; } else { - $arg =~ s{/*$}{}; - $dir = $arg; - $dirabbrevs{$dir} = $dir; + $dir = realpath($arg); + $dirnames{$dir} = $dir; + $prefix .= 'bindir'; } push @dirs, $dir; - $dirnames{$dir} = $arg; - my $prefix = $dir; + $dirnames{$dir} ||= $arg; + $prefix .= $dir; $prefix =~ tr/^a-zA-Z0-9/_/c; $prefixes{$dir} = $prefix . '.'; shift @ARGV; @@ -312,9 +315,6 @@ sub print_codespeed_results { $environment = $reponame; } elsif (exists $ENV{GIT_PERF_REPO_NAME} and $ENV{GIT_PERF_REPO_NAME} ne "") { $environment = $ENV{GIT_PERF_REPO_NAME}; - } elsif (exists $ENV{GIT_TEST_INSTALLED} and $ENV{GIT_TEST_INSTALLED} ne "") { - $environment = $ENV{GIT_TEST_INSTALLED}; - $environment =~ s|/bin-wrappers$||; } else { $environment = `uname -r`; chomp $environment; @@ -342,7 +342,8 @@ sub print_codespeed_results { } } - print to_json(\@data, {utf8 => 1, pretty => 1, canonical => 1}), "\n"; + require JSON; + print JSON::to_json(\@data, {utf8 => 1, pretty => 1, canonical => 1}), "\n"; } binmode STDOUT, ":utf8" or die "PANIC on binmode: $!"; diff --git a/t/perf/p0001-rev-list.sh b/t/perf/p0001-rev-list.sh index ebf172401b..3042a85666 100755 --- a/t/perf/p0001-rev-list.sh +++ b/t/perf/p0001-rev-list.sh @@ -14,6 +14,24 @@ test_perf 'rev-list --all --objects' ' git rev-list --all --objects >/dev/null ' +test_perf 'rev-list --parents' ' + git rev-list --parents HEAD >/dev/null +' + +test_expect_success 'create dummy file' ' + echo unlikely-to-already-be-there >dummy && + git add dummy && + git commit -m dummy +' + +test_perf 'rev-list -- dummy' ' + git rev-list HEAD -- dummy +' + +test_perf 'rev-list --parents -- dummy' ' + git rev-list --parents HEAD -- dummy +' + test_expect_success 'create new unreferenced commit' ' commit=$(git commit-tree HEAD^{tree} -p HEAD) && test_export commit diff --git a/t/perf/p5302-pack-index.sh b/t/perf/p5302-pack-index.sh index 99bdb16c85..a9b3e112d9 100755 --- a/t/perf/p5302-pack-index.sh +++ b/t/perf/p5302-pack-index.sh @@ -13,35 +13,40 @@ test_expect_success 'repack' ' export PACK ' -test_expect_success 'create target repositories' ' - for repo in t1 t2 t3 t4 t5 t6 - do - git init --bare $repo - done -' - test_perf 'index-pack 0 threads' ' - GIT_DIR=t1 git index-pack --threads=1 --stdin < $PACK + rm -rf repo.git && + git init --bare repo.git && + GIT_DIR=repo.git git index-pack --threads=1 --stdin < $PACK ' test_perf 'index-pack 1 thread ' ' - GIT_DIR=t2 GIT_FORCE_THREADS=1 git index-pack --threads=1 --stdin < $PACK + rm -rf repo.git && + git init --bare repo.git && + GIT_DIR=repo.git GIT_FORCE_THREADS=1 git index-pack --threads=1 --stdin < $PACK ' test_perf 'index-pack 2 threads' ' - GIT_DIR=t3 git index-pack --threads=2 --stdin < $PACK + rm -rf repo.git && + git init --bare repo.git && + GIT_DIR=repo.git git index-pack --threads=2 --stdin < $PACK ' test_perf 'index-pack 4 threads' ' - GIT_DIR=t4 git index-pack --threads=4 --stdin < $PACK + rm -rf repo.git && + git init --bare repo.git && + GIT_DIR=repo.git git index-pack --threads=4 --stdin < $PACK ' test_perf 'index-pack 8 threads' ' - GIT_DIR=t5 git index-pack --threads=8 --stdin < $PACK + rm -rf repo.git && + git init --bare repo.git && + GIT_DIR=repo.git git index-pack --threads=8 --stdin < $PACK ' test_perf 'index-pack default number of threads' ' - GIT_DIR=t6 git index-pack --stdin < $PACK + rm -rf repo.git && + git init --bare repo.git && + GIT_DIR=repo.git git index-pack --stdin < $PACK ' test_done diff --git a/t/perf/p5310-pack-bitmaps.sh b/t/perf/p5310-pack-bitmaps.sh index bb91dbb173..6a3a42531b 100755 --- a/t/perf/p5310-pack-bitmaps.sh +++ b/t/perf/p5310-pack-bitmaps.sh @@ -12,8 +12,7 @@ test_perf_large_repo # We intentionally use the deprecated pack.writebitmaps # config so that we can test against older versions of git. test_expect_success 'setup bitmap config' ' - git config pack.writebitmaps true && - git config pack.writebitmaphashcache true + git config pack.writebitmaps true ' test_perf 'repack to disk' ' diff --git a/t/perf/p5311-pack-bitmaps-fetch.sh b/t/perf/p5311-pack-bitmaps-fetch.sh index b04575951f..47c3fd7581 100755 --- a/t/perf/p5311-pack-bitmaps-fetch.sh +++ b/t/perf/p5311-pack-bitmaps-fetch.sh @@ -7,7 +7,6 @@ test_perf_default_repo test_expect_success 'create bitmapped server repo' ' git config pack.writebitmaps true && - git config pack.writebitmaphashcache true && git repack -ad ' diff --git a/t/perf/p5600-partial-clone.sh b/t/perf/p5600-partial-clone.sh new file mode 100755 index 0000000000..3e04bd2ae1 --- /dev/null +++ b/t/perf/p5600-partial-clone.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +test_description='performance of partial clones' +. ./perf-lib.sh + +test_perf_default_repo + +test_expect_success 'enable server-side config' ' + git config uploadpack.allowFilter true && + git config uploadpack.allowAnySHA1InWant true +' + +test_perf 'clone without blobs' ' + rm -rf bare.git && + git clone --no-local --bare --filter=blob:none . bare.git +' + +test_perf 'checkout of result' ' + rm -rf worktree && + mkdir -p worktree/.git && + tar -C bare.git -cf - . | tar -C worktree/.git -xf - && + git -C worktree config core.bare false && + git -C worktree checkout -f +' + +test_done diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh index 169f92eae3..b58a43ea43 100644 --- a/t/perf/perf-lib.sh +++ b/t/perf/perf-lib.sh @@ -21,19 +21,21 @@ # because it will change our working directory. TEST_DIRECTORY=$(pwd)/.. TEST_OUTPUT_DIRECTORY=$(pwd) -ABSOLUTE_GIT_TEST_INSTALLED=$( - test -n "$GIT_TEST_INSTALLED" && cd "$GIT_TEST_INSTALLED" && pwd) TEST_NO_CREATE_REPO=t TEST_NO_MALLOC_CHECK=t . ../test-lib.sh -if test -z "$GIT_TEST_INSTALLED"; then - perf_results_prefix= -else - perf_results_prefix=$(printf "%s" "${GIT_TEST_INSTALLED%/bin-wrappers}" | tr -c "[a-zA-Z0-9]" "[_*]")"." - GIT_TEST_INSTALLED=$ABSOLUTE_GIT_TEST_INSTALLED +if test -n "$GIT_TEST_INSTALLED" -a -z "$PERF_SET_GIT_TEST_INSTALLED" +then + error "Do not use GIT_TEST_INSTALLED with the perf tests. + +Instead use: + + ./run <path-to-git> -- <tests> + +See t/perf/README for details." fi # Variables from test-lib that are normally internal to the tests; we @@ -179,7 +181,7 @@ test_wrapper_ () { base=$(basename "$0" .sh) echo "$test_count" >>"$perf_results_dir"/$base.subtests echo "$1" >"$perf_results_dir"/$base.$test_count.descr - base="$perf_results_dir"/"$perf_results_prefix$(basename "$0" .sh)"."$test_count" + base="$perf_results_dir"/"$PERF_RESULTS_PREFIX$(basename "$0" .sh)"."$test_count" "$test_wrapper_func_" "$@" fi diff --git a/t/perf/run b/t/perf/run index 9aaa733c77..c7b86104e1 100755 --- a/t/perf/run +++ b/t/perf/run @@ -70,6 +70,24 @@ build_git_rev () { ) || die "failed to build revision '$mydir'" } +set_git_test_installed () { + mydir=$1 + + mydir_abs=$(cd $mydir && pwd) + mydir_abs_wrappers="$mydir_abs_wrappers/bin-wrappers" + if test -d "$mydir_abs_wrappers" + then + GIT_TEST_INSTALLED=$mydir_abs_wrappers + else + # Older versions of git lacked bin-wrappers; + # fallback to the files in the root. + GIT_TEST_INSTALLED=$mydir_abs + fi + export GIT_TEST_INSTALLED + PERF_SET_GIT_TEST_INSTALLED=true + export PERF_SET_GIT_TEST_INSTALLED +} + run_dirs_helper () { mydir=${1%/} shift @@ -79,7 +97,16 @@ run_dirs_helper () { if test $# -gt 0 -a "$1" = --; then shift fi - if [ ! -d "$mydir" ]; then + + PERF_RESULTS_PREFIX= + if test "$mydir" = "." + then + unset GIT_TEST_INSTALLED + elif test -d "$mydir" + then + PERF_RESULTS_PREFIX=bindir$(cd $mydir && printf "%s" "$(pwd)" | tr -c "[a-zA-Z0-9]" "_"). + set_git_test_installed "$mydir" + else rev=$(git rev-parse --verify "$mydir" 2>/dev/null) || die "'$mydir' is neither a directory nor a valid revision" if [ ! -d build/$rev ]; then @@ -87,16 +114,12 @@ run_dirs_helper () { fi build_git_rev $rev "$mydir" mydir=build/$rev + + PERF_RESULTS_PREFIX=build_$rev. + set_git_test_installed "$mydir" fi - if test "$mydir" = .; then - unset GIT_TEST_INSTALLED - else - GIT_TEST_INSTALLED="$mydir/bin-wrappers" - # Older versions of git lacked bin-wrappers; fallback to the - # files in the root. - test -d "$GIT_TEST_INSTALLED" || GIT_TEST_INSTALLED=$mydir - export GIT_TEST_INSTALLED - fi + export PERF_RESULTS_PREFIX + run_one_dir "$@" } diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index b6566003dd..31de7e90f3 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -726,7 +726,7 @@ donthaveit=yes test_expect_success DONTHAVEIT 'unmet prerequisite causes test to be skipped' ' donthaveit=no ' -if test $haveit$donthaveit != yesyes +if test -z "$GIT_TEST_FAIL_PREREQS" -a $haveit$donthaveit != yesyes then say "bug in test framework: prerequisite tags do not work reliably" exit 1 @@ -747,7 +747,7 @@ donthaveiteither=yes test_expect_success DONTHAVEIT,HAVEIT 'unmet prerequisites causes test to be skipped' ' donthaveiteither=no ' -if test $haveit$donthaveit$donthaveiteither != yesyesyes +if test -z "$GIT_TEST_FAIL_PREREQS" -a $haveit$donthaveit$donthaveiteither != yesyesyes then say "bug in test framework: multiple prerequisite tags do not work reliably" exit 1 @@ -763,7 +763,7 @@ test_expect_success !LAZY_TRUE 'missing lazy prereqs skip tests' ' donthavetrue=no ' -if test "$havetrue$donthavetrue" != yesyes +if test -z "$GIT_TEST_FAIL_PREREQS" -a "$havetrue$donthavetrue" != yesyes then say 'bug in test framework: lazy prerequisites do not work' exit 1 @@ -779,7 +779,7 @@ test_expect_success LAZY_FALSE 'missing negative lazy prereqs will skip' ' havefalse=no ' -if test "$nothavefalse$havefalse" != yesyes +if test -z "$GIT_TEST_FAIL_PREREQS" -a "$nothavefalse$havefalse" != yesyes then say 'bug in test framework: negative lazy prerequisites do not work' exit 1 @@ -790,7 +790,7 @@ test_expect_success 'tests clean up after themselves' ' test_when_finished clean=yes ' -if test $clean != yes +if test -z "$GIT_TEST_FAIL_PREREQS" -a $clean != yes then say "bug in test framework: basic cleanup command does not work reliably" exit 1 @@ -825,6 +825,24 @@ test_expect_success 'tests clean up even on failures' " EOF " +test_expect_success 'test_atexit is run' " + test_must_fail run_sub_test_lib_test \ + atexit-cleanup 'Run atexit commands' -i <<-\\EOF && + test_expect_success 'tests clean up even after a failure' ' + > ../../clean-atexit && + test_atexit rm ../../clean-atexit && + > ../../also-clean-atexit && + test_atexit rm ../../also-clean-atexit && + > ../../dont-clean-atexit && + (exit 1) + ' + test_done + EOF + test_path_is_file dont-clean-atexit && + test_path_is_missing clean-atexit && + test_path_is_missing also-clean-atexit +" + test_expect_success 'test_oid setup' ' test_oid_init ' diff --git a/t/t0001-init.sh b/t/t0001-init.sh index 1f462204ea..0276d14a0b 100755 --- a/t/t0001-init.sh +++ b/t/t0001-init.sh @@ -93,7 +93,7 @@ test_expect_success 'No extra GIT_* on alias scripts' ' sed -n \ -e "/^GIT_PREFIX=/d" \ -e "/^GIT_TEXTDOMAINDIR=/d" \ - -e "/^GIT_TR2_PARENT/d" \ + -e "/^GIT_TRACE2_PARENT/d" \ -e "/^GIT_/s/=.*//p" | sort EOF @@ -175,7 +175,7 @@ test_expect_success 'reinit' ' test_expect_success 'init with --template' ' mkdir template-source && echo content >template-source/file && - git init --template=../template-source template-custom && + git init --template=template-source template-custom && test_cmp template-source/file template-custom/.git/file ' diff --git a/t/t0007-git-var.sh b/t/t0007-git-var.sh index 5868a87352..1f600e2cae 100755 --- a/t/t0007-git-var.sh +++ b/t/t0007-git-var.sh @@ -17,7 +17,7 @@ test_expect_success 'get GIT_COMMITTER_IDENT' ' test_cmp expect actual ' -test_expect_success !AUTOIDENT 'requested identites are strict' ' +test_expect_success !FAIL_PREREQS,!AUTOIDENT 'requested identites are strict' ' ( sane_unset GIT_COMMITTER_NAME && sane_unset GIT_COMMITTER_EMAIL && diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh index b8f366c442..cebc77fab0 100755 --- a/t/t0040-parse-options.sh +++ b/t/t0040-parse-options.sh @@ -48,6 +48,12 @@ Standard options -q, --quiet be quiet --expect <string> expected output in the variable dump +Alias + -A, --alias-source <string> + get a string + -Z, --alias-target <string> + get a string + EOF test_expect_success 'test help' ' @@ -203,23 +209,38 @@ file: (not set) EOF test_expect_success 'unambiguously abbreviated option' ' + GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \ test-tool parse-options --int 2 --boolean --no-bo >output 2>output.err && test_must_be_empty output.err && test_cmp expect output ' test_expect_success 'unambiguously abbreviated option with "="' ' + GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \ test-tool parse-options --expect="integer: 2" --int=2 ' test_expect_success 'ambiguously abbreviated option' ' - test_expect_code 129 test-tool parse-options --strin 123 + test_expect_code 129 env GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \ + test-tool parse-options --strin 123 ' test_expect_success 'non ambiguous option (after two options it abbreviates)' ' + GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \ test-tool parse-options --expect="string: 123" --st 123 ' +test_expect_success 'Alias options do not contribute to abbreviation' ' + test-tool parse-options --alias-source 123 >output && + grep "^string: 123" output && + test-tool parse-options --alias-target 123 >output && + grep "^string: 123" output && + test_must_fail test-tool parse-options --alias && + GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \ + test-tool parse-options --alias 123 >output && + grep "^string: 123" output +' + cat >typo.err <<\EOF error: did you mean `--boolean` (with two dashes ?) EOF @@ -325,6 +346,7 @@ file: (not set) EOF test_expect_success 'negation of OPT_NONEG flags is not ambiguous' ' + GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \ test-tool parse-options --no-ambig >output 2>output.err && test_must_be_empty output.err && test_cmp expect output @@ -370,4 +392,11 @@ test_expect_success '--no-verbose resets multiple verbose to 0' ' test-tool parse-options --expect="verbose: 0" -v -v -v --no-verbose ' +test_expect_success 'GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS works' ' + GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=false \ + test-tool parse-options --ye && + test_must_fail env GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=true \ + test-tool parse-options --ye +' + test_done diff --git a/t/t0210-trace2-normal.sh b/t/t0210-trace2-normal.sh index 03a0aedb1d..ce7574edb1 100755 --- a/t/t0210-trace2-normal.sh +++ b/t/t0210-trace2-normal.sh @@ -3,6 +3,11 @@ test_description='test trace2 facility (normal target)' . ./test-lib.sh +# Turn off any inherited trace2 settings for this test. +sane_unset GIT_TRACE2 GIT_TRACE2_PERF GIT_TRACE2_EVENT +sane_unset GIT_TRACE2_BRIEF +sane_unset GIT_TRACE2_CONFIG_PARAMS + # Add t/helper directory to PATH so that we can use a relative # path to run nested instances of test-tool.exe (see 004child). # This helps with HEREDOC comparisons later. @@ -15,11 +20,6 @@ PATH="$TTDIR:$PATH" && export PATH # Warning: So you may see extra lines in artifact files when # Warning: interactively debugging. -# Turn off any inherited trace2 settings for this test. -unset GIT_TR2 GIT_TR2_PERF GIT_TR2_EVENT -unset GIT_TR2_BRIEF -unset GIT_TR2_CONFIG_PARAMS - V=$(git version | sed -e 's/^git version //') && export V # There are multiple trace2 targets: normal, perf, and event. @@ -27,12 +27,12 @@ V=$(git version | sed -e 's/^git version //') && export V # to whatever filtering that target decides to do). # This script tests the normal target in isolation. # -# Defer setting GIT_TR2 until the actual command line we want to test +# Defer setting GIT_TRACE2 until the actual command line we want to test # because hidden git and test-tool commands run by the test harness # can contaminate our output. # Enable "brief" feature which turns off "<clock> <file>:<line> " prefix. -GIT_TR2_BRIEF=1 && export GIT_TR2_BRIEF +GIT_TRACE2_BRIEF=1 && export GIT_TRACE2_BRIEF # Basic tests of the trace2 normal stream. Since this stream is used # primarily with printf-style debugging/tracing, we do limited testing @@ -54,7 +54,7 @@ GIT_TR2_BRIEF=1 && export GIT_TR2_BRIEF test_expect_success 'normal stream, return code 0' ' test_when_finished "rm trace.normal actual expect" && - GIT_TR2="$(pwd)/trace.normal" test-tool trace2 001return 0 && + GIT_TRACE2="$(pwd)/trace.normal" test-tool trace2 001return 0 && perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual && cat >expect <<-EOF && version $V @@ -68,7 +68,7 @@ test_expect_success 'normal stream, return code 0' ' test_expect_success 'normal stream, return code 1' ' test_when_finished "rm trace.normal actual expect" && - test_must_fail env GIT_TR2="$(pwd)/trace.normal" test-tool trace2 001return 1 && + test_must_fail env GIT_TRACE2="$(pwd)/trace.normal" test-tool trace2 001return 1 && perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual && cat >expect <<-EOF && version $V @@ -80,13 +80,28 @@ test_expect_success 'normal stream, return code 1' ' test_cmp expect actual ' +test_expect_success 'automatic filename' ' + test_when_finished "rm -r traces actual expect" && + mkdir traces && + GIT_TRACE2="$(pwd)/traces" test-tool trace2 001return 0 && + perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <"$(ls traces/*)" >actual && + cat >expect <<-EOF && + version $V + start _EXE_ trace2 001return 0 + cmd_name trace2 (trace2) + exit elapsed:_TIME_ code:0 + atexit elapsed:_TIME_ code:0 + EOF + test_cmp expect actual +' + # Verb 002exit # # Explicit exit(code) from within cmd_<verb> propagates <code>. test_expect_success 'normal stream, exit code 0' ' test_when_finished "rm trace.normal actual expect" && - GIT_TR2="$(pwd)/trace.normal" test-tool trace2 002exit 0 && + GIT_TRACE2="$(pwd)/trace.normal" test-tool trace2 002exit 0 && perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual && cat >expect <<-EOF && version $V @@ -100,7 +115,7 @@ test_expect_success 'normal stream, exit code 0' ' test_expect_success 'normal stream, exit code 1' ' test_when_finished "rm trace.normal actual expect" && - test_must_fail env GIT_TR2="$(pwd)/trace.normal" test-tool trace2 002exit 1 && + test_must_fail env GIT_TRACE2="$(pwd)/trace.normal" test-tool trace2 002exit 1 && perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual && cat >expect <<-EOF && version $V @@ -118,7 +133,7 @@ test_expect_success 'normal stream, exit code 1' ' test_expect_success 'normal stream, error event' ' test_when_finished "rm trace.normal actual expect" && - GIT_TR2="$(pwd)/trace.normal" test-tool trace2 003error "hello world" "this is a test" && + GIT_TRACE2="$(pwd)/trace.normal" test-tool trace2 003error "hello world" "this is a test" && perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual && cat >expect <<-EOF && version $V @@ -132,4 +147,43 @@ test_expect_success 'normal stream, error event' ' test_cmp expect actual ' +sane_unset GIT_TRACE2_BRIEF + +# Now test without environment variables and get all Trace2 settings +# from the global config. + +test_expect_success 'using global config, normal stream, return code 0' ' + test_when_finished "rm trace.normal actual expect" && + test_config_global trace2.normalBrief 1 && + test_config_global trace2.normalTarget "$(pwd)/trace.normal" && + test-tool trace2 001return 0 && + perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual && + cat >expect <<-EOF && + version $V + start _EXE_ trace2 001return 0 + cmd_name trace2 (trace2) + exit elapsed:_TIME_ code:0 + atexit elapsed:_TIME_ code:0 + EOF + test_cmp expect actual +' + +test_expect_success 'using global config with include' ' + test_when_finished "rm trace.normal actual expect real.gitconfig" && + test_config_global trace2.normalBrief 1 && + test_config_global trace2.normalTarget "$(pwd)/trace.normal" && + mv "$(pwd)/.gitconfig" "$(pwd)/real.gitconfig" && + test_config_global include.path "$(pwd)/real.gitconfig" && + test-tool trace2 001return 0 && + perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual && + cat >expect <<-EOF && + version $V + start _EXE_ trace2 001return 0 + cmd_name trace2 (trace2) + exit elapsed:_TIME_ code:0 + atexit elapsed:_TIME_ code:0 + EOF + test_cmp expect actual +' + test_done diff --git a/t/t0211-trace2-perf.sh b/t/t0211-trace2-perf.sh index 953e2f7847..2c3ad6e8c1 100755 --- a/t/t0211-trace2-perf.sh +++ b/t/t0211-trace2-perf.sh @@ -3,6 +3,11 @@ test_description='test trace2 facility (perf target)' . ./test-lib.sh +# 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 + # Add t/helper directory to PATH so that we can use a relative # path to run nested instances of test-tool.exe (see 004child). # This helps with HEREDOC comparisons later. @@ -15,11 +20,6 @@ PATH="$TTDIR:$PATH" && export PATH # Warning: So you may see extra lines in artifact files when # Warning: interactively debugging. -# Turn off any inherited trace2 settings for this test. -unset GIT_TR2 GIT_TR2_PERF GIT_TR2_EVENT -unset GIT_TR2_PERF_BRIEF -unset GIT_TR2_CONFIG_PARAMS - V=$(git version | sed -e 's/^git version //') && export V # There are multiple trace2 targets: normal, perf, and event. @@ -27,13 +27,13 @@ V=$(git version | sed -e 's/^git version //') && export V # to whatever filtering that target decides to do). # Test each target independently. # -# Defer setting GIT_TR2_PERF until the actual command we want to +# Defer setting GIT_TRACE2_PERF until the actual command we want to # test because hidden git and test-tool commands in the test # harness can contaminate our output. # Enable "brief" feature which turns off the prefix: # "<clock> <file>:<line> | <nr_parents> | " -GIT_TR2_PERF_BRIEF=1 && export GIT_TR2_PERF_BRIEF +GIT_TRACE2_PERF_BRIEF=1 && export GIT_TRACE2_PERF_BRIEF # Repeat some of the t0210 tests using the perf target stream instead of # the normal stream. @@ -46,11 +46,11 @@ GIT_TR2_PERF_BRIEF=1 && export GIT_TR2_PERF_BRIEF test_expect_success 'perf stream, return code 0' ' test_when_finished "rm trace.perf actual expect" && - GIT_TR2_PERF="$(pwd)/trace.perf" test-tool trace2 001return 0 && + GIT_TRACE2_PERF="$(pwd)/trace.perf" test-tool trace2 001return 0 && perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <trace.perf >actual && cat >expect <<-EOF && d0|main|version|||||$V - d0|main|start|||||_EXE_ trace2 001return 0 + d0|main|start||_T_ABS_|||_EXE_ trace2 001return 0 d0|main|cmd_name|||||trace2 (trace2) d0|main|exit||_T_ABS_|||code:0 d0|main|atexit||_T_ABS_|||code:0 @@ -60,11 +60,11 @@ test_expect_success 'perf stream, return code 0' ' test_expect_success 'perf stream, return code 1' ' test_when_finished "rm trace.perf actual expect" && - test_must_fail env GIT_TR2_PERF="$(pwd)/trace.perf" test-tool trace2 001return 1 && + test_must_fail env GIT_TRACE2_PERF="$(pwd)/trace.perf" test-tool trace2 001return 1 && perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <trace.perf >actual && cat >expect <<-EOF && d0|main|version|||||$V - d0|main|start|||||_EXE_ trace2 001return 1 + d0|main|start||_T_ABS_|||_EXE_ trace2 001return 1 d0|main|cmd_name|||||trace2 (trace2) d0|main|exit||_T_ABS_|||code:1 d0|main|atexit||_T_ABS_|||code:1 @@ -78,11 +78,11 @@ test_expect_success 'perf stream, return code 1' ' test_expect_success 'perf stream, error event' ' test_when_finished "rm trace.perf actual expect" && - GIT_TR2_PERF="$(pwd)/trace.perf" test-tool trace2 003error "hello world" "this is a test" && + GIT_TRACE2_PERF="$(pwd)/trace.perf" test-tool trace2 003error "hello world" "this is a test" && perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <trace.perf >actual && cat >expect <<-EOF && d0|main|version|||||$V - d0|main|start|||||_EXE_ trace2 003error '\''hello world'\'' '\''this is a test'\'' + d0|main|start||_T_ABS_|||_EXE_ trace2 003error '\''hello world'\'' '\''this is a test'\'' d0|main|cmd_name|||||trace2 (trace2) d0|main|error|||||hello world d0|main|error|||||this is a test @@ -124,19 +124,19 @@ test_expect_success 'perf stream, error event' ' test_expect_success 'perf stream, child processes' ' test_when_finished "rm trace.perf actual expect" && - GIT_TR2_PERF="$(pwd)/trace.perf" test-tool trace2 004child test-tool trace2 004child test-tool trace2 001return 0 && + GIT_TRACE2_PERF="$(pwd)/trace.perf" test-tool trace2 004child test-tool trace2 004child test-tool trace2 001return 0 && perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <trace.perf >actual && cat >expect <<-EOF && d0|main|version|||||$V - d0|main|start|||||_EXE_ trace2 004child test-tool trace2 004child test-tool trace2 001return 0 + d0|main|start||_T_ABS_|||_EXE_ trace2 004child test-tool trace2 004child test-tool trace2 001return 0 d0|main|cmd_name|||||trace2 (trace2) d0|main|child_start||_T_ABS_|||[ch0] class:? argv: test-tool trace2 004child test-tool trace2 001return 0 d1|main|version|||||$V - d1|main|start|||||_EXE_ trace2 004child test-tool trace2 001return 0 + d1|main|start||_T_ABS_|||_EXE_ trace2 004child test-tool trace2 001return 0 d1|main|cmd_name|||||trace2 (trace2/trace2) d1|main|child_start||_T_ABS_|||[ch0] class:? argv: test-tool trace2 001return 0 d2|main|version|||||$V - d2|main|start|||||_EXE_ trace2 001return 0 + d2|main|start||_T_ABS_|||_EXE_ trace2 001return 0 d2|main|cmd_name|||||trace2 (trace2/trace2/trace2) d2|main|exit||_T_ABS_|||code:0 d2|main|atexit||_T_ABS_|||code:0 @@ -150,4 +150,25 @@ test_expect_success 'perf stream, child processes' ' test_cmp expect actual ' +sane_unset GIT_TRACE2_PERF_BRIEF + +# Now test without environment variables and get all Trace2 settings +# from the global config. + +test_expect_success 'using global config, perf stream, return code 0' ' + test_when_finished "rm trace.perf actual expect" && + test_config_global trace2.perfBrief 1 && + test_config_global trace2.perfTarget "$(pwd)/trace.perf" && + test-tool trace2 001return 0 && + perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <trace.perf >actual && + cat >expect <<-EOF && + d0|main|version|||||$V + d0|main|start||_T_ABS_|||_EXE_ trace2 001return 0 + d0|main|cmd_name|||||trace2 (trace2) + d0|main|exit||_T_ABS_|||code:0 + d0|main|atexit||_T_ABS_|||code:0 + EOF + test_cmp expect actual +' + test_done diff --git a/t/t0212-trace2-event.sh b/t/t0212-trace2-event.sh index 028b6c5671..ff5b9cc729 100755 --- a/t/t0212-trace2-event.sh +++ b/t/t0212-trace2-event.sh @@ -3,6 +3,11 @@ test_description='test trace2 facility' . ./test-lib.sh +# Turn off any inherited trace2 settings for this test. +sane_unset GIT_TRACE2 GIT_TRACE2_PERF GIT_TRACE2_EVENT +sane_unset GIT_TRACE2_BARE +sane_unset GIT_TRACE2_CONFIG_PARAMS + perl -MJSON::PP -e 0 >/dev/null 2>&1 && test_set_prereq JSON_PP # Add t/helper directory to PATH so that we can use a relative @@ -17,11 +22,6 @@ PATH="$TTDIR:$PATH" && export PATH # Warning: So you may see extra lines in artifact files when # Warning: interactively debugging. -# Turn off any inherited trace2 settings for this test. -unset GIT_TR2 GIT_TR2_PERF GIT_TR2_EVENT -unset GIT_TR2_BARE -unset GIT_TR2_CONFIG_PARAMS - V=$(git version | sed -e 's/^git version //') && export V # There are multiple trace2 targets: normal, perf, and event. @@ -29,7 +29,7 @@ V=$(git version | sed -e 's/^git version //') && export V # to whatever filtering that target decides to do). # Test each target independently. # -# Defer setting GIT_TR2_PERF until the actual command we want to +# Defer setting GIT_TRACE2_PERF until the actual command we want to # test because hidden git and test-tool commands in the test # harness can contaminate our output. @@ -42,7 +42,7 @@ V=$(git version | sed -e 's/^git version //') && export V test_expect_success JSON_PP 'event stream, error event' ' test_when_finished "rm trace.event actual expect" && - GIT_TR2_EVENT="$(pwd)/trace.event" test-tool trace2 003error "hello world" "this is a test" && + GIT_TRACE2_EVENT="$(pwd)/trace.event" test-tool trace2 003error "hello world" "this is a test" && perl "$TEST_DIRECTORY/t0212/parse_events.perl" <trace.event >actual && sed -e "s/^|//" >expect <<-EOF && |VAR1 = { @@ -79,7 +79,7 @@ test_expect_success JSON_PP 'event stream, error event' ' test_expect_success JSON_PP 'event stream, return code 0' ' test_when_finished "rm trace.event actual expect" && - GIT_TR2_EVENT="$(pwd)/trace.event" test-tool trace2 004child test-tool trace2 004child test-tool trace2 001return 0 && + GIT_TRACE2_EVENT="$(pwd)/trace.event" test-tool trace2 004child test-tool trace2 004child test-tool trace2 001return 0 && perl "$TEST_DIRECTORY/t0212/parse_events.perl" <trace.event >actual && sed -e "s/^|//" >expect <<-EOF && |VAR1 = { @@ -168,7 +168,7 @@ test_expect_success JSON_PP 'event stream, list config' ' test_when_finished "rm trace.event actual expect" && git config --local t0212.abc 1 && git config --local t0212.def "hello world" && - GIT_TR2_EVENT="$(pwd)/trace.event" GIT_TR2_CONFIG_PARAMS="t0212.*" test-tool trace2 001return 0 && + GIT_TRACE2_EVENT="$(pwd)/trace.event" GIT_TRACE2_CONFIG_PARAMS="t0212.*" test-tool trace2 001return 0 && perl "$TEST_DIRECTORY/t0212/parse_events.perl" <trace.event >actual && sed -e "s/^|//" >expect <<-EOF && |VAR1 = { @@ -201,7 +201,7 @@ test_expect_success JSON_PP 'event stream, list config' ' test_expect_success JSON_PP 'basic trace2_data' ' test_when_finished "rm trace.event actual expect" && - GIT_TR2_EVENT="$(pwd)/trace.event" test-tool trace2 006data test_category k1 v1 test_category k2 v2 && + GIT_TRACE2_EVENT="$(pwd)/trace.event" test-tool trace2 006data test_category k1 v1 test_category k2 v2 && perl "$TEST_DIRECTORY/t0212/parse_events.perl" <trace.event >actual && sed -e "s/^|//" >expect <<-EOF && |VAR1 = { @@ -233,4 +233,36 @@ test_expect_success JSON_PP 'basic trace2_data' ' test_cmp expect actual ' +# Now test without environment variables and get all Trace2 settings +# from the global config. + +test_expect_success JSON_PP 'using global config, event stream, error event' ' + test_when_finished "rm trace.event actual expect" && + test_config_global trace2.eventTarget "$(pwd)/trace.event" && + test-tool trace2 003error "hello world" "this is a test" && + perl "$TEST_DIRECTORY/t0212/parse_events.perl" <trace.event >actual && + sed -e "s/^|//" >expect <<-EOF && + |VAR1 = { + | "_SID0_":{ + | "argv":[ + | "_EXE_", + | "trace2", + | "003error", + | "hello world", + | "this is a test" + | ], + | "errors":[ + | "%s", + | "%s" + | ], + | "exit_code":0, + | "hierarchy":"trace2", + | "name":"trace2", + | "version":"$V" + | } + |}; + EOF + test_cmp expect actual +' + test_done diff --git a/t/t0212/parse_events.perl b/t/t0212/parse_events.perl index a2776ba216..6584bb5634 100644 --- a/t/t0212/parse_events.perl +++ b/t/t0212/parse_events.perl @@ -26,7 +26,7 @@ use Getopt::Long; # The version of the trace2 event target format that we understand. # This is reported in the 'version' event in the 'evt' field. -# It comes from the GIT_TR2_EVENT_VERSION macro in trace2/tr2_tgt_event.c +# It comes from the GIT_TRACE2_EVENT_VERSION macro in trace2/tr2_tgt_event.c my $evt_version = '1'; my $show_children = 1; diff --git a/t/t0301-credential-cache.sh b/t/t0301-credential-cache.sh index fd92533acf..ebd5fa5249 100755 --- a/t/t0301-credential-cache.sh +++ b/t/t0301-credential-cache.sh @@ -10,7 +10,7 @@ test -z "$NO_UNIX_SOCKETS" || { } # don't leave a stale daemon running -trap 'code=$?; git credential-cache exit; (exit $code); die' EXIT +test_atexit 'git credential-cache exit' # test that the daemon works with no special setup helper_test cache @@ -108,9 +108,4 @@ test_expect_success SYMLINKS 'use user socket if user directory is a symlink to helper_test_timeout cache --timeout=1 -# we can't rely on our "trap" above working after test_done, -# as test_done will delete the trash directory containing -# our socket, leaving us with no way to access the daemon. -git credential-cache exit - test_done diff --git a/t/t0410-partial-clone.sh b/t/t0410-partial-clone.sh index bce02788e6..5bd892f2f7 100755 --- a/t/t0410-partial-clone.sh +++ b/t/t0410-partial-clone.sh @@ -518,6 +518,4 @@ test_expect_success 'fetching of missing objects from an HTTP server' ' git verify-pack --verbose "$IDX" | grep "$HASH" ' -stop_httpd - test_done diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh index a37753047e..7099d33508 100755 --- a/t/t1007-hash-object.sh +++ b/t/t1007-hash-object.sh @@ -199,10 +199,6 @@ test_expect_success 'too-short tree' ' test_i18ngrep "too-short tree object" err ' -hex2oct() { - perl -ne 'printf "\\%03o", hex for /../g' -} - test_expect_success 'malformed mode in tree' ' hex_sha1=$(echo foo | git hash-object --stdin -w) && bin_sha1=$(echo $hex_sha1 | hex2oct) && diff --git a/t/t1090-sparse-checkout-scope.sh b/t/t1090-sparse-checkout-scope.sh index 090b7fc3d3..40cc004326 100755 --- a/t/t1090-sparse-checkout-scope.sh +++ b/t/t1090-sparse-checkout-scope.sh @@ -31,20 +31,6 @@ test_expect_success 'perform sparse checkout of master' ' test_path_is_file c ' -test_expect_success 'checkout -b checkout.optimizeNewBranch interaction' ' - cp .git/info/sparse-checkout .git/info/sparse-checkout.bak && - test_when_finished " - mv -f .git/info/sparse-checkout.bak .git/info/sparse-checkout - git checkout master - " && - echo "/b" >>.git/info/sparse-checkout && - test "$(git ls-files -t b)" = "S b" && - git -c checkout.optimizeNewBranch=true checkout -b fast && - test "$(git ls-files -t b)" = "S b" && - git checkout -b slow && - test "$(git ls-files -t b)" = "H b" -' - test_expect_success 'merge feature branch into sparse checkout of master' ' git merge feature && test_path_is_file a && diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh index dfece751b5..2dc853d1be 100755 --- a/t/t1301-shared-repo.sh +++ b/t/t1301-shared-repo.sh @@ -136,7 +136,7 @@ test_expect_success POSIXPERM 'forced modes' ' ( cd new && umask 002 && - git init --shared=0660 --template=../templates && + git init --shared=0660 --template=templates && >frotz && git add frotz && git commit -a -m initial && @@ -192,7 +192,7 @@ test_expect_success POSIXPERM 're-init respects core.sharedrepository (remote)' umask 0022 && git init --bare --shared=0666 child.git && test_path_is_missing child.git/foo && - git init --bare --template=../templates child.git && + git init --bare --template=templates child.git && echo "-rw-rw-rw-" >expect && test_modebits child.git/foo >actual && test_cmp expect actual @@ -203,7 +203,7 @@ test_expect_success POSIXPERM 'template can set core.sharedrepository' ' umask 0022 && git config core.sharedrepository 0666 && cp .git/config templates/config && - git init --bare --template=../templates child.git && + git init --bare --template=templates child.git && echo "-rw-rw-rw-" >expect && test_modebits child.git/HEAD >actual && test_cmp expect actual diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh index 635918505d..9571e366f8 100755 --- a/t/t1305-config-include.sh +++ b/t/t1305-config-include.sh @@ -229,6 +229,19 @@ test_expect_success 'conditional include, early config reading' ' ) ' +test_expect_success 'conditional include with /**/' ' + REPO=foo/bar/repo && + git init $REPO && + cat >>$REPO/.git/config <<-\EOF && + [includeIf "gitdir:**/foo/**/bar/**"] + path=bar7 + EOF + echo "[test]seven=7" >$REPO/.git/bar7 && + echo 7 >expect && + git -C $REPO config test.seven >actual && + test_cmp expect actual +' + test_expect_success SYMLINKS 'conditional include, set up symlinked $HOME' ' mkdir real-home && ln -s real-home home && @@ -296,6 +309,45 @@ test_expect_success SYMLINKS 'conditional include, gitdir matching symlink, icas ) ' +test_expect_success 'conditional include, onbranch' ' + echo "[includeIf \"onbranch:foo-branch\"]path=bar9" >>.git/config && + echo "[test]nine=9" >.git/bar9 && + git checkout -b master && + test_must_fail git config test.nine && + git checkout -b foo-branch && + echo 9 >expect && + git config test.nine >actual && + test_cmp expect actual +' + +test_expect_success 'conditional include, onbranch, wildcard' ' + echo "[includeIf \"onbranch:?oo-*/**\"]path=bar10" >>.git/config && + echo "[test]ten=10" >.git/bar10 && + git checkout -b not-foo-branch/a && + test_must_fail git config test.ten && + + echo 10 >expect && + git checkout -b foo-branch/a/b/c && + git config test.ten >actual && + test_cmp expect actual && + + git checkout -b moo-bar/a && + git config test.ten >actual && + test_cmp expect actual +' + +test_expect_success 'conditional include, onbranch, implicit /** for /' ' + echo "[includeIf \"onbranch:foo-dir/\"]path=bar11" >>.git/config && + echo "[test]eleven=11" >.git/bar11 && + git checkout -b not-foo-dir/a && + test_must_fail git config test.eleven && + + echo 11 >expect && + git checkout -b foo-dir/a/b/c && + git config test.eleven >actual && + test_cmp expect actual +' + test_expect_success 'include cycles are detected' ' cat >.gitconfig <<-\EOF && [test]value = gitconfig diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh index ae8a448e34..79f731db37 100755 --- a/t/t1410-reflog.sh +++ b/t/t1410-reflog.sh @@ -232,25 +232,34 @@ test_expect_success '--expire=never' ' ' test_expect_success 'gc.reflogexpire=never' ' + test_config gc.reflogexpire never && + test_config gc.reflogexpireunreachable never && + + git reflog expire --verbose --all >output && + test_line_count = 9 output && - git config gc.reflogexpire never && - git config gc.reflogexpireunreachable never && - git reflog expire --verbose --all && git reflog refs/heads/master >output && test_line_count = 4 output ' test_expect_success 'gc.reflogexpire=false' ' + test_config gc.reflogexpire false && + test_config gc.reflogexpireunreachable false && - git config gc.reflogexpire false && - git config gc.reflogexpireunreachable false && git reflog expire --verbose --all && git reflog refs/heads/master >output && - test_line_count = 4 output && + test_line_count = 4 output + +' - git config --unset gc.reflogexpire && - git config --unset gc.reflogexpireunreachable +test_expect_success 'git reflog expire unknown reference' ' + test_config gc.reflogexpire never && + test_config gc.reflogexpireunreachable never && + test_must_fail git reflog expire master@{123} 2>stderr && + test_i18ngrep "points nowhere" stderr && + test_must_fail git reflog expire does-not-exist 2>stderr && + test_i18ngrep "points nowhere" stderr ' test_expect_success 'checkout should not delete log for packed ref' ' diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh index 49f08d5b9c..0f268a3664 100755 --- a/t/t1450-fsck.sh +++ b/t/t1450-fsck.sh @@ -256,10 +256,6 @@ test_expect_success 'unparseable tree object' ' test_i18ngrep ! "fatal: empty filename in tree entry" out ' -hex2oct() { - perl -ne 'printf "\\%03o", hex for /../g' -} - test_expect_success 'tree entry with type mismatch' ' test_when_finished "remove_object \$blob" && test_when_finished "remove_object \$tree" && diff --git a/t/t2014-switch.sh b/t/t2014-checkout-switch.sh index ccfb147113..ccfb147113 100755 --- a/t/t2014-switch.sh +++ b/t/t2014-checkout-switch.sh diff --git a/t/t2018-checkout-branch.sh b/t/t2018-checkout-branch.sh index c5014ad9a6..822381dd9d 100755 --- a/t/t2018-checkout-branch.sh +++ b/t/t2018-checkout-branch.sh @@ -60,38 +60,47 @@ test_expect_success 'setup' ' ' test_expect_success 'checkout -b to a new branch, set to HEAD' ' + test_when_finished " + git checkout branch1 && + test_might_fail git branch -D branch2" && do_checkout branch2 ' -test_expect_success 'checkout -b to a new branch, set to an explicit ref' ' - git checkout branch1 && - git branch -D branch2 && +test_expect_success 'checkout -b to a merge base' ' + test_when_finished " + git checkout branch1 && + test_might_fail git branch -D branch2" && + git checkout -b branch2 branch1... +' +test_expect_success 'checkout -b to a new branch, set to an explicit ref' ' + test_when_finished " + git checkout branch1 && + test_might_fail git branch -D branch2" && do_checkout branch2 $HEAD1 ' test_expect_success 'checkout -b to a new branch with unmergeable changes fails' ' - git checkout branch1 && - - # clean up from previous test - git branch -D branch2 && - setup_dirty_unmergeable && test_must_fail do_checkout branch2 $HEAD1 && test_dirty_unmergeable ' test_expect_success 'checkout -f -b to a new branch with unmergeable changes discards changes' ' + test_when_finished " + git checkout branch1 && + test_might_fail git branch -D branch2" && + # still dirty and on branch1 do_checkout branch2 $HEAD1 "-f -b" && test_must_fail test_dirty_unmergeable ' test_expect_success 'checkout -b to a new branch preserves mergeable changes' ' - git checkout branch1 && - - # clean up from previous test - git branch -D branch2 && + test_when_finished " + git reset --hard && + git checkout branch1 && + test_might_fail git branch -D branch2" && setup_dirty_mergeable && do_checkout branch2 $HEAD1 && @@ -99,27 +108,18 @@ test_expect_success 'checkout -b to a new branch preserves mergeable changes' ' ' test_expect_success 'checkout -f -b to a new branch with mergeable changes discards changes' ' - # clean up from previous test - git reset --hard && - - git checkout branch1 && - - # clean up from previous test - git branch -D branch2 && - + test_when_finished git reset --hard HEAD && setup_dirty_mergeable && do_checkout branch2 $HEAD1 "-f -b" && test_must_fail test_dirty_mergeable ' test_expect_success 'checkout -b to an existing branch fails' ' - git reset --hard HEAD && - + test_when_finished git reset --hard HEAD && test_must_fail do_checkout branch2 $HEAD2 ' test_expect_success 'checkout -b to @{-1} fails with the right branch name' ' - git reset --hard HEAD && git checkout branch1 && git checkout branch2 && echo >expect "fatal: A branch named '\''branch1'\'' already exists." && @@ -133,6 +133,12 @@ test_expect_success 'checkout -B to an existing branch resets branch to HEAD' ' do_checkout branch2 "" -B ' +test_expect_success 'checkout -B to a merge base' ' + git checkout branch1 && + + git checkout -B branch2 branch1... +' + test_expect_success 'checkout -B to an existing branch from detached HEAD resets branch to HEAD' ' git checkout $(git rev-parse --verify HEAD) && @@ -160,6 +166,7 @@ test_expect_success 'checkout -f -B to an existing branch with unmergeable chang ' test_expect_success 'checkout -B to an existing branch preserves mergeable changes' ' + test_when_finished git reset --hard && git checkout branch1 && setup_dirty_mergeable && @@ -168,9 +175,6 @@ test_expect_success 'checkout -B to an existing branch preserves mergeable chang ' test_expect_success 'checkout -f -B to an existing branch with mergeable changes discards changes' ' - # clean up from previous test - git reset --hard && - git checkout branch1 && setup_dirty_mergeable && diff --git a/t/t2020-checkout-detach.sh b/t/t2020-checkout-detach.sh index 1fa670625c..b748db9946 100755 --- a/t/t2020-checkout-detach.sh +++ b/t/t2020-checkout-detach.sh @@ -195,16 +195,22 @@ test_expect_success 'describe_detached_head prints no SHA-1 ellipsis when not as # The first detach operation is more chatty than the following ones. cat >1st_detach <<-EOF && - Note: checking out 'HEAD^'. + Note: switching to 'HEAD^'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this - state without impacting any branches by performing another checkout. + state without impacting any branches by switching back to a branch. If you want to create a new branch to retain commits you create, you may - do so (now or later) by using -b with the checkout command again. Example: + do so (now or later) by using -c with the switch command. Example: - git checkout -b <new-branch-name> + git switch -c <new-branch-name> + + Or undo this operation with: + + git switch - + + Turn off this advice by setting config variable advice.detachedHead to false HEAD is now at \$commit three EOF @@ -271,16 +277,22 @@ test_expect_success 'describe_detached_head does print SHA-1 ellipsis when asked # The first detach operation is more chatty than the following ones. cat >1st_detach <<-EOF && - Note: checking out 'HEAD^'. + Note: switching to 'HEAD^'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this - state without impacting any branches by performing another checkout. + state without impacting any branches by switching back to a branch. If you want to create a new branch to retain commits you create, you may - do so (now or later) by using -b with the checkout command again. Example: + do so (now or later) by using -c with the switch command. Example: + + git switch -c <new-branch-name> + + Or undo this operation with: + + git switch - - git checkout -b <new-branch-name> + Turn off this advice by setting config variable advice.detachedHead to false HEAD is now at \$commit... three EOF diff --git a/t/t2060-switch.sh b/t/t2060-switch.sh new file mode 100755 index 0000000000..f9efa29dfb --- /dev/null +++ b/t/t2060-switch.sh @@ -0,0 +1,96 @@ +#!/bin/sh + +test_description='switch basic functionality' + +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit first && + git branch first-branch && + test_commit second && + test_commit third && + git remote add origin nohost:/nopath && + git update-ref refs/remotes/origin/foo first-branch +' + +test_expect_success 'switch branch no arguments' ' + test_must_fail git switch +' + +test_expect_success 'switch branch' ' + git switch first-branch && + test_path_is_missing second.t +' + +test_expect_success 'switch and detach' ' + test_when_finished git switch master && + test_must_fail git switch master^{commit} && + git switch --detach master^{commit} && + test_must_fail git symbolic-ref HEAD +' + +test_expect_success 'switch and detach current branch' ' + test_when_finished git switch master && + git switch master && + git switch --detach && + test_must_fail git symbolic-ref HEAD +' + +test_expect_success 'switch and create branch' ' + test_when_finished git switch master && + git switch -c temp master^ && + test_cmp_rev master^ refs/heads/temp && + echo refs/heads/temp >expected-branch && + git symbolic-ref HEAD >actual-branch && + test_cmp expected-branch actual-branch +' + +test_expect_success 'force create branch from HEAD' ' + test_when_finished git switch master && + git switch --detach master && + test_must_fail git switch -c temp && + git switch -C temp && + test_cmp_rev master refs/heads/temp && + echo refs/heads/temp >expected-branch && + git symbolic-ref HEAD >actual-branch && + test_cmp expected-branch actual-branch +' + +test_expect_success 'new orphan branch from empty' ' + test_when_finished git switch master && + test_must_fail git switch --orphan new-orphan HEAD && + git switch --orphan new-orphan && + test_commit orphan && + git cat-file commit refs/heads/new-orphan >commit && + ! grep ^parent commit && + git ls-files >tracked-files && + echo orphan.t >expected && + test_cmp expected tracked-files +' + +test_expect_success 'switching ignores file of same branch name' ' + test_when_finished git switch master && + : >first-branch && + git switch first-branch && + echo refs/heads/first-branch >expected && + git symbolic-ref HEAD >actual && + test_cmp expected actual +' + +test_expect_success 'guess and create branch ' ' + test_when_finished git switch master && + test_must_fail git switch --no-guess foo && + git switch foo && + echo refs/heads/foo >expected && + git symbolic-ref HEAD >actual && + test_cmp expected actual +' + +test_expect_success 'not switching when something is in progress' ' + test_when_finished rm -f .git/MERGE_HEAD && + # fake a merge-in-progress + cp .git/HEAD .git/MERGE_HEAD && + test_must_fail git switch -d @^ +' + +test_done diff --git a/t/t2070-restore.sh b/t/t2070-restore.sh new file mode 100755 index 0000000000..2650df1966 --- /dev/null +++ b/t/t2070-restore.sh @@ -0,0 +1,98 @@ +#!/bin/sh + +test_description='restore basic functionality' + +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit first && + echo first-and-a-half >>first.t && + git add first.t && + test_commit second && + echo one >one && + echo two >two && + echo untracked >untracked && + echo ignored >ignored && + echo /ignored >.gitignore && + git add one two .gitignore && + git update-ref refs/heads/one master +' + +test_expect_success 'restore without pathspec is not ok' ' + test_must_fail git restore && + test_must_fail git restore --source=first +' + +test_expect_success 'restore a file, ignoring branch of same name' ' + cat one >expected && + echo dirty >>one && + git restore one && + test_cmp expected one +' + +test_expect_success 'restore a file on worktree from another ref' ' + test_when_finished git reset --hard && + git cat-file blob first:./first.t >expected && + git restore --source=first first.t && + test_cmp expected first.t && + git cat-file blob HEAD:./first.t >expected && + git show :first.t >actual && + test_cmp expected actual +' + +test_expect_success 'restore a file in the index from another ref' ' + test_when_finished git reset --hard && + git cat-file blob first:./first.t >expected && + git restore --source=first --staged first.t && + git show :first.t >actual && + test_cmp expected actual && + git cat-file blob HEAD:./first.t >expected && + test_cmp expected first.t +' + +test_expect_success 'restore a file in both the index and worktree from another ref' ' + test_when_finished git reset --hard && + git cat-file blob first:./first.t >expected && + git restore --source=first --staged --worktree first.t && + git show :first.t >actual && + test_cmp expected actual && + test_cmp expected first.t +' + +test_expect_success 'restore --staged uses HEAD as source' ' + test_when_finished git reset --hard && + git cat-file blob :./first.t >expected && + echo index-dirty >>first.t && + git add first.t && + git restore --staged first.t && + git cat-file blob :./first.t >actual && + test_cmp expected actual +' + +test_expect_success 'restore --ignore-unmerged ignores unmerged entries' ' + git init unmerged && + ( + cd unmerged && + echo one >unmerged && + echo one >common && + git add unmerged common && + git commit -m common && + git switch -c first && + echo first >unmerged && + git commit -am first && + git switch -c second master && + echo second >unmerged && + git commit -am second && + test_must_fail git merge first && + + echo dirty >>common && + test_must_fail git restore . && + + git restore --ignore-unmerged --quiet . >output 2>&1 && + git diff common >diff-output && + test_must_be_empty output && + test_must_be_empty diff-output + ) +' + +test_done diff --git a/t/t2071-restore-patch.sh b/t/t2071-restore-patch.sh new file mode 100755 index 0000000000..98b2476e7c --- /dev/null +++ b/t/t2071-restore-patch.sh @@ -0,0 +1,110 @@ +#!/bin/sh + +test_description='git restore --patch' + +. ./lib-patch-mode.sh + +test_expect_success PERL 'setup' ' + mkdir dir && + echo parent >dir/foo && + echo dummy >bar && + git add bar dir/foo && + git commit -m initial && + test_tick && + test_commit second dir/foo head && + set_and_save_state bar bar_work bar_index && + save_head +' + +test_expect_success PERL 'restore -p without pathspec is fine' ' + echo q >cmd && + git restore -p <cmd +' + +# note: bar sorts before dir/foo, so the first 'n' is always to skip 'bar' + +test_expect_success PERL 'saying "n" does nothing' ' + set_and_save_state dir/foo work head && + test_write_lines n n | git restore -p && + verify_saved_state bar && + verify_saved_state dir/foo +' + +test_expect_success PERL 'git restore -p' ' + set_and_save_state dir/foo work head && + test_write_lines n y | git restore -p && + verify_saved_state bar && + verify_state dir/foo head head +' + +test_expect_success PERL 'git restore -p with staged changes' ' + set_state dir/foo work index && + test_write_lines n y | git restore -p && + verify_saved_state bar && + verify_state dir/foo index index +' + +test_expect_success PERL 'git restore -p --source=HEAD' ' + set_state dir/foo work index && + # the third n is to get out in case it mistakenly does not apply + test_write_lines n y n | git restore -p --source=HEAD && + verify_saved_state bar && + verify_state dir/foo head index +' + +test_expect_success PERL 'git restore -p --source=HEAD^' ' + set_state dir/foo work index && + # the third n is to get out in case it mistakenly does not apply + test_write_lines n y n | git restore -p --source=HEAD^ && + verify_saved_state bar && + verify_state dir/foo parent index +' + +test_expect_success PERL 'git restore -p handles deletion' ' + set_state dir/foo work index && + rm dir/foo && + test_write_lines n y | git restore -p && + verify_saved_state bar && + verify_state dir/foo index index +' + +# The idea in the rest is that bar sorts first, so we always say 'y' +# first and if the path limiter fails it'll apply to bar instead of +# dir/foo. There's always an extra 'n' to reject edits to dir/foo in +# the failure case (and thus get out of the loop). + +test_expect_success PERL 'path limiting works: dir' ' + set_state dir/foo work head && + test_write_lines y n | git restore -p dir && + verify_saved_state bar && + verify_state dir/foo head head +' + +test_expect_success PERL 'path limiting works: -- dir' ' + set_state dir/foo work head && + test_write_lines y n | git restore -p -- dir && + verify_saved_state bar && + verify_state dir/foo head head +' + +test_expect_success PERL 'path limiting works: HEAD^ -- dir' ' + set_state dir/foo work head && + # the third n is to get out in case it mistakenly does not apply + test_write_lines y n n | git restore -p --source=HEAD^ -- dir && + verify_saved_state bar && + verify_state dir/foo parent head +' + +test_expect_success PERL 'path limiting works: foo inside dir' ' + set_state dir/foo work head && + # the third n is to get out in case it mistakenly does not apply + test_write_lines y n n | (cd dir && git restore -p foo) && + verify_saved_state bar && + verify_state dir/foo head head +' + +test_expect_success PERL 'none of this moved HEAD' ' + verify_saved_head +' + +test_done diff --git a/t/t2400-worktree-add.sh b/t/t2400-worktree-add.sh index 286bba35d8..e819ba741e 100755 --- a/t/t2400-worktree-add.sh +++ b/t/t2400-worktree-add.sh @@ -570,4 +570,21 @@ test_expect_success '"add" an existing locked but missing worktree' ' git worktree add --force --force --detach gnoo ' +test_expect_success FUNNYNAMES 'sanitize generated worktree name' ' + git worktree add --detach ". weird*..?.lock.lock" && + test -d .git/worktrees/---weird-.- +' + +test_expect_success '"add" should not fail because of another bad worktree' ' + git init add-fail && + ( + cd add-fail && + test_commit first && + mkdir sub && + git worktree add sub/to-be-deleted && + rm -rf sub && + git worktree add second + ) +' + test_done diff --git a/t/t3000-ls-files-others.sh b/t/t3000-ls-files-others.sh index afd4756134..0aefadacb0 100755 --- a/t/t3000-ls-files-others.sh +++ b/t/t3000-ls-files-others.sh @@ -3,7 +3,7 @@ # Copyright (c) 2005 Junio C Hamano # -test_description='git ls-files test (--others should pick up symlinks). +test_description='basic tests for ls-files --others This test runs git ls-files --others with the following on the filesystem. diff --git a/t/t3009-ls-files-others-nonsubmodule.sh b/t/t3009-ls-files-others-nonsubmodule.sh new file mode 100755 index 0000000000..963f3462b7 --- /dev/null +++ b/t/t3009-ls-files-others-nonsubmodule.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +test_description='test git ls-files --others with non-submodule repositories + +This test runs git ls-files --others with the following working tree: + + nonrepo-no-files/ + plain directory with no files + nonrepo-untracked-file/ + plain directory with an untracked file + repo-no-commit-no-files/ + git repository without a commit or a file + repo-no-commit-untracked-file/ + git repository without a commit but with an untracked file + repo-with-commit-no-files/ + git repository with a commit and no untracked files + repo-with-commit-untracked-file/ + git repository with a commit and an untracked file +' + +. ./test-lib.sh + +test_expect_success 'setup: directories' ' + mkdir nonrepo-no-files/ && + mkdir nonrepo-untracked-file && + : >nonrepo-untracked-file/untracked && + git init repo-no-commit-no-files && + git init repo-no-commit-untracked-file && + : >repo-no-commit-untracked-file/untracked && + git init repo-with-commit-no-files && + git -C repo-with-commit-no-files commit --allow-empty -mmsg && + git init repo-with-commit-untracked-file && + test_commit -C repo-with-commit-untracked-file msg && + : >repo-with-commit-untracked-file/untracked +' + +test_expect_success 'ls-files --others handles untracked git repositories' ' + git ls-files -o >output && + cat >expect <<-EOF && + nonrepo-untracked-file/untracked + output + repo-no-commit-no-files/ + repo-no-commit-untracked-file/ + repo-with-commit-no-files/ + repo-with-commit-untracked-file/ + EOF + test_cmp expect output +' + +test_done diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index 478b82cf9b..411a70b0ce 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -42,6 +42,10 @@ test_expect_success 'git branch a/b/c should create a branch' ' git branch a/b/c && test_path_is_file .git/refs/heads/a/b/c ' +test_expect_success 'git branch mb master... should create a branch' ' + git branch mb master... && test_path_is_file .git/refs/heads/mb +' + test_expect_success 'git branch HEAD should fail' ' test_must_fail git branch HEAD ' @@ -202,18 +206,22 @@ test_expect_success 'git branch -M baz bam should succeed when baz is checked ou git worktree add -f bazdir2 baz && git branch -M baz bam && test $(git -C bazdir rev-parse --abbrev-ref HEAD) = bam && - test $(git -C bazdir2 rev-parse --abbrev-ref HEAD) = bam + test $(git -C bazdir2 rev-parse --abbrev-ref HEAD) = bam && + rm -r bazdir bazdir2 && + git worktree prune ' test_expect_success 'git branch -M baz bam should succeed within a worktree in which baz is checked out' ' git checkout -b baz && - git worktree add -f bazdir3 baz && + git worktree add -f bazdir baz && ( - cd bazdir3 && + cd bazdir && git branch -M baz bam && test $(git rev-parse --abbrev-ref HEAD) = bam ) && - test $(git rev-parse --abbrev-ref HEAD) = bam + test $(git rev-parse --abbrev-ref HEAD) = bam && + rm -r bazdir && + git worktree prune ' test_expect_success 'git branch -M master should work when master is checked out' ' @@ -264,6 +272,30 @@ test_expect_success 'git branch --list -d t should fail' ' test_must_fail git rev-parse refs/heads/t ' +test_expect_success 'deleting checked-out branch from repo that is a submodule' ' + test_when_finished "rm -rf repo1 repo2" && + + git init repo1 && + git init repo1/sub && + test_commit -C repo1/sub x && + git -C repo1 submodule add ./sub && + git -C repo1 commit -m "adding sub" && + + git clone --recurse-submodules repo1 repo2 && + git -C repo2/sub checkout -b work && + test_must_fail git -C repo2/sub branch -D work +' + +test_expect_success 'bare main worktree has HEAD at branch deleted by secondary worktree' ' + test_when_finished "rm -rf nonbare base secondary" && + + git init nonbare && + test_commit -C nonbare x && + git clone --bare nonbare bare && + git -C bare worktree add --detach ../secondary master && + git -C secondary branch -D master +' + test_expect_success 'git branch --list -v with --abbrev' ' test_when_finished "git branch -D t" && git branch t && @@ -292,8 +324,8 @@ test_expect_success 'git branch --list -v with --abbrev' ' test_expect_success 'git branch --column' ' COLUMNS=81 git branch --column=column >actual && cat >expected <<\EOF && - a/b/c bam foo l * master n o/p r - abc bar j/k m/m master2 o/o q + a/b/c bam foo l * master mb o/o q + abc bar j/k m/m master2 n o/p r EOF test_cmp expected actual ' @@ -315,6 +347,7 @@ test_expect_success 'git branch --column with an extremely long branch name' ' m/m * master master2 + mb n o/o o/p @@ -332,8 +365,8 @@ test_expect_success 'git branch with column.*' ' git config --unset column.branch && git config --unset column.ui && cat >expected <<\EOF && - a/b/c bam foo l * master n o/p r - abc bar j/k m/m master2 o/o q + a/b/c bam foo l * master mb o/o q + abc bar j/k m/m master2 n o/p r EOF test_cmp expected actual ' @@ -357,6 +390,7 @@ test_expect_success 'git branch -v with column.ui ignored' ' m/m * master master2 + mb n o/o o/p @@ -774,7 +808,9 @@ test_expect_success 'test deleting branch without config' ' test_expect_success 'deleting currently checked out branch fails' ' git worktree add -b my7 my7 && test_must_fail git -C my7 branch -d my7 && - test_must_fail git branch -d my7 + test_must_fail git branch -d my7 && + rm -r my7 && + git worktree prune ' test_expect_success 'test --track without .fetch entries' ' diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh index be55148930..71818b90f0 100755 --- a/t/t3203-branch-output.sh +++ b/t/t3203-branch-output.sh @@ -136,10 +136,13 @@ test_expect_success 'git branch `--show-current` works properly with worktrees' branch-two EOF git checkout branch-one && - git worktree add worktree branch-two && + test_when_finished " + git worktree remove worktree_dir + " && + git worktree add worktree_dir branch-two && { git branch --show-current && - git -C worktree branch --show-current + git -C worktree_dir branch --show-current } >actual && test_cmp expect actual ' @@ -284,6 +287,24 @@ test_expect_success 'git branch --format option' ' test_i18ncmp expect actual ' +test_expect_success 'worktree colors correct' ' + cat >expect <<-EOF && + * <GREEN>(HEAD detached from fromtag)<RESET> + ambiguous<RESET> + branch-one<RESET> + + <CYAN>branch-two<RESET> + master<RESET> + ref-to-branch<RESET> -> branch-one + ref-to-remote<RESET> -> origin/branch-one + EOF + git worktree add worktree_dir branch-two && + git branch --color >actual.raw && + rm -r worktree_dir && + git worktree prune && + test_decode_color <actual.raw >actual && + test_i18ncmp expect actual +' + test_expect_success "set up color tests" ' echo "<RED>master<RESET>" >expect.color && echo "master" >expect.bare && @@ -308,4 +329,23 @@ test_expect_success '--color overrides auto-color' ' test_cmp expect.color actual ' +test_expect_success 'verbose output lists worktree path' ' + one=$(git rev-parse --short HEAD) && + two=$(git rev-parse --short master) && + cat >expect <<-EOF && + * (HEAD detached from fromtag) $one one + ambiguous $one one + branch-one $two two + + branch-two $one ($(pwd)/worktree_dir) one + master $two two + ref-to-branch $two two + ref-to-remote $two two + EOF + git worktree add worktree_dir branch-two && + git branch -vv >actual && + rm -r worktree_dir && + git worktree prune && + test_i18ncmp expect actual +' + test_done diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh index 84bbf88cf9..704bbc6541 100755 --- a/t/t3301-notes.sh +++ b/t/t3301-notes.sh @@ -1120,9 +1120,10 @@ test_expect_success 'GIT_NOTES_REWRITE_REF overrides config' ' test_config notes.rewriteMode overwrite && test_config notes.rewriteRef refs/notes/other && echo $(git rev-parse HEAD^) $(git rev-parse HEAD) | - GIT_NOTES_REWRITE_REF= git notes copy --for-rewrite=foo && + GIT_NOTES_REWRITE_REF=refs/notes/commits \ + git notes copy --for-rewrite=foo && git log -1 >actual && - test_cmp expect actual + grep "replacement note 3" actual ' test_expect_success 'git notes copy diagnoses too many or too few parameters' ' diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh index 42f147858d..80b23fd326 100755 --- a/t/t3400-rebase.sh +++ b/t/t3400-rebase.sh @@ -285,7 +285,7 @@ EOF test_cmp From_.msg out ' -test_expect_success 'rebase--am.sh and --show-current-patch' ' +test_expect_success 'rebase --am and --show-current-patch' ' test_create_repo conflict-apply && ( cd conflict-apply && diff --git a/t/t3401-rebase-and-am-rename.sh b/t/t3401-rebase-and-am-rename.sh index e0b5111993..a0b9438b22 100755 --- a/t/t3401-rebase-and-am-rename.sh +++ b/t/t3401-rebase-and-am-rename.sh @@ -42,7 +42,7 @@ test_expect_success 'rebase --interactive: directory rename detected' ' git checkout B^0 && set_fake_editor && - FAKE_LINES="1" git rebase --interactive A && + FAKE_LINES="1" git -c merge.directoryRenames=true rebase --interactive A && git ls-files -s >out && test_line_count = 5 out && @@ -58,7 +58,7 @@ test_expect_failure 'rebase (am): directory rename detected' ' git checkout B^0 && - git rebase A && + git -c merge.directoryRenames=true rebase A && git ls-files -s >out && test_line_count = 5 out && @@ -74,7 +74,7 @@ test_expect_success 'rebase --merge: directory rename detected' ' git checkout B^0 && - git rebase --merge A && + git -c merge.directoryRenames=true rebase --merge A && git ls-files -s >out && test_line_count = 5 out && @@ -92,7 +92,7 @@ test_expect_failure 'am: directory rename detected' ' git format-patch -1 B && - git am --3way 0001*.patch && + git -c merge.directoryRenames=true am --3way 0001*.patch && git ls-files -s >out && test_line_count = 5 out && diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 1723e1a858..46d971b4ef 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -1031,7 +1031,7 @@ test_expect_success 'rebase -i --root reword root commit' ' test -z "$(git show -s --format=%p HEAD^)" ' -test_expect_success 'rebase -i --root when root has untracked file confilct' ' +test_expect_success 'rebase -i --root when root has untracked file conflict' ' test_when_finished "reset_rebase" && git checkout -b failing-root-pick A && echo x >file2 && diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh index 13f5688135..22d218698e 100755 --- a/t/t3415-rebase-autosquash.sh +++ b/t/t3415-rebase-autosquash.sh @@ -277,7 +277,7 @@ test_expect_success 'autosquash with empty custom instructionFormat' ' ( set_cat_todo_editor && test_must_fail git -c rebase.instructionFormat= \ - rebase --autosquash --force -i HEAD^ >actual && + rebase --autosquash --force-rebase -i HEAD^ >actual && git log -1 --format="pick %h %s" >expect && test_cmp expect actual ) diff --git a/t/t3422-rebase-incompatible-options.sh b/t/t3422-rebase-incompatible-options.sh index bb78a6ec86..a5868ea152 100755 --- a/t/t3422-rebase-incompatible-options.sh +++ b/t/t3422-rebase-incompatible-options.sh @@ -65,12 +65,13 @@ test_rebase_am_only --ignore-whitespace test_rebase_am_only --committer-date-is-author-date test_rebase_am_only -C4 -test_expect_success '--preserve-merges incompatible with --signoff' ' +test_expect_success REBASE_P '--preserve-merges incompatible with --signoff' ' git checkout B^0 && test_must_fail git rebase --preserve-merges --signoff A ' -test_expect_success '--preserve-merges incompatible with --rebase-merges' ' +test_expect_success REBASE_P \ + '--preserve-merges incompatible with --rebase-merges' ' git checkout B^0 && test_must_fail git rebase --preserve-merges --rebase-merges A ' diff --git a/t/t3427-rebase-subtree.sh b/t/t3427-rebase-subtree.sh index 3780877e4e..d8640522a0 100755 --- a/t/t3427-rebase-subtree.sh +++ b/t/t3427-rebase-subtree.sh @@ -38,7 +38,8 @@ test_expect_success 'setup' ' ' # FAILURE: Does not preserve master4. -test_expect_failure 'Rebase -Xsubtree --preserve-merges --onto commit 4' ' +test_expect_failure REBASE_P \ + 'Rebase -Xsubtree --preserve-merges --onto commit 4' ' reset_rebase && git checkout -b rebase-preserve-merges-4 master && git filter-branch --prune-empty -f --subdirectory-filter files_subtree && @@ -48,7 +49,8 @@ test_expect_failure 'Rebase -Xsubtree --preserve-merges --onto commit 4' ' ' # FAILURE: Does not preserve master5. -test_expect_failure 'Rebase -Xsubtree --preserve-merges --onto commit 5' ' +test_expect_failure REBASE_P \ + 'Rebase -Xsubtree --preserve-merges --onto commit 5' ' reset_rebase && git checkout -b rebase-preserve-merges-5 master && git filter-branch --prune-empty -f --subdirectory-filter files_subtree && @@ -58,7 +60,8 @@ test_expect_failure 'Rebase -Xsubtree --preserve-merges --onto commit 5' ' ' # FAILURE: Does not preserve master4. -test_expect_failure 'Rebase -Xsubtree --keep-empty --preserve-merges --onto commit 4' ' +test_expect_failure REBASE_P \ + 'Rebase -Xsubtree --keep-empty --preserve-merges --onto commit 4' ' reset_rebase && git checkout -b rebase-keep-empty-4 master && git filter-branch --prune-empty -f --subdirectory-filter files_subtree && @@ -68,7 +71,8 @@ test_expect_failure 'Rebase -Xsubtree --keep-empty --preserve-merges --onto comm ' # FAILURE: Does not preserve master5. -test_expect_failure 'Rebase -Xsubtree --keep-empty --preserve-merges --onto commit 5' ' +test_expect_failure REBASE_P \ + 'Rebase -Xsubtree --keep-empty --preserve-merges --onto commit 5' ' reset_rebase && git checkout -b rebase-keep-empty-5 master && git filter-branch --prune-empty -f --subdirectory-filter files_subtree && @@ -78,7 +82,8 @@ test_expect_failure 'Rebase -Xsubtree --keep-empty --preserve-merges --onto comm ' # FAILURE: Does not preserve Empty. -test_expect_failure 'Rebase -Xsubtree --keep-empty --preserve-merges --onto empty commit' ' +test_expect_failure REBASE_P \ + 'Rebase -Xsubtree --keep-empty --preserve-merges --onto empty commit' ' reset_rebase && git checkout -b rebase-keep-empty-empty master && git filter-branch --prune-empty -f --subdirectory-filter files_subtree && diff --git a/t/t3430-rebase-merges.sh b/t/t3430-rebase-merges.sh index 4c69255ee6..7b6c4847ad 100755 --- a/t/t3430-rebase-merges.sh +++ b/t/t3430-rebase-merges.sh @@ -164,6 +164,19 @@ test_expect_success 'failed `merge <branch>` does not crash' ' grep "^Merge branch ${SQ}G${SQ}$" .git/rebase-merge/message ' +test_expect_success 'fast-forward merge -c still rewords' ' + git checkout -b fast-forward-merge-c H && + ( + set_fake_editor && + FAKE_COMMIT_MESSAGE=edited \ + GIT_SEQUENCE_EDITOR="echo merge -c H G >" \ + git rebase -ir @^ + ) && + echo edited >expected && + git log --pretty=format:%B -1 >actual && + test_cmp expected actual +' + test_expect_success 'with a branch tip that was cherry-picked already' ' git checkout -b already-upstream master && base="$(git rev-parse --verify HEAD)" && @@ -224,8 +237,24 @@ test_expect_success 'refs/rewritten/* is worktree-local' ' test_cmp_rev HEAD "$(cat wt/b)" ' +test_expect_success '--abort cleans up refs/rewritten' ' + git checkout -b abort-cleans-refs-rewritten H && + GIT_SEQUENCE_EDITOR="echo break >>" git rebase -ir @^ && + git rev-parse --verify refs/rewritten/onto && + git rebase --abort && + test_must_fail git rev-parse --verify refs/rewritten/onto +' + +test_expect_success '--quit cleans up refs/rewritten' ' + git checkout -b quit-cleans-refs-rewritten H && + GIT_SEQUENCE_EDITOR="echo break >>" git rebase -ir @^ && + git rev-parse --verify refs/rewritten/onto && + git rebase --quit && + test_must_fail git rev-parse --verify refs/rewritten/onto +' + test_expect_success 'post-rewrite hook and fixups work for merges' ' - git checkout -b post-rewrite && + git checkout -b post-rewrite H && test_commit same1 && git reset --hard HEAD^ && test_commit same2 && @@ -271,7 +300,7 @@ test_expect_success 'root commits' ' EOF test_config sequence.editor \""$PWD"/replace-editor.sh\" && test_tick && - git rebase -i --force --root -r && + git rebase -i --force-rebase --root -r && test "Parsnip" = "$(git show -s --format=%an HEAD^)" && test $(git rev-parse second-root^0) != $(git rev-parse HEAD^) && test $(git rev-parse second-root:second-root.t) = \ @@ -364,7 +393,7 @@ test_expect_success 'octopus merges' ' test_cmp_rev HEAD $before && test_tick && - git rebase -i --force -r HEAD^^ && + git rebase -i --force-rebase -r HEAD^^ && test "Hank" = "$(git show -s --format=%an HEAD)" && test "$before" != $(git rev-parse HEAD) && test_cmp_graph HEAD^^.. <<-\EOF diff --git a/t/t3507-cherry-pick-conflict.sh b/t/t3507-cherry-pick-conflict.sh index 0db166152a..9b9b4ca8d4 100755 --- a/t/t3507-cherry-pick-conflict.sh +++ b/t/t3507-cherry-pick-conflict.sh @@ -25,6 +25,11 @@ test_expect_success setup ' test_commit base foo b && test_commit picked foo c && test_commit --signoff picked-signed foo d && + git checkout -b topic initial && + test_commit redundant-pick foo c redundant && + git commit --allow-empty --allow-empty-message && + git tag empty && + git checkout master && git config advice.detachedhead false ' @@ -88,7 +93,7 @@ test_expect_success 'cherry-pick --no-commit does not set CHERRY_PICK_HEAD' ' test_expect_success 'cherry-pick w/dirty tree does not set CHERRY_PICK_HEAD' ' pristine_detach initial && - echo foo > foo && + echo foo >foo && test_must_fail git cherry-pick base && test_must_fail git rev-parse --verify CHERRY_PICK_HEAD ' @@ -96,7 +101,7 @@ test_expect_success 'cherry-pick w/dirty tree does not set CHERRY_PICK_HEAD' ' test_expect_success \ 'cherry-pick --strategy=resolve w/dirty tree does not set CHERRY_PICK_HEAD' ' pristine_detach initial && - echo foo > foo && + echo foo >foo && test_must_fail git cherry-pick --strategy=resolve base && test_must_fail git rev-parse --verify CHERRY_PICK_HEAD ' @@ -156,6 +161,25 @@ test_expect_success 'successful commit clears CHERRY_PICK_HEAD' ' test_must_fail git rev-parse --verify CHERRY_PICK_HEAD ' +test_expect_success 'successful final commit clears cherry-pick state' ' + pristine_detach initial && + + test_must_fail git cherry-pick base picked-signed && + echo resolved >foo && + test_path_is_file .git/sequencer/todo && + git commit -a && + test_must_fail test_path_exists .git/sequencer +' + +test_expect_success 'reset after final pick clears cherry-pick state' ' + pristine_detach initial && + + test_must_fail git cherry-pick base picked-signed && + echo resolved >foo && + test_path_is_file .git/sequencer/todo && + git reset && + test_must_fail test_path_exists .git/sequencer +' test_expect_success 'failed cherry-pick produces dirty index' ' pristine_detach initial && @@ -175,23 +199,63 @@ test_expect_success 'failed cherry-pick registers participants in index' ' git ls-files --stage foo && git checkout picked -- foo && git ls-files --stage foo - } > stages && + } >stages && sed " 1 s/ 0 / 1 / 2 s/ 0 / 2 / 3 s/ 0 / 3 / - " < stages > expected && + " stages >expected && git read-tree -u --reset HEAD && test_must_fail git cherry-pick picked && - git ls-files --stage --unmerged > actual && + git ls-files --stage --unmerged >actual && test_cmp expected actual ' +test_expect_success \ + 'cherry-pick conflict, ensure commit.cleanup = scissors places scissors line properly' ' + pristine_detach initial && + git config commit.cleanup scissors && + cat <<-EOF >expected && + picked + + # ------------------------ >8 ------------------------ + # Do not modify or remove the line above. + # Everything below it will be ignored. + # + # Conflicts: + # foo + EOF + + test_must_fail git cherry-pick picked && + + test_i18ncmp expected .git/MERGE_MSG +' + +test_expect_success \ + 'cherry-pick conflict, ensure cleanup=scissors places scissors line properly' ' + pristine_detach initial && + git config --unset commit.cleanup && + cat <<-EOF >expected && + picked + + # ------------------------ >8 ------------------------ + # Do not modify or remove the line above. + # Everything below it will be ignored. + # + # Conflicts: + # foo + EOF + + test_must_fail git cherry-pick --cleanup=scissors picked && + + test_i18ncmp expected .git/MERGE_MSG +' + test_expect_success 'failed cherry-pick describes conflict in work tree' ' pristine_detach initial && - cat <<-EOF > expected && + cat <<-EOF >expected && <<<<<<< HEAD a ======= @@ -201,14 +265,14 @@ test_expect_success 'failed cherry-pick describes conflict in work tree' ' test_must_fail git cherry-pick picked && - sed "s/[a-f0-9]*\.\.\./objid/" foo > actual && + sed "s/[a-f0-9]*\.\.\./objid/" foo >actual && test_cmp expected actual ' test_expect_success 'diff3 -m style' ' pristine_detach initial && git config merge.conflictstyle diff3 && - cat <<-EOF > expected && + cat <<-EOF >expected && <<<<<<< HEAD a ||||||| parent of objid picked @@ -220,14 +284,14 @@ test_expect_success 'diff3 -m style' ' test_must_fail git cherry-pick picked && - sed "s/[a-f0-9]*\.\.\./objid/" foo > actual && + sed "s/[a-f0-9]*\.\.\./objid/" foo >actual && test_cmp expected actual ' test_expect_success 'revert also handles conflicts sanely' ' git config --unset merge.conflictstyle && pristine_detach initial && - cat <<-EOF > expected && + cat <<-EOF >expected && <<<<<<< HEAD a ======= @@ -241,24 +305,24 @@ test_expect_success 'revert also handles conflicts sanely' ' git ls-files --stage foo && git checkout base -- foo && git ls-files --stage foo - } > stages && + } >stages && sed " 1 s/ 0 / 1 / 2 s/ 0 / 2 / 3 s/ 0 / 3 / - " < stages > expected-stages && + " stages >expected-stages && git read-tree -u --reset HEAD && head=$(git rev-parse HEAD) && test_must_fail git revert picked && newhead=$(git rev-parse HEAD) && - git ls-files --stage --unmerged > actual-stages && + git ls-files --stage --unmerged >actual-stages && test "$head" = "$newhead" && test_must_fail git update-index --refresh -q && test_must_fail git diff-index --exit-code HEAD && test_cmp expected-stages actual-stages && - sed "s/[a-f0-9]*\.\.\./objid/" foo > actual && + sed "s/[a-f0-9]*\.\.\./objid/" foo >actual && test_cmp expected actual ' @@ -284,7 +348,7 @@ test_expect_success 'revert --no-commit sets REVERT_HEAD' ' test_expect_success 'revert w/dirty tree does not set REVERT_HEAD' ' pristine_detach base && - echo foo > foo && + echo foo >foo && test_must_fail git revert base && test_must_fail git rev-parse --verify CHERRY_PICK_HEAD && test_must_fail git rev-parse --verify REVERT_HEAD @@ -316,10 +380,30 @@ test_expect_success 'failed commit does not clear REVERT_HEAD' ' test_cmp_rev picked REVERT_HEAD ' +test_expect_success 'successful final commit clears revert state' ' + 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_expect_success 'reset after final pick clears revert state' ' + 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_expect_success 'revert conflict, diff3 -m style' ' pristine_detach initial && git config merge.conflictstyle diff3 && - cat <<-EOF > expected && + cat <<-EOF >expected && <<<<<<< HEAD a ||||||| objid picked @@ -331,10 +415,56 @@ test_expect_success 'revert conflict, diff3 -m style' ' test_must_fail git revert picked && - sed "s/[a-f0-9]*\.\.\./objid/" foo > actual && + sed "s/[a-f0-9]*\.\.\./objid/" foo >actual && test_cmp expected actual ' +test_expect_success \ + 'revert conflict, ensure commit.cleanup = scissors places scissors line properly' ' + pristine_detach initial && + git config commit.cleanup scissors && + cat >expected <<-EOF && + Revert "picked" + + This reverts commit OBJID. + + # ------------------------ >8 ------------------------ + # Do not modify or remove the line above. + # Everything below it will be ignored. + # + # Conflicts: + # foo + EOF + + test_must_fail git revert picked && + + sed "s/$OID_REGEX/OBJID/" .git/MERGE_MSG >actual && + test_i18ncmp expected actual +' + +test_expect_success \ + 'revert conflict, ensure cleanup=scissors places scissors line properly' ' + pristine_detach initial && + git config --unset commit.cleanup && + cat >expected <<-EOF && + Revert "picked" + + This reverts commit OBJID. + + # ------------------------ >8 ------------------------ + # Do not modify or remove the line above. + # Everything below it will be ignored. + # + # Conflicts: + # foo + EOF + + test_must_fail git revert --cleanup=scissors picked && + + sed "s/$OID_REGEX/OBJID/" .git/MERGE_MSG >actual && + test_i18ncmp expected actual +' + test_expect_success 'failed cherry-pick does not forget -s' ' pristine_detach initial && test_must_fail git cherry-pick -s picked && @@ -345,7 +475,7 @@ test_expect_success 'commit after failed cherry-pick does not add duplicated -s' pristine_detach initial && test_must_fail git cherry-pick -s picked-signed && git commit -a -s && - test $(git show -s |grep -c "Signed-off-by") = 1 + test $(git show -s >tmp && grep -c "Signed-off-by" tmp && rm tmp) = 1 ' test_expect_success 'commit after failed cherry-pick adds -s at the right place' ' @@ -359,7 +489,7 @@ test_expect_success 'commit after failed cherry-pick adds -s at the right place' Signed-off-by: C O Mitter <committer@example.com> # Conflicts: EOF - grep -e "^# Conflicts:" -e '^Signed-off-by' <.git/COMMIT_EDITMSG >actual && + grep -e "^# Conflicts:" -e '^Signed-off-by' .git/COMMIT_EDITMSG >actual && test_cmp expect actual && cat <<-\EOF >expected && @@ -378,7 +508,7 @@ test_expect_success 'commit --amend -s places the sign-off at the right place' ' # emulate old-style conflicts block mv .git/MERGE_MSG .git/MERGE_MSG+ && - sed -e "/^# Conflicts:/,\$s/^# *//" <.git/MERGE_MSG+ >.git/MERGE_MSG && + sed -e "/^# Conflicts:/,\$s/^# *//" .git/MERGE_MSG+ >.git/MERGE_MSG && git commit -a && git commit --amend -s && @@ -388,7 +518,7 @@ test_expect_success 'commit --amend -s places the sign-off at the right place' ' Signed-off-by: C O Mitter <committer@example.com> Conflicts: EOF - grep -e "^Conflicts:" -e '^Signed-off-by' <.git/COMMIT_EDITMSG >actual && + grep -e "^Conflicts:" -e '^Signed-off-by' .git/COMMIT_EDITMSG >actual && test_cmp expect actual ' @@ -405,4 +535,23 @@ test_expect_success 'cherry-pick preserves sparse-checkout' ' test_i18ngrep ! "Changes not staged for commit:" actual ' +test_expect_success 'cherry-pick --continue remembers --keep-redundant-commits' ' + test_when_finished "git cherry-pick --abort || :" && + pristine_detach initial && + test_must_fail git cherry-pick --keep-redundant-commits picked redundant && + echo c >foo && + git add foo && + git cherry-pick --continue +' + +test_expect_success 'cherry-pick --continue remembers --allow-empty and --allow-empty-message' ' + test_when_finished "git cherry-pick --abort || :" && + pristine_detach initial && + test_must_fail git cherry-pick --allow-empty --allow-empty-message \ + picked empty && + echo c >foo && + git add foo && + git cherry-pick --continue +' + test_done diff --git a/t/t3511-cherry-pick-x.sh b/t/t3511-cherry-pick-x.sh index 9888bf34b9..84a587daf3 100755 --- a/t/t3511-cherry-pick-x.sh +++ b/t/t3511-cherry-pick-x.sh @@ -298,4 +298,24 @@ test_expect_success 'cherry-pick preserves commit message' ' test_cmp expect actual ' +test_expect_success 'cherry-pick -x cleans commit message' ' + pristine_detach initial && + git cherry-pick -x mesg-unclean && + git log -1 --pretty=format:%B >actual && + printf "%s\n(cherry picked from commit %s)\n" \ + "$mesg_unclean" $(git rev-parse mesg-unclean) | + git stripspace >expect && + test_cmp expect actual +' + +test_expect_success 'cherry-pick -x respects commit.cleanup' ' + pristine_detach initial && + git -c commit.cleanup=strip cherry-pick -x mesg-unclean && + git log -1 --pretty=format:%B >actual && + printf "%s\n(cherry picked from commit %s)\n" \ + "$mesg_unclean" $(git rev-parse mesg-unclean) | + git stripspace -s >expect && + test_cmp expect actual +' + test_done diff --git a/t/t3700-add.sh b/t/t3700-add.sh index be582a513b..c325167b90 100755 --- a/t/t3700-add.sh +++ b/t/t3700-add.sh @@ -296,6 +296,17 @@ test_expect_success '"git add ." in empty repo' ' ) ' +test_expect_success 'error on a repository with no commits' ' + rm -fr empty && + git init empty && + test_must_fail git add empty >actual 2>&1 && + cat >expect <<-EOF && + error: '"'empty/'"' does not have a commit checked out + fatal: adding files failed + EOF + test_i18ncmp expect actual +' + test_expect_success 'git add --dry-run of existing changed file' " echo new >>track-this && git add --dry-run track-this >actual 2>&1 && @@ -396,6 +407,7 @@ test_expect_success 'no file status change if no pathspec is given in subdir' ' ' test_expect_success 'all statuses changed in folder if . is given' ' + rm -fr empty && git add --chmod=+x . && test $(git ls-files --stage | grep ^100644 | wc -l) -eq 0 && git add --chmod=-x . && diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh index 65dfbc033a..69991a3168 100755 --- a/t/t3701-add-interactive.sh +++ b/t/t3701-add-interactive.sh @@ -639,4 +639,12 @@ test_expect_success 'add -p patch editing works with pathological context lines' test_cmp expected-2 actual ' +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 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 +' test_done diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh index 5f8272b6f9..b22e671608 100755 --- a/t/t3903-stash.sh +++ b/t/t3903-stash.sh @@ -8,22 +8,22 @@ test_description='Test git stash' . ./test-lib.sh test_expect_success 'stash some dirty working directory' ' - echo 1 > file && + echo 1 >file && git add file && echo unrelated >other-file && git add other-file && test_tick && git commit -m initial && - echo 2 > file && + echo 2 >file && git add file && - echo 3 > file && + echo 3 >file && test_tick && git stash && git diff-files --quiet && git diff-index --cached --quiet HEAD ' -cat > expect << EOF +cat >expect <<EOF diff --git a/file b/file index 0cfbf08..00750ed 100644 --- a/file @@ -35,7 +35,7 @@ EOF test_expect_success 'parents of stash' ' test $(git rev-parse stash^) = $(git rev-parse HEAD) && - git diff stash^2..stash > output && + git diff stash^2..stash >output && test_cmp expect output ' @@ -74,7 +74,7 @@ test_expect_success 'apply stashed changes' ' test_expect_success 'apply stashed changes (including index)' ' git reset --hard HEAD^ && - echo 6 > other-file && + echo 6 >other-file && git add other-file && test_tick && git commit -m other-file && @@ -99,12 +99,12 @@ test_expect_success 'stash drop complains of extra options' ' test_expect_success 'drop top stash' ' git reset --hard && - git stash list > stashlist1 && - echo 7 > file && + git stash list >expected && + echo 7 >file && git stash && git stash drop && - git stash list > stashlist2 && - test_cmp stashlist1 stashlist2 && + git stash list >actual && + test_cmp expected actual && git stash apply && test 3 = $(cat file) && test 1 = $(git show :file) && @@ -113,9 +113,9 @@ test_expect_success 'drop top stash' ' test_expect_success 'drop middle stash' ' git reset --hard && - echo 8 > file && + echo 8 >file && git stash && - echo 9 > file && + echo 9 >file && git stash && git stash drop stash@{1} && test 2 = $(git stash list | wc -l) && @@ -160,7 +160,7 @@ test_expect_success 'stash pop' ' test 0 = $(git stash list | wc -l) ' -cat > expect << EOF +cat >expect <<EOF diff --git a/file2 b/file2 new file mode 100644 index 0000000..1fe912c @@ -170,7 +170,7 @@ index 0000000..1fe912c +bar2 EOF -cat > expect1 << EOF +cat >expect1 <<EOF diff --git a/file b/file index 257cc56..5716ca5 100644 --- a/file @@ -180,7 +180,7 @@ index 257cc56..5716ca5 100644 +bar EOF -cat > expect2 << EOF +cat >expect2 <<EOF diff --git a/file b/file index 7601807..5716ca5 100644 --- a/file @@ -198,79 +198,79 @@ index 0000000..1fe912c EOF test_expect_success 'stash branch' ' - echo foo > file && + echo foo >file && git commit file -m first && - echo bar > file && - echo bar2 > file2 && + echo bar >file && + echo bar2 >file2 && git add file2 && git stash && - echo baz > file && + echo baz >file && git commit file -m second && git stash branch stashbranch && test refs/heads/stashbranch = $(git symbolic-ref HEAD) && test $(git rev-parse HEAD) = $(git rev-parse master^) && - git diff --cached > output && + git diff --cached >output && test_cmp expect output && - git diff > output && + git diff >output && test_cmp expect1 output && git add file && git commit -m alternate\ second && - git diff master..stashbranch > output && + git diff master..stashbranch >output && test_cmp output expect2 && test 0 = $(git stash list | wc -l) ' test_expect_success 'apply -q is quiet' ' - echo foo > file && + echo foo >file && git stash && - git stash apply -q > output.out 2>&1 && + git stash apply -q >output.out 2>&1 && test_must_be_empty output.out ' test_expect_success 'save -q is quiet' ' - git stash save --quiet > output.out 2>&1 && + git stash save --quiet >output.out 2>&1 && test_must_be_empty output.out ' test_expect_success 'pop -q is quiet' ' - git stash pop -q > output.out 2>&1 && + git stash pop -q >output.out 2>&1 && test_must_be_empty output.out ' test_expect_success 'pop -q --index works and is quiet' ' - echo foo > file && + echo foo >file && git add file && git stash save --quiet && - git stash pop -q --index > output.out 2>&1 && + git stash pop -q --index >output.out 2>&1 && test foo = "$(git show :file)" && test_must_be_empty output.out ' test_expect_success 'drop -q is quiet' ' git stash && - git stash drop -q > output.out 2>&1 && + git stash drop -q >output.out 2>&1 && test_must_be_empty output.out ' test_expect_success 'stash -k' ' - echo bar3 > file && - echo bar4 > file2 && + echo bar3 >file && + echo bar4 >file2 && git add file2 && git stash -k && test bar,bar4 = $(cat file),$(cat file2) ' test_expect_success 'stash --no-keep-index' ' - echo bar33 > file && - echo bar44 > file2 && + echo bar33 >file && + echo bar44 >file2 && git add file2 && git stash --no-keep-index && test bar,bar2 = $(cat file),$(cat file2) ' test_expect_success 'stash --invalid-option' ' - echo bar5 > file && - echo bar6 > file2 && + echo bar5 >file && + echo bar6 >file2 && git add file2 && test_must_fail git stash --invalid-option && test_must_fail git stash save --invalid-option && @@ -287,6 +287,14 @@ test_expect_success 'stash an added file' ' test new = "$(cat file3)" ' +test_expect_success 'stash --intent-to-add file' ' + git reset --hard && + echo new >file4 && + git add --intent-to-add file4 && + test_when_finished "git rm -f file4" && + test_must_fail git stash +' + test_expect_success 'stash rm then recreate' ' git reset --hard && git rm file && @@ -444,6 +452,36 @@ test_expect_failure 'stash file to directory' ' test foo = "$(cat file/file)" ' +test_expect_success 'giving too many ref arguments does not modify files' ' + git stash clear && + test_when_finished "git reset --hard HEAD" && + echo foo >file2 && + git stash && + echo bar >file2 && + git stash && + test-tool chmtime =123456789 file2 && + for type in apply pop "branch stash-branch" + do + test_must_fail git stash $type stash@{0} stash@{1} 2>err && + test_i18ngrep "Too many revisions" err && + test 123456789 = $(test-tool chmtime -g file2) || return 1 + done +' + +test_expect_success 'drop: too many arguments errors out (does nothing)' ' + git stash list >expect && + test_must_fail git stash drop stash@{0} stash@{1} 2>err && + test_i18ngrep "Too many revisions" err && + git stash list >actual && + test_cmp expect actual +' + +test_expect_success 'show: too many arguments errors out (does nothing)' ' + test_must_fail git stash show stash@{0} stash@{1} 2>err 1>out && + test_i18ngrep "Too many revisions" err && + test_must_be_empty out +' + test_expect_success 'stash create - no changes' ' git stash clear && test_when_finished "git reset --hard HEAD" && @@ -456,11 +494,12 @@ test_expect_success 'stash branch - no stashes on stack, stash-like argument' ' git stash clear && test_when_finished "git reset --hard HEAD" && git reset --hard && - echo foo >> file && + echo foo >>file && STASH_ID=$(git stash create) && git reset --hard && git stash branch stash-branch ${STASH_ID} && - test_when_finished "git reset --hard HEAD && git checkout master && git branch -D stash-branch" && + test_when_finished "git reset --hard HEAD && git checkout master && + git branch -D stash-branch" && test $(git ls-files --modified | wc -l) -eq 1 ' @@ -468,25 +507,31 @@ test_expect_success 'stash branch - stashes on stack, stash-like argument' ' git stash clear && test_when_finished "git reset --hard HEAD" && git reset --hard && - echo foo >> file && + echo foo >>file && git stash && test_when_finished "git stash drop" && - echo bar >> file && + echo bar >>file && STASH_ID=$(git stash create) && git reset --hard && git stash branch stash-branch ${STASH_ID} && - test_when_finished "git reset --hard HEAD && git checkout master && git branch -D stash-branch" && + test_when_finished "git reset --hard HEAD && git checkout master && + git branch -D stash-branch" && test $(git ls-files --modified | wc -l) -eq 1 ' +test_expect_success 'stash branch complains with no arguments' ' + test_must_fail git stash branch 2>err && + test_i18ngrep "No branch name specified" err +' + test_expect_success 'stash show format defaults to --stat' ' git stash clear && test_when_finished "git reset --hard HEAD" && git reset --hard && - echo foo >> file && + echo foo >>file && git stash && test_when_finished "git stash drop" && - echo bar >> file && + echo bar >>file && STASH_ID=$(git stash create) && git reset --hard && cat >expected <<-EOF && @@ -501,10 +546,10 @@ test_expect_success 'stash show - stashes on stack, stash-like argument' ' git stash clear && test_when_finished "git reset --hard HEAD" && git reset --hard && - echo foo >> file && + echo foo >>file && git stash && test_when_finished "git stash drop" && - echo bar >> file && + echo bar >>file && STASH_ID=$(git stash create) && git reset --hard && echo "1 0 file" >expected && @@ -516,10 +561,10 @@ test_expect_success 'stash show -p - stashes on stack, stash-like argument' ' git stash clear && test_when_finished "git reset --hard HEAD" && git reset --hard && - echo foo >> file && + echo foo >>file && git stash && test_when_finished "git stash drop" && - echo bar >> file && + echo bar >>file && STASH_ID=$(git stash create) && git reset --hard && cat >expected <<-EOF && @@ -539,7 +584,7 @@ test_expect_success 'stash show - no stashes on stack, stash-like argument' ' git stash clear && test_when_finished "git reset --hard HEAD" && git reset --hard && - echo foo >> file && + echo foo >>file && STASH_ID=$(git stash create) && git reset --hard && echo "1 0 file" >expected && @@ -551,7 +596,7 @@ test_expect_success 'stash show -p - no stashes on stack, stash-like argument' ' git stash clear && test_when_finished "git reset --hard HEAD" && git reset --hard && - echo foo >> file && + echo foo >>file && STASH_ID=$(git stash create) && git reset --hard && cat >expected <<-EOF && @@ -567,13 +612,31 @@ test_expect_success 'stash show -p - no stashes on stack, stash-like argument' ' test_cmp expected actual ' -test_expect_success 'stash drop - fail early if specified stash is not a stash reference' ' +test_expect_success 'stash show --patience shows diff' ' + git reset --hard && + echo foo >>file && + STASH_ID=$(git stash create) && + git reset --hard && + cat >expected <<-EOF && + diff --git a/file b/file + index 7601807..71b52c4 100644 + --- a/file + +++ b/file + @@ -1 +1,2 @@ + baz + +foo + EOF + git stash show --patience ${STASH_ID} >actual && + test_cmp expected actual +' + +test_expect_success 'drop: fail early if specified stash is not a stash ref' ' git stash clear && test_when_finished "git reset --hard HEAD && git stash clear" && git reset --hard && - echo foo > file && + echo foo >file && git stash && - echo bar > file && + echo bar >file && git stash && test_must_fail git stash drop $(git rev-parse stash@{0}) && git stash pop && @@ -581,13 +644,13 @@ test_expect_success 'stash drop - fail early if specified stash is not a stash r git reset --hard HEAD ' -test_expect_success 'stash pop - fail early if specified stash is not a stash reference' ' +test_expect_success 'pop: fail early if specified stash is not a stash ref' ' git stash clear && test_when_finished "git reset --hard HEAD && git stash clear" && git reset --hard && - echo foo > file && + echo foo >file && git stash && - echo bar > file && + echo bar >file && git stash && test_must_fail git stash pop $(git rev-parse stash@{0}) && git stash pop && @@ -597,8 +660,8 @@ test_expect_success 'stash pop - fail early if specified stash is not a stash re test_expect_success 'ref with non-existent reflog' ' git stash clear && - echo bar5 > file && - echo bar6 > file2 && + echo bar5 >file && + echo bar6 >file2 && git add file2 && git stash && test_must_fail git rev-parse --quiet --verify does-not-exist && @@ -618,8 +681,8 @@ test_expect_success 'ref with non-existent reflog' ' test_expect_success 'invalid ref of the form stash@{n}, n >= N' ' git stash clear && test_must_fail git stash drop stash@{0} && - echo bar5 > file && - echo bar6 > file2 && + echo bar5 >file && + echo bar6 >file2 && git add file2 && git stash && test_must_fail git stash drop stash@{1} && @@ -645,7 +708,25 @@ test_expect_success 'invalid ref of the form "n", n >= N' ' git stash drop ' -test_expect_success 'stash branch should not drop the stash if the branch exists' ' +test_expect_success 'valid ref of the form "n", n < N' ' + git stash clear && + echo bar5 >file && + echo bar6 >file2 && + git add file2 && + git stash && + git stash show 0 && + git stash branch tmp 0 && + git checkout master && + git stash && + git stash apply 0 && + git reset --hard && + git stash pop 0 && + git stash && + git stash drop 0 && + test_must_fail git stash drop +' + +test_expect_success 'branch: do not drop the stash if the branch exists' ' git stash clear && echo foo >file && git add file && @@ -656,7 +737,7 @@ test_expect_success 'stash branch should not drop the stash if the branch exists git rev-parse stash@{0} -- ' -test_expect_success 'stash branch should not drop the stash if the apply fails' ' +test_expect_success 'branch: should not drop the stash if the apply fails' ' git stash clear && git reset HEAD~1 --hard && echo foo >file && @@ -670,7 +751,7 @@ test_expect_success 'stash branch should not drop the stash if the apply fails' git rev-parse stash@{0} -- ' -test_expect_success 'stash apply shows status same as git status (relative to current directory)' ' +test_expect_success 'apply: show same status as git status (relative to ./)' ' git stash clear && echo 1 >subdir/subfile1 && echo 2 >subdir/subfile2 && @@ -689,7 +770,7 @@ test_expect_success 'stash apply shows status same as git status (relative to cu test_i18ncmp expect actual ' -cat > expect << EOF +cat >expect <<EOF diff --git a/HEAD b/HEAD new file mode 100644 index 0000000..fe0cbee @@ -702,14 +783,14 @@ EOF test_expect_success 'stash where working directory contains "HEAD" file' ' git stash clear && git reset --hard && - echo file-not-a-ref > HEAD && + echo file-not-a-ref >HEAD && git add HEAD && test_tick && git stash && git diff-files --quiet && git diff-index --cached --quiet HEAD && test "$(git rev-parse stash^)" = "$(git rev-parse HEAD)" && - git diff stash^..stash > output && + git diff stash^..stash >output && test_cmp expect output ' @@ -1011,7 +1092,7 @@ test_expect_success 'stash push -p with pathspec shows no changes only once' ' test_i18ncmp expect actual ' -test_expect_success 'stash push with pathspec shows no changes when there are none' ' +test_expect_success 'push <pathspec>: show no changes when there are none' ' >foo && git add foo && git commit -m "tmp" && @@ -1021,12 +1102,35 @@ test_expect_success 'stash push with pathspec shows no changes when there are no test_i18ncmp expect actual ' -test_expect_success 'stash push with pathspec not in the repository errors out' ' +test_expect_success 'push: <pathspec> not in the repository errors out' ' >untracked && test_must_fail git stash push untracked && test_path_is_file untracked ' +test_expect_success 'push: -q is quiet with changes' ' + >foo && + git add foo && + git stash push -q >output 2>&1 && + test_must_be_empty output +' + +test_expect_success 'push: -q is quiet with no changes' ' + git stash push -q >output 2>&1 && + test_must_be_empty output +' + +test_expect_success 'push: -q is quiet even if there is no initial commit' ' + git init foo_dir && + test_when_finished rm -rf foo_dir && + ( + cd foo_dir && + >bar && + test_must_fail git stash push -q >output 2>&1 && + test_must_be_empty output + ) +' + test_expect_success 'untracked files are left in place when -u is not given' ' >file && git add file && @@ -1096,6 +1200,12 @@ test_expect_success 'stash -- <subdir> works with binary files' ' test_path_is_file subdir/untracked ' +test_expect_success 'stash with user.name and user.email set works' ' + test_config user.name "A U Thor" && + test_config user.email "a.u@thor" && + git stash +' + test_expect_success 'stash works when user.name and user.email are not set' ' git reset && >1 && diff --git a/t/t3905-stash-include-untracked.sh b/t/t3905-stash-include-untracked.sh index cc1c8a7bb2..29ca76f2fb 100755 --- a/t/t3905-stash-include-untracked.sh +++ b/t/t3905-stash-include-untracked.sh @@ -283,4 +283,10 @@ test_expect_success 'stash -u -- <non-existant> shows no changes when there are test_i18ncmp expect actual ' +test_expect_success 'stash -u with globs' ' + >untracked.txt && + git stash -u -- ":(glob)**/*.txt" && + test_path_is_missing untracked.txt +' + test_done diff --git a/t/t3907-stash-show-config.sh b/t/t3907-stash-show-config.sh new file mode 100755 index 0000000000..10914bba7b --- /dev/null +++ b/t/t3907-stash-show-config.sh @@ -0,0 +1,83 @@ +#!/bin/sh + +test_description='Test git stash show configuration.' + +. ./test-lib.sh + +test_expect_success 'setup' ' + test_commit file +' + +# takes three parameters: +# 1. the stash.showStat value (or "<unset>") +# 2. the stash.showPatch value (or "<unset>") +# 3. the diff options of the expected output (or nothing for no output) +test_stat_and_patch () { + if test "<unset>" = "$1" + then + test_unconfig stash.showStat + else + test_config stash.showStat "$1" + fi && + + if test "<unset>" = "$2" + then + test_unconfig stash.showPatch + else + test_config stash.showPatch "$2" + fi && + + shift 2 && + echo 2 >file.t && + if test $# != 0 + then + git diff "$@" >expect + fi && + git stash && + git stash show >actual && + + if test $# = 0 + then + test_must_be_empty actual + else + test_cmp expect actual + fi +} + +test_expect_success 'showStat unset showPatch unset' ' + test_stat_and_patch "<unset>" "<unset>" --stat +' + +test_expect_success 'showStat unset showPatch false' ' + test_stat_and_patch "<unset>" false --stat +' + +test_expect_success 'showStat unset showPatch true' ' + test_stat_and_patch "<unset>" true --stat -p +' + +test_expect_success 'showStat false showPatch unset' ' + test_stat_and_patch false "<unset>" +' + +test_expect_success 'showStat false showPatch false' ' + test_stat_and_patch false false +' + +test_expect_success 'showStat false showPatch true' ' + test_stat_and_patch false true -p +' + +test_expect_success 'showStat true showPatch unset' ' + test_stat_and_patch true "<unset>" --stat +' + +test_expect_success 'showStat true showPatch false' ' + test_stat_and_patch true false --stat +' + +test_expect_success 'showStat true showPatch true' ' + test_stat_and_patch true true --stat -p +' + +test_done diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh index 9f8f0e84ad..a9054d2db1 100755 --- a/t/t4013-diff-various.sh +++ b/t/t4013-diff-various.sh @@ -338,6 +338,8 @@ format-patch --inline --stdout initial..master^^ format-patch --stdout --cover-letter -n initial..master^ diff --abbrev initial..side +diff -U initial..side +diff -U1 initial..side diff -r initial..side diff --stat initial..side diff -r --stat initial..side diff --git a/t/t4013/diff.diff_-U1_initial..side b/t/t4013/diff.diff_-U1_initial..side new file mode 100644 index 0000000000..b69f8f048a --- /dev/null +++ b/t/t4013/diff.diff_-U1_initial..side @@ -0,0 +1,29 @@ +$ git diff -U1 initial..side +diff --git a/dir/sub b/dir/sub +index 35d242b..7289e35 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -2 +2,3 @@ A + B ++1 ++2 +diff --git a/file0 b/file0 +index 01e79c3..f4615da 100644 +--- a/file0 ++++ b/file0 +@@ -3 +3,4 @@ + 3 ++A ++B ++C +diff --git a/file3 b/file3 +new file mode 100644 +index 0000000..7289e35 +--- /dev/null ++++ b/file3 +@@ -0,0 +1,4 @@ ++A ++B ++1 ++2 +$ diff --git a/t/t4013/diff.diff_-U2_initial..side b/t/t4013/diff.diff_-U2_initial..side new file mode 100644 index 0000000000..8ffe04f203 --- /dev/null +++ b/t/t4013/diff.diff_-U2_initial..side @@ -0,0 +1,31 @@ +$ git diff -U2 initial..side +diff --git a/dir/sub b/dir/sub +index 35d242b..7289e35 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++1 ++2 +diff --git a/file0 b/file0 +index 01e79c3..f4615da 100644 +--- a/file0 ++++ b/file0 +@@ -2,2 +2,5 @@ + 2 + 3 ++A ++B ++C +diff --git a/file3 b/file3 +new file mode 100644 +index 0000000..7289e35 +--- /dev/null ++++ b/file3 +@@ -0,0 +1,4 @@ ++A ++B ++1 ++2 +$ diff --git a/t/t4013/diff.diff_-U_initial..side b/t/t4013/diff.diff_-U_initial..side new file mode 100644 index 0000000000..c66c0dd5c6 --- /dev/null +++ b/t/t4013/diff.diff_-U_initial..side @@ -0,0 +1,32 @@ +$ git diff -U initial..side +diff --git a/dir/sub b/dir/sub +index 35d242b..7289e35 100644 +--- a/dir/sub ++++ b/dir/sub +@@ -1,2 +1,4 @@ + A + B ++1 ++2 +diff --git a/file0 b/file0 +index 01e79c3..f4615da 100644 +--- a/file0 ++++ b/file0 +@@ -1,3 +1,6 @@ + 1 + 2 + 3 ++A ++B ++C +diff --git a/file3 b/file3 +new file mode 100644 +index 0000000..7289e35 +--- /dev/null ++++ b/file3 +@@ -0,0 +1,4 @@ ++A ++B ++1 ++2 +$ diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh index b6e2fdbc44..ca7debf1d4 100755 --- a/t/t4014-format-patch.sh +++ b/t/t4014-format-patch.sh @@ -36,8 +36,27 @@ test_expect_success setup ' git checkout master && git diff-tree -p C2 | git apply --index && test_tick && - git commit -m "Master accepts moral equivalent of #2" + git commit -m "Master accepts moral equivalent of #2" && + git checkout side && + git checkout -b patchid && + for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file2 && + for i in 1 2 3 A 4 B C 7 8 9 10 D E F 5 6; do echo "$i"; done >file3 && + for i in 8 9 10; do echo "$i"; done >file && + git add file file2 file3 && + test_tick && + git commit -m "patchid 1" && + for i in 4 A B 7 8 9 10; do echo "$i"; done >file2 && + for i in 8 9 10 5 6; do echo "$i"; done >file3 && + git add file2 file3 && + test_tick && + git commit -m "patchid 2" && + for i in 10 5 6; do echo "$i"; done >file && + git add file && + test_tick && + git commit -m "patchid 3" && + + git checkout master ' test_expect_success "format-patch --ignore-if-in-upstream" ' @@ -738,6 +757,76 @@ test_expect_success 'format-patch --notes --signoff' ' sed "1,/^---$/d" out | grep "test message" ' +test_expect_success 'format-patch notes output control' ' + git notes add -m "notes config message" HEAD && + test_when_finished git notes remove HEAD && + + git format-patch -1 --stdout >out && + ! grep "notes config message" out && + git format-patch -1 --stdout --notes >out && + grep "notes config message" out && + git format-patch -1 --stdout --no-notes >out && + ! grep "notes config message" out && + git format-patch -1 --stdout --notes --no-notes >out && + ! grep "notes config message" out && + git format-patch -1 --stdout --no-notes --notes >out && + grep "notes config message" out && + + test_config format.notes true && + git format-patch -1 --stdout >out && + grep "notes config message" out && + git format-patch -1 --stdout --notes >out && + grep "notes config message" out && + git format-patch -1 --stdout --no-notes >out && + ! grep "notes config message" out && + git format-patch -1 --stdout --notes --no-notes >out && + ! grep "notes config message" out && + git format-patch -1 --stdout --no-notes --notes >out && + grep "notes config message" out +' + +test_expect_success 'format-patch with multiple notes refs' ' + git notes --ref note1 add -m "this is note 1" HEAD && + test_when_finished git notes --ref note1 remove HEAD && + git notes --ref note2 add -m "this is note 2" HEAD && + test_when_finished git notes --ref note2 remove HEAD && + + git format-patch -1 --stdout >out && + ! grep "this is note 1" out && + ! grep "this is note 2" out && + git format-patch -1 --stdout --notes=note1 >out && + grep "this is note 1" out && + ! grep "this is note 2" out && + git format-patch -1 --stdout --notes=note2 >out && + ! grep "this is note 1" out && + grep "this is note 2" out && + git format-patch -1 --stdout --notes=note1 --notes=note2 >out && + grep "this is note 1" out && + grep "this is note 2" out && + + test_config format.notes note1 && + git format-patch -1 --stdout >out && + grep "this is note 1" out && + ! grep "this is note 2" out && + git format-patch -1 --stdout --no-notes >out && + ! grep "this is note 1" out && + ! grep "this is note 2" out && + git format-patch -1 --stdout --notes=note2 >out && + grep "this is note 1" out && + grep "this is note 2" out && + git format-patch -1 --stdout --no-notes --notes=note2 >out && + ! grep "this is note 1" out && + grep "this is note 2" out && + + git config --add format.notes note2 && + git format-patch -1 --stdout >out && + grep "this is note 1" out && + grep "this is note 2" out && + git format-patch -1 --stdout --no-notes >out && + ! grep "this is note 1" out && + ! grep "this is note 2" out +' + echo "fatal: --name-only does not make sense" > expect.name-only echo "fatal: --name-status does not make sense" > expect.name-status echo "fatal: --check does not make sense" > expect.check @@ -1559,7 +1648,7 @@ test_expect_success 'format-patch -o overrides format.outputDirectory' ' ' test_expect_success 'format-patch --base' ' - git checkout side && + git checkout patchid && git format-patch --stdout --base=HEAD~3 -1 | tail -n 7 >actual1 && git format-patch --stdout --base=HEAD~3 HEAD~.. | tail -n 7 >actual2 && echo >expected && @@ -1568,7 +1657,14 @@ test_expect_success 'format-patch --base' ' echo "prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --stable | awk "{print \$1}")" >>expected && signature >> expected && test_cmp expected actual1 && - test_cmp expected actual2 + test_cmp expected actual2 && + echo >fail && + echo "base-commit: $(git rev-parse HEAD~3)" >>fail && + echo "prerequisite-patch-id: $(git show --patch HEAD~2 | git patch-id --unstable | awk "{print \$1}")" >>fail && + echo "prerequisite-patch-id: $(git show --patch HEAD~1 | git patch-id --unstable | awk "{print \$1}")" >>fail && + signature >> fail && + ! test_cmp fail actual1 && + ! test_cmp fail actual2 ' test_expect_success 'format-patch --base errors out when base commit is in revision list' ' diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh index 22f9f88f0a..9261d6d3a0 100755 --- a/t/t4018-diff-funcname.sh +++ b/t/t4018-diff-funcname.sh @@ -43,6 +43,7 @@ diffpatterns=" php python ruby + rust tex custom1 custom2 diff --git a/t/t4018/matlab-class-definition b/t/t4018/matlab-class-definition new file mode 100644 index 0000000000..84daedfb4e --- /dev/null +++ b/t/t4018/matlab-class-definition @@ -0,0 +1,5 @@ +classdef RIGHT + properties + ChangeMe + end +end diff --git a/t/t4018/matlab-function b/t/t4018/matlab-function new file mode 100644 index 0000000000..897a9b13ff --- /dev/null +++ b/t/t4018/matlab-function @@ -0,0 +1,4 @@ +function y = RIGHT() +x = 5; +y = ChangeMe + x; +end diff --git a/t/t4018/matlab-octave-section-1 b/t/t4018/matlab-octave-section-1 new file mode 100644 index 0000000000..3bb6c4670e --- /dev/null +++ b/t/t4018/matlab-octave-section-1 @@ -0,0 +1,3 @@ +%%% RIGHT section +# this is octave script +ChangeMe = 1; diff --git a/t/t4018/matlab-octave-section-2 b/t/t4018/matlab-octave-section-2 new file mode 100644 index 0000000000..ab2980f7f2 --- /dev/null +++ b/t/t4018/matlab-octave-section-2 @@ -0,0 +1,3 @@ +## RIGHT section +# this is octave script +ChangeMe = 1; diff --git a/t/t4018/matlab-section b/t/t4018/matlab-section new file mode 100644 index 0000000000..5ea59a5de0 --- /dev/null +++ b/t/t4018/matlab-section @@ -0,0 +1,3 @@ +%% RIGHT section +% this is understood by both matlab and octave +ChangeMe = 1; diff --git a/t/t4018/rust-fn b/t/t4018/rust-fn new file mode 100644 index 0000000000..cbe02155f1 --- /dev/null +++ b/t/t4018/rust-fn @@ -0,0 +1,5 @@ +pub(self) fn RIGHT<T>(x: &[T]) where T: Debug { + let _ = x; + // a comment + let a = ChangeMe; +} diff --git a/t/t4018/rust-impl b/t/t4018/rust-impl new file mode 100644 index 0000000000..09df3cd93b --- /dev/null +++ b/t/t4018/rust-impl @@ -0,0 +1,5 @@ +impl<'a, T: AsRef<[u8]>> std::RIGHT for Git<'a> { + + pub fn ChangeMe(&self) -> () { + } +} diff --git a/t/t4018/rust-struct b/t/t4018/rust-struct new file mode 100644 index 0000000000..76aff1c0d8 --- /dev/null +++ b/t/t4018/rust-struct @@ -0,0 +1,5 @@ +#[derive(Debug)] +pub(super) struct RIGHT<'a> { + name: &'a str, + age: ChangeMe, +} diff --git a/t/t4018/rust-trait b/t/t4018/rust-trait new file mode 100644 index 0000000000..ea397f09ed --- /dev/null +++ b/t/t4018/rust-trait @@ -0,0 +1,5 @@ +unsafe trait RIGHT<T> { + fn len(&self) -> u32; + fn ChangeMe(&self, n: u32) -> T; + fn iter<F>(&self, f: F) where F: Fn(T); +} diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh index 4331b3118a..0168946b63 100755 --- a/t/t4053-diff-no-index.sh +++ b/t/t4053-diff-no-index.sh @@ -50,8 +50,7 @@ test_expect_success 'git diff --no-index executed outside repo gives correct err export GIT_CEILING_DIRECTORIES && cd non/git && test_must_fail git diff --no-index a 2>actual.err && - echo "usage: git diff --no-index <path> <path>" >expect.err && - test_cmp expect.err actual.err + test_i18ngrep "usage: git diff --no-index" actual.err ) ' diff --git a/t/t4067-diff-partial-clone.sh b/t/t4067-diff-partial-clone.sh new file mode 100755 index 0000000000..90c8fb2901 --- /dev/null +++ b/t/t4067-diff-partial-clone.sh @@ -0,0 +1,103 @@ +#!/bin/sh + +test_description='behavior of diff when reading objects in a partial clone' + +. ./test-lib.sh + +test_expect_success 'git show batches blobs' ' + test_when_finished "rm -rf server client trace" && + + test_create_repo server && + echo a >server/a && + echo b >server/b && + git -C server add a b && + git -C server commit -m x && + + test_config -C server uploadpack.allowfilter 1 && + test_config -C server uploadpack.allowanysha1inwant 1 && + git clone --bare --filter=blob:limit=0 "file://$(pwd)/server" client && + + # 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 show HEAD && + grep "git> done" trace >done_lines && + test_line_count = 1 done_lines +' + +test_expect_success 'diff batches blobs' ' + test_when_finished "rm -rf server client trace" && + + test_create_repo server && + echo a >server/a && + echo b >server/b && + git -C server add a b && + git -C server commit -m x && + echo c >server/c && + echo d >server/d && + git -C server add c d && + git -C server commit -m x && + + test_config -C server uploadpack.allowfilter 1 && + test_config -C server uploadpack.allowanysha1inwant 1 && + git clone --bare --filter=blob:limit=0 "file://$(pwd)/server" client && + + # 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 HEAD^ HEAD && + grep "git> done" trace >done_lines && + test_line_count = 1 done_lines +' + +test_expect_success 'diff skips same-OID blobs' ' + test_when_finished "rm -rf server client trace" && + + test_create_repo server && + echo a >server/a && + echo b >server/b && + git -C server add a b && + git -C server commit -m x && + echo another-a >server/a && + git -C server add a && + git -C server commit -m x && + + test_config -C server uploadpack.allowfilter 1 && + test_config -C server uploadpack.allowanysha1inwant 1 && + git clone --bare --filter=blob:limit=0 "file://$(pwd)/server" client && + + echo a | git hash-object --stdin >hash-old-a && + echo another-a | git hash-object --stdin >hash-new-a && + echo b | git hash-object --stdin >hash-b && + + # Ensure that only a and another-a are fetched. + GIT_TRACE_PACKET="$(pwd)/trace" git -C client diff HEAD^ HEAD && + grep "want $(cat hash-old-a)" trace && + grep "want $(cat hash-new-a)" trace && + ! grep "want $(cat hash-b)" trace +' + +test_expect_success 'diff with rename detection batches blobs' ' + 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 && + rm server/b && + printf "b\nb\nb\nb\nbX\n" >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 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 -M HEAD^ HEAD >out && + grep "similarity index" out && + grep "git> done" trace >done_lines && + test_line_count = 1 done_lines +' + +test_done diff --git a/t/t4202-log.sh b/t/t4202-log.sh index 819c24d10e..c20209324c 100755 --- a/t/t4202-log.sh +++ b/t/t4202-log.sh @@ -352,7 +352,7 @@ test_expect_success 'log with grep.patternType configuration and command line' ' test_cmp expect actual ' -test_expect_success 'log with various grep.patternType configurations & command-lines' ' +test_expect_success !FAIL_PREREQS 'log with various grep.patternType configurations & command-lines' ' git init pattern-type && ( cd pattern-type && diff --git a/t/t4253-am-keep-cr-dos.sh b/t/t4253-am-keep-cr-dos.sh index 553fe3e88e..6e1b73ec3a 100755 --- a/t/t4253-am-keep-cr-dos.sh +++ b/t/t4253-am-keep-cr-dos.sh @@ -51,14 +51,16 @@ test_expect_success 'am with dos files without --keep-cr' ' test_expect_success 'am with dos files with --keep-cr' ' git checkout -b dosfiles-keep-cr initial && - git format-patch -k --stdout initial..master | git am --keep-cr -k -3 && + git format-patch -k --stdout initial..master >output && + git am --keep-cr -k -3 output && git diff --exit-code master ' test_expect_success 'am with dos files config am.keepcr' ' git config am.keepcr 1 && git checkout -b dosfiles-conf-keepcr initial && - git format-patch -k --stdout initial..master | git am -k -3 && + git format-patch -k --stdout initial..master >output && + git am -k -3 output && git diff --exit-code master ' diff --git a/t/t4257-am-interactive.sh b/t/t4257-am-interactive.sh new file mode 100755 index 0000000000..5344bd248a --- /dev/null +++ b/t/t4257-am-interactive.sh @@ -0,0 +1,52 @@ +#!/bin/sh + +test_description='am --interactive tests' +. ./test-lib.sh + +test_expect_success 'set up patches to apply' ' + test_commit unrelated && + test_commit no-conflict && + test_commit conflict-patch file patch && + git format-patch --stdout -2 >mbox && + + git reset --hard unrelated && + test_commit conflict-master file master base +' + +# Sanity check our setup. +test_expect_success 'applying all patches generates conflict' ' + test_must_fail git am mbox && + echo resolved >file && + git add -u && + git am --resolved +' + +test_expect_success 'interactive am can apply a single patch' ' + git reset --hard base && + # apply the first, but not the second + test_write_lines y n | git am -i mbox && + + echo no-conflict >expect && + git log -1 --format=%s >actual && + test_cmp expect actual +' + +test_expect_success 'interactive am can resolve conflict' ' + git reset --hard base && + # apply both; the second one will conflict + test_write_lines y y | test_must_fail git am -i mbox && + echo resolved >file && + git add -u && + # interactive "--resolved" will ask us if we want to apply the result + echo y | git am -i --resolved && + + echo conflict-patch >expect && + git log -1 --format=%s >actual && + test_cmp expect actual && + + echo resolved >expect && + git cat-file blob HEAD:file >actual && + test_cmp expect actual +' + +test_done diff --git a/t/t5150-request-pull.sh b/t/t5150-request-pull.sh index fca001eb9b..852dcd913f 100755 --- a/t/t5150-request-pull.sh +++ b/t/t5150-request-pull.sh @@ -246,4 +246,57 @@ test_expect_success 'request-pull ignores OPTIONS_KEEPDASHDASH poison' ' ' +test_expect_success 'request-pull quotes regex metacharacters properly' ' + + rm -fr downstream.git && + git init --bare downstream.git && + ( + cd local && + git checkout initial && + git merge --ff-only master && + git tag -mrelease v2.0 && + git push origin refs/tags/v2.0:refs/tags/v2-0 && + test_must_fail git request-pull initial "$downstream_url" tags/v2.0 \ + 2>../err + ) && + grep "No match for commit .*" err && + grep "Are you sure you pushed" err + +' + +test_expect_success 'pull request with mismatched object' ' + + rm -fr downstream.git && + git init --bare downstream.git && + ( + cd local && + git checkout initial && + git merge --ff-only master && + git push origin HEAD:refs/tags/full && + test_must_fail git request-pull initial "$downstream_url" tags/full \ + 2>../err + ) && + grep "points to a different object" err && + grep "Are you sure you pushed" err + +' + +test_expect_success 'pull request with stale object' ' + + rm -fr downstream.git && + git init --bare downstream.git && + ( + cd local && + git checkout initial && + git merge --ff-only master && + git push origin refs/tags/full && + git tag -f -m"Thirty-one days" full && + test_must_fail git request-pull initial "$downstream_url" tags/full \ + 2>../err + ) && + grep "points to a different object" err && + grep "Are you sure you pushed" err + +' + test_done diff --git a/t/t5200-update-server-info.sh b/t/t5200-update-server-info.sh new file mode 100755 index 0000000000..21a58eecb9 --- /dev/null +++ b/t/t5200-update-server-info.sh @@ -0,0 +1,41 @@ +#!/bin/sh + +test_description='Test git update-server-info' + +. ./test-lib.sh + +test_expect_success 'setup' 'test_commit file' + +test_expect_success 'create info/refs' ' + git update-server-info && + test_path_is_file .git/info/refs +' + +test_expect_success 'modify and store mtime' ' + test-tool chmtime =0 .git/info/refs && + test-tool chmtime --get .git/info/refs >a +' + +test_expect_success 'info/refs is not needlessly overwritten' ' + git update-server-info && + test-tool chmtime --get .git/info/refs >b && + test_cmp a b +' + +test_expect_success 'info/refs can be forced to update' ' + git update-server-info -f && + test-tool chmtime --get .git/info/refs >b && + ! test_cmp a b +' + +test_expect_success 'info/refs updates when changes are made' ' + test-tool chmtime =0 .git/info/refs && + test-tool chmtime --get .git/info/refs >b && + test_cmp a b && + git update-ref refs/heads/foo HEAD && + git update-server-info && + test-tool chmtime --get .git/info/refs >b && + ! test_cmp a b +' + +test_done diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh index 1eeb828a15..df60f18fb8 100755 --- a/t/t5304-prune.sh +++ b/t/t5304-prune.sh @@ -341,4 +341,12 @@ test_expect_success 'prune: handle expire option correctly' ' git prune --no-expire ' +test_expect_success 'trivial prune with bitmaps enabled' ' + git repack -adb && + blob=$(echo bitmap-unreachable-blob | git hash-object -w --stdin) && + git prune --expire=now && + git cat-file -e HEAD && + test_must_fail git cat-file -e $blob +' + test_done diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh index 82d7f7f6a5..a26c8ba9a2 100755 --- a/t/t5310-pack-bitmaps.sh +++ b/t/t5310-pack-bitmaps.sh @@ -34,8 +34,7 @@ test_expect_success 'setup repo with moderate-sized history' ' bitmaptip=$(git rev-parse master) && blob=$(echo tagged-blob | git hash-object -w --stdin) && git tag tagged-blob $blob && - git config repack.writebitmaps true && - git config pack.writebitmaphashcache true + git config repack.writebitmaps true ' test_expect_success 'full repack creates bitmaps' ' @@ -269,7 +268,7 @@ test_expect_success JGIT 'we can read jgit bitmaps' ' git clone --bare . compat-jgit.git && ( cd compat-jgit.git && - rm -f .git/objects/pack/*.bitmap && + rm -f objects/pack/*.bitmap && jgit gc && git rev-list --test-bitmap HEAD ) diff --git a/t/t5317-pack-objects-filter-objects.sh b/t/t5317-pack-objects-filter-objects.sh index 24541ea137..2d2f5d0229 100755 --- a/t/t5317-pack-objects-filter-objects.sh +++ b/t/t5317-pack-objects-filter-objects.sh @@ -25,7 +25,7 @@ test_expect_success 'verify blob count in normal packfile' ' awk -f print_2.awk ls_files_result | sort >expected && - git -C r1 pack-objects --rev --stdout >all.pack <<-EOF && + git -C r1 pack-objects --revs --stdout >all.pack <<-EOF && HEAD EOF git -C r1 index-pack ../all.pack && @@ -39,7 +39,7 @@ test_expect_success 'verify blob count in normal packfile' ' ' test_expect_success 'verify blob:none packfile has no blobs' ' - git -C r1 pack-objects --rev --stdout --filter=blob:none >filter.pack <<-EOF && + git -C r1 pack-objects --revs --stdout --filter=blob:none >filter.pack <<-EOF && HEAD EOF git -C r1 index-pack ../filter.pack && @@ -74,7 +74,7 @@ test_expect_success 'get an error for missing tree object' ' git -C r5 commit -m "foo" && del=$(git -C r5 rev-parse HEAD^{tree} | sed "s|..|&/|") && rm r5/.git/objects/$del && - test_must_fail git -C r5 pack-objects --rev --stdout 2>bad_tree <<-EOF && + test_must_fail git -C r5 pack-objects --revs --stdout 2>bad_tree <<-EOF && HEAD EOF grep "bad tree object" bad_tree @@ -88,7 +88,7 @@ test_expect_success 'setup for tests of tree:0' ' ' test_expect_success 'verify tree:0 packfile has no blobs or trees' ' - git -C r1 pack-objects --rev --stdout --filter=tree:0 >commitsonly.pack <<-EOF && + git -C r1 pack-objects --revs --stdout --filter=tree:0 >commitsonly.pack <<-EOF && HEAD EOF git -C r1 index-pack ../commitsonly.pack && @@ -98,7 +98,7 @@ test_expect_success 'verify tree:0 packfile has no blobs or trees' ' test_expect_success 'grab tree directly when using tree:0' ' # We should get the tree specified directly but not its blobs or subtrees. - git -C r1 pack-objects --rev --stdout --filter=tree:0 >commitsonly.pack <<-EOF && + git -C r1 pack-objects --revs --stdout --filter=tree:0 >commitsonly.pack <<-EOF && HEAD: EOF git -C r1 index-pack ../commitsonly.pack && @@ -128,7 +128,7 @@ test_expect_success 'verify blob count in normal packfile' ' awk -f print_2.awk ls_files_result | sort >expected && - git -C r2 pack-objects --rev --stdout >all.pack <<-EOF && + git -C r2 pack-objects --revs --stdout >all.pack <<-EOF && HEAD EOF git -C r2 index-pack ../all.pack && @@ -142,7 +142,7 @@ test_expect_success 'verify blob count in normal packfile' ' ' test_expect_success 'verify blob:limit=500 omits all blobs' ' - git -C r2 pack-objects --rev --stdout --filter=blob:limit=500 >filter.pack <<-EOF && + git -C r2 pack-objects --revs --stdout --filter=blob:limit=500 >filter.pack <<-EOF && HEAD EOF git -C r2 index-pack ../filter.pack && @@ -157,7 +157,7 @@ test_expect_success 'verify blob:limit=500 omits all blobs' ' ' test_expect_success 'verify blob:limit=1000' ' - git -C r2 pack-objects --rev --stdout --filter=blob:limit=1000 >filter.pack <<-EOF && + git -C r2 pack-objects --revs --stdout --filter=blob:limit=1000 >filter.pack <<-EOF && HEAD EOF git -C r2 index-pack ../filter.pack && @@ -176,7 +176,7 @@ test_expect_success 'verify blob:limit=1001' ' awk -f print_2.awk ls_files_result | sort >expected && - git -C r2 pack-objects --rev --stdout --filter=blob:limit=1001 >filter.pack <<-EOF && + git -C r2 pack-objects --revs --stdout --filter=blob:limit=1001 >filter.pack <<-EOF && HEAD EOF git -C r2 index-pack ../filter.pack && @@ -194,7 +194,7 @@ test_expect_success 'verify blob:limit=10001' ' awk -f print_2.awk ls_files_result | sort >expected && - git -C r2 pack-objects --rev --stdout --filter=blob:limit=10001 >filter.pack <<-EOF && + git -C r2 pack-objects --revs --stdout --filter=blob:limit=10001 >filter.pack <<-EOF && HEAD EOF git -C r2 index-pack ../filter.pack && @@ -212,7 +212,7 @@ test_expect_success 'verify blob:limit=1k' ' awk -f print_2.awk ls_files_result | sort >expected && - git -C r2 pack-objects --rev --stdout --filter=blob:limit=1k >filter.pack <<-EOF && + git -C r2 pack-objects --revs --stdout --filter=blob:limit=1k >filter.pack <<-EOF && HEAD EOF git -C r2 index-pack ../filter.pack && @@ -230,7 +230,7 @@ test_expect_success 'verify explicitly specifying oversized blob in input' ' awk -f print_2.awk ls_files_result | sort >expected && - git -C r2 pack-objects --rev --stdout --filter=blob:limit=1k >filter.pack <<-EOF && + git -C r2 pack-objects --revs --stdout --filter=blob:limit=1k >filter.pack <<-EOF && HEAD $(git -C r2 rev-parse HEAD:large.10000) EOF @@ -249,7 +249,7 @@ test_expect_success 'verify blob:limit=1m' ' awk -f print_2.awk ls_files_result | sort >expected && - git -C r2 pack-objects --rev --stdout --filter=blob:limit=1m >filter.pack <<-EOF && + git -C r2 pack-objects --revs --stdout --filter=blob:limit=1m >filter.pack <<-EOF && HEAD EOF git -C r2 index-pack ../filter.pack && @@ -277,6 +277,10 @@ test_expect_success 'verify normal and blob:limit packfiles have same commits/tr ' # Test sparse:path=<path> filter. +# !!!! +# NOTE: sparse:path filter support has been dropped for security reasons, +# so the tests have been changed to make sure that using it fails. +# !!!! # Use a local file containing a sparse-checkout specification to filter # out blobs not required for the corresponding sparse-checkout. We do not # require sparse-checkout to actually be enabled. @@ -302,7 +306,7 @@ test_expect_success 'verify blob count in normal packfile' ' awk -f print_2.awk ls_files_result | sort >expected && - git -C r3 pack-objects --rev --stdout >all.pack <<-EOF && + git -C r3 pack-objects --revs --stdout >all.pack <<-EOF && HEAD EOF git -C r3 index-pack ../all.pack && @@ -315,73 +319,24 @@ test_expect_success 'verify blob count in normal packfile' ' test_cmp expected observed ' -test_expect_success 'verify sparse:path=pattern1' ' - git -C r3 ls-files -s dir1/sparse1 dir1/sparse2 >ls_files_result && - awk -f print_2.awk ls_files_result | - sort >expected && - - git -C r3 pack-objects --rev --stdout --filter=sparse:path=../pattern1 >filter.pack <<-EOF && +test_expect_success 'verify sparse:path=pattern1 fails' ' + test_must_fail git -C r3 pack-objects --revs --stdout \ + --filter=sparse:path=../pattern1 <<-EOF HEAD EOF - git -C r3 index-pack ../filter.pack && - - git -C r3 verify-pack -v ../filter.pack >verify_result && - grep blob verify_result | - awk -f print_1.awk | - sort >observed && - - test_cmp expected observed -' - -test_expect_success 'verify normal and sparse:path=pattern1 packfiles have same commits/trees' ' - git -C r3 verify-pack -v ../all.pack >verify_result && - grep -E "commit|tree" verify_result | - awk -f print_1.awk | - sort >expected && - - git -C r3 verify-pack -v ../filter.pack >verify_result && - grep -E "commit|tree" verify_result | - awk -f print_1.awk | - sort >observed && - - test_cmp expected observed ' -test_expect_success 'verify sparse:path=pattern2' ' - git -C r3 ls-files -s sparse1 dir1/sparse1 >ls_files_result && - awk -f print_2.awk ls_files_result | - sort >expected && - - git -C r3 pack-objects --rev --stdout --filter=sparse:path=../pattern2 >filter.pack <<-EOF && +test_expect_success 'verify sparse:path=pattern2 fails' ' + test_must_fail git -C r3 pack-objects --revs --stdout \ + --filter=sparse:path=../pattern2 <<-EOF HEAD EOF - git -C r3 index-pack ../filter.pack && - - git -C r3 verify-pack -v ../filter.pack >verify_result && - grep blob verify_result | - awk -f print_1.awk | - sort >observed && - - test_cmp expected observed -' - -test_expect_success 'verify normal and sparse:path=pattern2 packfiles have same commits/trees' ' - git -C r3 verify-pack -v ../all.pack >verify_result && - grep -E "commit|tree" verify_result | - awk -f print_1.awk | - sort >expected && - - git -C r3 verify-pack -v ../filter.pack >verify_result && - grep -E "commit|tree" verify_result | - awk -f print_1.awk | - sort >observed && - - test_cmp expected observed ' # Test sparse:oid=<oid-ish> filter. -# Like sparse:path, but we get the sparse-checkout specification from -# a blob rather than a file on disk. +# Use a blob containing a sparse-checkout specification to filter +# out blobs not required for the corresponding sparse-checkout. We do not +# require sparse-checkout to actually be enabled. test_expect_success 'setup r4' ' git init r4 && @@ -404,7 +359,7 @@ test_expect_success 'verify blob count in normal packfile' ' awk -f print_2.awk ls_files_result | sort >expected && - git -C r4 pack-objects --rev --stdout >all.pack <<-EOF && + git -C r4 pack-objects --revs --stdout >all.pack <<-EOF && HEAD EOF git -C r4 index-pack ../all.pack && @@ -423,7 +378,7 @@ test_expect_success 'verify sparse:oid=OID' ' sort >expected && oid=$(git -C r4 ls-files -s pattern | awk -f print_2.awk) && - git -C r4 pack-objects --rev --stdout --filter=sparse:oid=$oid >filter.pack <<-EOF && + git -C r4 pack-objects --revs --stdout --filter=sparse:oid=$oid >filter.pack <<-EOF && HEAD EOF git -C r4 index-pack ../filter.pack && @@ -441,7 +396,7 @@ test_expect_success 'verify sparse:oid=oid-ish' ' awk -f print_2.awk ls_files_result | sort >expected && - git -C r4 pack-objects --rev --stdout --filter=sparse:oid=master:pattern >filter.pack <<-EOF && + git -C r4 pack-objects --revs --stdout --filter=sparse:oid=master:pattern >filter.pack <<-EOF && HEAD EOF git -C r4 index-pack ../filter.pack && @@ -470,19 +425,19 @@ test_expect_success 'setup r1 - delete loose blobs' ' ' test_expect_success 'verify pack-objects fails w/ missing objects' ' - test_must_fail git -C r1 pack-objects --rev --stdout >miss.pack <<-EOF + test_must_fail git -C r1 pack-objects --revs --stdout >miss.pack <<-EOF HEAD EOF ' test_expect_success 'verify pack-objects fails w/ --missing=error' ' - test_must_fail git -C r1 pack-objects --rev --stdout --missing=error >miss.pack <<-EOF + test_must_fail git -C r1 pack-objects --revs --stdout --missing=error >miss.pack <<-EOF HEAD EOF ' test_expect_success 'verify pack-objects w/ --missing=allow-any' ' - git -C r1 pack-objects --rev --stdout --missing=allow-any >miss.pack <<-EOF + git -C r1 pack-objects --revs --stdout --missing=allow-any >miss.pack <<-EOF HEAD EOF ' diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh index 069e4e28e4..5267c4be20 100755 --- a/t/t5318-commit-graph.sh +++ b/t/t5318-commit-graph.sh @@ -23,6 +23,14 @@ test_expect_success 'write graph with no packs' ' test_path_is_file info/commit-graph ' +test_expect_success 'close with correct error on bad input' ' + cd "$TRASH_DIRECTORY/full" && + echo doesnotexist >in && + { git commit-graph write --stdin-packs <in 2>stderr; ret=$?; } && + test "$ret" = 1 && + test_i18ngrep "error adding pack" stderr +' + test_expect_success 'create commits and repack' ' cd "$TRASH_DIRECTORY/full" && for i in $(test_seq 3) @@ -366,6 +374,26 @@ GRAPH_OCTOPUS_DATA_OFFSET=$(($GRAPH_COMMIT_DATA_OFFSET + \ GRAPH_BYTE_OCTOPUS=$(($GRAPH_OCTOPUS_DATA_OFFSET + 4)) 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 +} + +corrupt_graph_verify() { + grepstr=$1 + test_must_fail git commit-graph verify 2>test_err && + grep -v "^+" test_err >err && + test_i18ngrep "$grepstr" err && + if test "$2" != "no-copy" + then + cp $objdir/info/commit-graph commit-graph-pre-write-test + fi && + git status --short && + GIT_TEST_COMMIT_GRAPH_DIE_ON_LOAD=true git commit-graph write && + git commit-graph verify +} + # usage: corrupt_graph_and_verify <position> <data> <string> [<zero_pos>] # Manipulates the commit-graph file at the position # by inserting the data, optionally zeroing the file @@ -376,19 +404,28 @@ corrupt_graph_and_verify() { pos=$1 data="${2:-\0}" grepstr=$3 - cd "$TRASH_DIRECTORY/full" && + corrupt_graph_setup && orig_size=$(wc -c < $objdir/info/commit-graph) && zero_pos=${4:-${orig_size}} && - test_when_finished mv commit-graph-backup $objdir/info/commit-graph && - cp $objdir/info/commit-graph commit-graph-backup && printf "$data" | dd of="$objdir/info/commit-graph" bs=1 seek="$pos" conv=notrunc && dd of="$objdir/info/commit-graph" bs=1 seek="$zero_pos" if=/dev/null && generate_zero_bytes $(($orig_size - $zero_pos)) >>"$objdir/info/commit-graph" && - test_must_fail git commit-graph verify 2>test_err && - grep -v "^+" test_err >err && - test_i18ngrep "$grepstr" err + corrupt_graph_verify "$grepstr" + } +test_expect_success POSIXPERM,SANITY 'detect permission problem' ' + corrupt_graph_setup && + chmod 000 $objdir/info/commit-graph && + corrupt_graph_verify "Could not open" "no-copy" +' + +test_expect_success 'detect too small' ' + corrupt_graph_setup && + echo "a small graph" >$objdir/info/commit-graph && + corrupt_graph_verify "too small" +' + test_expect_success 'detect bad signature' ' corrupt_graph_and_verify 0 "\0" \ "graph signature" @@ -499,6 +536,7 @@ test_expect_success 'git fsck (checks commit-graph)' ' git fsck && corrupt_graph_and_verify $GRAPH_BYTE_FOOTER "\00" \ "incorrect checksum" && + cp commit-graph-pre-write-test $objdir/info/commit-graph && test_must_fail git fsck ' diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh index 70926b5bc0..1ebf19ec3c 100755 --- a/t/t5319-multi-pack-index.sh +++ b/t/t5319-multi-pack-index.sh @@ -86,13 +86,14 @@ test_expect_success 'write midx with one v1 pack' ' ' midx_git_two_modes () { + git -c core.multiPackIndex=false $1 >expect && + git -c core.multiPackIndex=true $1 >actual && if [ "$2" = "sorted" ] then - git -c core.multiPackIndex=false $1 | sort >expect && - git -c core.multiPackIndex=true $1 | sort >actual - else - git -c core.multiPackIndex=false $1 >expect && - git -c core.multiPackIndex=true $1 >actual + sort <expect >expect.sorted && + mv expect.sorted expect && + sort <actual >actual.sorted && + mv actual.sorted actual fi && test_cmp expect actual } @@ -103,8 +104,8 @@ compare_results_with_midx () { midx_git_two_modes "rev-list --objects --all" && midx_git_two_modes "log --raw" && midx_git_two_modes "count-objects --verbose" && - midx_git_two_modes "cat-file --batch-all-objects --buffer --batch-check" && - midx_git_two_modes "cat-file --batch-all-objects --buffer --batch-check --unsorted" sorted + midx_git_two_modes "cat-file --batch-all-objects --batch-check" && + midx_git_two_modes "cat-file --batch-all-objects --batch-check --unordered" sorted ' } @@ -116,6 +117,20 @@ test_expect_success 'write midx with one v2 pack' ' compare_results_with_midx "one v2 pack" +test_expect_success 'corrupt idx not opened' ' + idx=$(test-tool read-midx $objdir | grep "\.idx\$") && + mv $objdir/pack/$idx backup-$idx && + test_when_finished "mv backup-\$idx \$objdir/pack/\$idx" && + + # This is the minimum size for a sha-1 based .idx; this lets + # us pass perfunctory tests, but anything that actually opens and reads + # the idx file will complain. + test_copy_bytes 1064 <backup-$idx >$objdir/pack/$idx && + + git -c core.multiPackIndex=true rev-list --objects --all 2>err && + test_must_be_empty err +' + test_expect_success 'add more objects' ' for i in $(test_seq 6 10) do diff --git a/t/t5407-post-rewrite-hook.sh b/t/t5407-post-rewrite-hook.sh index a4a5903cba..7344253bfb 100755 --- a/t/t5407-post-rewrite-hook.sh +++ b/t/t5407-post-rewrite-hook.sh @@ -131,7 +131,7 @@ test_expect_success 'git rebase -m --skip' ' test_expect_success 'git rebase with implicit use of interactive backend' ' git reset --hard D && clear_hook_input && - test_must_fail git rebase --keep --onto A B && + test_must_fail git rebase --keep-empty --onto A B && echo C > foo && git add foo && git rebase --continue && @@ -146,7 +146,7 @@ test_expect_success 'git rebase with implicit use of interactive backend' ' test_expect_success 'git rebase --skip with implicit use of interactive backend' ' git reset --hard D && clear_hook_input && - test_must_fail git rebase --keep --onto A B && + test_must_fail git rebase --keep-empty --onto A B && test_must_fail git rebase --skip && echo D > foo && git add foo && diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh index 0ef4d6f20c..1c71c0ec77 100755 --- a/t/t5500-fetch-pack.sh +++ b/t/t5500-fetch-pack.sh @@ -920,7 +920,4 @@ test_expect_success 'fetch with --filter=blob:limit=0 and HTTP' ' fetch_filter_blob_limit_zero "$HTTPD_DOCUMENT_ROOT_PATH/server" "$HTTPD_URL/smart/server" ' -stop_httpd - - test_done diff --git a/t/t5509-fetch-push-namespaces.sh b/t/t5509-fetch-push-namespaces.sh index c88df78c0b..75cbfcc392 100755 --- a/t/t5509-fetch-push-namespaces.sh +++ b/t/t5509-fetch-push-namespaces.sh @@ -124,4 +124,32 @@ test_expect_success 'try to update a hidden full ref' ' test_must_fail git -C original push pushee-namespaced master ' +test_expect_success 'set up ambiguous HEAD' ' + git init ambiguous && + ( + cd ambiguous && + git commit --allow-empty -m foo && + git update-ref refs/namespaces/ns/refs/heads/one HEAD && + git update-ref refs/namespaces/ns/refs/heads/two HEAD && + git symbolic-ref refs/namespaces/ns/HEAD \ + refs/namespaces/ns/refs/heads/two + ) +' + +test_expect_success 'clone chooses correct HEAD (v0)' ' + GIT_NAMESPACE=ns git -c protocol.version=0 \ + clone ambiguous ambiguous-v0 && + echo refs/heads/two >expect && + git -C ambiguous-v0 symbolic-ref HEAD >actual && + test_cmp expect actual +' + +test_expect_success 'clone chooses correct HEAD (v2)' ' + GIT_NAMESPACE=ns git -c protocol.version=2 \ + clone ambiguous ambiguous-v2 && + echo refs/heads/two >expect && + git -C ambiguous-v2 symbolic-ref HEAD >actual && + test_cmp expect actual +' + test_done diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index 3b7b30568c..e98d90dd9b 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -978,6 +978,4 @@ test_expect_success '--negotiation-tip limits "have" lines sent with HTTP protoc check_negotiation_tip ' -stop_httpd - test_done diff --git a/t/t5514-fetch-multiple.sh b/t/t5514-fetch-multiple.sh index 0030c92e1a..5426d4b5ab 100755 --- a/t/t5514-fetch-multiple.sh +++ b/t/t5514-fetch-multiple.sh @@ -105,9 +105,12 @@ test_expect_success 'git fetch --multiple (two remotes)' ' git remote rm origin && git remote add one ../one && git remote add two ../two && - git fetch --multiple one two && + GIT_TRACE=1 git fetch --multiple one two 2>trace && git branch -r > output && - test_cmp ../expect output) + test_cmp ../expect output && + grep "built-in: git gc" trace >gc && + test_line_count = 1 gc + ) ' test_expect_success 'git fetch --multiple (bad remote names)' ' diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh index 4bfbb79654..c81ca360ac 100755 --- a/t/t5516-fetch-push.sh +++ b/t/t5516-fetch-push.sh @@ -1241,9 +1241,9 @@ do cd shallow && # Some protocol versions (e.g. 2) support fetching # unadvertised objects, so restrict this test to v0. - test_must_fail ok=sigpipe env GIT_TEST_PROTOCOL_VERSION= \ + test_must_fail env GIT_TEST_PROTOCOL_VERSION= \ git fetch ../testrepo/.git $SHA1_3 && - test_must_fail ok=sigpipe env GIT_TEST_PROTOCOL_VERSION= \ + test_must_fail env GIT_TEST_PROTOCOL_VERSION= \ git fetch ../testrepo/.git $SHA1_1 && git --git-dir=../testrepo/.git config uploadpack.allowreachablesha1inwant true && git fetch ../testrepo/.git $SHA1_1 && @@ -1251,8 +1251,9 @@ 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 ok=sigpipe env GIT_TEST_PROTOCOL_VERSION= \ - git fetch ../testrepo/.git $SHA1_3 + test_must_fail env GIT_TEST_PROTOCOL_VERSION= \ + git fetch ../testrepo/.git $SHA1_3 2>err && + test_i18ngrep "remote error:.*not our ref.*$SHA1_3\$" err ) ' done @@ -1284,6 +1285,17 @@ test_expect_success 'fetch follows tags by default' ' test_cmp expect actual ' +test_expect_success 'peeled advertisements are not considered ref tips' ' + mk_empty testrepo && + git -C testrepo commit --allow-empty -m one && + 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= \ + git fetch testrepo $oid 2>err && + test_i18ngrep "Server does not allow request for unadvertised object" err +' + test_expect_success 'pushing a specific ref applies remote.$name.push as refmap' ' mk_test testrepo heads/master && rm -fr src dst && @@ -1382,7 +1394,7 @@ test_expect_success 'push does not follow tags by default' ' test_cmp expect actual ' -test_expect_success 'push --follow-tag only pushes relevant tags' ' +test_expect_success 'push --follow-tags only pushes relevant tags' ' mk_test testrepo heads/master && rm -fr src dst && git init src && @@ -1396,7 +1408,7 @@ test_expect_success 'push --follow-tag only pushes relevant tags' ' git tag -m "future" future && git checkout master && git for-each-ref refs/heads/master refs/tags/tag >../expect && - git push --follow-tag ../dst master + git push --follow-tags ../dst master ) && ( cd dst && diff --git a/t/t5521-pull-options.sh b/t/t5521-pull-options.sh index c19d8dbc9d..ccde8ba491 100755 --- a/t/t5521-pull-options.sh +++ b/t/t5521-pull-options.sh @@ -77,6 +77,14 @@ test_expect_success 'git pull -q -v' ' 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_be_empty out && + test -s err) +' + test_expect_success 'git pull --force' ' mkdir clonedoldstyle && diff --git a/t/t5530-upload-pack-error.sh b/t/t5530-upload-pack-error.sh index 4f6e32b04c..a1d3031d40 100755 --- a/t/t5530-upload-pack-error.sh +++ b/t/t5530-upload-pack-error.sh @@ -57,13 +57,25 @@ test_expect_success 'upload-pack fails due to error in rev-list' ' grep "bad tree object" output.err ' -test_expect_success 'upload-pack error message when bad ref requested' ' +test_expect_success 'upload-pack fails due to bad want (no object)' ' printf "0045want %s multi_ack_detailed\n00000009done\n0000" \ "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef" >input && test_must_fail git upload-pack . <input >output 2>output.err && - grep -q "not our ref" output.err && - ! grep -q multi_ack_detailed output.err + grep "not our ref" output.err && + grep "ERR" output && + ! grep multi_ack_detailed output.err +' + +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 && + test_must_fail git upload-pack . <input >output 2>output.err && + grep "not our ref" output.err && + grep "ERR" output && + ! grep multi_ack_detailed output.err ' test_expect_success 'upload-pack fails due to error in pack-objects enumeration' ' diff --git a/t/t5531-deep-submodule-push.sh b/t/t5531-deep-submodule-push.sh index e2c37fd978..4ad059e6be 100755 --- a/t/t5531-deep-submodule-push.sh +++ b/t/t5531-deep-submodule-push.sh @@ -363,7 +363,7 @@ test_expect_success 'push succeeds if submodule has no remote and is on the firs ) && git add b && git commit -m "added submodule" && - git push --recurse-submodule=check origin master + git push --recurse-submodules=check origin master ) ' diff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh index 6caf628efa..66f0b64d39 100755 --- a/t/t5537-fetch-shallow.sh +++ b/t/t5537-fetch-shallow.sh @@ -255,6 +255,4 @@ test_expect_success 'shallow fetches check connectivity before writing shallow f git -C client fsck ' -stop_httpd - test_done diff --git a/t/t5539-fetch-http-shallow.sh b/t/t5539-fetch-http-shallow.sh index cdb687b93a..b4ad81f006 100755 --- a/t/t5539-fetch-http-shallow.sh +++ b/t/t5539-fetch-http-shallow.sh @@ -149,5 +149,4 @@ test_expect_success 'fetching deepen' ' ) ' -stop_httpd test_done diff --git a/t/t5540-http-push-webdav.sh b/t/t5540-http-push-webdav.sh index 88ff5a49e4..a094fd5e71 100755 --- a/t/t5540-http-push-webdav.sh +++ b/t/t5540-http-push-webdav.sh @@ -176,6 +176,4 @@ test_expect_failure 'push to password-protected repository (no user in URL)' ' test_cmp expect actual ' -stop_httpd - test_done diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh index 0e3055ab98..8ef8763e06 100755 --- a/t/t5541-http-push-smart.sh +++ b/t/t5541-http-push-smart.sh @@ -383,5 +383,4 @@ test_expect_success 'colorize errors/hints' ' test_i18ngrep ! "^hint: " decoded ' -stop_httpd test_done diff --git a/t/t5542-push-http-shallow.sh b/t/t5542-push-http-shallow.sh index 5165833157..ddc1db722d 100755 --- a/t/t5542-push-http-shallow.sh +++ b/t/t5542-push-http-shallow.sh @@ -90,5 +90,4 @@ EOF ) ' -stop_httpd test_done diff --git a/t/t5545-push-options.sh b/t/t5545-push-options.sh index b47a95871c..6d1d59c9b1 100755 --- a/t/t5545-push-options.sh +++ b/t/t5545-push-options.sh @@ -278,6 +278,4 @@ test_expect_success 'push options keep quoted characters intact (http)' ' test_cmp expect "$HTTPD_DOCUMENT_ROOT_PATH"/upstream.git/hooks/pre-receive.push_options ' -stop_httpd - test_done diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh index 694b77c855..b811d89cfd 100755 --- a/t/t5550-http-fetch-dumb.sh +++ b/t/t5550-http-fetch-dumb.sh @@ -424,5 +424,4 @@ test_expect_success 'fetching via http alternates works' ' git -c http.followredirects=true clone "$HTTPD_URL/dumb/alt-child.git" ' -stop_httpd test_done diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh index c760514716..ac74626a7b 100755 --- a/t/t5551-http-fetch-smart.sh +++ b/t/t5551-http-fetch-smart.sh @@ -469,5 +469,4 @@ test_expect_success 'server-side error detected' ' grep "server-side error" actual ' -stop_httpd test_done diff --git a/t/t5561-http-backend.sh b/t/t5561-http-backend.sh index 1c49054595..6eb0294978 100755 --- a/t/t5561-http-backend.sh +++ b/t/t5561-http-backend.sh @@ -132,5 +132,4 @@ test_expect_success 'server request log matches test results' ' check_access_log exp ' -stop_httpd test_done diff --git a/t/t5570-git-daemon.sh b/t/t5570-git-daemon.sh index 58ee787685..34487bbb8c 100755 --- a/t/t5570-git-daemon.sh +++ b/t/t5570-git-daemon.sh @@ -90,6 +90,7 @@ test_expect_success 'fetch notices corrupt pack' ' test_expect_success 'fetch notices corrupt idx' ' cp -R "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_pack.git "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_bad2.git && (cd "$GIT_DAEMON_DOCUMENT_ROOT_PATH"/repo_bad2.git && + rm -f objects/pack/multi-pack-index && p=$(ls objects/pack/pack-*.idx) && chmod u+w $p && printf %0256d 0 | dd of=$p bs=256 count=1 seek=1 conv=notrunc @@ -198,5 +199,4 @@ test_expect_success FAKENC 'hostname interpolation works after LF-stripping' ' test_cmp expect actual ' -stop_git_daemon test_done diff --git a/t/t5580-clone-push-unc.sh b/t/t5580-clone-push-unc.sh index 217adf3a63..b3c8a92450 100755 --- a/t/t5580-clone-push-unc.sh +++ b/t/t5580-clone-push-unc.sh @@ -62,4 +62,16 @@ test_expect_success MINGW 'remote nick cannot contain backslashes' ' test_i18ngrep ! "unable to access" err ' +test_expect_success 'unc alternates' ' + tree="$(git rev-parse HEAD:)" && + mkdir test-unc-alternate && + ( + cd test-unc-alternate && + git init && + test_must_fail git show $tree && + echo "$UNCPATH/.git/objects" >.git/objects/info/alternates && + git show $tree + ) +' + test_done diff --git a/t/t5581-http-curl-verbose.sh b/t/t5581-http-curl-verbose.sh index cd9283eeec..5129b0724f 100755 --- a/t/t5581-http-curl-verbose.sh +++ b/t/t5581-http-curl-verbose.sh @@ -23,6 +23,4 @@ test_expect_success 'failure in git-upload-pack is shown' ' grep "< HTTP/1.1 500 Intentional Breakage" curl_log ' -stop_httpd - test_done diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh index a454b143ea..37d76808d4 100755 --- a/t/t5601-clone.sh +++ b/t/t5601-clone.sh @@ -611,10 +611,6 @@ test_expect_success 'GIT_TRACE_PACKFILE produces a usable pack' ' git -C replay.git index-pack -v --stdin <tmp.pack ' -hex2oct () { - perl -ne 'printf "\\%03o", hex for /../g' -} - test_expect_success 'clone on case-insensitive fs' ' git init icasefs && ( @@ -634,9 +630,8 @@ test_expect_success CASE_INSENSITIVE_FS 'colliding file detection' ' test_i18ngrep "the following paths have collided" icasefs/warning ' -partial_clone () { +partial_clone_server () { SERVER="$1" && - URL="$2" && rm -rf "$SERVER" client && test_create_repo "$SERVER" && @@ -646,8 +641,14 @@ partial_clone () { test_commit -C "$SERVER" two && HASH2=$(git hash-object "$SERVER/two.t") && test_config -C "$SERVER" uploadpack.allowfilter 1 && - test_config -C "$SERVER" uploadpack.allowanysha1inwant 1 && + test_config -C "$SERVER" uploadpack.allowanysha1inwant 1 +} + +partial_clone () { + SERVER="$1" && + URL="$2" && + partial_clone_server "${SERVER}" && git clone --filter=blob:limit=0 "$URL" client && git -C client fsck && @@ -664,6 +665,11 @@ test_expect_success 'partial clone' ' partial_clone server "file://$(pwd)/server" ' +test_expect_success 'partial clone with -o' ' + partial_clone_server server && + git clone -o blah --filter=blob:limit=0 "file://$(pwd)/server" client +' + test_expect_success 'partial clone: warn if server does not support object filtering' ' rm -rf server client && test_create_repo server && @@ -733,6 +739,4 @@ test_expect_success 'partial clone using HTTP' ' partial_clone "$HTTPD_DOCUMENT_ROOT_PATH/server" "$HTTPD_URL/smart/server" ' -stop_httpd - test_done diff --git a/t/t5607-clone-bundle.sh b/t/t5607-clone-bundle.sh index cf39e9e243..2a0fb15cf1 100755 --- a/t/t5607-clone-bundle.sh +++ b/t/t5607-clone-bundle.sh @@ -14,6 +14,12 @@ test_expect_success 'setup' ' git tag -d third ' +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 && + test_i18ngrep "need a repository" err +' + test_expect_success 'annotated tags can be excluded by rev-list options' ' git bundle create bundle --all --since=7.Apr.2005.15:14:00.-0700 && git ls-remote bundle > output && diff --git a/t/t5616-partial-clone.sh b/t/t5616-partial-clone.sh index 9643acb161..b91ef548f8 100755 --- a/t/t5616-partial-clone.sh +++ b/t/t5616-partial-clone.sh @@ -244,11 +244,25 @@ test_expect_success 'fetch what is specified on CLI even if already promised' ' . "$TEST_DIRECTORY"/lib-httpd.sh start_httpd -# Converts bytes into a form suitable for inclusion in a sed command. For -# example, "printf 'ab\r\n' | hex_unpack" results in '\x61\x62\x0d\x0a'. -sed_escape () { - perl -e '$/ = undef; $input = <>; print unpack("H2" x length($input), $input)' | - sed 's/\(..\)/\\x\1/g' +# Converts bytes into their hexadecimal representation. For example, +# "printf 'ab\r\n' | hex_unpack" results in '61620d0a'. +hex_unpack () { + perl -e '$/ = undef; $input = <>; print unpack("H2" x length($input), $input)' +} + +# Inserts $1 at the start of the string and every 2 characters thereafter. +intersperse () { + sed 's/\(..\)/'$1'\1/g' +} + +# Create a one-time-sed 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" } test_expect_success 'upon cloning, check that all refs point to objects' ' @@ -270,10 +284,7 @@ test_expect_success 'upon cloning, check that all refs point to objects' ' # Replace the existing packfile with the crafted one. 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 <incomplete.pack) + 5))" \ - "$(sed_escape <incomplete.pack)" \ - >"$HTTPD_ROOT_PATH/one-time-sed" && + replace_packfile incomplete.pack && # Use protocol v2 because the sed command looks for the "packfile" # section header. @@ -313,10 +324,7 @@ test_expect_success 'when partial cloning, tolerate server not sending target of # Replace the existing packfile with the crafted one. 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 <incomplete.pack) + 5))" \ - "$(sed_escape <incomplete.pack)" \ - >"$HTTPD_ROOT_PATH/one-time-sed" && + replace_packfile incomplete.pack && # Use protocol v2 because the sed command looks for the "packfile" # section header. @@ -331,6 +339,82 @@ test_expect_success 'when partial cloning, tolerate server not sending target of ! test -e "$HTTPD_ROOT_PATH/one-time-sed" ' -stop_httpd +test_expect_success 'tolerate server sending REF_DELTA against missing promisor objects' ' + SERVER="$HTTPD_DOCUMENT_ROOT_PATH/server" && + rm -rf "$SERVER" repo && + test_create_repo "$SERVER" && + test_config -C "$SERVER" uploadpack.allowfilter 1 && + test_config -C "$SERVER" uploadpack.allowanysha1inwant 1 && + + # Create a commit with 2 blobs to be used as delta bases. + for i in $(test_seq 10) + do + echo "this is a line" >>"$SERVER/foo.txt" && + echo "this is another line" >>"$SERVER/have.txt" + done && + git -C "$SERVER" add foo.txt have.txt && + git -C "$SERVER" commit -m bar && + git -C "$SERVER" rev-parse HEAD:foo.txt >deltabase_missing && + git -C "$SERVER" rev-parse HEAD:have.txt >deltabase_have && + + # 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 && + git -C repo hash-object -w -- "$SERVER/have.txt" && + + # Sanity check to ensure that the client does not have + # deltabase_missing. + git -C repo rev-list --objects --ignore-missing \ + -- $(cat deltabase_missing) >objlist && + test_line_count = 0 objlist && + + # Another commit. This commit will be fetched by the client. + echo "abcdefghijklmnopqrstuvwxyz" >>"$SERVER/foo.txt" && + echo "abcdefghijklmnopqrstuvwxyz" >>"$SERVER/have.txt" && + git -C "$SERVER" add foo.txt have.txt && + git -C "$SERVER" commit -m baz && + + # Pack a thin pack containing, among other things, HEAD:foo.txt + # delta-ed against HEAD^:foo.txt and HEAD:have.txt delta-ed against + # HEAD^:have.txt. + printf "%s\n--not\n%s\n" \ + $(git -C "$SERVER" rev-parse HEAD) \ + $(git -C "$SERVER" rev-parse HEAD^) | + git -C "$SERVER" pack-objects --thin --stdout >thin.pack && + + # Ensure that the pack contains one delta against HEAD^:foo.txt. Since + # the delta contains at least 26 novel characters, the size cannot be + # contained in 4 bits, so the object header will take up 2 bytes. The + # most significant nybble of the first byte is 0b1111 (0b1 to indicate + # that the header continues, and 0b111 to indicate REF_DELTA), followed + # by any 3 nybbles, then the OID of the delta base. + printf "f.,..%s" $(intersperse "," <deltabase_missing) >want && + hex_unpack <thin.pack | intersperse "," >have && + grep $(cat want) have && + + # Ensure that the pack contains one delta against HEAD^:have.txt, + # similar to the above. + printf "f.,..%s" $(intersperse "," <deltabase_have) >want && + hex_unpack <thin.pack | intersperse "," >have && + grep $(cat want) have && + + replace_packfile thin.pack && + + # Use protocol v2 because the sed command looks for the "packfile" + # section header. + test_config -C "$SERVER" protocol.version 2 && + + # Fetch the thin pack and ensure that index-pack is able to handle the + # REF_DELTA object with a missing promisor delta base. + GIT_TRACE_PACKET="$(pwd)/trace" git -C repo -c protocol.version=2 fetch && + + # Ensure that the missing delta base was directly fetched, but not the + # one that the client has. + 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" +' test_done diff --git a/t/t5617-clone-submodules-remote.sh b/t/t5617-clone-submodules-remote.sh new file mode 100755 index 0000000000..37fcce9c40 --- /dev/null +++ b/t/t5617-clone-submodules-remote.sh @@ -0,0 +1,54 @@ +#!/bin/sh + +test_description='Test cloning repos with submodules using remote-tracking branches' + +. ./test-lib.sh + +pwd=$(pwd) + +test_expect_success 'setup' ' + git checkout -b master && + test_commit commit1 && + mkdir sub && + ( + cd sub && + git init && + test_commit subcommit1 && + git tag sub_when_added_to_super + ) && + git submodule add "file://$pwd/sub" sub && + git commit -m "add submodule" && + ( + cd sub && + test_commit subcommit2 + ) +' + +test_expect_success 'clone with --no-remote-submodules' ' + test_when_finished "rm -rf super_clone" && + git clone --recurse-submodules --no-remote-submodules "file://$pwd/." super_clone && + ( + cd super_clone/sub && + git diff --exit-code sub_when_added_to_super + ) +' + +test_expect_success 'clone with --remote-submodules' ' + test_when_finished "rm -rf super_clone" && + git clone --recurse-submodules --remote-submodules "file://$pwd/." super_clone && + ( + cd super_clone/sub && + git diff --exit-code remotes/origin/master + ) +' + +test_expect_success 'check the default is --no-remote-submodules' ' + test_when_finished "rm -rf super_clone" && + git clone --recurse-submodules "file://$pwd/." super_clone && + ( + cd super_clone/sub && + git diff --exit-code sub_when_added_to_super + ) +' + +test_done diff --git a/t/t5700-protocol-v1.sh b/t/t5700-protocol-v1.sh index d5ed196bfd..7c9511c593 100755 --- a/t/t5700-protocol-v1.sh +++ b/t/t5700-protocol-v1.sh @@ -292,6 +292,4 @@ test_expect_success 'push with http:// using protocol v1' ' grep "git< version 1" log ' -stop_httpd - test_done diff --git a/t/t5701-git-serve.sh b/t/t5701-git-serve.sh index fe45bf828d..ffb9613885 100755 --- a/t/t5701-git-serve.sh +++ b/t/t5701-git-serve.sh @@ -1,6 +1,6 @@ #!/bin/sh -test_description='test git-serve and server commands' +test_description='test protocol v2 server commands' . ./test-lib.sh @@ -14,7 +14,8 @@ test_expect_success 'test capability advertisement' ' 0000 EOF - GIT_TEST_SIDEBAND_ALL=0 git serve --advertise-capabilities >out && + GIT_TEST_SIDEBAND_ALL=0 test-tool serve-v2 \ + --advertise-capabilities >out && test-tool pkt-line unpack <out >actual && test_cmp expect actual ' @@ -24,11 +25,11 @@ test_expect_success 'stateless-rpc flag does not list capabilities' ' test-tool pkt-line pack >in <<-EOF && 0000 EOF - git serve --stateless-rpc >out <in && + test-tool serve-v2 --stateless-rpc >out <in && test_must_be_empty out && # EOF - git serve --stateless-rpc >out && + test-tool serve-v2 --stateless-rpc >out && test_must_be_empty out ' @@ -37,7 +38,7 @@ test_expect_success 'request invalid capability' ' foobar 0000 EOF - test_must_fail git serve --stateless-rpc 2>err <in && + test_must_fail test-tool serve-v2 --stateless-rpc 2>err <in && test_i18ngrep "unknown capability" err ' @@ -46,7 +47,7 @@ test_expect_success 'request with no command' ' agent=git/test 0000 EOF - test_must_fail git serve --stateless-rpc 2>err <in && + test_must_fail test-tool serve-v2 --stateless-rpc 2>err <in && test_i18ngrep "no command requested" err ' @@ -56,7 +57,7 @@ test_expect_success 'request invalid command' ' agent=git/test 0000 EOF - test_must_fail git serve --stateless-rpc 2>err <in && + test_must_fail test-tool serve-v2 --stateless-rpc 2>err <in && test_i18ngrep "invalid command" err ' @@ -87,7 +88,7 @@ test_expect_success 'basics of ls-refs' ' 0000 EOF - git serve --stateless-rpc <in >out && + test-tool serve-v2 --stateless-rpc <in >out && test-tool pkt-line unpack <out >actual && test_cmp expect actual ' @@ -107,7 +108,7 @@ test_expect_success 'basic ref-prefixes' ' 0000 EOF - git serve --stateless-rpc <in >out && + test-tool serve-v2 --stateless-rpc <in >out && test-tool pkt-line unpack <out >actual && test_cmp expect actual ' @@ -127,7 +128,7 @@ test_expect_success 'refs/heads prefix' ' 0000 EOF - git serve --stateless-rpc <in >out && + test-tool serve-v2 --stateless-rpc <in >out && test-tool pkt-line unpack <out >actual && test_cmp expect actual ' @@ -148,7 +149,7 @@ test_expect_success 'peel parameter' ' 0000 EOF - git serve --stateless-rpc <in >out && + test-tool serve-v2 --stateless-rpc <in >out && test-tool pkt-line unpack <out >actual && test_cmp expect actual ' @@ -169,7 +170,7 @@ test_expect_success 'symrefs parameter' ' 0000 EOF - git serve --stateless-rpc <in >out && + test-tool serve-v2 --stateless-rpc <in >out && test-tool pkt-line unpack <out >actual && test_cmp expect actual ' @@ -189,7 +190,7 @@ test_expect_success 'sending server-options' ' 0000 EOF - git serve --stateless-rpc <in >out && + test-tool serve-v2 --stateless-rpc <in >out && test-tool pkt-line unpack <out >actual && test_cmp expect actual ' @@ -204,7 +205,10 @@ test_expect_success 'unexpected lines are not allowed in fetch request' ' 0000 EOF - test_must_fail git -C server serve --stateless-rpc <in >/dev/null 2>err && + ( + cd server && + test_must_fail test-tool serve-v2 --stateless-rpc + ) <in >/dev/null 2>err && grep "unexpected line: .this-is-not-a-command." err ' diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh index e112b6086c..5b33f625dd 100755 --- a/t/t5702-protocol-v2.sh +++ b/t/t5702-protocol-v2.sh @@ -182,6 +182,13 @@ test_expect_success 'server-options are sent when using ls-remote' ' grep "server-option=world" log ' +test_expect_success 'warn if using server-option with ls-remote with legacy protocol' ' + test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 git -c protocol.version=0 \ + ls-remote -o hello -o world "file://$(pwd)/file_parent" master 2>err && + + test_i18ngrep "see protocol.version in" err && + test_i18ngrep "server options require protocol version 2 or later" err +' test_expect_success 'clone with file:// using protocol v2' ' test_when_finished "rm -f log" && @@ -251,6 +258,40 @@ test_expect_success 'server-options are sent when fetching' ' grep "server-option=world" log ' +test_expect_success 'warn if using server-option with fetch with legacy protocol' ' + test_when_finished "rm -rf temp_child" && + + git init temp_child && + + test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 git -C temp_child -c protocol.version=0 \ + fetch -o hello -o world "file://$(pwd)/file_parent" master 2>err && + + test_i18ngrep "see protocol.version in" err && + test_i18ngrep "server options require protocol version 2 or later" err +' + +test_expect_success 'server-options are sent when cloning' ' + test_when_finished "rm -rf log myclone" && + + GIT_TRACE_PACKET="$(pwd)/log" git -c protocol.version=2 \ + clone --server-option=hello --server-option=world \ + "file://$(pwd)/file_parent" myclone && + + grep "server-option=hello" log && + grep "server-option=world" log +' + +test_expect_success 'warn if using server-option with clone with legacy protocol' ' + test_when_finished "rm -rf myclone" && + + test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 git -c protocol.version=0 \ + clone --server-option=hello --server-option=world \ + "file://$(pwd)/file_parent" myclone 2>err && + + test_i18ngrep "see protocol.version in" err && + test_i18ngrep "server options require protocol version 2 or later" err +' + test_expect_success 'upload-pack respects config using protocol v2' ' git init server && write_script server/.git/hook <<-\EOF && @@ -359,12 +400,13 @@ test_expect_success 'even with handcrafted request, filter does not work if not 0000 EOF - test_must_fail git -C server serve --stateless-rpc <in >/dev/null 2>err && + test_must_fail test-tool -C server serve-v2 --stateless-rpc \ + <in >/dev/null 2>err && grep "unexpected line: .filter blob:none." err && # Exercise to ensure that if advertised, filter works git -C server config uploadpack.allowfilter 1 && - git -C server serve --stateless-rpc <in >/dev/null + test-tool -C server serve-v2 --stateless-rpc <in >/dev/null ' test_expect_success 'default refspec is used to filter ref when fetchcing' ' @@ -687,6 +729,4 @@ test_expect_success 'when server does not send "ready", expect FLUSH' ' test_i18ngrep "expected no other sections to be sent after no .ready." err ' -stop_httpd - test_done diff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh index f87b2f6df3..0951d1bbdc 100755 --- a/t/t5703-upload-pack-ref-in-want.sh +++ b/t/t5703-upload-pack-ref-in-want.sh @@ -48,15 +48,15 @@ test_expect_success 'setup repository' ' ' test_expect_success 'config controls ref-in-want advertisement' ' - git serve --advertise-capabilities >out && + test-tool serve-v2 --advertise-capabilities >out && ! grep -a ref-in-want out && git config uploadpack.allowRefInWant false && - git serve --advertise-capabilities >out && + test-tool serve-v2 --advertise-capabilities >out && ! grep -a ref-in-want out && git config uploadpack.allowRefInWant true && - git serve --advertise-capabilities >out && + test-tool serve-v2 --advertise-capabilities >out && grep -a ref-in-want out ' @@ -70,7 +70,7 @@ test_expect_success 'invalid want-ref line' ' 0000 EOF - test_must_fail git serve --stateless-rpc 2>out <in && + test_must_fail test-tool serve-v2 --stateless-rpc 2>out <in && grep "unknown ref" out ' @@ -90,7 +90,7 @@ test_expect_success 'basic want-ref' ' 0000 EOF - git serve --stateless-rpc >out <in && + test-tool serve-v2 --stateless-rpc >out <in && check_output ' @@ -112,7 +112,7 @@ test_expect_success 'multiple want-ref lines' ' 0000 EOF - git serve --stateless-rpc >out <in && + test-tool serve-v2 --stateless-rpc >out <in && check_output ' @@ -133,7 +133,7 @@ test_expect_success 'mix want and want-ref' ' 0000 EOF - git serve --stateless-rpc >out <in && + test-tool serve-v2 --stateless-rpc >out <in && check_output ' @@ -153,7 +153,7 @@ test_expect_success 'want-ref with ref we already have commit for' ' 0000 EOF - git serve --stateless-rpc >out <in && + test-tool serve-v2 --stateless-rpc >out <in && check_output ' @@ -257,8 +257,6 @@ test_expect_success 'server loses a ref - ref in want' ' test_i18ngrep "fatal: remote error: unknown ref refs/heads/raster" err ' -stop_httpd - REPO="$(pwd)/repo" LOCAL_PRISTINE="$(pwd)/local_pristine" diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh index aaaa722cca..2d6c4a281e 100755 --- a/t/t5801-remote-helpers.sh +++ b/t/t5801-remote-helpers.sh @@ -8,6 +8,8 @@ test_description='Test remote-helper import and export commands' . ./test-lib.sh . "$TEST_DIRECTORY"/lib-gpg.sh +PATH="$TEST_DIRECTORY/t5801:$PATH" + compare_refs() { git --git-dir="$1/.git" rev-parse --verify $2 >expect && git --git-dir="$3/.git" rev-parse --verify $4 >actual && @@ -124,7 +126,7 @@ test_expect_success 'forced push' ' ' test_expect_success 'cloning without refspec' ' - GIT_REMOTE_TESTGIT_REFSPEC="" \ + GIT_REMOTE_TESTGIT_NOREFSPEC=1 \ git clone "testgit::${PWD}/server" local2 2>error && test_i18ngrep "this remote helper should implement refspec capability" error && compare_refs local2 HEAD server HEAD @@ -133,7 +135,7 @@ test_expect_success 'cloning without refspec' ' test_expect_success 'pulling without refspecs' ' (cd local2 && git reset --hard && - GIT_REMOTE_TESTGIT_REFSPEC="" git pull 2>../error) && + GIT_REMOTE_TESTGIT_NOREFSPEC=1 git pull 2>../error) && test_i18ngrep "this remote helper should implement refspec capability" error && compare_refs local2 HEAD server HEAD ' @@ -143,8 +145,8 @@ test_expect_success 'pushing without refspecs' ' (cd local2 && echo content >>file && git commit -a -m ten && - GIT_REMOTE_TESTGIT_REFSPEC="" && - export GIT_REMOTE_TESTGIT_REFSPEC && + GIT_REMOTE_TESTGIT_NOREFSPEC=1 && + export GIT_REMOTE_TESTGIT_NOREFSPEC && test_must_fail git push 2>../error) && test_i18ngrep "remote-helper doesn.t support push; refspec needed" error ' @@ -301,4 +303,14 @@ test_expect_success 'fetch url' ' compare_refs server HEAD local FETCH_HEAD ' +test_expect_success 'fetch tag' ' + (cd server && + git tag v1.0 + ) && + (cd local && + git fetch + ) && + compare_refs local v1.0 server v1.0 +' + test_done diff --git a/t/t5801/git-remote-testgit b/t/t5801/git-remote-testgit new file mode 100755 index 0000000000..6b9f0b5dc7 --- /dev/null +++ b/t/t5801/git-remote-testgit @@ -0,0 +1,151 @@ +#!/bin/sh +# Copyright (c) 2012 Felipe Contreras + +# The first argument can be a url when the fetch/push command was a url +# instead of a configured remote. In this case, use a generic alias. +if test "$1" = "testgit::$2"; then + alias=_ +else + alias=$1 +fi +url=$2 + +dir="$GIT_DIR/testgit/$alias" + +h_refspec="refs/heads/*:refs/testgit/$alias/heads/*" +t_refspec="refs/tags/*:refs/testgit/$alias/tags/*" + +if test -n "$GIT_REMOTE_TESTGIT_NOREFSPEC" +then + h_refspec="" + t_refspec="" +fi + +GIT_DIR="$url/.git" +export GIT_DIR + +force= + +mkdir -p "$dir" + +if test -z "$GIT_REMOTE_TESTGIT_NO_MARKS" +then + gitmarks="$dir/git.marks" + testgitmarks="$dir/testgit.marks" + test -e "$gitmarks" || >"$gitmarks" + test -e "$testgitmarks" || >"$testgitmarks" +fi + +while read line +do + case $line in + capabilities) + echo 'import' + echo 'export' + test -n "$h_refspec" && echo "refspec $h_refspec" + test -n "$t_refspec" && echo "refspec $t_refspec" + if test -n "$gitmarks" + then + echo "*import-marks $gitmarks" + echo "*export-marks $gitmarks" + fi + test -n "$GIT_REMOTE_TESTGIT_SIGNED_TAGS" && echo "signed-tags" + test -n "$GIT_REMOTE_TESTGIT_NO_PRIVATE_UPDATE" && echo "no-private-update" + echo 'option' + echo + ;; + list) + git for-each-ref --format='? %(refname)' 'refs/heads/' 'refs/tags/' + head=$(git symbolic-ref HEAD) + echo "@$head HEAD" + echo + ;; + import*) + # read all import lines + while true + do + ref="${line#* }" + refs="$refs $ref" + read line + test "${line%% *}" != "import" && break + done + + if test -n "$gitmarks" + then + echo "feature import-marks=$gitmarks" + echo "feature export-marks=$gitmarks" + fi + + if test -n "$GIT_REMOTE_TESTGIT_FAILURE" + then + echo "feature done" + exit 1 + fi + + echo "feature done" + git fast-export \ + ${h_refspec:+"--refspec=$h_refspec"} \ + ${t_refspec:+"--refspec=$t_refspec"} \ + ${testgitmarks:+"--import-marks=$testgitmarks"} \ + ${testgitmarks:+"--export-marks=$testgitmarks"} \ + $refs + echo "done" + ;; + export) + if test -n "$GIT_REMOTE_TESTGIT_FAILURE" + then + # consume input so fast-export doesn't get SIGPIPE; + # git would also notice that case, but we want + # to make sure we are exercising the later + # error checks + while read line; do + test "done" = "$line" && break + done + exit 1 + fi + + before=$(git for-each-ref --format=' %(refname) %(objectname) ') + + git fast-import \ + ${force:+--force} \ + ${testgitmarks:+"--import-marks=$testgitmarks"} \ + ${testgitmarks:+"--export-marks=$testgitmarks"} \ + --quiet + + # figure out which refs were updated + git for-each-ref --format='%(refname) %(objectname)' | + while read ref a + do + case "$before" in + *" $ref $a "*) + continue ;; # unchanged + esac + if test -z "$GIT_REMOTE_TESTGIT_PUSH_ERROR" + then + echo "ok $ref" + else + echo "error $ref $GIT_REMOTE_TESTGIT_PUSH_ERROR" + fi + done + + echo + ;; + option\ *) + read cmd opt val <<-EOF + $line + EOF + case $opt in + force) + test $val = "true" && force="true" || force= + echo "ok" + ;; + *) + echo "unsupported" + ;; + esac + ;; + '') + exit + ;; + esac +done diff --git a/t/t5812-proto-disable-http.sh b/t/t5812-proto-disable-http.sh index 872788ac8c..af8772fada 100755 --- a/t/t5812-proto-disable-http.sh +++ b/t/t5812-proto-disable-http.sh @@ -34,5 +34,4 @@ test_expect_success 'http can be limited to from-user' ' clone "$HTTPD_URL/smart-redir-perm/repo.git" redir.git ' -stop_httpd test_done diff --git a/t/t6000-rev-list-misc.sh b/t/t6000-rev-list-misc.sh index 0507999729..52a9e38d66 100755 --- a/t/t6000-rev-list-misc.sh +++ b/t/t6000-rev-list-misc.sh @@ -48,6 +48,26 @@ test_expect_success 'rev-list --objects with pathspecs and copied files' ' ! grep one output ' +test_expect_success 'rev-list --objects --no-object-names has no space/names' ' + git rev-list --objects --no-object-names HEAD >output && + ! grep wanted_file output && + ! grep unwanted_file output && + ! grep " " output +' + +test_expect_success 'rev-list --objects --no-object-names works with cat-file' ' + git rev-list --objects --no-object-names --all >list-output && + git cat-file --batch-check <list-output >cat-output && + ! grep missing cat-output +' + +test_expect_success '--no-object-names and --object-names are last-one-wins' ' + git rev-list --objects --no-object-names --object-names --all >output && + grep wanted_file output && + git rev-list --objects --object-names --no-object-names --all >output && + ! grep wanted_file output +' + test_expect_success 'rev-list A..B and rev-list ^A B are the same' ' git commit --allow-empty -m another && git tag -a -m "annotated" v1.0 && diff --git a/t/t6042-merge-rename-corner-cases.sh b/t/t6042-merge-rename-corner-cases.sh index 09dfa8bd92..c5b57f40c3 100755 --- a/t/t6042-merge-rename-corner-cases.sh +++ b/t/t6042-merge-rename-corner-cases.sh @@ -411,6 +411,122 @@ test_expect_success 'disappearing dir in rename/directory conflict handled' ' ) ' +# Test for basic rename/add-dest conflict, with rename needing content merge: +# Commit O: a +# Commit A: rename a->b, modifying b too +# Commit B: modify a, add different b + +test_expect_success 'setup rename-with-content-merge vs. add' ' + test_create_repo rename-with-content-merge-and-add && + ( + cd rename-with-content-merge-and-add && + + test_seq 1 5 >a && + git add a && + git commit -m O && + git tag O && + + git checkout -b A O && + git mv a b && + test_seq 0 5 >b && + git add b && + git commit -m A && + + git checkout -b B O && + echo 6 >>a && + echo hello world >b && + git add a b && + git commit -m B + ) +' + +test_expect_success 'handle rename-with-content-merge vs. add' ' + ( + cd rename-with-content-merge-and-add && + + git checkout A^0 && + + test_must_fail git merge -s recursive B^0 >out && + test_i18ngrep "CONFLICT (rename/add)" out && + + git ls-files -s >out && + test_line_count = 2 out && + git ls-files -u >out && + test_line_count = 2 out && + # Also, make sure both unmerged entries are for "b" + git ls-files -u b >out && + test_line_count = 2 out && + git ls-files -o >out && + test_line_count = 1 out && + + test_path_is_missing a && + test_path_is_file b && + + test_seq 0 6 >tmp && + git hash-object tmp >expect && + git rev-parse B:b >>expect && + git rev-parse >actual \ + :2:b :3:b && + test_cmp expect actual && + + # Test that the two-way merge in b is as expected + git cat-file -p :2:b >>ours && + git cat-file -p :3:b >>theirs && + >empty && + test_must_fail git merge-file \ + -L "HEAD" \ + -L "" \ + -L "B^0" \ + ours empty theirs && + test_cmp ours b + ) +' + +test_expect_success 'handle rename-with-content-merge vs. add, merge other way' ' + ( + cd rename-with-content-merge-and-add && + + git reset --hard && + git clean -fdx && + + git checkout B^0 && + + test_must_fail git merge -s recursive A^0 >out && + test_i18ngrep "CONFLICT (rename/add)" out && + + git ls-files -s >out && + test_line_count = 2 out && + git ls-files -u >out && + test_line_count = 2 out && + # Also, make sure both unmerged entries are for "b" + git ls-files -u b >out && + test_line_count = 2 out && + git ls-files -o >out && + test_line_count = 1 out && + + test_path_is_missing a && + test_path_is_file b && + + test_seq 0 6 >tmp && + git rev-parse B:b >expect && + git hash-object tmp >>expect && + git rev-parse >actual \ + :2:b :3:b && + test_cmp expect actual && + + # Test that the two-way merge in b is as expected + git cat-file -p :2:b >>ours && + git cat-file -p :3:b >>theirs && + >empty && + test_must_fail git merge-file \ + -L "HEAD" \ + -L "" \ + -L "A^0" \ + ours empty theirs && + test_cmp ours b + ) +' + # Test for all kinds of things that can go wrong with rename/rename (2to1): # Commit A: new files: a & b # Commit B: rename a->c, modify b diff --git a/t/t6043-merge-rename-directories.sh b/t/t6043-merge-rename-directories.sh index 62c564707b..50b7543483 100755 --- a/t/t6043-merge-rename-directories.sh +++ b/t/t6043-merge-rename-directories.sh @@ -75,7 +75,7 @@ test_expect_success '1a-check: Simple directory rename detection' ' git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 >out && git ls-files -s >out && test_line_count = 4 out && @@ -142,7 +142,7 @@ test_expect_success '1b-check: Merge a directory with another' ' git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -s >out && test_line_count = 4 out && @@ -201,7 +201,7 @@ test_expect_success '1c-check: Transitive renaming' ' git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 >out && git ls-files -s >out && test_line_count = 3 out && @@ -270,7 +270,7 @@ test_expect_success '1d-check: Directory renames cause a rename/rename(2to1) con git checkout A^0 && - test_must_fail git merge -s recursive B^0 >out && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && test_i18ngrep "CONFLICT (rename/rename)" out && git ls-files -s >out && @@ -350,7 +350,7 @@ test_expect_success '1e-check: Renamed directory, with all files being renamed t git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -s >out && test_line_count = 3 out && @@ -416,7 +416,7 @@ test_expect_success '1f-check: Split a directory into two other directories' ' git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -s >out && test_line_count = 6 out && @@ -497,7 +497,7 @@ test_expect_success '2a-check: Directory split into two on one side, with equal git checkout A^0 && - test_must_fail git merge -s recursive B^0 >out && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && test_i18ngrep "CONFLICT.*directory rename split" out && git ls-files -s >out && @@ -559,7 +559,7 @@ test_expect_success '2b-check: Directory split into two on one side, with equal git checkout A^0 && - git merge -s recursive B^0 >out && + git -c merge.directoryRenames=true merge -s recursive B^0 >out && git ls-files -s >out && test_line_count = 3 out && @@ -640,7 +640,7 @@ test_expect_success '3a-check: Avoid implicit rename if involved as source on ot git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -s >out && test_line_count = 3 out && @@ -705,7 +705,7 @@ test_expect_success '3b-check: Avoid implicit rename if involved as source on cu git checkout A^0 && - test_must_fail git merge -s recursive B^0 >out && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && test_i18ngrep CONFLICT.*rename/rename.*z/d.*x/d.*w/d out && test_i18ngrep ! CONFLICT.*rename/rename.*y/d out && @@ -826,7 +826,7 @@ test_expect_success '4a-check: Directory split, with original directory still pr git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -s >out && test_line_count = 5 out && @@ -915,7 +915,7 @@ test_expect_success '5a-check: Merge directories, other side adds files to origi git checkout A^0 && - test_must_fail git merge -s recursive B^0 >out && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && test_i18ngrep "CONFLICT.*implicit dir rename" out && git ls-files -s >out && @@ -989,7 +989,7 @@ test_expect_success '5b-check: Rename/delete in order to get add/add/add conflic git checkout A^0 && - test_must_fail git merge -s recursive B^0 >out && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && test_i18ngrep "CONFLICT (add/add).* y/d" out && git ls-files -s >out && @@ -1069,7 +1069,7 @@ test_expect_success '5c-check: Transitive rename would cause rename/rename/renam git checkout A^0 && - test_must_fail git merge -s recursive B^0 >out && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && test_i18ngrep "CONFLICT (rename/rename).*x/d.*w/d.*z/d" out && test_i18ngrep "CONFLICT (add/add).* y/d" out && @@ -1153,7 +1153,7 @@ test_expect_success '5d-check: Directory/file/file conflict due to directory ren git checkout A^0 && - test_must_fail git merge -s recursive B^0 >out && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && test_i18ngrep "CONFLICT (file/directory).*y/d" out && git ls-files -s >out && @@ -1243,7 +1243,7 @@ test_expect_success '6a-check: Tricky rename/delete' ' git checkout A^0 && - test_must_fail git merge -s recursive B^0 >out && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && test_i18ngrep "CONFLICT (rename/delete).*z/c.*y/c" out && git ls-files -s >out && @@ -1308,7 +1308,7 @@ test_expect_success '6b-check: Same rename done on both sides' ' git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -s >out && test_line_count = 3 out && @@ -1370,7 +1370,7 @@ test_expect_success '6c-check: Rename only done on same side' ' git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -s >out && test_line_count = 3 out && @@ -1432,7 +1432,7 @@ test_expect_success '6d-check: We do not always want transitive renaming' ' git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -s >out && test_line_count = 3 out && @@ -1495,7 +1495,7 @@ test_expect_success '6e-check: Add/add from one side' ' git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -s >out && test_line_count = 4 out && @@ -1591,7 +1591,7 @@ test_expect_success '7a-check: rename-dir vs. rename-dir (NOT split evenly) PLUS git checkout A^0 && - test_must_fail git merge -s recursive B^0 >out && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && test_i18ngrep "CONFLICT (rename/rename).*z/b.*y/b.*w/b" out && test_i18ngrep "CONFLICT (rename/rename).*z/c.*y/c.*x/c" out && @@ -1663,7 +1663,7 @@ test_expect_success '7b-check: rename/rename(2to1), but only due to transitive r git checkout A^0 && - test_must_fail git merge -s recursive B^0 >out && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && test_i18ngrep "CONFLICT (rename/rename)" out && git ls-files -s >out && @@ -1740,7 +1740,7 @@ test_expect_success '7c-check: rename/rename(1to...2or3); transitive rename may git checkout A^0 && - test_must_fail git merge -s recursive B^0 >out && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && test_i18ngrep "CONFLICT (rename/rename).*x/d.*w/d.*y/d" out && git ls-files -s >out && @@ -1804,7 +1804,7 @@ test_expect_success '7d-check: transitive rename involved in rename/delete; how git checkout A^0 && - test_must_fail git merge -s recursive B^0 >out && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && test_i18ngrep "CONFLICT (rename/delete).*x/d.*y/d" out && git ls-files -s >out && @@ -1894,7 +1894,7 @@ test_expect_success '7e-check: transitive rename in rename/delete AND dirs in th git checkout A^0 && - test_must_fail git merge -s recursive B^0 >out && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && test_i18ngrep "CONFLICT (rename/delete).*x/d.*y/d" out && git ls-files -s >out && @@ -1985,7 +1985,7 @@ test_expect_success '8a-check: Dual-directory rename, one into the others way' ' git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -s >out && test_line_count = 6 out && @@ -2063,7 +2063,7 @@ test_expect_success '8b-check: Dual-directory rename, one into the others way, w git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -s >out && test_line_count = 6 out && @@ -2135,7 +2135,7 @@ test_expect_success '8c-check: modify/delete or rename+modify/delete' ' git checkout A^0 && - test_must_fail git merge -s recursive B^0 >out && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && test_i18ngrep "CONFLICT (modify/delete).* z/d" out && git ls-files -s >out && @@ -2212,7 +2212,7 @@ test_expect_success '8d-check: rename/delete...or not?' ' git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -s >out && test_line_count = 3 out && @@ -2287,7 +2287,7 @@ test_expect_success '8e-check: Both sides rename, one side adds to original dire git checkout A^0 && - test_must_fail git merge -s recursive B^0 >out 2>err && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && test_i18ngrep CONFLICT.*rename/rename.*z/c.*y/c.*w/c out && test_i18ngrep CONFLICT.*rename/rename.*z/b.*y/b.*w/b out && @@ -2374,7 +2374,7 @@ test_expect_success '9a-check: Inner renamed directory within outer renamed dire git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -s >out && test_line_count = 7 out && @@ -2444,7 +2444,7 @@ test_expect_success '9b-check: Transitive rename with content merge' ' git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -s >out && test_line_count = 3 out && @@ -2534,7 +2534,7 @@ test_expect_success '9c-check: Doubly transitive rename?' ' git checkout A^0 && - git merge -s recursive B^0 >out && + git -c merge.directoryRenames=true merge -s recursive B^0 >out && test_i18ngrep "WARNING: Avoiding applying x -> z rename to x/f" out && git ls-files -s >out && @@ -2622,7 +2622,7 @@ test_expect_success '9d-check: N-way transitive rename?' ' git checkout A^0 && - git merge -s recursive B^0 >out && + git -c merge.directoryRenames=true merge -s recursive B^0 >out && test_i18ngrep "WARNING: Avoiding applying z -> y rename to z/t" out && test_i18ngrep "WARNING: Avoiding applying y -> x rename to y/a" out && test_i18ngrep "WARNING: Avoiding applying x -> w rename to x/b" out && @@ -2704,7 +2704,7 @@ test_expect_success C_LOCALE_OUTPUT '9e-check: N-to-1 whammo' ' git checkout A^0 && - test_must_fail git merge -s recursive B^0 >out && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out && grep "CONFLICT (implicit dir rename): Cannot map more than one path to combined/yo" out >error_line && grep -q dir1/yo error_line && grep -q dir2/yo error_line && @@ -2782,7 +2782,7 @@ test_expect_success '9f-check: Renamed directory that only contained immediate s git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -s >out && test_line_count = 4 out && @@ -2849,7 +2849,7 @@ test_expect_failure '9g-check: Renamed directory that only contained immediate s git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -s >out && test_line_count = 4 out && @@ -2918,7 +2918,7 @@ test_expect_success '9h-check: Avoid dir rename on merely modified path' ' git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -s >out && test_line_count = 3 out && @@ -2993,7 +2993,7 @@ test_expect_success '10a-check: Overwrite untracked with normal rename/delete' ' echo very >z/c && echo important >z/d && - test_must_fail git merge -s recursive B^0 >out 2>err && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && test_i18ngrep "The following untracked working tree files would be overwritten by merge" err && git ls-files -s >out && @@ -3061,7 +3061,7 @@ test_expect_success '10b-check: Overwrite untracked with dir rename + delete' ' echo important >y/d && echo contents >y/e && - test_must_fail git merge -s recursive B^0 >out 2>err && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && test_i18ngrep "CONFLICT (rename/delete).*Version B\^0 of y/d left in tree at y/d~B\^0" out && test_i18ngrep "Error: Refusing to lose untracked file at y/e; writing to y/e~B\^0 instead" out && @@ -3137,7 +3137,7 @@ test_expect_success '10c-check: Overwrite untracked with dir rename/rename(1to2) git checkout A^0 && echo important >y/c && - test_must_fail git merge -s recursive B^0 >out 2>err && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && test_i18ngrep "CONFLICT (rename/rename)" out && test_i18ngrep "Refusing to lose untracked file at y/c; adding as y/c~B\^0 instead" out && @@ -3174,7 +3174,7 @@ test_expect_success '10c-check: Overwrite untracked with dir rename/rename(1to2) mkdir y && echo important >y/c && - test_must_fail git merge -s recursive A^0 >out 2>err && + test_must_fail git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err && test_i18ngrep "CONFLICT (rename/rename)" out && test_i18ngrep "Refusing to lose untracked file at y/c; adding as y/c~HEAD instead" out && @@ -3249,7 +3249,7 @@ test_expect_success '10d-check: Delete untracked with dir rename/rename(2to1)' ' git checkout A^0 && echo important >y/wham && - test_must_fail git merge -s recursive B^0 >out 2>err && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && test_i18ngrep "CONFLICT (rename/rename)" out && test_i18ngrep "Refusing to lose untracked file at y/wham" out && @@ -3327,7 +3327,7 @@ test_expect_failure '10e-check: Does git complain about untracked file that is n mkdir z && echo random >z/c && - git merge -s recursive B^0 >out 2>err && + git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && test_i18ngrep ! "following untracked working tree files would be overwritten by merge" err && git ls-files -s >out && @@ -3407,7 +3407,7 @@ test_expect_success '11a-check: Avoid losing dirty contents with simple rename' git checkout A^0 && echo stuff >>z/c && - test_must_fail git merge -s recursive B^0 >out 2>err && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && test_i18ngrep "Refusing to lose dirty file at z/c" out && test_seq 1 10 >expected && @@ -3479,7 +3479,7 @@ test_expect_success '11b-check: Avoid losing dirty file involved in directory re git checkout A^0 && echo stuff >>z/c && - git merge -s recursive B^0 >out 2>err && + git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && test_i18ngrep "Refusing to lose dirty file at z/c" out && grep -q stuff z/c && @@ -3554,7 +3554,7 @@ test_expect_success '11c-check: Avoid losing not-uptodate with rename + D/F conf git checkout A^0 && echo stuff >>y/c && - test_must_fail git merge -s recursive B^0 >out 2>err && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && test_i18ngrep "following files would be overwritten by merge" err && grep -q stuff y/c && @@ -3621,7 +3621,7 @@ test_expect_success '11d-check: Avoid losing not-uptodate with rename + D/F conf git checkout A^0 && echo stuff >>z/c && - test_must_fail git merge -s recursive B^0 >out 2>err && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && test_i18ngrep "Refusing to lose dirty file at z/c" out && grep -q stuff z/c && @@ -3700,7 +3700,7 @@ test_expect_success '11e-check: Avoid deleting not-uptodate with dir rename/rena git checkout A^0 && echo mods >>y/c && - test_must_fail git merge -s recursive B^0 >out 2>err && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && test_i18ngrep "CONFLICT (rename/rename)" out && test_i18ngrep "Refusing to lose dirty file at y/c" out && @@ -3782,7 +3782,7 @@ test_expect_success '11f-check: Avoid deleting not-uptodate with dir rename/rena git checkout A^0 && echo important >>y/wham && - test_must_fail git merge -s recursive B^0 >out 2>err && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && test_i18ngrep "CONFLICT (rename/rename)" out && test_i18ngrep "Refusing to lose dirty file at y/wham" out && @@ -3870,7 +3870,7 @@ test_expect_success '12a-check: Moving one directory hierarchy into another' ' git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -s >out && test_line_count = 6 out && @@ -3910,7 +3910,7 @@ test_expect_success '12a-check: Moving one directory hierarchy into another' ' # To which, I can do no more than shrug my shoulders and say that # even simple rules give weird results when given weird inputs. -test_expect_success '12b-setup: Moving one directory hierarchy into another' ' +test_expect_success '12b-setup: Moving two directory hierarchies into each other' ' test_create_repo 12b && ( cd 12b && @@ -3940,13 +3940,13 @@ test_expect_success '12b-setup: Moving one directory hierarchy into another' ' ) ' -test_expect_success '12b-check: Moving one directory hierarchy into another' ' +test_expect_success '12b-check: Moving two directory hierarchies into each other' ' ( cd 12b && git checkout A^0 && - git merge -s recursive B^0 && + git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -s >out && test_line_count = 4 out && @@ -4016,7 +4016,7 @@ test_expect_success '12c-check: Moving one directory hierarchy into another w/ c git checkout A^0 && - test_must_fail git merge -s recursive B^0 && + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 && git ls-files -u >out && test_line_count = 12 out && @@ -4051,4 +4051,356 @@ test_expect_success '12c-check: Moving one directory hierarchy into another w/ c ) ' +########################################################################### +# SECTION 13: Checking informational and conflict messages +# +# A year after directory rename detection became the default, it was +# instead decided to report conflicts on the pathname on the basis that +# some users may expect the new files added or moved into a directory to +# be unrelated to all the other files in that directory, and thus that +# directory rename detection is unexpected. Test that the messages printed +# match our expectation. +########################################################################### + +# Testcase 13a, Basic directory rename with newly added files +# Commit O: z/{b,c} +# Commit A: y/{b,c} +# Commit B: z/{b,c,d,e/f} +# Expected: y/{b,c,d,e/f}, with notices/conflicts for both y/d and y/e/f + +test_expect_success '13a-setup: messages for newly added files' ' + test_create_repo 13a && + ( + cd 13a && + + mkdir z && + echo b >z/b && + echo c >z/c && + git add z && + test_tick && + git commit -m "O" && + + git branch O && + git branch A && + git branch B && + + git checkout A && + git mv z y && + test_tick && + git commit -m "A" && + + git checkout B && + echo d >z/d && + mkdir z/e && + echo f >z/e/f && + git add z/d z/e/f && + test_tick && + git commit -m "B" + ) +' + +test_expect_success '13a-check(conflict): messages for newly added files' ' + ( + cd 13a && + + git checkout A^0 && + + test_must_fail git merge -s recursive B^0 >out 2>err && + + test_i18ngrep CONFLICT..file.location.*z/e/f.added.in.B^0.*y/e/f out && + test_i18ngrep CONFLICT..file.location.*z/d.added.in.B^0.*y/d out && + + git ls-files >paths && + ! grep z/ paths && + grep "y/[de]" paths && + + test_path_is_missing z/d && + test_path_is_file y/d && + test_path_is_missing z/e/f && + test_path_is_file y/e/f + ) +' + +test_expect_success '13a-check(info): messages for newly added files' ' + ( + cd 13a && + + git reset --hard && + git checkout A^0 && + + git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && + + test_i18ngrep Path.updated:.*z/e/f.added.in.B^0.*y/e/f out && + test_i18ngrep Path.updated:.*z/d.added.in.B^0.*y/d out && + + git ls-files >paths && + ! grep z/ paths && + grep "y/[de]" paths && + + test_path_is_missing z/d && + test_path_is_file y/d && + test_path_is_missing z/e/f && + test_path_is_file y/e/f + ) +' + +# Testcase 13b, Transitive rename with conflicted content merge and default +# "conflict" setting +# (Related to testcase 1c, 9b) +# Commit O: z/{b,c}, x/d_1 +# Commit A: y/{b,c}, x/d_2 +# Commit B: z/{b,c,d_3} +# Expected: y/{b,c,d_merged}, with two conflict messages for y/d, +# one about content, and one about file location + +test_expect_success '13b-setup: messages for transitive rename with conflicted content' ' + test_create_repo 13b && + ( + cd 13b && + + mkdir x && + mkdir z && + test_seq 1 10 >x/d && + echo b >z/b && + echo c >z/c && + git add x z && + test_tick && + git commit -m "O" && + + git branch O && + git branch A && + git branch B && + + git checkout A && + git mv z y && + echo 11 >>x/d && + git add x/d && + test_tick && + git commit -m "A" && + + git checkout B && + echo eleven >>x/d && + git mv x/d z/d && + git add z/d && + test_tick && + git commit -m "B" + ) +' + +test_expect_success '13b-check(conflict): messages for transitive rename with conflicted content' ' + ( + cd 13b && + + git checkout A^0 && + + test_must_fail git merge -s recursive B^0 >out 2>err && + + test_i18ngrep CONFLICT.*content.*Merge.conflict.in.y/d out && + test_i18ngrep CONFLICT..file.location.*x/d.renamed.to.z/d.*moved.to.y/d out && + + git ls-files >paths && + ! grep z/ paths && + grep "y/d" paths && + + test_path_is_missing z/d && + test_path_is_file y/d + ) +' + +test_expect_success '13b-check(info): messages for transitive rename with conflicted content' ' + ( + cd 13b && + + git reset --hard && + git checkout A^0 && + + test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && + + test_i18ngrep CONFLICT.*content.*Merge.conflict.in.y/d out && + test_i18ngrep Path.updated:.*x/d.renamed.to.z/d.in.B^0.*moving.it.to.y/d out && + + git ls-files >paths && + ! grep z/ paths && + grep "y/d" paths && + + test_path_is_missing z/d && + test_path_is_file y/d + ) +' + +# Testcase 13c, Rename/rename(1to1) due to directory rename +# Commit O: z/{b,c}, x/{d,e} +# Commit A: y/{b,c,d}, x/e +# Commit B: z/{b,c,d}, x/e +# Expected: y/{b,c,d}, with info or conflict messages for d ( +# A: renamed x/d -> z/d; B: renamed z/ -> y/ AND renamed x/d to y/d +# One could argue A had partial knowledge of what was done with +# d and B had full knowledge, but that's a slippery slope as +# shown in testcase 13d. + +test_expect_success '13c-setup: messages for rename/rename(1to1) via transitive rename' ' + test_create_repo 13c && + ( + cd 13c && + + mkdir x && + mkdir z && + test_seq 1 10 >x/d && + echo e >x/e && + echo b >z/b && + echo c >z/c && + git add x z && + test_tick && + git commit -m "O" && + + git branch O && + git branch A && + git branch B && + + git checkout A && + git mv z y && + git mv x/d y/ && + test_tick && + git commit -m "A" && + + git checkout B && + git mv x/d z/d && + git add z/d && + test_tick && + git commit -m "B" + ) +' + +test_expect_success '13c-check(conflict): messages for rename/rename(1to1) via transitive rename' ' + ( + cd 13c && + + git checkout A^0 && + + test_must_fail git merge -s recursive B^0 >out 2>err && + + test_i18ngrep CONFLICT..file.location.*x/d.renamed.to.z/d.*moved.to.y/d out && + + git ls-files >paths && + ! grep z/ paths && + grep "y/d" paths && + + test_path_is_missing z/d && + test_path_is_file y/d + ) +' + +test_expect_success '13c-check(info): messages for rename/rename(1to1) via transitive rename' ' + ( + cd 13c && + + git reset --hard && + git checkout A^0 && + + git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && + + test_i18ngrep Path.updated:.*x/d.renamed.to.z/d.in.B^0.*moving.it.to.y/d out && + + git ls-files >paths && + ! grep z/ paths && + grep "y/d" paths && + + test_path_is_missing z/d && + test_path_is_file y/d + ) +' + +# Testcase 13d, Rename/rename(1to1) due to directory rename on both sides +# Commit O: a/{z,y}, b/x, c/w +# Commit A: a/z, b/{y,x}, d/w +# Commit B: a/z, d/x, c/{y,w} +# Expected: a/z, d/{y,x,w} with no file location conflict for x +# Easy cases: +# * z is always in a; so it stays in a. +# * x starts in b, only modified on one side to move into d/ +# * w starts in c, only modified on one side to move into d/ +# Hard case: +# * A renames a/y to b/y, and B renames b/->d/ => a/y -> d/y +# * B renames a/y to c/y, and A renames c/->d/ => a/y -> d/y +# No conflict in where a/y ends up, so put it in d/y. + +test_expect_success '13d-setup: messages for rename/rename(1to1) via dual transitive rename' ' + test_create_repo 13d && + ( + cd 13d && + + mkdir a && + mkdir b && + mkdir c && + echo z >a/z && + echo y >a/y && + echo x >b/x && + echo w >c/w && + git add a b c && + test_tick && + git commit -m "O" && + + git branch O && + git branch A && + git branch B && + + git checkout A && + git mv a/y b/ && + git mv c/ d/ && + test_tick && + git commit -m "A" && + + git checkout B && + git mv a/y c/ && + git mv b/ d/ && + test_tick && + git commit -m "B" + ) +' + +test_expect_success '13d-check(conflict): messages for rename/rename(1to1) via dual transitive rename' ' + ( + cd 13d && + + git checkout A^0 && + + test_must_fail git merge -s recursive B^0 >out 2>err && + + test_i18ngrep CONFLICT..file.location.*a/y.renamed.to.b/y.*moved.to.d/y out && + test_i18ngrep CONFLICT..file.location.*a/y.renamed.to.c/y.*moved.to.d/y out && + + git ls-files >paths && + ! grep b/ paths && + ! grep c/ paths && + grep "d/y" paths && + + test_path_is_missing b/y && + test_path_is_missing c/y && + test_path_is_file d/y + ) +' + +test_expect_success '13d-check(info): messages for rename/rename(1to1) via dual transitive rename' ' + ( + cd 13d && + + git reset --hard && + git checkout A^0 && + + git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err && + + test_i18ngrep Path.updated.*a/y.renamed.to.b/y.*moving.it.to.d/y out && + test_i18ngrep Path.updated.*a/y.renamed.to.c/y.*moving.it.to.d/y out && + + git ls-files >paths && + ! grep b/ paths && + ! grep c/ paths && + grep "d/y" paths && + + test_path_is_missing b/y && + test_path_is_missing c/y && + test_path_is_file d/y + ) +' + test_done diff --git a/t/t6046-merge-skip-unneeded-updates.sh b/t/t6046-merge-skip-unneeded-updates.sh index 38e24f787c..3a47623ed3 100755 --- a/t/t6046-merge-skip-unneeded-updates.sh +++ b/t/t6046-merge-skip-unneeded-updates.sh @@ -466,7 +466,7 @@ test_expect_success '3a-check-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' git checkout A^0 && - GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err && + 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 && @@ -495,7 +495,7 @@ test_expect_success '3a-check-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' git checkout B^0 && - GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err && + 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 && @@ -560,7 +560,7 @@ test_expect_success '3b-check-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' git checkout A^0 && - GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err && + 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 && @@ -589,7 +589,7 @@ test_expect_success '3b-check-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' ' git checkout B^0 && - GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err && + 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 && diff --git a/t/t6050-replace.sh b/t/t6050-replace.sh index d638119750..e7e64e085d 100755 --- a/t/t6050-replace.sh +++ b/t/t6050-replace.sh @@ -40,7 +40,8 @@ commit_peeling_shows_parents () test "$_found" = "$_parent" || return 1 _parent_number=$(( $_parent_number + 1 )) done && - test_must_fail git rev-parse --verify $_commit^$_parent_number + test_must_fail git rev-parse --verify $_commit^$_parent_number 2>err && + test_i18ngrep "Needed a single revision" err } commit_has_parents () @@ -393,9 +394,11 @@ test_expect_success 'replace ref cleanup' ' ' test_expect_success '--graft with and without already replaced object' ' - test $(git log --oneline | wc -l) = 7 && + git log --oneline >log && + test_line_count = 7 log && git replace --graft $HASH5 && - test $(git log --oneline | wc -l) = 3 && + git log --oneline >log && + test_line_count = 3 log && commit_has_parents $HASH5 && test_must_fail git replace --graft $HASH5 $HASH4 $HASH3 && git replace --force -g $HASH5 $HASH4 $HASH3 && @@ -403,6 +406,28 @@ test_expect_success '--graft with and without already replaced object' ' git replace -d $HASH5 ' +test_expect_success '--graft using a tag as the new parent' ' + git tag new_parent $HASH5 && + git replace --graft $HASH7 new_parent && + commit_has_parents $HASH7 $HASH5 && + git replace -d $HASH7 && + git tag -a -m "annotated new parent tag" annotated_new_parent $HASH5 && + git replace --graft $HASH7 annotated_new_parent && + commit_has_parents $HASH7 $HASH5 && + git replace -d $HASH7 +' + +test_expect_success '--graft using a tag as the replaced object' ' + git tag replaced_object $HASH7 && + git replace --graft replaced_object $HASH5 && + commit_has_parents $HASH7 $HASH5 && + git replace -d $HASH7 && + git tag -a -m "annotated replaced object tag" annotated_replaced_object $HASH7 && + git replace --graft annotated_replaced_object $HASH5 && + commit_has_parents $HASH7 $HASH5 && + git replace -d $HASH7 +' + test_expect_success GPG 'set up a signed commit' ' echo "line 17" >>hello && echo "line 18" >>hello && diff --git a/t/t6102-rev-list-unexpected-objects.sh b/t/t6102-rev-list-unexpected-objects.sh new file mode 100755 index 0000000000..28611c978e --- /dev/null +++ b/t/t6102-rev-list-unexpected-objects.sh @@ -0,0 +1,127 @@ +#!/bin/sh + +test_description='git rev-list should handle unexpected object types' + +. ./test-lib.sh + +test_expect_success 'setup well-formed objects' ' + blob="$(printf "foo" | git hash-object -w --stdin)" && + tree="$(printf "100644 blob $blob\tfoo" | git mktree)" && + commit="$(git commit-tree $tree -m "first commit")" && + git cat-file commit $commit >good-commit +' + +test_expect_success 'setup unexpected non-blob entry' ' + printf "100644 foo\0$(echo $tree | hex2oct)" >broken-tree && + broken_tree="$(git hash-object -w --literally -t tree broken-tree)" +' + +test_expect_failure 'traverse unexpected non-blob entry (lone)' ' + test_must_fail git rev-list --objects $broken_tree +' + +test_expect_success 'traverse unexpected non-blob entry (seen)' ' + test_must_fail git rev-list --objects $tree $broken_tree >output 2>&1 && + test_i18ngrep "is not a blob" output +' + +test_expect_success 'setup unexpected non-tree entry' ' + printf "40000 foo\0$(echo $blob | hex2oct)" >broken-tree && + broken_tree="$(git hash-object -w --literally -t tree broken-tree)" +' + +test_expect_success 'traverse unexpected non-tree entry (lone)' ' + test_must_fail git rev-list --objects $broken_tree +' + +test_expect_success 'traverse unexpected non-tree entry (seen)' ' + test_must_fail git rev-list --objects $blob $broken_tree >output 2>&1 && + test_i18ngrep "is not a tree" output +' + +test_expect_success 'setup unexpected non-commit parent' ' + sed "/^author/ { h; s/.*/parent $blob/; G; }" <good-commit \ + >broken-commit && + broken_commit="$(git hash-object -w --literally -t commit \ + broken-commit)" +' + +test_expect_success 'traverse unexpected non-commit parent (lone)' ' + test_must_fail git rev-list --objects $broken_commit >output 2>&1 && + test_i18ngrep "not a commit" output +' + +test_expect_success 'traverse unexpected non-commit parent (seen)' ' + test_must_fail git rev-list --objects $commit $broken_commit \ + >output 2>&1 && + test_i18ngrep "not a commit" output +' + +test_expect_success 'setup unexpected non-tree root' ' + sed -e "s/$tree/$blob/" <good-commit >broken-commit && + broken_commit="$(git hash-object -w --literally -t commit \ + broken-commit)" +' + +test_expect_success 'traverse unexpected non-tree root (lone)' ' + test_must_fail git rev-list --objects $broken_commit +' + +test_expect_success 'traverse unexpected non-tree root (seen)' ' + test_must_fail git rev-list --objects $blob $broken_commit \ + >output 2>&1 && + test_i18ngrep "not a tree" output +' + +test_expect_success 'setup unexpected non-commit tag' ' + git tag -a -m "tagged commit" tag $commit && + git cat-file tag tag >good-tag && + test_when_finished "git tag -d tag" && + sed -e "s/$commit/$blob/" <good-tag >broken-tag && + tag=$(git hash-object -w --literally -t tag broken-tag) +' + +test_expect_success 'traverse unexpected non-commit tag (lone)' ' + test_must_fail git rev-list --objects $tag +' + +test_expect_success 'traverse unexpected non-commit tag (seen)' ' + test_must_fail git rev-list --objects $blob $tag >output 2>&1 && + test_i18ngrep "not a commit" output +' + +test_expect_success 'setup unexpected non-tree tag' ' + git tag -a -m "tagged tree" tag $tree && + git cat-file tag tag >good-tag && + test_when_finished "git tag -d tag" && + sed -e "s/$tree/$blob/" <good-tag >broken-tag && + tag=$(git hash-object -w --literally -t tag broken-tag) +' + +test_expect_success 'traverse unexpected non-tree tag (lone)' ' + test_must_fail git rev-list --objects $tag +' + +test_expect_success 'traverse unexpected non-tree tag (seen)' ' + test_must_fail git rev-list --objects $blob $tag >output 2>&1 && + test_i18ngrep "not a tree" output +' + +test_expect_success 'setup unexpected non-blob tag' ' + git tag -a -m "tagged blob" tag $blob && + git cat-file tag tag >good-tag && + test_when_finished "git tag -d tag" && + sed -e "s/$blob/$commit/" <good-tag >broken-tag && + tag=$(git hash-object -w --literally -t tag broken-tag) +' + +test_expect_failure 'traverse unexpected non-blob tag (lone)' ' + test_must_fail git rev-list --objects $tag +' + +test_expect_success 'traverse unexpected non-blob tag (seen)' ' + test_must_fail git rev-list --objects $commit $tag >output 2>&1 && + test_i18ngrep "not a blob" output +' + +test_done diff --git a/t/t6112-rev-list-filters-objects.sh b/t/t6112-rev-list-filters-objects.sh index 9c11427719..acd7f5ab80 100755 --- a/t/t6112-rev-list-filters-objects.sh +++ b/t/t6112-rev-list-filters-objects.sh @@ -157,6 +157,10 @@ test_expect_success 'verify blob:limit=1m' ' ' # Test sparse:path=<path> filter. +# !!!! +# NOTE: sparse:path filter support has been dropped for security reasons, +# so the tests have been changed to make sure that using it fails. +# !!!! # Use a local file containing a sparse-checkout specification to filter # out blobs not required for the corresponding sparse-checkout. We do not # require sparse-checkout to actually be enabled. @@ -176,37 +180,20 @@ test_expect_success 'setup r3' ' echo sparse1 >pattern2 ' -test_expect_success 'verify sparse:path=pattern1 omits top-level files' ' - git -C r3 ls-files -s sparse1 sparse2 >ls_files_result && - awk -f print_2.awk ls_files_result | - sort >expected && - - git -C r3 rev-list --quiet --objects --filter-print-omitted \ - --filter=sparse:path=../pattern1 HEAD >revs && - awk -f print_1.awk revs | - sed "s/~//" | - sort >observed && - - test_cmp expected observed +test_expect_success 'verify sparse:path=pattern1 fails' ' + test_must_fail git -C r3 rev-list --quiet --objects \ + --filter-print-omitted --filter=sparse:path=../pattern1 HEAD ' -test_expect_success 'verify sparse:path=pattern2 omits both sparse2 files' ' - git -C r3 ls-files -s sparse2 dir1/sparse2 >ls_files_result && - awk -f print_2.awk ls_files_result | - sort >expected && - - git -C r3 rev-list --quiet --objects --filter-print-omitted \ - --filter=sparse:path=../pattern2 HEAD >revs && - awk -f print_1.awk revs | - sed "s/~//" | - sort >observed && - - test_cmp expected observed +test_expect_success 'verify sparse:path=pattern2 fails' ' + test_must_fail git -C r3 rev-list --quiet --objects \ + --filter-print-omitted --filter=sparse:path=../pattern2 HEAD ' # Test sparse:oid=<oid-ish> filter. -# Like sparse:path, but we get the sparse-checkout specification from -# a blob rather than a file on disk. +# Use a blob containing a sparse-checkout specification to filter +# out blobs not required for the corresponding sparse-checkout. We do not +# require sparse-checkout to actually be enabled. test_expect_success 'setup r3 part 2' ' echo dir1/ >r3/pattern && diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index 0ffd630713..d9235217fc 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -392,8 +392,15 @@ test_atom head upstream:track '[ahead 1]' test_atom head upstream:trackshort '>' test_atom head upstream:track,nobracket 'ahead 1' test_atom head upstream:nobracket,track 'ahead 1' -test_atom head push:track '[ahead 1]' -test_atom head push:trackshort '>' + +test_expect_success 'setup for push:track[short]' ' + test_commit third && + git update-ref refs/remotes/myfork/master master && + git reset master~1 +' + +test_atom head push:track '[behind 1]' +test_atom head push:trackshort '<' test_expect_success 'Check that :track[short] cannot be used with other atoms' ' test_must_fail git for-each-ref --format="%(refname:track)" 2>/dev/null && @@ -420,8 +427,10 @@ test_expect_success 'Check for invalid refname format' ' test_expect_success 'set up color tests' ' cat >expected.color <<-EOF && $(git rev-parse --short refs/heads/master) <GREEN>master<RESET> + $(git rev-parse --short refs/remotes/myfork/master) <GREEN>myfork/master<RESET> $(git rev-parse --short refs/remotes/origin/master) <GREEN>origin/master<RESET> $(git rev-parse --short refs/tags/testtag) <GREEN>testtag<RESET> + $(git rev-parse --short refs/tags/third) <GREEN>third<RESET> $(git rev-parse --short refs/tags/two) <GREEN>two<RESET> EOF sed "s/<[^>]*>//g" <expected.color >expected.bare && diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh index fc067ed672..35408d53fd 100755 --- a/t/t6302-for-each-ref-filter.sh +++ b/t/t6302-for-each-ref-filter.sh @@ -441,4 +441,17 @@ test_expect_success '--merged is incompatible with --no-merged' ' test_must_fail git for-each-ref --merged HEAD --no-merged HEAD ' +test_expect_success 'validate worktree atom' ' + cat >expect <<-EOF && + master: $(pwd) + master_worktree: $(pwd)/worktree_dir + side: not checked out + EOF + git worktree add -b master_worktree worktree_dir master && + git for-each-ref --format="%(refname:short): %(if)%(worktreepath)%(then)%(worktreepath)%(else)not checked out%(end)" refs/heads/ >actual && + rm -r worktree_dir && + git worktree prune && + test_cmp expect actual +' + test_done diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh index 4684d06552..c0f04dc6b0 100755 --- a/t/t6500-gc.sh +++ b/t/t6500-gc.sh @@ -71,6 +71,8 @@ test_expect_success 'gc --keep-largest-pack' ' git gc --keep-largest-pack && ( cd .git/objects/pack && ls *.pack ) >pack-list && test_line_count = 2 pack-list && + awk "/^P /{print \$2}" <.git/objects/info/packs >pack-info && + test_line_count = 2 pack-info && test_path_is_file $BASE_PACK && git fsck ) @@ -120,6 +122,25 @@ test_expect_success 'gc --quiet' ' test_must_be_empty stderr ' +test_expect_success 'gc.reflogExpire{Unreachable,}=never skips "expire" via "gc"' ' + test_config gc.reflogExpire never && + test_config gc.reflogExpireUnreachable never && + + GIT_TRACE=$(pwd)/trace.out git gc && + + # Check that git-pack-refs is run as a sanity check (done via + # gc_before_repack()) but that git-expire is not. + grep -E "^trace: (built-in|exec|run_command): git pack-refs --" trace.out && + ! grep -E "^trace: (built-in|exec|run_command): git reflog expire --" trace.out +' + +test_expect_success 'one of gc.reflogExpire{Unreachable,}=never does not skip "expire" via "gc"' ' + >trace.out && + test_config gc.reflogExpire never && + GIT_TRACE=$(pwd)/trace.out git gc && + grep -E "^trace: (built-in|exec|run_command): git reflog expire --" trace.out +' + run_and_wait_for_auto_gc () { # We read stdout from gc for the side effect of waiting until the # background gc process exits, closing its fd 9. Furthermore, the @@ -162,7 +183,15 @@ test_expect_success 'background auto gc respects lock for all operations' ' # now fake a concurrent gc that holds the lock; we can use our # shell pid so that it looks valid. hostname=$(hostname || echo unknown) && - printf "$$ %s" "$hostname" >.git/gc.pid && + shell_pid=$$ && + if test_have_prereq MINGW && test -f /proc/$shell_pid/winpid + then + # In Git for Windows, Bash (actually, the MSYS2 runtime) has a + # different idea of PIDs than git.exe (actually Windows). Use + # the Windows PID in this case. + shell_pid=$(cat /proc/$shell_pid/winpid) + fi && + printf "%d %s" "$shell_pid" "$hostname" >.git/gc.pid && # our gc should exit zero without doing anything run_and_wait_for_auto_gc && diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh index 0b01862c23..80eb13d94e 100755 --- a/t/t7004-tag.sh +++ b/t/t7004-tag.sh @@ -932,6 +932,27 @@ test_expect_success GPG \ test_cmp expect actual ' +get_tag_header gpgsign-enabled $commit commit $time >expect +echo "A message" >>expect +echo '-----BEGIN PGP SIGNATURE-----' >>expect +test_expect_success GPG \ + 'git tag configured tag.gpgsign enables GPG sign' \ + 'test_config tag.gpgsign true && + git tag -m "A message" gpgsign-enabled && + get_tag_msg gpgsign-enabled>actual && + test_cmp expect actual +' + +get_tag_header no-sign $commit commit $time >expect +echo "A message" >>expect +test_expect_success GPG \ + 'git tag --no-sign configured tag.gpgsign skip GPG sign' \ + 'test_config tag.gpgsign true && + git tag -a --no-sign -m "A message" no-sign && + get_tag_msg no-sign>actual && + test_cmp expect actual +' + test_expect_success GPG \ 'trying to create a signed tag with non-existing -F file should fail' ' ! test -f nonexistingfile && @@ -1700,6 +1721,17 @@ test_expect_success '--points-at finds annotated tags of tags' ' test_cmp expect actual ' +test_expect_success 'recursive tagging should give advice' ' + sed -e "s/|$//" <<-EOF >expect && + hint: You have created a nested tag. The object referred to by your new tag is + 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^{} + EOF + git tag -m nested nested annotated-v4.0 2>actual && + test_i18ncmp expect actual +' + test_expect_success 'multiple --points-at are OR-ed together' ' cat >expect <<-\EOF && v2.0 diff --git a/t/t7113-post-index-change-hook.sh b/t/t7113-post-index-change-hook.sh new file mode 100755 index 0000000000..f011ad7eec --- /dev/null +++ b/t/t7113-post-index-change-hook.sh @@ -0,0 +1,144 @@ +#!/bin/sh + +test_description='post index change hook' + +. ./test-lib.sh + +test_expect_success 'setup' ' + mkdir -p dir1 && + touch dir1/file1.txt && + echo testing >dir1/file2.txt && + git add . && + git commit -m "initial" +' + +test_expect_success 'test status, add, commit, others trigger hook without flags set' ' + mkdir -p .git/hooks && + write_script .git/hooks/post-index-change <<-\EOF && + if test "$1" -eq 1; then + echo "Invalid combination of flags passed to hook; updated_workdir is set." >testfailure + exit 1 + fi + if test "$2" -eq 1; then + echo "Invalid combination of flags passed to hook; updated_skipworktree is set." >testfailure + exit 1 + fi + if test -f ".git/index.lock"; then + echo ".git/index.lock exists" >testfailure + exit 3 + fi + if ! test -f ".git/index"; then + echo ".git/index does not exist" >testfailure + exit 3 + fi + echo "success" >testsuccess + EOF + mkdir -p dir2 && + touch dir2/file1.txt && + touch dir2/file2.txt && + : force index to be dirty && + test-tool chmtime +60 dir1/file1.txt && + git status && + test_path_is_file testsuccess && rm -f testsuccess && + test_path_is_missing testfailure && + git add . && + test_path_is_file testsuccess && rm -f testsuccess && + test_path_is_missing testfailure && + git commit -m "second" && + test_path_is_file testsuccess && rm -f testsuccess && + test_path_is_missing testfailure && + git checkout -- dir1/file1.txt && + test_path_is_file testsuccess && rm -f testsuccess && + test_path_is_missing testfailure && + git update-index && + test_path_is_missing testsuccess && + test_path_is_missing testfailure && + git reset --soft && + test_path_is_missing testsuccess && + test_path_is_missing testfailure +' + +test_expect_success 'test checkout and reset trigger the hook' ' + write_script .git/hooks/post-index-change <<-\EOF && + if test "$1" -eq 1 && test "$2" -eq 1; then + echo "Invalid combination of flags passed to hook; updated_workdir and updated_skipworktree are both set." >testfailure + exit 1 + fi + if test "$1" -eq 0 && test "$2" -eq 0; then + echo "Invalid combination of flags passed to hook; neither updated_workdir or updated_skipworktree are set." >testfailure + exit 2 + fi + if test "$1" -eq 1; then + if test -f ".git/index.lock"; then + echo "updated_workdir set but .git/index.lock exists" >testfailure + exit 3 + fi + if ! test -f ".git/index"; then + echo "updated_workdir set but .git/index does not exist" >testfailure + exit 3 + fi + else + echo "update_workdir should be set for checkout" >testfailure + exit 4 + fi + echo "success" >testsuccess + EOF + : force index to be dirty && + test-tool chmtime +60 dir1/file1.txt && + git checkout master && + test_path_is_file testsuccess && rm -f testsuccess && + test_path_is_missing testfailure && + test-tool chmtime +60 dir1/file1.txt && + git checkout HEAD && + test_path_is_file testsuccess && rm -f testsuccess && + test_path_is_missing testfailure && + test-tool chmtime +60 dir1/file1.txt && + git reset --hard && + test_path_is_file testsuccess && rm -f testsuccess && + test_path_is_missing testfailure && + git checkout -B test && + test_path_is_file testsuccess && rm -f testsuccess && + test_path_is_missing testfailure +' + +test_expect_success 'test reset --mixed and update-index triggers the hook' ' + write_script .git/hooks/post-index-change <<-\EOF && + if test "$1" -eq 1 && test "$2" -eq 1; then + echo "Invalid combination of flags passed to hook; updated_workdir and updated_skipworktree are both set." >testfailure + exit 1 + fi + if test "$1" -eq 0 && test "$2" -eq 0; then + echo "Invalid combination of flags passed to hook; neither updated_workdir or updated_skipworktree are set." >testfailure + exit 2 + fi + if test "$2" -eq 1; then + if test -f ".git/index.lock"; then + echo "updated_skipworktree set but .git/index.lock exists" >testfailure + exit 3 + fi + if ! test -f ".git/index"; then + echo "updated_skipworktree set but .git/index does not exist" >testfailure + exit 3 + fi + else + echo "updated_skipworktree should be set for reset --mixed and update-index" >testfailure + exit 4 + fi + echo "success" >testsuccess + EOF + : force index to be dirty && + test-tool chmtime +60 dir1/file1.txt && + git reset --mixed --quiet HEAD~1 && + test_path_is_file testsuccess && rm -f testsuccess && + test_path_is_missing testfailure && + git hash-object -w --stdin <dir1/file2.txt >expect && + git update-index --cacheinfo 100644 "$(cat expect)" dir1/file1.txt && + test_path_is_file testsuccess && rm -f testsuccess && + test_path_is_missing testfailure && + git update-index --skip-worktree dir1/file2.txt && + git update-index --remove dir1/file2.txt && + test_path_is_file testsuccess && rm -f testsuccess && + test_path_is_missing testfailure +' + +test_done diff --git a/t/t7201-co.sh b/t/t7201-co.sh index 72b9b375ba..5990299fc9 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -223,13 +223,8 @@ test_expect_success 'switch to another branch while carrying a deletion' ' test_must_fail git checkout simple 2>errs && test_i18ngrep overwritten errs && - git checkout --merge simple 2>errs && - test_i18ngrep ! overwritten errs && - git ls-files -u && - test_must_fail git cat-file -t :0:two && - test "$(git cat-file -t :1:two)" = blob && - test "$(git cat-file -t :2:two)" = blob && - test_must_fail git cat-file -t :3:two + test_must_fail git read-tree --quiet -m -u HEAD simple 2>errs && + test_must_be_empty errs ' test_expect_success 'checkout to detach HEAD (with advice declined)' ' diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh index aba2d4d6ee..a208cb26e1 100755 --- a/t/t7400-submodule-basic.sh +++ b/t/t7400-submodule-basic.sh @@ -46,6 +46,15 @@ test_expect_success 'submodule update aborts on missing gitmodules url' ' test_must_fail git submodule init ' +test_expect_success 'add aborts on repository with no commits' ' + cat >expect <<-\EOF && + '"'repo-no-commits'"' does not have a commit checked out + EOF + git init repo-no-commits && + test_must_fail git submodule add ../a ./repo-no-commits 2>actual && + test_i18ncmp expect actual +' + test_expect_success 'setup - repository in init subdirectory' ' mkdir init && ( @@ -809,7 +818,7 @@ test_expect_success '../bar/a/b/c works with relative local path - ../foo/bar.gi cp pristine-.git-config .git/config && cp pristine-.gitmodules .gitmodules && mkdir -p a/b/c && - (cd a/b/c && git init) && + (cd a/b/c && git init && test_commit msg) && git config remote.origin.url ../foo/bar.git && git submodule add ../bar/a/b/c ./a/b/c && git submodule init && diff --git a/t/t7405-submodule-merge.sh b/t/t7405-submodule-merge.sh index 7855bd8648..aa33978ed2 100755 --- a/t/t7405-submodule-merge.sh +++ b/t/t7405-submodule-merge.sh @@ -417,7 +417,7 @@ test_expect_failure 'directory/submodule conflict; keep submodule clean' ' ) ' -test_expect_failure 'directory/submodule conflict; should not treat submodule files as untracked or in the way' ' +test_expect_failure !FAIL_PREREQS 'directory/submodule conflict; should not treat submodule files as untracked or in the way' ' test_when_finished "git -C directory-submodule/path reset --hard" && test_when_finished "git -C directory-submodule reset --hard" && ( diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh index 77729ac4aa..706ae762e0 100755 --- a/t/t7407-submodule-foreach.sh +++ b/t/t7407-submodule-foreach.sh @@ -411,4 +411,14 @@ test_expect_success 'multi-argument command passed to foreach is not shell-evalu test_cmp expected actual ' +test_expect_success 'option-like arguments passed to foreach commands are not lost' ' + ( + cd super && + git submodule foreach "echo be --quiet" > ../expected && + git submodule foreach echo be --quiet > ../actual + ) && + grep -sq -e "--quiet" expected && + test_cmp expected actual +' + test_done diff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh index 89690b7adb..ad28e93880 100755 --- a/t/t7411-submodule-config.sh +++ b/t/t7411-submodule-config.sh @@ -142,6 +142,15 @@ test_expect_success 'reading submodules config from the working tree with "submo ) ' +test_expect_success 'unsetting submodules config from the working tree with "submodule--helper config --unset"' ' + (cd super && + git submodule--helper config --unset submodule.submodule.url && + git submodule--helper config submodule.submodule.url >actual && + test_must_be_empty actual + ) +' + + test_expect_success 'writing submodules config with "submodule--helper config"' ' (cd super && echo "new_url" >expect && @@ -234,18 +243,14 @@ test_expect_success 'reading nested submodules config' ' ) ' -# When this test eventually passes, before turning it into -# test_expect_success, remember to replace the test_i18ngrep below with -# a "test_must_be_empty warning" to be sure that the warning is actually -# removed from the code. -test_expect_failure 'reading nested submodules config when .gitmodules is not in the working tree' ' +test_expect_success 'reading nested submodules config when .gitmodules is not in the working tree' ' test_when_finished "git -C super/submodule checkout .gitmodules" && (cd super && echo "./nested_submodule" >expect && rm submodule/.gitmodules && test-tool submodule-nested-repo-config \ submodule submodule.nested_submodule.url >actual 2>warning && - test_i18ngrep "nested submodules without %s in the working tree are not supported yet" warning && + test_must_be_empty warning && test_cmp expect actual ) ' diff --git a/t/t7419-submodule-set-branch.sh b/t/t7419-submodule-set-branch.sh new file mode 100755 index 0000000000..c4b370ea85 --- /dev/null +++ b/t/t7419-submodule-set-branch.sh @@ -0,0 +1,93 @@ +#!/bin/sh +# +# Copyright (c) 2019 Denton Liu +# + +test_description='Test submodules set-branch subcommand + +This test verifies that the set-branch subcommand of git-submodule is working +as expected. +' + +TEST_NO_CREATE_REPO=1 +. ./test-lib.sh + +test_expect_success 'submodule config cache setup' ' + mkdir submodule && + (cd submodule && + git init && + echo a >a && + git add . && + git commit -ma && + git checkout -b topic && + echo b >a && + git add . && + git commit -mb + ) && + mkdir super && + (cd super && + git init && + git submodule add ../submodule && + git commit -m "add submodule" + ) +' + +test_expect_success 'ensure submodule branch is unset' ' + (cd super && + test_must_fail grep branch .gitmodules + ) +' + +test_expect_success 'test submodule set-branch --branch' ' + (cd super && + git submodule set-branch --branch topic submodule && + grep "branch = topic" .gitmodules && + git submodule update --remote && + cat <<-\EOF >expect && + b + EOF + git -C submodule show -s --pretty=%s >actual && + test_cmp expect actual + ) +' + +test_expect_success 'test submodule set-branch --default' ' + (cd super && + git submodule set-branch --default submodule && + test_must_fail grep branch .gitmodules && + git submodule update --remote && + cat <<-\EOF >expect && + a + EOF + git -C submodule show -s --pretty=%s >actual && + test_cmp expect actual + ) +' + +test_expect_success 'test submodule set-branch -b' ' + (cd super && + git submodule set-branch -b topic submodule && + grep "branch = topic" .gitmodules && + git submodule update --remote && + cat <<-\EOF >expect && + b + EOF + git -C submodule show -s --pretty=%s >actual && + test_cmp expect actual + ) +' + +test_expect_success 'test submodule set-branch -d' ' + (cd super && + git submodule set-branch -d submodule && + test_must_fail grep branch .gitmodules && + git submodule update --remote && + cat <<-\EOF >expect && + a + EOF + git -C submodule show -s --pretty=%s >actual && + test_cmp expect actual + ) +' + +test_done diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh index ca4a740da0..14c92e4c25 100755 --- a/t/t7502-commit-porcelain.sh +++ b/t/t7502-commit-porcelain.sh @@ -16,7 +16,8 @@ commit_msg_is () { # Arguments: [<prefix] [<commit message>] [<commit options>] check_summary_oneline() { test_tick && - git commit ${3+"$3"} -m "$2" | head -1 > act && + git commit ${3+"$3"} -m "$2" >raw && + head -n 1 raw >act && # branch name SUMMARY_PREFIX="$(git name-rev --name-only HEAD)" && @@ -68,7 +69,7 @@ test_expect_success 'output summary format for merges' ' git checkout recursive-a && test_must_fail git merge recursive-b && # resolve the conflict - echo commit-a > file1 && + echo commit-a >file1 && git add file1 && check_summary_oneline "" "Merge" ' @@ -142,9 +143,11 @@ test_expect_success 'sign off' ' >positive && git add positive && git commit -s -m "thank you" && - actual=$(git cat-file commit HEAD | sed -ne "s/Signed-off-by: //p") && - expected=$(git var GIT_COMMITTER_IDENT | sed -e "s/>.*/>/") && - test "z$actual" = "z$expected" + git cat-file commit HEAD >commit.msg && + sed -ne "s/Signed-off-by: //p" commit.msg >actual && + git var GIT_COMMITTER_IDENT >ident && + sed -e "s/>.*/>/" ident >expected && + test_cmp expected actual ' @@ -153,8 +156,8 @@ test_expect_success 'multiple -m' ' >negative && git add negative && git commit -m "one" -m "two" -m "three" && - actual=$(git cat-file commit HEAD | sed -e "1,/^\$/d") && - expected=$(echo one; echo; echo two; echo; echo three) && + actual=$(git cat-file commit HEAD >tmp && sed -e "1,/^\$/d" tmp && rm tmp) && + expected=$(test_write_lines "one" "" "two" "" "three") && test "z$actual" = "z$expected" ' @@ -163,7 +166,8 @@ test_expect_success 'verbose' ' echo minus >negative && git add negative && - git status -v | sed -ne "/^diff --git /p" >actual && + git status -v >raw && + sed -ne "/^diff --git /p" raw >actual && echo "diff --git a/negative b/negative" >expect && test_cmp expect actual @@ -189,7 +193,8 @@ test_expect_success 'cleanup commit messages (verbatim option,-t)' ' echo >>negative && git commit --cleanup=verbatim --no-status -t expect -a && - git cat-file -p HEAD |sed -e "1,/^\$/d" >actual && + git cat-file -p HEAD >raw && + sed -e "1,/^\$/d" raw >actual && test_cmp expect actual ' @@ -198,7 +203,8 @@ test_expect_success 'cleanup commit messages (verbatim option,-F)' ' echo >>negative && git commit --cleanup=verbatim -F expect -a && - git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + git cat-file -p HEAD >raw && + sed -e "1,/^\$/d" raw >actual && test_cmp expect actual ' @@ -207,7 +213,8 @@ test_expect_success 'cleanup commit messages (verbatim option,-m)' ' echo >>negative && git commit --cleanup=verbatim -m "$mesg_with_comment_and_newlines" -a && - git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + git cat-file -p HEAD >raw && + sed -e "1,/^\$/d" raw >actual && test_cmp expect actual ' @@ -215,10 +222,11 @@ test_expect_success 'cleanup commit messages (verbatim option,-m)' ' test_expect_success 'cleanup commit messages (whitespace option,-F)' ' echo >>negative && - { echo;echo "# text";echo; } >text && + test_write_lines "" "# text" "" >text && echo "# text" >expect && git commit --cleanup=whitespace -F text -a && - git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + git cat-file -p HEAD >raw && + sed -e "1,/^\$/d" raw >actual && test_cmp expect actual ' @@ -226,48 +234,51 @@ test_expect_success 'cleanup commit messages (whitespace option,-F)' ' test_expect_success 'cleanup commit messages (scissors option,-F,-e)' ' echo >>negative && - cat >text <<EOF && + cat >text <<-\EOF && -# to be kept + # to be kept - # ------------------------ >8 ------------------------ -# to be kept, too -# ------------------------ >8 ------------------------ -to be removed -# ------------------------ >8 ------------------------ -to be removed, too -EOF + # ------------------------ >8 ------------------------ + # to be kept, too + # ------------------------ >8 ------------------------ + to be removed + # ------------------------ >8 ------------------------ + to be removed, too + EOF - cat >expect <<EOF && -# to be kept + cat >expect <<-\EOF && + # to be kept - # ------------------------ >8 ------------------------ -# to be kept, too -EOF + # ------------------------ >8 ------------------------ + # to be kept, too + EOF git commit --cleanup=scissors -e -F text -a && - git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + git cat-file -p HEAD >raw && + sed -e "1,/^\$/d" raw >actual && test_cmp expect actual ' test_expect_success 'cleanup commit messages (scissors option,-F,-e, scissors on first line)' ' echo >>negative && - cat >text <<EOF && -# ------------------------ >8 ------------------------ -to be removed -EOF + cat >text <<-\EOF && + # ------------------------ >8 ------------------------ + to be removed + EOF git commit --cleanup=scissors -e -F text -a --allow-empty-message && - git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + git cat-file -p HEAD >raw && + sed -e "1,/^\$/d" raw >actual && test_must_be_empty actual ' test_expect_success 'cleanup commit messages (strip option,-F)' ' echo >>negative && - { echo;echo "# text";echo sample;echo; } >text && + test_write_lines "" "# text" "sample" "" >text && echo sample >expect && git commit --cleanup=strip -F text -a && - git cat-file -p HEAD |sed -e "1,/^\$/d">actual && + git cat-file -p HEAD >raw && + sed -e "1,/^\$/d" raw >actual && test_cmp expect actual ' @@ -275,7 +286,7 @@ test_expect_success 'cleanup commit messages (strip option,-F)' ' test_expect_success 'cleanup commit messages (strip option,-F,-e)' ' echo >>negative && - { echo;echo sample;echo; } >text && + test_write_lines "" "sample" "" >text && git commit -e -F text -a && head -n 4 .git/COMMIT_EDITMSG >actual ' @@ -387,11 +398,11 @@ test_expect_success AUTOIDENT 'message shows committer when it is automatic' ' ' write_script .git/FAKE_EDITOR <<EOF -echo editor started > "$(pwd)/.git/result" +echo editor started >"$(pwd)/.git/result" exit 0 EOF -test_expect_success !AUTOIDENT 'do not fire editor when committer is bogus' ' +test_expect_success !FAIL_PREREQS,!AUTOIDENT 'do not fire editor when committer is bogus' ' >.git/result && echo >>negative && @@ -455,7 +466,7 @@ EOF test_expect_success EXECKEEPSPID 'a SIGTERM should break locks' ' echo >>negative && ! "$SHELL_PATH" -c '\'' - echo kill -TERM $$ >> .git/FAKE_EDITOR + echo kill -TERM $$ >>.git/FAKE_EDITOR GIT_EDITOR=.git/FAKE_EDITOR export GIT_EDITOR exec git commit -a'\'' && @@ -471,7 +482,8 @@ test_expect_success 'Hand committing of a redundant merge removes dups' ' test_must_fail git merge second master && git checkout master g && EDITOR=: git commit -a && - git cat-file commit HEAD | sed -n -e "s/^parent //p" -e "/^$/q" >actual && + git cat-file commit HEAD >raw && + sed -n -e "s/^parent //p" -e "/^$/q" raw >actual && test_cmp expect actual ' @@ -480,7 +492,8 @@ test_expect_success 'A single-liner subject with a token plus colon is not a foo git reset --hard && git commit -s -m "hello: kitty" --allow-empty && - git cat-file commit HEAD | sed -e "1,/^$/d" >actual && + git cat-file commit HEAD >raw && + sed -e "1,/^$/d" raw >actual && test_line_count = 3 actual ' diff --git a/t/t7508-status.sh b/t/t7508-status.sh index e1f11293e2..681bc314b4 100755 --- a/t/t7508-status.sh +++ b/t/t7508-status.sh @@ -94,13 +94,13 @@ test_expect_success 'status --column' ' # (use "git pull" to merge the remote branch into yours) # # Changes to be committed: -# (use "git reset HEAD <file>..." to unstage) +# (use "git restore --staged <file>..." to unstage) # # new file: dir2/added # # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) -# (use "git checkout -- <file>..." to discard changes in working directory) +# (use "git restore <file>..." to discard changes in working directory) # # modified: dir1/modified # @@ -128,13 +128,13 @@ cat >expect <<\EOF # (use "git pull" to merge the remote branch into yours) # # Changes to be committed: -# (use "git reset HEAD <file>..." to unstage) +# (use "git restore --staged <file>..." to unstage) # # new file: dir2/added # # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) -# (use "git checkout -- <file>..." to discard changes in working directory) +# (use "git restore <file>..." to discard changes in working directory) # # modified: dir1/modified # @@ -278,13 +278,13 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) new file: dir2/added Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified @@ -347,13 +347,13 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) new file: dir2/added Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified @@ -420,13 +420,13 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) new file: dir2/added Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified @@ -484,13 +484,13 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) new file: dir2/added Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified @@ -542,13 +542,13 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) new file: dir2/added Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified @@ -605,13 +605,13 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) new file: ../dir2/added Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: modified @@ -676,13 +676,13 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) <GREEN>new file: dir2/added<RESET> Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) <RED>modified: dir1/modified<RESET> @@ -802,13 +802,13 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) new file: dir2/added Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified @@ -852,7 +852,7 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) modified: dir1/modified @@ -896,14 +896,14 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) new file: dir2/added new file: sm Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified @@ -956,14 +956,14 @@ and have 1 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) new file: dir2/added new file: sm Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified @@ -1019,7 +1019,7 @@ and have 2 and 2 different commits each, respectively. Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified @@ -1068,14 +1068,14 @@ and have 2 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD^1 <file>..." to unstage) + (use "git restore --source=HEAD^1 --staged <file>..." to unstage) new file: dir2/added new file: sm Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified @@ -1123,13 +1123,13 @@ and have 2 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) modified: sm Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified @@ -1235,13 +1235,13 @@ and have 2 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) modified: sm Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) (commit or discard the untracked or modified content in submodules) modified: dir1/modified @@ -1295,13 +1295,13 @@ and have 2 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) modified: sm Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified modified: sm (new commits) @@ -1379,13 +1379,13 @@ cat > expect << EOF ; (use "git pull" to merge the remote branch into yours) ; ; Changes to be committed: -; (use "git reset HEAD <file>..." to unstage) +; (use "git restore --staged <file>..." to unstage) ; ; modified: sm ; ; Changes not staged for commit: ; (use "git add <file>..." to update what will be committed) -; (use "git checkout -- <file>..." to discard changes in working directory) +; (use "git restore <file>..." to discard changes in working directory) ; ; modified: dir1/modified ; modified: sm (new commits) @@ -1431,7 +1431,7 @@ and have 2 and 2 different commits each, respectively. Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified @@ -1458,13 +1458,13 @@ and have 2 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) modified: sm Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified @@ -1581,13 +1581,13 @@ and have 2 and 2 different commits each, respectively. (use "git pull" to merge the remote branch into yours) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) modified: sm Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: dir1/modified diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh index 458608cc1e..b9f5d73423 100755 --- a/t/t7512-status-help.sh +++ b/t/t7512-status-help.sh @@ -85,7 +85,7 @@ You are currently rebasing branch '\''rebase_conflicts'\'' on '\''$ONTO'\''. (use "git rebase --abort" to check out the original branch) Unmerged paths: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) (use "git add <file>..." to mark resolution) both modified: main.txt @@ -110,7 +110,7 @@ You are currently rebasing branch '\''rebase_conflicts'\'' on '\''$ONTO'\''. (all conflicts fixed: run "git rebase --continue") Changes to be committed: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) modified: main.txt @@ -148,7 +148,7 @@ You are currently rebasing branch '\''rebase_i_conflicts_second'\'' on '\''$ONTO (use "git rebase --abort" to check out the original branch) Unmerged paths: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) (use "git add <file>..." to mark resolution) both modified: main.txt @@ -176,7 +176,7 @@ You are currently rebasing branch '\''rebase_i_conflicts_second'\'' on '\''$ONTO (all conflicts fixed: run "git rebase --continue") Changes to be committed: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) modified: main.txt @@ -246,7 +246,7 @@ You are currently splitting a commit while rebasing branch '\''split_commit'\'' Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: main.txt @@ -354,7 +354,7 @@ You are currently splitting a commit while rebasing branch '\''several_edits'\'' Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: main.txt @@ -453,7 +453,7 @@ You are currently splitting a commit while rebasing branch '\''several_edits'\'' Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: main.txt @@ -557,7 +557,7 @@ You are currently splitting a commit while rebasing branch '\''several_edits'\'' Changes not staged for commit: (use "git add <file>..." to update what will be committed) - (use "git checkout -- <file>..." to discard changes in working directory) + (use "git restore <file>..." to discard changes in working directory) modified: main.txt @@ -780,6 +780,24 @@ EOF test_i18ncmp expected actual ' +test_expect_success 'status when cherry-picking after committing conflict resolution' ' + git reset --hard cherry_branch && + test_when_finished "git cherry-pick --abort" && + test_must_fail git cherry-pick cherry_branch_second one_cherry && + echo end >main.txt && + git commit -a && + cat >expected <<EOF && +On branch cherry_branch +Cherry-pick currently in progress. + (run "git cherry-pick --continue" to continue) + (use "git cherry-pick --abort" to cancel the cherry-pick operation) + +nothing to commit (use -u to show untracked files) +EOF + git status --untracked-files=no >actual && + test_i18ncmp expected actual +' + test_expect_success 'status showing detached at and from a tag' ' test_commit atag tagging && git checkout atag && @@ -816,7 +834,7 @@ You are currently reverting commit $TO_REVERT. (use "git revert --abort" to cancel the revert operation) Unmerged paths: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) (use "git add <file>..." to mark resolution) both modified: to-revert.txt @@ -837,7 +855,7 @@ You are currently reverting commit $TO_REVERT. (use "git revert --abort" to cancel the revert operation) Changes to be committed: - (use "git reset HEAD <file>..." to unstage) + (use "git restore --staged <file>..." to unstage) modified: to-revert.txt @@ -857,6 +875,24 @@ EOF test_i18ncmp expected actual ' +test_expect_success 'status while reverting after committing conflict resolution' ' + test_when_finished "git revert --abort" && + git reset --hard new && + test_must_fail git revert old new && + echo reverted >to-revert.txt && + git commit -a && + cat >expected <<EOF && +On branch master +Revert currently in progress. + (run "git revert --continue" to continue) + (use "git revert --abort" to cancel the revert operation) + +nothing to commit (use -u to show untracked files) +EOF + git status --untracked-files=no >actual && + test_i18ncmp expected actual +' + test_expect_success 'prepare for different number of commits rebased' ' git reset --hard master && git checkout -b several_commits && diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh index c441861331..f19202b509 100755 --- a/t/t7513-interpret-trailers.sh +++ b/t/t7513-interpret-trailers.sh @@ -538,33 +538,50 @@ test_expect_success 'with 2 files arguments' ' test_cmp expected actual ' -test_expect_success 'with message that has comments' ' - cat basic_message >message_with_comments && - sed -e "s/ Z\$/ /" >>message_with_comments <<-\EOF && - # comment - - # other comment - Cc: Z - # yet another comment - Reviewed-by: Johan - Reviewed-by: Z - # last comment - - EOF - cat basic_patch >>message_with_comments && - cat basic_message >expected && - cat >>expected <<-\EOF && - # comment - - Reviewed-by: Johan - Cc: Peff - # last comment - - EOF - cat basic_patch >>expected && - git interpret-trailers --trim-empty --trailer "Cc: Peff" message_with_comments >actual && - test_cmp expected actual -' +# Cover multiple comment characters with the same test input. +for char in "#" ";" +do + case "$char" in + "#") + # This is the default, so let's explicitly _not_ + # set any config to make sure it behaves as we expect. + ;; + *) + config="-c core.commentChar=$char" + ;; + esac + + test_expect_success "with message that has comments ($char)" ' + cat basic_message >message_with_comments && + sed -e "s/ Z\$/ /" \ + -e "s/#/$char/g" >>message_with_comments <<-EOF && + # comment + + # other comment + Cc: Z + # yet another comment + Reviewed-by: Johan + Reviewed-by: Z + # last comment + + EOF + cat basic_patch >>message_with_comments && + cat basic_message >expected && + sed -e "s/#/$char/g" >>expected <<-\EOF && + # comment + + Reviewed-by: Johan + Cc: Peff + # last comment + + EOF + cat basic_patch >>expected && + git $config interpret-trailers \ + --trim-empty --trailer "Cc: Peff" \ + message_with_comments >actual && + test_cmp expected actual + ' +done test_expect_success 'with message that has an old style conflict block' ' cat basic_message >message_with_comments && diff --git a/t/t7519-status-fsmonitor.sh b/t/t7519-status-fsmonitor.sh index 3e0a61db23..81a375fa0f 100755 --- a/t/t7519-status-fsmonitor.sh +++ b/t/t7519-status-fsmonitor.sh @@ -346,4 +346,12 @@ test_expect_success UNTRACKED_CACHE 'ignore .git changes when invalidating UNTR' test_cmp before after ' +test_expect_success 'discard_index() also discards fsmonitor info' ' + test_config core.fsmonitor "$TEST_DIRECTORY/t7519/fsmonitor-all" && + test_might_fail git update-index --refresh && + test-tool read-cache --print-and-refresh=tracked 2 >actual && + printf "tracked is%s up to date\n" "" " not" >expect && + test_cmp expect actual +' + test_done diff --git a/t/t7525-status-rename.sh b/t/t7525-status-rename.sh index ef8b1b3078..a62736dce0 100755 --- a/t/t7525-status-rename.sh +++ b/t/t7525-status-rename.sh @@ -84,7 +84,7 @@ test_expect_success 'status score=100%' ' test_i18ngrep "deleted:" actual && test_i18ngrep "new file:" actual && - git status --find-rename=100% >actual && + git status --find-renames=100% >actual && test_i18ngrep "deleted:" actual && test_i18ngrep "new file:" actual ' @@ -93,11 +93,11 @@ test_expect_success 'status score=01%' ' git status -M=01% >actual && test_i18ngrep "renamed:" actual && - git status --find-rename=01% >actual && + git status --find-renames=01% >actual && test_i18ngrep "renamed:" actual ' -test_expect_success 'copies not overridden by find-rename' ' +test_expect_success 'copies not overridden by find-renames' ' cp renamed copy && git add copy && @@ -105,7 +105,7 @@ test_expect_success 'copies not overridden by find-rename' ' test_i18ngrep "copied:" actual && test_i18ngrep "renamed:" actual && - git -c status.renames=copies status --find-rename=01% >actual && + git -c status.renames=copies status --find-renames=01% >actual && test_i18ngrep "copied:" actual && test_i18ngrep "renamed:" actual ' diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh index 106148254d..132608879a 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -233,20 +233,65 @@ test_expect_success 'merge --squash c3 with c7' ' cat result.9z >file && git commit --no-edit -a && - { - cat <<-EOF - Squashed commit of the following: + cat >expect <<-EOF && + Squashed commit of the following: - $(git show -s c7) + $(git show -s c7) - # Conflicts: - # file - EOF - } >expect && - git cat-file commit HEAD | sed -e '1,/^$/d' >actual && + # Conflicts: + # file + EOF + git cat-file commit HEAD >raw && + sed -e '1,/^$/d' raw >actual && test_cmp expect actual ' +test_expect_success 'merge c3 with c7 with commit.cleanup = scissors' ' + git config commit.cleanup scissors && + git reset --hard c3 && + test_must_fail git merge c7 && + cat result.9z >file && + git commit --no-edit -a && + + cat >expect <<-\EOF && + Merge tag '"'"'c7'"'"' + + # ------------------------ >8 ------------------------ + # Do not modify or remove the line above. + # Everything below it will be ignored. + # + # Conflicts: + # file + EOF + git cat-file commit HEAD >raw && + sed -e '1,/^$/d' raw >actual && + test_i18ncmp expect actual +' + +test_expect_success 'merge c3 with c7 with --squash commit.cleanup = scissors' ' + git config commit.cleanup scissors && + git reset --hard c3 && + test_must_fail git merge --squash c7 && + cat result.9z >file && + git commit --no-edit -a && + + cat >expect <<-EOF && + Squashed commit of the following: + + $(git show -s c7) + + # ------------------------ >8 ------------------------ + # Do not modify or remove the line above. + # Everything below it will be ignored. + # + # Conflicts: + # file + EOF + git cat-file commit HEAD >raw && + sed -e '1,/^$/d' raw >actual && + test_i18ncmp expect actual +' + test_debug 'git log --graph --decorate --oneline --all' test_expect_success 'merge c1 with c2 and c3' ' @@ -525,6 +570,12 @@ test_expect_success 'combining --squash and --no-ff is refused' ' test_must_fail git merge --no-ff --squash c1 ' +test_expect_success 'combining --squash and --commit is refused' ' + git reset --hard c0 && + test_must_fail git merge --squash --commit c1 && + test_must_fail git merge --commit --squash c1 +' + test_expect_success 'option --ff-only overwrites --no-ff' ' git merge --no-ff --ff-only c1 && test_must_fail git merge --no-ff --ff-only c2 @@ -680,10 +731,10 @@ cat >editor <<\EOF ( echo "Merge work done on the side branch c1" echo - cat <"$1" + cat "$1" ) >"$1.tmp" && mv "$1.tmp" "$1" # strip comments and blank lines from end of message -sed -e '/^#/d' < "$1" | sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' > expected +sed -e '/^#/d' "$1" | sed -e :a -e '/^\n*$/{$d;N;ba' -e '}' >expected EOF chmod 755 editor @@ -768,14 +819,14 @@ test_expect_success 'set up mod-256 conflict scenario' ' git commit -m base && # one side changes the first line of each to "master" - sed s/-1/-master/ <file >tmp && + sed s/-1/-master/ file >tmp && mv tmp file && git commit -am master && # and the other to "side"; merging the two will # yield 256 separate conflicts git checkout -b side HEAD^ && - sed s/-1/-side/ <file >tmp && + sed s/-1/-side/ file >tmp && mv tmp file && git commit -am side ' @@ -814,7 +865,7 @@ EOF test_expect_success EXECKEEPSPID 'killed merge can be completed with --continue' ' git reset --hard c0 && ! "$SHELL_PATH" -c '\'' - echo kill -TERM $$ >> .git/FAKE_EDITOR + echo kill -TERM $$ >>.git/FAKE_EDITOR GIT_EDITOR=.git/FAKE_EDITOR export GIT_EDITOR exec git merge --no-ff --edit c1'\'' && @@ -822,4 +873,50 @@ test_expect_success EXECKEEPSPID 'killed merge can be completed with --continue' verify_parents $c0 $c1 ' +test_expect_success 'merge --quit' ' + git init merge-quit && + ( + cd merge-quit && + test_commit base && + echo one >>base.t && + git commit -am one && + git branch one && + git checkout base && + echo two >>base.t && + git commit -am two && + test_must_fail git -c rerere.enabled=true merge one && + test_path_is_file .git/MERGE_HEAD && + test_path_is_file .git/MERGE_MODE && + test_path_is_file .git/MERGE_MSG && + git rerere status >rerere.before && + git merge --quit && + test_path_is_missing .git/MERGE_HEAD && + test_path_is_missing .git/MERGE_MODE && + test_path_is_missing .git/MERGE_MSG && + git rerere status >rerere.after && + test_must_be_empty rerere.after && + ! test_cmp rerere.after rerere.before + ) +' + +test_expect_success 'merge suggests matching remote refname' ' + git commit --allow-empty -m not-local && + git update-ref refs/remotes/origin/not-local HEAD && + git reset --hard HEAD^ && + + # This is white-box testing hackery; we happen to know + # that reading packed refs is more picky about the memory + # ownership of strings we pass to for_each_ref() callbacks. + git pack-refs --all --prune && + + test_must_fail git merge not-local 2>stderr && + grep origin/not-local stderr +' + +test_expect_success 'suggested names are not ambiguous' ' + git update-ref refs/heads/origin/not-local HEAD && + test_must_fail git merge not-local 2>stderr && + grep remotes/origin/not-local stderr +' + test_done diff --git a/t/t7604-merge-custom-message.sh b/t/t7604-merge-custom-message.sh index 89619cf446..cd4f9607dc 100755 --- a/t/t7604-merge-custom-message.sh +++ b/t/t7604-merge-custom-message.sh @@ -16,16 +16,16 @@ create_merge_msgs() { } test_expect_success 'setup' ' - echo c0 > c0.c && + echo c0 >c0.c && git add c0.c && git commit -m c0 && git tag c0 && - echo c1 > c1.c && + echo c1 >c1.c && git add c1.c && git commit -m c1 && git tag c1 && git reset --hard c0 && - echo c2 > c2.c && + echo c2 >c2.c && git add c2.c && git commit -m c2 && git tag c2 && @@ -36,15 +36,80 @@ test_expect_success 'setup' ' test_expect_success 'merge c2 with a custom message' ' git reset --hard c1 && git merge -m "$(cat exp.subject)" c2 && - git cat-file commit HEAD | sed -e "1,/^$/d" >actual && + git cat-file commit HEAD >raw && + sed -e "1,/^$/d" raw >actual && test_cmp exp.subject actual ' test_expect_success 'merge --log appends to custom message' ' git reset --hard c1 && git merge --log -m "$(cat exp.subject)" c2 && - git cat-file commit HEAD | sed -e "1,/^$/d" >actual && + git cat-file commit HEAD >raw && + sed -e "1,/^$/d" raw >actual && test_cmp exp.log actual ' +mesg_with_comment_and_newlines=' +# text + +' + +test_expect_success 'prepare file with comment line and trailing newlines' ' + printf "%s" "$mesg_with_comment_and_newlines" >expect +' + +test_expect_success 'cleanup commit messages (verbatim option)' ' + git reset --hard c1 && + git merge --cleanup=verbatim -F expect c2 && + git cat-file commit HEAD >raw && + sed -e "1,/^$/d" raw >actual && + test_cmp expect actual +' + +test_expect_success 'cleanup commit messages (whitespace option)' ' + git reset --hard c1 && + test_write_lines "" "# text" "" >text && + echo "# text" >expect && + git merge --cleanup=whitespace -F text c2 && + git cat-file commit HEAD >raw && + sed -e "1,/^$/d" raw >actual && + test_cmp expect actual +' + +test_expect_success 'cleanup merge messages (scissors option)' ' + git reset --hard c1 && + cat >text <<-\EOF && + + # to be kept + + # ------------------------ >8 ------------------------ + # to be kept, too + # ------------------------ >8 ------------------------ + to be removed + # ------------------------ >8 ------------------------ + to be removed, too + EOF + + cat >expect <<-\EOF && + # to be kept + + # ------------------------ >8 ------------------------ + # to be kept, too + EOF + git merge --cleanup=scissors -e -F text c2 && + git cat-file commit HEAD >raw && + sed -e "1,/^$/d" raw >actual && + test_cmp expect actual +' + +test_expect_success 'cleanup commit messages (strip option)' ' + git reset --hard c1 && + test_write_lines "" "# text" "sample" "" >text && + echo sample >expect && + git merge --cleanup=strip -F text c2 && + git cat-file commit HEAD >raw && + sed -e "1,/^$/d" raw >actual && + test_cmp expect actual +' + test_done diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh index a9fb971615..ad288ddc69 100755 --- a/t/t7610-mergetool.sh +++ b/t/t7610-mergetool.sh @@ -130,18 +130,71 @@ test_expect_success 'custom mergetool' ' test_when_finished "git reset --hard" && git checkout -b test$test_count branch1 && git submodule update -N && - test_must_fail git merge master >/dev/null 2>&1 && - ( yes "" | git mergetool both >/dev/null 2>&1 ) && - ( yes "" | git mergetool file1 file1 ) && - ( yes "" | git mergetool file2 "spaced name" >/dev/null 2>&1 ) && - ( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) && - ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) && - ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) && - ( yes "l" | git mergetool submod >/dev/null 2>&1 ) && - test "$(cat file1)" = "master updated" && - test "$(cat file2)" = "master new" && - test "$(cat subdir/file3)" = "master new sub" && - test "$(cat submod/bar)" = "branch1 submodule" && + test_must_fail git merge master && + yes "" | git mergetool both && + yes "" | git mergetool file1 file1 && + yes "" | git mergetool file2 "spaced name" && + yes "" | git mergetool subdir/file3 && + yes "d" | git mergetool file11 && + yes "d" | git mergetool file12 && + yes "l" | git mergetool submod && + echo "master updated" >expect && + test_cmp expect file1 && + echo "master new" >expect && + test_cmp expect file2 && + echo "master new sub" >expect && + test_cmp expect subdir/file3 && + echo "branch1 submodule" >expect && + test_cmp expect submod/bar && + git commit -m "branch1 resolved with mergetool" +' + +test_expect_success 'gui mergetool' ' + test_config merge.guitool myguitool && + test_config mergetool.myguitool.cmd "(printf \"gui \" && cat \"\$REMOTE\") >\"\$MERGED\"" && + test_config mergetool.myguitool.trustExitCode true && + test_when_finished "git reset --hard" && + git checkout -b test$test_count branch1 && + git submodule update -N && + test_must_fail git merge master && + yes "" | git mergetool --gui both && + yes "" | git mergetool -g file1 file1 && + yes "" | git mergetool --gui file2 "spaced name" && + yes "" | git mergetool --gui subdir/file3 && + yes "d" | git mergetool --gui file11 && + yes "d" | git mergetool --gui file12 && + yes "l" | git mergetool --gui submod && + echo "gui master updated" >expect && + test_cmp expect file1 && + echo "gui master new" >expect && + test_cmp expect file2 && + echo "gui master new sub" >expect && + test_cmp expect subdir/file3 && + echo "branch1 submodule" >expect && + test_cmp expect submod/bar && + git commit -m "branch1 resolved with mergetool" +' + +test_expect_success 'gui mergetool without merge.guitool set falls back to merge.tool' ' + test_when_finished "git reset --hard" && + git checkout -b test$test_count branch1 && + git submodule update -N && + test_must_fail git merge master && + yes "" | git mergetool --gui both && + yes "" | git mergetool -g file1 file1 && + yes "" | git mergetool --gui file2 "spaced name" && + yes "" | git mergetool --gui subdir/file3 && + yes "d" | git mergetool --gui file11 && + yes "d" | git mergetool --gui file12 && + yes "l" | git mergetool --gui submod && + echo "master updated" >expect && + test_cmp expect file1 && + echo "master new" >expect && + test_cmp expect file2 && + echo "master new sub" >expect && + test_cmp expect subdir/file3 && + echo "branch1 submodule" >expect && + test_cmp expect submod/bar && git commit -m "branch1 resolved with mergetool" ' @@ -153,20 +206,21 @@ test_expect_success 'mergetool crlf' ' # test_when_finished is LIFO.) test_config core.autocrlf true && git checkout -b test$test_count branch1 && - test_must_fail git merge master >/dev/null 2>&1 && - ( yes "" | git mergetool file1 >/dev/null 2>&1 ) && - ( yes "" | git mergetool file2 >/dev/null 2>&1 ) && - ( yes "" | git mergetool "spaced name" >/dev/null 2>&1 ) && - ( yes "" | git mergetool both >/dev/null 2>&1 ) && - ( yes "" | git mergetool subdir/file3 >/dev/null 2>&1 ) && - ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) && - ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) && - ( yes "r" | git mergetool submod >/dev/null 2>&1 ) && + test_must_fail git merge master && + yes "" | git mergetool file1 && + yes "" | git mergetool file2 && + yes "" | git mergetool "spaced name" && + yes "" | git mergetool both && + yes "" | git mergetool subdir/file3 && + yes "d" | git mergetool file11 && + yes "d" | git mergetool file12 && + yes "r" | git mergetool submod && test "$(printf x | cat file1 -)" = "$(printf "master updated\r\nx")" && test "$(printf x | cat file2 -)" = "$(printf "master new\r\nx")" && test "$(printf x | cat subdir/file3 -)" = "$(printf "master new sub\r\nx")" && git submodule update -N && - test "$(cat submod/bar)" = "master submodule" && + echo "master submodule" >expect && + test_cmp expect submod/bar && git commit -m "branch1 resolved with mergetool - autocrlf" ' @@ -176,9 +230,10 @@ test_expect_success 'mergetool in subdir' ' git submodule update -N && ( cd subdir && - test_must_fail git merge master >/dev/null 2>&1 && - ( yes "" | git mergetool file3 >/dev/null 2>&1 ) && - test "$(cat file3)" = "master new sub" + test_must_fail git merge master && + yes "" | git mergetool file3 && + echo "master new sub" >expect && + test_cmp expect file3 ) ' @@ -188,17 +243,20 @@ test_expect_success 'mergetool on file in parent dir' ' git submodule update -N && ( cd subdir && - test_must_fail git merge master >/dev/null 2>&1 && - ( yes "" | git mergetool file3 >/dev/null 2>&1 ) && - ( yes "" | git mergetool ../file1 >/dev/null 2>&1 ) && - ( yes "" | git mergetool ../file2 ../spaced\ name >/dev/null 2>&1 ) && - ( yes "" | git mergetool ../both >/dev/null 2>&1 ) && - ( yes "d" | git mergetool ../file11 >/dev/null 2>&1 ) && - ( yes "d" | git mergetool ../file12 >/dev/null 2>&1 ) && - ( yes "l" | git mergetool ../submod >/dev/null 2>&1 ) && - test "$(cat ../file1)" = "master updated" && - test "$(cat ../file2)" = "master new" && - test "$(cat ../submod/bar)" = "branch1 submodule" && + test_must_fail git merge master && + yes "" | git mergetool file3 && + yes "" | git mergetool ../file1 && + yes "" | git mergetool ../file2 ../spaced\ name && + yes "" | git mergetool ../both && + yes "d" | git mergetool ../file11 && + yes "d" | git mergetool ../file12 && + yes "l" | git mergetool ../submod && + echo "master updated" >expect && + test_cmp expect ../file1 && + echo "master new" >expect && + test_cmp expect ../file2 && + echo "branch1 submodule" >expect && + test_cmp expect ../submod/bar && git commit -m "branch1 resolved with mergetool - subdir" ) ' @@ -209,9 +267,9 @@ test_expect_success 'mergetool skips autoresolved' ' git submodule update -N && test_must_fail git merge master && test -n "$(git ls-files -u)" && - ( yes "d" | git mergetool file11 >/dev/null 2>&1 ) && - ( yes "d" | git mergetool file12 >/dev/null 2>&1 ) && - ( yes "l" | git mergetool submod >/dev/null 2>&1 ) && + yes "d" | git mergetool file11 && + yes "d" | git mergetool file12 && + yes "l" | git mergetool submod && output="$(git mergetool --no-prompt)" && test "$output" = "No files need merging" ' @@ -223,13 +281,17 @@ test_expect_success 'mergetool merges all from subdir (rerere disabled)' ' ( cd subdir && test_must_fail git merge master && - ( yes "r" | git mergetool ../submod ) && - ( yes "d" "d" | git mergetool --no-prompt ) && - test "$(cat ../file1)" = "master updated" && - test "$(cat ../file2)" = "master new" && - test "$(cat file3)" = "master new sub" && + yes "r" | git mergetool ../submod && + yes "d" "d" | git mergetool --no-prompt && + echo "master updated" >expect && + test_cmp expect ../file1 && + echo "master new" >expect && + test_cmp expect ../file2 && + echo "master new sub" >expect && + test_cmp expect file3 && ( cd .. && git submodule update -N ) && - test "$(cat ../submod/bar)" = "master submodule" && + echo "master submodule" >expect && + test_cmp expect ../submod/bar && git commit -m "branch2 resolved by mergetool from subdir" ) ' @@ -242,13 +304,17 @@ test_expect_success 'mergetool merges all from subdir (rerere enabled)' ' ( cd subdir && test_must_fail git merge master && - ( yes "r" | git mergetool ../submod ) && - ( yes "d" "d" | git mergetool --no-prompt ) && - test "$(cat ../file1)" = "master updated" && - test "$(cat ../file2)" = "master new" && - test "$(cat file3)" = "master new sub" && + yes "r" | git mergetool ../submod && + yes "d" "d" | git mergetool --no-prompt && + echo "master updated" >expect && + test_cmp expect ../file1 && + echo "master new" >expect && + test_cmp expect ../file2 && + echo "master new sub" >expect && + test_cmp expect file3 && ( cd .. && git submodule update -N ) && - test "$(cat ../submod/bar)" = "master submodule" && + echo "master submodule" >expect && + test_cmp expect ../submod/bar && git commit -m "branch2 resolved by mergetool from subdir" ) ' @@ -259,9 +325,9 @@ test_expect_success 'mergetool skips resolved paths when rerere is active' ' rm -rf .git/rr-cache && git checkout -b test$test_count branch1 && git submodule update -N && - test_must_fail git merge master >/dev/null 2>&1 && - ( yes "l" | git mergetool --no-prompt submod >/dev/null 2>&1 ) && - ( yes "d" "d" | git mergetool --no-prompt >/dev/null 2>&1 ) && + test_must_fail git merge master && + yes "l" | git mergetool --no-prompt submod && + yes "d" "d" | git mergetool --no-prompt && git submodule update -N && output="$(yes "n" | git mergetool --no-prompt)" && test "$output" = "No files need merging" @@ -302,9 +368,10 @@ test_expect_success 'mergetool takes partial path' ' git submodule update -N && test_must_fail git merge master && - ( yes "" | git mergetool subdir ) && + yes "" | git mergetool subdir && - test "$(cat subdir/file3)" = "master new sub" + echo "master new sub" >expect && + test_cmp expect subdir/file3 ' test_expect_success 'mergetool delete/delete conflict' ' @@ -369,14 +436,16 @@ test_expect_success 'deleted vs modified submodule' ' git checkout -b test$test_count.a test$test_count && test_must_fail git merge master && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && - ( yes "" | git mergetool both >/dev/null 2>&1 ) && - ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && - ( yes "r" | git mergetool submod ) && + yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && + yes "" | git mergetool both && + yes "d" | git mergetool file11 file12 && + yes "r" | git mergetool submod && rmdir submod && mv submod-movedaside submod && - test "$(cat submod/bar)" = "branch1 submodule" && + echo "branch1 submodule" >expect && + test_cmp expect submod/bar && git submodule update -N && - test "$(cat submod/bar)" = "master submodule" && + echo "master submodule" >expect && + test_cmp expect submod/bar && output="$(git mergetool --no-prompt)" && test "$output" = "No files need merging" && git commit -m "Merge resolved by keeping module" && @@ -386,10 +455,10 @@ test_expect_success 'deleted vs modified submodule' ' git submodule update -N && test_must_fail git merge master && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && - ( yes "" | git mergetool both >/dev/null 2>&1 ) && - ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && - ( yes "l" | git mergetool submod ) && + yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && + yes "" | git mergetool both && + yes "d" | git mergetool file11 file12 && + yes "l" | git mergetool submod && test ! -e submod && output="$(git mergetool --no-prompt)" && test "$output" = "No files need merging" && @@ -400,10 +469,10 @@ test_expect_success 'deleted vs modified submodule' ' git submodule update -N && test_must_fail git merge test$test_count && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && - ( yes "" | git mergetool both >/dev/null 2>&1 ) && - ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && - ( yes "r" | git mergetool submod ) && + yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && + yes "" | git mergetool both && + yes "d" | git mergetool file11 file12 && + yes "r" | git mergetool submod && test ! -e submod && test -d submod.orig && git submodule update -N && @@ -416,13 +485,15 @@ test_expect_success 'deleted vs modified submodule' ' git submodule update -N && test_must_fail git merge test$test_count && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && - ( yes "" | git mergetool both >/dev/null 2>&1 ) && - ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && - ( yes "l" | git mergetool submod ) && - test "$(cat submod/bar)" = "master submodule" && - git submodule update -N && - test "$(cat submod/bar)" = "master submodule" && + yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && + yes "" | git mergetool both && + yes "d" | git mergetool file11 file12 && + yes "l" | git mergetool submod && + echo "master submodule" >expect && + test_cmp expect submod/bar && + git submodule update -N && + echo "master submodule" >expect && + test_cmp expect submod/bar && output="$(git mergetool --no-prompt)" && test "$output" = "No files need merging" && git commit -m "Merge resolved by keeping module" @@ -440,14 +511,16 @@ test_expect_success 'file vs modified submodule' ' git checkout -b test$test_count.a branch1 && test_must_fail git merge master && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && - ( yes "" | git mergetool both >/dev/null 2>&1 ) && - ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && - ( yes "r" | git mergetool submod ) && + yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && + yes "" | git mergetool both && + yes "d" | git mergetool file11 file12 && + yes "r" | git mergetool submod && rmdir submod && mv submod-movedaside submod && - test "$(cat submod/bar)" = "branch1 submodule" && + echo "branch1 submodule" >expect && + test_cmp expect submod/bar && git submodule update -N && - test "$(cat submod/bar)" = "master submodule" && + echo "master submodule" >expect && + test_cmp expect submod/bar && output="$(git mergetool --no-prompt)" && test "$output" = "No files need merging" && git commit -m "Merge resolved by keeping module" && @@ -456,12 +529,13 @@ test_expect_success 'file vs modified submodule' ' git checkout -b test$test_count.b test$test_count && test_must_fail git merge master && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && - ( yes "" | git mergetool both >/dev/null 2>&1 ) && - ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && - ( yes "l" | git mergetool submod ) && + yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && + yes "" | git mergetool both && + yes "d" | git mergetool file11 file12 && + yes "l" | git mergetool submod && git submodule update -N && - test "$(cat submod)" = "not a submodule" && + echo "not a submodule" >expect && + test_cmp expect submod && output="$(git mergetool --no-prompt)" && test "$output" = "No files need merging" && git commit -m "Merge resolved by keeping file" && @@ -472,13 +546,14 @@ test_expect_success 'file vs modified submodule' ' git submodule update -N && test_must_fail git merge test$test_count && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && - ( yes "" | git mergetool both >/dev/null 2>&1 ) && - ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && - ( yes "r" | git mergetool submod ) && + yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && + yes "" | git mergetool both && + yes "d" | git mergetool file11 file12 && + yes "r" | git mergetool submod && test -d submod.orig && git submodule update -N && - test "$(cat submod)" = "not a submodule" && + echo "not a submodule" >expect && + test_cmp expect submod && output="$(git mergetool --no-prompt)" && test "$output" = "No files need merging" && git commit -m "Merge resolved by keeping file" && @@ -488,13 +563,15 @@ test_expect_success 'file vs modified submodule' ' git submodule update -N && test_must_fail git merge test$test_count && test -n "$(git ls-files -u)" && - ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 >/dev/null 2>&1 ) && - ( yes "" | git mergetool both>/dev/null 2>&1 ) && - ( yes "d" | git mergetool file11 file12 >/dev/null 2>&1 ) && - ( yes "l" | git mergetool submod ) && - test "$(cat submod/bar)" = "master submodule" && - git submodule update -N && - test "$(cat submod/bar)" = "master submodule" && + yes "" | git mergetool file1 file2 spaced\ name subdir/file3 && + yes "" | git mergetool both && + yes "d" | git mergetool file11 file12 && + yes "l" | git mergetool submod && + echo "master submodule" >expect && + test_cmp expect submod/bar && + git submodule update -N && + echo "master submodule" >expect && + test_cmp expect submod/bar && output="$(git mergetool --no-prompt)" && test "$output" = "No files need merging" && git commit -m "Merge resolved by keeping module" @@ -543,22 +620,26 @@ test_expect_success 'submodule in subdirectory' ' git add subdir/subdir_module && git commit -m "change submodule in subdirectory on test$test_count.b" && - test_must_fail git merge test$test_count.a >/dev/null 2>&1 && + test_must_fail git merge test$test_count.a && ( cd subdir && - ( yes "l" | git mergetool subdir_module ) + yes "l" | git mergetool subdir_module ) && - test "$(cat subdir/subdir_module/file15)" = "test$test_count.b" && + echo "test$test_count.b" >expect && + test_cmp expect subdir/subdir_module/file15 && git submodule update -N && - test "$(cat subdir/subdir_module/file15)" = "test$test_count.b" && + echo "test$test_count.b" >expect && + test_cmp expect subdir/subdir_module/file15 && git reset --hard && git submodule update -N && - test_must_fail git merge test$test_count.a >/dev/null 2>&1 && - ( yes "r" | git mergetool subdir/subdir_module ) && - test "$(cat subdir/subdir_module/file15)" = "test$test_count.b" && + test_must_fail git merge test$test_count.a && + yes "r" | git mergetool subdir/subdir_module && + echo "test$test_count.b" >expect && + test_cmp expect subdir/subdir_module/file15 && git submodule update -N && - test "$(cat subdir/subdir_module/file15)" = "test$test_count.a" && + echo "test$test_count.a" >expect && + test_cmp expect subdir/subdir_module/file15 && git commit -m "branch1 resolved with mergetool" ' @@ -574,22 +655,25 @@ test_expect_success 'directory vs modified submodule' ' test_must_fail git merge master && test -n "$(git ls-files -u)" && - ( yes "l" | git mergetool submod ) && - test "$(cat submod/file16)" = "not a submodule" && + yes "l" | git mergetool submod && + echo "not a submodule" >expect && + test_cmp expect submod/file16 && rm -rf submod.orig && git reset --hard && test_must_fail git merge master && test -n "$(git ls-files -u)" && test ! -e submod.orig && - ( yes "r" | git mergetool submod ) && + yes "r" | git mergetool submod && test -d submod.orig && - test "$(cat submod.orig/file16)" = "not a submodule" && + echo "not a submodule" >expect && + test_cmp expect submod.orig/file16 && rm -r submod.orig && mv submod-movedaside/.git submod && ( cd submod && git clean -f && git reset --hard ) && git submodule update -N && - test "$(cat submod/bar)" = "master submodule" && + echo "master submodule" >expect && + test_cmp expect submod/bar && git reset --hard && rm -rf submod-movedaside && @@ -597,17 +681,19 @@ test_expect_success 'directory vs modified submodule' ' git submodule update -N && test_must_fail git merge test$test_count && test -n "$(git ls-files -u)" && - ( yes "l" | git mergetool submod ) && + yes "l" | git mergetool submod && git submodule update -N && - test "$(cat submod/bar)" = "master submodule" && + echo "master submodule" >expect && + test_cmp expect submod/bar && git reset --hard && git submodule update -N && test_must_fail git merge test$test_count && test -n "$(git ls-files -u)" && test ! -e submod.orig && - ( yes "r" | git mergetool submod ) && - test "$(cat submod/file16)" = "not a submodule" && + yes "r" | git mergetool submod && + echo "not a submodule" >expect && + test_cmp expect submod/file16 && git reset --hard master && ( cd submod && git clean -f && git reset --hard ) && @@ -641,7 +727,7 @@ test_expect_success 'filenames seen by tools start with ./' ' test_config mergetool.myecho.trustExitCode true && test_must_fail git merge master && git mergetool --no-prompt --tool myecho -- both >actual && - grep ^\./both_LOCAL_ actual >/dev/null + grep ^\./both_LOCAL_ actual ' test_lazy_prereq MKTEMP ' @@ -658,8 +744,8 @@ test_expect_success MKTEMP 'temporary filenames are used with mergetool.writeToT test_config mergetool.myecho.trustExitCode true && test_must_fail git merge master && git mergetool --no-prompt --tool myecho -- both >actual && - ! grep ^\./both_LOCAL_ actual >/dev/null && - grep /both_LOCAL_ actual >/dev/null + ! grep ^\./both_LOCAL_ actual && + grep /both_LOCAL_ actual ' test_expect_success 'diff.orderFile configuration is honored' ' diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh index 6162e2a8e6..86d05160a3 100755 --- a/t/t7700-repack.sh +++ b/t/t7700-repack.sh @@ -221,5 +221,22 @@ test_expect_success 'repack --keep-pack' ' ) ' -test_done +test_expect_success 'bitmaps are created by default in bare repos' ' + git clone --bare .git bare.git && + git -C bare.git repack -ad && + bitmap=$(ls bare.git/objects/pack/*.bitmap) && + test_path_is_file "$bitmap" +' + +test_expect_success 'incremental repack does not complain' ' + git -C bare.git repack -q 2>repack.err && + test_must_be_empty repack.err +' +test_expect_success 'bitmaps can be disabled on bare repos' ' + git -c repack.writeBitmaps=false -C bare.git repack -ad && + bitmap=$(ls bare.git/objects/pack/*.bitmap 2>/dev/null || :) && + test -z "$bitmap" +' + +test_done diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh index bb9a7f4ff9..6bac9ed180 100755 --- a/t/t7800-difftool.sh +++ b/t/t7800-difftool.sh @@ -279,11 +279,27 @@ test_expect_success 'difftool + mergetool config variables' ' echo branch >expect && git difftool --no-prompt branch >actual && test_cmp expect actual && + git difftool --gui --no-prompt branch >actual && + test_cmp expect actual && # set merge.tool to something bogus, diff.tool to test-tool test_config merge.tool bogus-tool && test_config diff.tool test-tool && git difftool --no-prompt branch >actual && + test_cmp expect actual && + git difftool --gui --no-prompt branch >actual && + test_cmp expect actual && + + # set merge.tool, diff.tool to something bogus, merge.guitool to test-tool + test_config diff.tool bogus-tool && + test_config merge.guitool test-tool && + git difftool --gui --no-prompt branch >actual && + test_cmp expect actual && + + # set merge.tool, diff.tool, merge.guitool to something bogus, diff.guitool to test-tool + test_config merge.guitool bogus-tool && + test_config diff.guitool test-tool && + git difftool --gui --no-prompt branch >actual && test_cmp expect actual ' @@ -705,4 +721,22 @@ test_expect_success SYMLINKS 'difftool --dir-diff handles modified symlinks' ' test_cmp expect actual ' +test_expect_success 'outside worktree' ' + echo 1 >1 && + echo 2 >2 && + test_expect_code 1 nongit git \ + -c diff.tool=echo -c difftool.echo.cmd="echo \$LOCAL \$REMOTE" \ + difftool --no-prompt --no-index ../1 ../2 >actual && + echo "../1 ../2" >expect && + test_cmp expect actual +' + +test_expect_success 'difftool --gui, --tool and --extcmd are mutually exclusive' ' + difftool_test_setup && + test_must_fail git difftool --gui --tool=test-tool && + test_must_fail git difftool --gui --extcmd=cat && + test_must_fail git difftool --tool=test-tool --extcmd=cat && + test_must_fail git difftool --gui --tool=test-tool --extcmd=cat +' + test_done diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh index 43aa4161cf..7d7b396c23 100755 --- a/t/t7810-grep.sh +++ b/t/t7810-grep.sh @@ -119,33 +119,33 @@ do test_cmp expected actual ' - test_expect_success "grep -w $L (with --column, --invert)" ' + test_expect_success "grep -w $L (with --column, --invert-match)" ' { echo ${HC}file:1:foo mmap bar echo ${HC}file:1:foo_mmap bar echo ${HC}file:1:foo_mmap bar mmap echo ${HC}file:1:foo mmap bar_mmap } >expected && - git grep --column --invert -w -e baz $H -- file >actual && + git grep --column --invert-match -w -e baz $H -- file >actual && test_cmp expected actual ' - test_expect_success "grep $L (with --column, --invert, extended OR)" ' + test_expect_success "grep $L (with --column, --invert-match, extended OR)" ' { echo ${HC}hello_world:6:HeLLo_world } >expected && - git grep --column --invert -e ll --or --not -e _ $H -- hello_world \ + git grep --column --invert-match -e ll --or --not -e _ $H -- hello_world \ >actual && test_cmp expected actual ' - test_expect_success "grep $L (with --column, --invert, extended AND)" ' + test_expect_success "grep $L (with --column, --invert-match, extended AND)" ' { echo ${HC}hello_world:3:Hello world echo ${HC}hello_world:3:Hello_world echo ${HC}hello_world:6:HeLLo_world } >expected && - git grep --column --invert --not -e _ --and --not -e ll $H -- hello_world \ + git grep --column --invert-match --not -e _ --and --not -e ll $H -- hello_world \ >actual && test_cmp expected actual ' @@ -412,7 +412,7 @@ do test_cmp expected actual ' - test_expect_success !PCRE "grep $L with grep.patterntype=perl errors without PCRE" ' + test_expect_success !FAIL_PREREQS,!PCRE "grep $L with grep.patterntype=perl errors without PCRE" ' test_must_fail git -c grep.patterntype=perl grep "foo.*bar" ' @@ -1010,7 +1010,7 @@ test_expect_success 'outside of git repository' ' echo ".gitignore:.*o*" && cat ../expect.full } >../expect.with.ignored && - git grep --no-index --no-exclude o >../actual.full && + git grep --no-index --no-exclude-standard o >../actual.full && test_cmp ../expect.with.ignored ../actual.full ) ' @@ -1051,7 +1051,7 @@ test_expect_success 'outside of git repository with fallbackToNoIndex' ' echo ".gitignore:.*o*" && cat ../expect.full } >../expect.with.ignored && - git -c grep.fallbackToNoIndex grep --no-exclude o >../actual.full && + git -c grep.fallbackToNoIndex grep --no-exclude-standard o >../actual.full && test_cmp ../expect.with.ignored ../actual.full ) ' @@ -1234,7 +1234,7 @@ test_expect_success PCRE 'grep --perl-regexp pattern' ' test_cmp expected actual ' -test_expect_success !PCRE 'grep --perl-regexp pattern errors without PCRE' ' +test_expect_success !FAIL_PREREQS,!PCRE 'grep --perl-regexp pattern errors without PCRE' ' test_must_fail git grep --perl-regexp "foo.*bar" ' @@ -1249,7 +1249,7 @@ test_expect_success LIBPCRE2 "grep -P with (*NO_JIT) doesn't error out" ' ' -test_expect_success !PCRE 'grep -P pattern errors without PCRE' ' +test_expect_success !FAIL_PREREQS,!PCRE 'grep -P pattern errors without PCRE' ' test_must_fail git grep -P "foo.*bar" ' diff --git a/t/t7814-grep-recurse-submodules.sh b/t/t7814-grep-recurse-submodules.sh index fa475d52fa..134a694516 100755 --- a/t/t7814-grep-recurse-submodules.sh +++ b/t/t7814-grep-recurse-submodules.sh @@ -380,11 +380,7 @@ test_expect_success 'grep --recurse-submodules should pass the pattern type alon fi ' -# Recursing down into nested submodules which do not have .gitmodules in their -# working tree does not work yet. This is because config_from_gitmodules() -# uses get_oid() and the latter is still not able to get objects from an -# arbitrary repository (the nested submodule, in this case). -test_expect_failure 'grep --recurse-submodules with submodules without .gitmodules in the working tree' ' +test_expect_success 'grep --recurse-submodules with submodules without .gitmodules in the working tree' ' test_when_finished "git -C submodule checkout .gitmodules" && rm submodule/.gitmodules && git grep --recurse-submodules -e "(.|.)[\d]" >actual && diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index ee1efcc59d..997f90b42b 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -481,6 +481,20 @@ test_expect_success $PREREQ 'long lines with auto encoding are quoted-printable' grep "Content-Transfer-Encoding: quoted-printable" msgtxt1 ' +test_expect_success $PREREQ 'carriage returns with auto encoding are quoted-printable' ' + clean_fake_sendmail && + cp $patches cr.patch && + printf "this is a line\r\n" >>cr.patch && + git send-email \ + --from="Example <nobody@example.com>" \ + --to=nobody@example.com \ + --smtp-server="$(pwd)/fake.sendmail" \ + --transfer-encoding=auto \ + --no-validate \ + cr.patch && + grep "Content-Transfer-Encoding: quoted-printable" msgtxt1 +' + for enc in auto quoted-printable base64 do test_expect_success $PREREQ "--validate passes with encoding $enc" ' @@ -1190,7 +1204,7 @@ test_expect_success $PREREQ 'no in-reply-to and no threading' ' --from="Example <nobody@example.com>" \ --to=nobody@example.com \ --no-thread \ - $patches $patches >stdout && + $patches >stdout && ! grep "In-Reply-To: " stdout ' @@ -1210,17 +1224,72 @@ test_expect_success $PREREQ 'sendemail.to works' ' git send-email \ --dry-run \ --from="Example <nobody@example.com>" \ - $patches $patches >stdout && + $patches >stdout && grep "To: Somebody <somebody@ex.com>" stdout ' +test_expect_success $PREREQ 'setup sendemail.identity' ' + git config --replace-all sendemail.to "default@example.com" && + git config --replace-all sendemail.isp.to "isp@example.com" && + git config --replace-all sendemail.cloud.to "cloud@example.com" +' + +test_expect_success $PREREQ 'sendemail.identity: reads the correct identity config' ' + git -c sendemail.identity=cloud send-email \ + --dry-run \ + --from="nobody@example.com" \ + $patches >stdout && + grep "To: cloud@example.com" stdout +' + +test_expect_success $PREREQ 'sendemail.identity: identity overrides sendemail.identity' ' + git -c sendemail.identity=cloud send-email \ + --identity=isp \ + --dry-run \ + --from="nobody@example.com" \ + $patches >stdout && + grep "To: isp@example.com" stdout +' + +test_expect_success $PREREQ 'sendemail.identity: --no-identity clears previous identity' ' + git -c sendemail.identity=cloud send-email \ + --no-identity \ + --dry-run \ + --from="nobody@example.com" \ + $patches >stdout && + grep "To: default@example.com" stdout +' + +test_expect_success $PREREQ 'sendemail.identity: bool identity variable existance overrides' ' + git -c sendemail.identity=cloud \ + -c sendemail.xmailer=true \ + -c sendemail.cloud.xmailer=false \ + send-email \ + --dry-run \ + --from="nobody@example.com" \ + $patches >stdout && + grep "To: cloud@example.com" stdout && + ! grep "X-Mailer" stdout +' + +test_expect_success $PREREQ 'sendemail.identity: bool variable fallback' ' + git -c sendemail.identity=cloud \ + -c sendemail.xmailer=false \ + send-email \ + --dry-run \ + --from="nobody@example.com" \ + $patches >stdout && + grep "To: cloud@example.com" stdout && + ! grep "X-Mailer" stdout +' + test_expect_success $PREREQ '--no-to overrides sendemail.to' ' git send-email \ --dry-run \ --from="Example <nobody@example.com>" \ --no-to \ --to=nobody@example.com \ - $patches $patches >stdout && + $patches >stdout && grep "To: nobody@example.com" stdout && ! grep "To: Somebody <somebody@ex.com>" stdout ' @@ -1231,7 +1300,7 @@ test_expect_success $PREREQ 'sendemail.cc works' ' --dry-run \ --from="Example <nobody@example.com>" \ --to=nobody@example.com \ - $patches $patches >stdout && + $patches >stdout && grep "Cc: Somebody <somebody@ex.com>" stdout ' @@ -1242,7 +1311,7 @@ test_expect_success $PREREQ '--no-cc overrides sendemail.cc' ' --no-cc \ --cc=bodies@example.com \ --to=nobody@example.com \ - $patches $patches >stdout && + $patches >stdout && grep "Cc: bodies@example.com" stdout && ! grep "Cc: Somebody <somebody@ex.com>" stdout ' @@ -1254,7 +1323,7 @@ test_expect_success $PREREQ 'sendemail.bcc works' ' --from="Example <nobody@example.com>" \ --to=nobody@example.com \ --smtp-server relay.example.com \ - $patches $patches >stdout && + $patches >stdout && grep "RCPT TO:<other@ex.com>" stdout ' @@ -1266,7 +1335,7 @@ test_expect_success $PREREQ '--no-bcc overrides sendemail.bcc' ' --bcc=bodies@example.com \ --to=nobody@example.com \ --smtp-server relay.example.com \ - $patches $patches >stdout && + $patches >stdout && grep "RCPT TO:<bodies@example.com>" stdout && ! grep "RCPT TO:<other@ex.com>" stdout ' @@ -1423,10 +1492,10 @@ test_expect_success $PREREQ 'setup expect' ' EOF ' -test_expect_success $PREREQ 'sendemail.transferencoding=7bit fails on 8bit data' ' +test_expect_success $PREREQ '--transfer-encoding overrides sendemail.transferEncoding' ' clean_fake_sendmail && - git config sendemail.transferEncoding 7bit && - test_must_fail git send-email \ + test_must_fail git -c sendemail.transferEncoding=8bit \ + send-email \ --transfer-encoding=7bit \ --smtp-server="$(pwd)/fake.sendmail" \ email-using-8bit \ @@ -1435,11 +1504,10 @@ test_expect_success $PREREQ 'sendemail.transferencoding=7bit fails on 8bit data' test -z "$(ls msgtxt*)" ' -test_expect_success $PREREQ '--transfer-encoding overrides sendemail.transferEncoding' ' +test_expect_success $PREREQ 'sendemail.transferEncoding via config' ' clean_fake_sendmail && - git config sendemail.transferEncoding 8bit && - test_must_fail git send-email \ - --transfer-encoding=7bit \ + test_must_fail git -c sendemail.transferEncoding=7bit \ + send-email \ --smtp-server="$(pwd)/fake.sendmail" \ email-using-8bit \ 2>errors >out && @@ -1447,16 +1515,15 @@ test_expect_success $PREREQ '--transfer-encoding overrides sendemail.transferEnc test -z "$(ls msgtxt*)" ' -test_expect_success $PREREQ 'sendemail.transferencoding=8bit' ' +test_expect_success $PREREQ 'sendemail.transferEncoding via cli' ' clean_fake_sendmail && - git send-email \ - --transfer-encoding=8bit \ + test_must_fail git send-email \ + --transfer-encoding=7bit \ --smtp-server="$(pwd)/fake.sendmail" \ email-using-8bit \ 2>errors >out && - sed '1,/^$/d' msgtxt1 >actual && - sed '1,/^$/d' email-using-8bit >expected && - test_cmp expected actual + grep "cannot send message as 7bit" errors && + test -z "$(ls msgtxt*)" ' test_expect_success $PREREQ 'setup expect' ' @@ -1773,6 +1840,15 @@ test_expect_success '--dump-aliases must be used alone' ' test_must_fail git send-email --dump-aliases --to=janice@example.com -1 refs/heads/accounting ' +test_expect_success $PREREQ 'aliases and sendemail.identity' ' + test_must_fail git \ + -c sendemail.identity=cloud \ + -c sendemail.aliasesfile=default-aliases \ + -c sendemail.cloud.aliasesfile=cloud-aliases \ + send-email -1 2>stderr && + test_i18ngrep "cloud-aliases" stderr +' + test_sendmail_aliases () { msg="$1" && shift && expect="$@" && diff --git a/t/t9115-git-svn-dcommit-funky-renames.sh b/t/t9115-git-svn-dcommit-funky-renames.sh index 64bb495834..9b44a44bc1 100755 --- a/t/t9115-git-svn-dcommit-funky-renames.sh +++ b/t/t9115-git-svn-dcommit-funky-renames.sh @@ -120,6 +120,4 @@ test_expect_success !MINGW,!UTF8_NFD_TO_NFC 'svn.pathnameencoding=cp932 rename o git svn dcommit ' -stop_httpd - test_done diff --git a/t/t9118-git-svn-funky-branch-names.sh b/t/t9118-git-svn-funky-branch-names.sh index 41a026637f..a159ff96b7 100755 --- a/t/t9118-git-svn-funky-branch-names.sh +++ b/t/t9118-git-svn-funky-branch-names.sh @@ -87,6 +87,4 @@ test_expect_success 'test dcommit to trailing_dotlock branch' ' ) ' -stop_httpd - test_done diff --git a/t/t9120-git-svn-clone-with-percent-escapes.sh b/t/t9120-git-svn-clone-with-percent-escapes.sh index b28a1741e3..40b714df31 100755 --- a/t/t9120-git-svn-clone-with-percent-escapes.sh +++ b/t/t9120-git-svn-clone-with-percent-escapes.sh @@ -74,6 +74,4 @@ test_expect_success 'test clone -s with unescaped space' ' ) ' -stop_httpd - test_done diff --git a/t/t9142-git-svn-shallow-clone.sh b/t/t9142-git-svn-shallow-clone.sh index 9ee23be640..a30730502d 100755 --- a/t/t9142-git-svn-shallow-clone.sh +++ b/t/t9142-git-svn-shallow-clone.sh @@ -26,6 +26,4 @@ test_expect_success 'clone trunk with "-r HEAD"' ' ( cd g && git rev-parse --symbolic --verify HEAD ) ' -stop_httpd - test_done diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index 59a13b6a77..141b7fa35e 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -3262,4 +3262,61 @@ test_expect_success PIPE 'V: checkpoint updates tags after tag' ' background_import_still_running ' +### +### series W (get-mark and empty orphan commits) +### + +cat >>W-input <<-W_INPUT_END + commit refs/heads/W-branch + mark :1 + author Full Name <user@company.tld> 1000000000 +0100 + committer Full Name <user@company.tld> 1000000000 +0100 + data 27 + Intentionally empty commit + LFsget-mark :1 + W_INPUT_END + +test_expect_success !MINGW 'W: get-mark & empty orphan commit with no newlines' ' + sed -e s/LFs// W-input | tr L "\n" | git fast-import +' + +test_expect_success !MINGW 'W: get-mark & empty orphan commit with one newline' ' + sed -e s/LFs/L/ W-input | tr L "\n" | git fast-import +' + +test_expect_success !MINGW 'W: get-mark & empty orphan commit with ugly second newline' ' + # Technically, this should fail as it has too many linefeeds + # according to the grammar in fast-import.txt. But, for whatever + # reason, it works. Since using the correct number of newlines + # does not work with older (pre-2.22) versions of git, allow apps + # that used this second-newline workaround to keep working by + # checking it with this test... + sed -e s/LFs/LL/ W-input | tr L "\n" | git fast-import +' + +test_expect_success !MINGW 'W: get-mark & empty orphan commit with erroneous third newline' ' + # ...but do NOT allow more empty lines than that (see previous test). + sed -e s/LFs/LLL/ W-input | tr L "\n" | test_must_fail git fast-import +' + +### +### series X (other new features) +### + +test_expect_success 'X: handling encoding' ' + test_tick && + cat >input <<-INPUT_END && + commit refs/heads/encoding + committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE + encoding iso-8859-7 + data <<COMMIT + INPUT_END + + printf "Pi: \360\nCOMMIT\n" >>input && + + git fast-import <input && + git cat-file -p encoding | grep $(printf "\360") && + git log -1 --format=%B encoding | grep $(printf "\317\200") +' + test_done diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh index 5690fe2810..b4004e05c2 100755 --- a/t/t9350-fast-export.sh +++ b/t/t9350-fast-export.sh @@ -94,22 +94,83 @@ test_expect_success 'fast-export --show-original-ids | git fast-import' ' test $MUSS = $(git rev-parse --verify refs/tags/muss) ' -test_expect_success 'iso-8859-1' ' +test_expect_success 'reencoding iso-8859-7' ' - git config i18n.commitencoding ISO8859-1 && - # use author and committer name in ISO-8859-1 to match it. - . "$TEST_DIRECTORY"/t3901/8859-1.txt && + test_when_finished "git reset --hard HEAD~1" && + test_config i18n.commitencoding iso-8859-7 && test_tick && echo rosten >file && - git commit -s -m den file && - git fast-export wer^..wer >iso8859-1.fi && - sed "s/wer/i18n/" iso8859-1.fi | + git commit -s -F "$TEST_DIRECTORY/t9350/simple-iso-8859-7-commit-message.txt" file && + git fast-export --reencode=yes wer^..wer >iso-8859-7.fi && + sed "s/wer/i18n/" iso-8859-7.fi | (cd new && git fast-import && + # The commit object, if not re-encoded, would be 240 bytes. + # Removing the "encoding iso-8859-7\n" header drops 20 bytes. + # Re-encoding the Pi character from \xF0 (\360) in iso-8859-7 + # to \xCF\x80 (\317\200) in UTF-8 adds a byte. Check for + # the expected size. + test 221 -eq "$(git cat-file -s i18n)" && + # ...and for the expected translation of bytes. git cat-file commit i18n >actual && - grep "Áéí óú" actual) + grep $(printf "\317\200") actual && + # Also make sure the commit does not have the "encoding" header + ! grep ^encoding actual) +' + +test_expect_success 'aborting on iso-8859-7' ' + test_when_finished "git reset --hard HEAD~1" && + test_config i18n.commitencoding iso-8859-7 && + echo rosten >file && + git commit -s -F "$TEST_DIRECTORY/t9350/simple-iso-8859-7-commit-message.txt" file && + test_must_fail git fast-export --reencode=abort wer^..wer >iso-8859-7.fi ' + +test_expect_success 'preserving iso-8859-7' ' + + test_when_finished "git reset --hard HEAD~1" && + test_config i18n.commitencoding iso-8859-7 && + echo rosten >file && + git commit -s -F "$TEST_DIRECTORY/t9350/simple-iso-8859-7-commit-message.txt" file && + git fast-export --reencode=no wer^..wer >iso-8859-7.fi && + sed "s/wer/i18n-no-recoding/" iso-8859-7.fi | + (cd new && + git fast-import && + # The commit object, if not re-encoded, is 240 bytes. + # Removing the "encoding iso-8859-7\n" header would drops 20 + # bytes. Re-encoding the Pi character from \xF0 (\360) in + # iso-8859-7 to \xCF\x80 (\317\200) in UTF-8 adds a byte. + # Check for the expected size... + test 240 -eq "$(git cat-file -s i18n-no-recoding)" && + # ...as well as the expected byte. + git cat-file commit i18n-no-recoding >actual && + grep $(printf "\360") actual && + # Also make sure the commit has the "encoding" header + grep ^encoding actual) +' + +test_expect_success 'encoding preserved if reencoding fails' ' + + test_when_finished "git reset --hard HEAD~1" && + test_config i18n.commitencoding iso-8859-7 && + echo rosten >file && + git commit -s -F "$TEST_DIRECTORY/t9350/broken-iso-8859-7-commit-message.txt" file && + git fast-export --reencode=yes wer^..wer >iso-8859-7.fi && + sed "s/wer/i18n-invalid/" iso-8859-7.fi | + (cd new && + git fast-import && + git cat-file commit i18n-invalid >actual && + # Make sure the commit still has the encoding header + grep ^encoding actual && + # Verify that the commit has the expected size; i.e. + # that no bytes were re-encoded to a different encoding. + test 252 -eq "$(git cat-file -s i18n-invalid)" && + # ...and check for the original special bytes + grep $(printf "\360") actual && + grep $(printf "\377") actual) +' + test_expect_success 'import/export-marks' ' git checkout -b marks master && @@ -224,7 +285,6 @@ GIT_COMMITTER_NAME='C O Mitter'; export GIT_COMMITTER_NAME test_expect_success 'setup copies' ' - git config --unset i18n.commitencoding && git checkout -b copy rein && git mv file file3 && git commit -m move1 && diff --git a/t/t9350/broken-iso-8859-7-commit-message.txt b/t/t9350/broken-iso-8859-7-commit-message.txt new file mode 100644 index 0000000000..d06ad75b44 --- /dev/null +++ b/t/t9350/broken-iso-8859-7-commit-message.txt @@ -0,0 +1 @@ +Pi: ; Invalid:
\ No newline at end of file diff --git a/t/t9350/simple-iso-8859-7-commit-message.txt b/t/t9350/simple-iso-8859-7-commit-message.txt new file mode 100644 index 0000000000..8b3f0c3dba --- /dev/null +++ b/t/t9350/simple-iso-8859-7-commit-message.txt @@ -0,0 +1 @@ +Pi:
\ No newline at end of file diff --git a/t/t9800-git-p4-basic.sh b/t/t9800-git-p4-basic.sh index 729cd25770..5856563068 100755 --- a/t/t9800-git-p4-basic.sh +++ b/t/t9800-git-p4-basic.sh @@ -326,8 +326,4 @@ test_expect_success 'submit from worktree' ' ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9801-git-p4-branch.sh b/t/t9801-git-p4-branch.sh index 6a86d6996b..67ff2711f5 100755 --- a/t/t9801-git-p4-branch.sh +++ b/t/t9801-git-p4-branch.sh @@ -151,7 +151,7 @@ test_expect_success 'import depot, branch detection, branchList branch definitio ' test_expect_success 'restart p4d' ' - kill_p4d && + stop_and_cleanup_p4d && start_p4d ' @@ -411,6 +411,46 @@ test_expect_failure 'git p4 clone file subset branch' ' ) ' +# Check that excluded files are omitted during import +test_expect_success 'git p4 clone complex branches with excluded files' ' + test_when_finished cleanup_git && + test_create_repo "$git" && + ( + cd "$git" && + git config git-p4.branchList branch1:branch2 && + git config --add git-p4.branchList branch1:branch3 && + git config --add git-p4.branchList branch1:branch4 && + git config --add git-p4.branchList branch1:branch5 && + git config --add git-p4.branchList branch1:branch6 && + git p4 clone --dest=. --detect-branches -//depot/branch1/file2 -//depot/branch2/file2 -//depot/branch3/file2 -//depot/branch4/file2 -//depot/branch5/file2 -//depot/branch6/file2 //depot@all && + git log --all --graph --decorate --stat && + git reset --hard p4/depot/branch1 && + test_path_is_file file1 && + test_path_is_missing file2 && + test_path_is_file file3 && + git reset --hard p4/depot/branch2 && + test_path_is_file file1 && + test_path_is_missing file2 && + test_path_is_missing file3 && + git reset --hard p4/depot/branch3 && + test_path_is_file file1 && + test_path_is_missing file2 && + test_path_is_missing file3 && + git reset --hard p4/depot/branch4 && + test_path_is_file file1 && + test_path_is_missing file2 && + test_path_is_file file3 && + git reset --hard p4/depot/branch5 && + test_path_is_file file1 && + test_path_is_missing file2 && + test_path_is_file file3 && + git reset --hard p4/depot/branch6 && + test_path_is_file file1 && + test_path_is_missing file2 && + test_path_is_missing file3 + ) +' + # From a report in http://stackoverflow.com/questions/11893688 # where --use-client-spec caused branch prefixes not to be removed; # every file in git appeared into a subdirectory of the branch name. @@ -505,7 +545,7 @@ test_expect_success 'use-client-spec detect-branches skips files in branches' ' ' test_expect_success 'restart p4d' ' - kill_p4d && + stop_and_cleanup_p4d && start_p4d ' @@ -610,8 +650,96 @@ test_expect_success 'Update a file in git side and submit to P4 using client vie ) ' -test_expect_success 'kill p4d' ' - kill_p4d +test_expect_success 'restart p4d (case folding enabled)' ' + stop_and_cleanup_p4d && + start_p4d -C1 +' + +# +# 1: //depot/main/mf1 +# 2: integrate //depot/main/... -> //depot/branch1/... +# 3: //depot/main/mf2 +# 4: //depot/BRANCH1/B1f3 +# 5: //depot/branch1/b1f4 +# +test_expect_success !CASE_INSENSITIVE_FS 'basic p4 branches for case folding' ' + ( + cd "$cli" && + mkdir -p main && + + echo mf1 >main/mf1 && + p4 add main/mf1 && + p4 submit -d "main/mf1" && + + p4 integrate //depot/main/... //depot/branch1/... && + p4 submit -d "integrate main to branch1" && + + echo mf2 >main/mf2 && + p4 add main/mf2 && + p4 submit -d "main/mf2" && + + mkdir BRANCH1 && + echo B1f3 >BRANCH1/B1f3 && + p4 add BRANCH1/B1f3 && + p4 submit -d "BRANCH1/B1f3" && + + echo b1f4 >branch1/b1f4 && + p4 add branch1/b1f4 && + p4 submit -d "branch1/b1f4" + ) +' + +# Check that files are properly split across branches when ignorecase is set +test_expect_success !CASE_INSENSITIVE_FS 'git p4 clone, branchList branch definition, ignorecase' ' + test_when_finished cleanup_git && + test_create_repo "$git" && + ( + cd "$git" && + git config git-p4.branchList main:branch1 && + git config --type=bool core.ignoreCase true && + git p4 clone --dest=. --detect-branches //depot@all && + + git log --all --graph --decorate --stat && + + git reset --hard p4/master && + test_path_is_file mf1 && + test_path_is_file mf2 && + test_path_is_missing B1f3 && + test_path_is_missing b1f4 && + + git reset --hard p4/depot/branch1 && + test_path_is_file mf1 && + test_path_is_missing mf2 && + test_path_is_file B1f3 && + test_path_is_file b1f4 + ) +' + +# Check that files are properly split across branches when ignorecase is set, use-client-spec case +test_expect_success !CASE_INSENSITIVE_FS 'git p4 clone with client-spec, branchList branch definition, ignorecase' ' + client_view "//depot/... //client/..." && + test_when_finished cleanup_git && + test_create_repo "$git" && + ( + cd "$git" && + git config git-p4.branchList main:branch1 && + git config --type=bool core.ignoreCase true && + git p4 clone --dest=. --use-client-spec --detect-branches //depot@all && + + git log --all --graph --decorate --stat && + + git reset --hard p4/master && + test_path_is_file mf1 && + test_path_is_file mf2 && + test_path_is_missing B1f3 && + test_path_is_missing b1f4 && + + git reset --hard p4/depot/branch1 && + test_path_is_file mf1 && + test_path_is_missing mf2 && + test_path_is_file B1f3 && + test_path_is_file b1f4 + ) ' test_done diff --git a/t/t9802-git-p4-filetype.sh b/t/t9802-git-p4-filetype.sh index 9978352d78..94edebe272 100755 --- a/t/t9802-git-p4-filetype.sh +++ b/t/t9802-git-p4-filetype.sh @@ -333,8 +333,4 @@ test_expect_success SYMLINKS 'empty symlink target' ' ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9803-git-p4-shell-metachars.sh b/t/t9803-git-p4-shell-metachars.sh index d5c3675100..2913277013 100755 --- a/t/t9803-git-p4-shell-metachars.sh +++ b/t/t9803-git-p4-shell-metachars.sh @@ -105,8 +105,4 @@ test_expect_success 'branch with shell char' ' ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9804-git-p4-label.sh b/t/t9804-git-p4-label.sh index e30f80e617..3236457106 100755 --- a/t/t9804-git-p4-label.sh +++ b/t/t9804-git-p4-label.sh @@ -108,8 +108,4 @@ test_expect_failure 'two labels on the same changelist' ' ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9805-git-p4-skip-submit-edit.sh b/t/t9805-git-p4-skip-submit-edit.sh index 5fbf904dc8..90ef647db7 100755 --- a/t/t9805-git-p4-skip-submit-edit.sh +++ b/t/t9805-git-p4-skip-submit-edit.sh @@ -98,8 +98,4 @@ test_expect_success 'no config, edited' ' ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9806-git-p4-options.sh b/t/t9806-git-p4-options.sh index 3f5291b857..4e794a01bf 100755 --- a/t/t9806-git-p4-options.sh +++ b/t/t9806-git-p4-options.sh @@ -300,9 +300,4 @@ test_expect_success 'use --git-dir option and GIT_DIR' ' test_path_is_file "$git"/cli_file2.t ' - -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9807-git-p4-submit.sh b/t/t9807-git-p4-submit.sh index 850d979119..eaaae414a1 100755 --- a/t/t9807-git-p4-submit.sh +++ b/t/t9807-git-p4-submit.sh @@ -593,8 +593,4 @@ test_expect_success 'update a shelve involving moved and copied files' ' ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9808-git-p4-chdir.sh b/t/t9808-git-p4-chdir.sh index 11d2b5102c..58a9b3b71e 100755 --- a/t/t9808-git-p4-chdir.sh +++ b/t/t9808-git-p4-chdir.sh @@ -83,8 +83,4 @@ test_expect_success SYMLINKS 'p4 client root symlink should stay symbolic' ' ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9809-git-p4-client-view.sh b/t/t9809-git-p4-client-view.sh index 897b3c3034..3cff1fce1b 100755 --- a/t/t9809-git-p4-client-view.sh +++ b/t/t9809-git-p4-client-view.sh @@ -836,8 +836,4 @@ test_expect_success 'quotes on both sides' ' git_verify "cdir 1/file11" "cdir 1/file12" ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9810-git-p4-rcs.sh b/t/t9810-git-p4-rcs.sh index cc53debe19..57b533dc6f 100755 --- a/t/t9810-git-p4-rcs.sh +++ b/t/t9810-git-p4-rcs.sh @@ -360,8 +360,4 @@ test_expect_failure 'Add keywords in git which do not match the default p4 value ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9811-git-p4-label-import.sh b/t/t9811-git-p4-label-import.sh index 602b0a5d5c..c1446f26ab 100755 --- a/t/t9811-git-p4-label-import.sh +++ b/t/t9811-git-p4-label-import.sh @@ -191,7 +191,7 @@ test_expect_success 'tag that cannot be exported' ' ( cd "$cli" && p4 sync ... && - !(p4 labels | grep GIT_TAG_ON_A_BRANCH) + ! p4 labels | grep GIT_TAG_ON_A_BRANCH ) ' @@ -259,9 +259,4 @@ test_expect_success 'importing labels with missing revisions' ' ) ' - -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9812-git-p4-wildcards.sh b/t/t9812-git-p4-wildcards.sh index 0206771fbb..254a7c2446 100755 --- a/t/t9812-git-p4-wildcards.sh +++ b/t/t9812-git-p4-wildcards.sh @@ -211,8 +211,4 @@ test_expect_success 'wildcard files requiring keyword scrub' ' ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9813-git-p4-preserve-users.sh b/t/t9813-git-p4-preserve-users.sh index 783c6ad165..fd018c87a8 100755 --- a/t/t9813-git-p4-preserve-users.sh +++ b/t/t9813-git-p4-preserve-users.sh @@ -138,8 +138,4 @@ test_expect_success 'not preserving user with mixed authorship' ' ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9814-git-p4-rename.sh b/t/t9814-git-p4-rename.sh index 60baa06e27..468767cbf4 100755 --- a/t/t9814-git-p4-rename.sh +++ b/t/t9814-git-p4-rename.sh @@ -242,8 +242,4 @@ test_expect_success P4D_HAVE_CONFIGURABLE_RUN_MOVE_ALLOW \ ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9815-git-p4-submit-fail.sh b/t/t9815-git-p4-submit-fail.sh index eaf03a6563..9779dc0d11 100755 --- a/t/t9815-git-p4-submit-fail.sh +++ b/t/t9815-git-p4-submit-fail.sh @@ -422,8 +422,4 @@ test_expect_success 'cleanup chmod after submit cancel' ' ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9816-git-p4-locked.sh b/t/t9816-git-p4-locked.sh index d048bd33fa..932841003c 100755 --- a/t/t9816-git-p4-locked.sh +++ b/t/t9816-git-p4-locked.sh @@ -138,8 +138,4 @@ test_expect_failure 'move with lock taken' ' ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9817-git-p4-exclude.sh b/t/t9817-git-p4-exclude.sh index aac568eadf..ec3d937c6a 100755 --- a/t/t9817-git-p4-exclude.sh +++ b/t/t9817-git-p4-exclude.sh @@ -22,7 +22,9 @@ test_expect_success 'create exclude repo' ' mkdir -p wanted discard && echo wanted >wanted/foo && echo discard >discard/foo && - p4 add wanted/foo discard/foo && + echo discard_file >discard_file && + echo discard_file_not >discard_file_not && + p4 add wanted/foo discard/foo discard_file discard_file_not && p4 submit -d "initial revision" ) ' @@ -33,7 +35,9 @@ test_expect_success 'check the repo was created correctly' ' ( cd "$git" && test_path_is_file wanted/foo && - test_path_is_file discard/foo + test_path_is_file discard/foo && + test_path_is_file discard_file && + test_path_is_file discard_file_not ) ' @@ -43,7 +47,21 @@ test_expect_success 'clone, excluding part of repo' ' ( cd "$git" && test_path_is_file wanted/foo && - test_path_is_missing discard/foo + test_path_is_missing discard/foo && + test_path_is_file discard_file && + test_path_is_file discard_file_not + ) +' + +test_expect_success 'clone, excluding single file, no trailing /' ' + test_when_finished cleanup_git && + git p4 clone -//depot/discard_file --dest="$git" //depot/...@all && + ( + cd "$git" && + test_path_is_file wanted/foo && + test_path_is_file discard/foo && + test_path_is_missing discard_file && + test_path_is_file discard_file_not ) ' @@ -52,20 +70,39 @@ test_expect_success 'clone, then sync with exclude' ' git p4 clone -//depot/discard/... --dest="$git" //depot/...@all && ( cd "$cli" && - p4 edit wanted/foo discard/foo && + p4 edit wanted/foo discard/foo discard_file_not && date >>wanted/foo && date >>discard/foo && + date >>discard_file_not && p4 submit -d "updating" && cd "$git" && git p4 sync -//depot/discard/... && test_path_is_file wanted/foo && - test_path_is_missing discard/foo + test_path_is_missing discard/foo && + test_path_is_file discard_file && + test_path_is_file discard_file_not ) ' -test_expect_success 'kill p4d' ' - kill_p4d +test_expect_success 'clone, then sync with exclude, no trailing /' ' + test_when_finished cleanup_git && + git p4 clone -//depot/discard/... -//depot/discard_file --dest="$git" //depot/...@all && + ( + cd "$cli" && + p4 edit wanted/foo discard/foo discard_file_not && + date >>wanted/foo && + date >>discard/foo && + date >>discard_file_not && + p4 submit -d "updating" && + + cd "$git" && + git p4 sync -//depot/discard/... -//depot/discard_file && + test_path_is_file wanted/foo && + test_path_is_missing discard/foo && + test_path_is_missing discard_file && + test_path_is_file discard_file_not + ) ' test_done diff --git a/t/t9818-git-p4-block.sh b/t/t9818-git-p4-block.sh index ce7cb22ad3..0db7ab9918 100755 --- a/t/t9818-git-p4-block.sh +++ b/t/t9818-git-p4-block.sh @@ -146,8 +146,4 @@ test_expect_success 'Clone repo with self-sizing block size' ' test_line_count \> 10 log ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9819-git-p4-case-folding.sh b/t/t9819-git-p4-case-folding.sh index d808c008c1..600ce1e0b0 100755 --- a/t/t9819-git-p4-case-folding.sh +++ b/t/t9819-git-p4-case-folding.sh @@ -53,8 +53,4 @@ test_expect_failure 'Clone UC repo with lc name' ' test_must_fail git p4 clone //depot/uc/... ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9820-git-p4-editor-handling.sh b/t/t9820-git-p4-editor-handling.sh index 3c22f74bd4..fa1bba1dd9 100755 --- a/t/t9820-git-p4-editor-handling.sh +++ b/t/t9820-git-p4-editor-handling.sh @@ -31,8 +31,4 @@ test_expect_success 'EDITOR with options' ' ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9821-git-p4-path-variations.sh b/t/t9821-git-p4-path-variations.sh index 81e46acfa8..ef80f1690b 100755 --- a/t/t9821-git-p4-path-variations.sh +++ b/t/t9821-git-p4-path-variations.sh @@ -193,8 +193,4 @@ test_expect_success 'Add a new file and clone path with new file (ignorecase)' ' ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9822-git-p4-path-encoding.sh b/t/t9822-git-p4-path-encoding.sh index c78477c19b..572d395498 100755 --- a/t/t9822-git-p4-path-encoding.sh +++ b/t/t9822-git-p4-path-encoding.sh @@ -7,6 +7,13 @@ test_description='Clone repositories with non ASCII paths' UTF8_ESCAPED="a-\303\244_o-\303\266_u-\303\274.txt" ISO8859_ESCAPED="a-\344_o-\366_u-\374.txt" +ISO8859="$(printf "$ISO8859_ESCAPED")" && +echo content123 >"$ISO8859" && +rm "$ISO8859" || { + skip_all="fs does not accept ISO-8859-1 filenames" + test_done +} + test_expect_success 'start p4d' ' start_p4d ' @@ -67,8 +74,4 @@ test_expect_success 'Delete iso8859-1 encoded paths and clone' ' ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9823-git-p4-mock-lfs.sh b/t/t9823-git-p4-mock-lfs.sh index 1f2dc369bf..88b76dc4d6 100755 --- a/t/t9823-git-p4-mock-lfs.sh +++ b/t/t9823-git-p4-mock-lfs.sh @@ -185,8 +185,4 @@ test_expect_success 'Run git p4 submit in repo configured with large file system ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9824-git-p4-git-lfs.sh b/t/t9824-git-p4-git-lfs.sh index ed80ca858c..a28dbbdd56 100755 --- a/t/t9824-git-p4-git-lfs.sh +++ b/t/t9824-git-p4-git-lfs.sh @@ -287,8 +287,4 @@ test_expect_success 'Add big files to repo and store files in LFS based on compr ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9825-git-p4-handle-utf16-without-bom.sh b/t/t9825-git-p4-handle-utf16-without-bom.sh index 1551845dc1..f049ff8229 100755 --- a/t/t9825-git-p4-handle-utf16-without-bom.sh +++ b/t/t9825-git-p4-handle-utf16-without-bom.sh @@ -43,8 +43,4 @@ test_expect_failure 'clone depot with invalid UTF-16 file in non-verbose mode' ' git p4 clone --dest="$git" //depot ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9826-git-p4-keep-empty-commits.sh b/t/t9826-git-p4-keep-empty-commits.sh index fa8b9daf1f..fd64afe064 100755 --- a/t/t9826-git-p4-keep-empty-commits.sh +++ b/t/t9826-git-p4-keep-empty-commits.sh @@ -127,8 +127,4 @@ test_expect_success 'Clone repo subdir with all history' ' ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9827-git-p4-change-filetype.sh b/t/t9827-git-p4-change-filetype.sh index 7433998f47..d3670bd7a2 100755 --- a/t/t9827-git-p4-change-filetype.sh +++ b/t/t9827-git-p4-change-filetype.sh @@ -59,8 +59,4 @@ test_expect_success SYMLINKS 'change symbolic link to file' ' ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9828-git-p4-map-user.sh b/t/t9828-git-p4-map-user.sh index e20395c89f..ca6c2942bd 100755 --- a/t/t9828-git-p4-map-user.sh +++ b/t/t9828-git-p4-map-user.sh @@ -54,8 +54,4 @@ test_expect_success 'Clone repo root path with all history' ' ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9829-git-p4-jobs.sh b/t/t9829-git-p4-jobs.sh index 971aeeea1f..88cfb1fcd3 100755 --- a/t/t9829-git-p4-jobs.sh +++ b/t/t9829-git-p4-jobs.sh @@ -92,8 +92,4 @@ test_expect_success 'check log message of changelist with more jobs' ' ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9830-git-p4-symlink-dir.sh b/t/t9830-git-p4-symlink-dir.sh index 2ad1b0810d..3fb6960c18 100755 --- a/t/t9830-git-p4-symlink-dir.sh +++ b/t/t9830-git-p4-symlink-dir.sh @@ -36,8 +36,4 @@ test_expect_success 'symlinked directory' ' ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9831-git-p4-triggers.sh b/t/t9831-git-p4-triggers.sh index be44c9751a..d743ca33ee 100755 --- a/t/t9831-git-p4-triggers.sh +++ b/t/t9831-git-p4-triggers.sh @@ -96,8 +96,4 @@ test_expect_success 'submit description with extra info lines from verbose p4 ch ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - test_done diff --git a/t/t9832-unshelve.sh b/t/t9832-unshelve.sh index 41c09f11f4..e9276c48f4 100755 --- a/t/t9832-unshelve.sh +++ b/t/t9832-unshelve.sh @@ -22,7 +22,10 @@ test_expect_success 'init depot' ' : >file_to_move && p4 add file_to_delete && p4 add file_to_move && - p4 submit -d "add files to delete" + p4 submit -d "add files to delete" && + echo file_to_integrate >file_to_integrate && + p4 add file_to_integrate && + p4 submit -d "add file to integrate" ) ' @@ -40,6 +43,7 @@ test_expect_success 'create shelved changelist' ' p4 delete file_to_delete && p4 edit file_to_move && p4 move file_to_move moved_file && + p4 integrate file_to_integrate integrated_file && p4 opened && p4 shelve -i <<EOF Change: new @@ -53,6 +57,7 @@ Files: //depot/file_to_delete //depot/file_to_move //depot/moved_file + //depot/integrated_file EOF ) && @@ -65,6 +70,7 @@ EOF test_path_is_file file2 && test_cmp file1 "$cli"/file1 && test_cmp file2 "$cli"/file2 && + test_cmp file_to_integrate "$cli"/integrated_file && test_path_is_missing file_to_delete && test_path_is_missing file_to_move && test_path_is_file moved_file @@ -174,8 +180,5 @@ test_expect_success 'unshelve specifying the origin' ' test_path_is_file file_to_shelve ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' test_done diff --git a/t/t9833-errors.sh b/t/t9833-errors.sh index 47b312e1c9..e22369ccdf 100755 --- a/t/t9833-errors.sh +++ b/t/t9833-errors.sh @@ -45,9 +45,4 @@ test_expect_success 'ticket logged out' ' ) ' -test_expect_success 'kill p4d' ' - kill_p4d -' - - test_done diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh index 681c41ba32..0367cec5fd 100644 --- a/t/test-lib-functions.sh +++ b/t/test-lib-functions.sh @@ -309,6 +309,26 @@ test_unset_prereq () { } test_set_prereq () { + if test -n "$GIT_TEST_FAIL_PREREQS" + then + case "$1" in + # The "!" case is handled below with + # test_unset_prereq() + !*) + ;; + # (Temporary?) whitelist of things we can't easily + # pretend not to support + SYMLINKS) + ;; + # Inspecting whether GIT_TEST_FAIL_PREREQS is on + # should be unaffected. + FAIL_PREREQS) + ;; + *) + return + esac + fi + case "$1" in !*) test_unset_prereq "${1#!}" @@ -943,6 +963,34 @@ test_when_finished () { } && (exit \"\$eval_ret\"); eval_ret=\$?; $test_cleanup" } +# This function can be used to schedule some commands to be run +# unconditionally at the end of the test script, e.g. to stop a daemon: +# +# test_expect_success 'test git daemon' ' +# git daemon & +# daemon_pid=$! && +# test_atexit 'kill $daemon_pid' && +# hello world +# ' +# +# The commands will be executed before the trash directory is removed, +# i.e. the atexit commands will still be able to access any pidfiles or +# socket files. +# +# Note that these commands will be run even when a test script run +# with '--immediate' fails. Be careful with your atexit commands to +# minimize any changes to the failed state. + +test_atexit () { + # We cannot detect when we are in a subshell in general, but by + # doing so on Bash is better than nothing (the test will + # silently pass on other shells). + test "${BASH_SUBSHELL-0}" = 0 || + error "bug in test script: test_atexit does nothing in a subshell" + test_atexit_cleanup="{ $* + } && (exit \"\$eval_ret\"); eval_ret=\$?; $test_atexit_cleanup" +} + # Most tests can use the created repository, but some may need to create more. # Usage: test_create_repo <directory> test_create_repo () { @@ -1211,6 +1259,12 @@ depacketize () { ' } +# Converts base-16 data into base-8. The output is given as a sequence of +# escaped octals, suitable for consumption by 'printf'. +hex2oct () { + perl -ne 'printf "\\%03o", hex for /../g' +} + # Set the hash algorithm in use to $1. Only useful when testing the testsuite. test_set_hash () { test_hash_algo="$1" diff --git a/t/test-lib.sh b/t/test-lib.sh index 562c57e685..d1ba33745a 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -57,6 +57,13 @@ fi . "$GIT_BUILD_DIR"/GIT-BUILD-OPTIONS export PERL_PATH SHELL_PATH +# Disallow the use of abbreviated options in the test suite by default +if test -z "${GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS}" +then + GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS=true + export GIT_TEST_DISALLOW_ABBREVIATED_OPTIONS +fi + ################################################################ # It appears that people try to run tests without building... "${GIT_TEST_INSTALLED:-$GIT_BUILD_DIR}/git$X" >/dev/null @@ -627,6 +634,10 @@ test_external_has_tap=0 die () { code=$? + # This is responsible for running the atexit commands even when a + # test script run with '--immediate' fails, or when the user hits + # ctrl-C, i.e. when 'test_done' is not invoked at all. + test_atexit_handler || code=$? if test -n "$GIT_EXIT_OK" then exit $code @@ -638,7 +649,10 @@ die () { GIT_EXIT_OK= trap 'die' EXIT -trap 'exit $?' INT TERM HUP +# Disable '-x' tracing, because with some shells, notably dash, it +# prevents running the cleanup commands when a test script run with +# '--verbose-log -x' is interrupted. +trap '{ code=$?; set +x; } 2>/dev/null; exit $code' INT TERM HUP # The user-facing functions are loaded from a separate file so that # test_perf subshells can have them too @@ -1049,9 +1063,28 @@ write_junit_xml_testcase () { junit_have_testcase=t } +test_atexit_cleanup=: +test_atexit_handler () { + # In a succeeding test script 'test_atexit_handler' is invoked + # twice: first from 'test_done', then from 'die' in the trap on + # EXIT. + # This condition and resetting 'test_atexit_cleanup' below makes + # sure that the registered cleanup commands are run only once. + test : != "$test_atexit_cleanup" || return 0 + + setup_malloc_check + test_eval_ "$test_atexit_cleanup" + test_atexit_cleanup=: + teardown_malloc_check +} + test_done () { GIT_EXIT_OK=t + # Run the atexit commands _before_ the trash directory is + # removed, so the commands can access pidfiles and socket files. + test_atexit_handler + if test -n "$write_junit_xml" && test -n "$junit_xml_path" then test -n "$junit_have_testcase" || { @@ -1405,6 +1438,7 @@ test -z "$NO_GETTEXT" && test_set_prereq GETTEXT if test -n "$GIT_TEST_GETTEXT_POISON_ORIG" then GIT_TEST_GETTEXT_POISON=$GIT_TEST_GETTEXT_POISON_ORIG + export GIT_TEST_GETTEXT_POISON unset GIT_TEST_GETTEXT_POISON_ORIG fi @@ -1487,7 +1521,7 @@ test_lazy_prereq NOT_ROOT ' ' test_lazy_prereq JGIT ' - type jgit + jgit --version ' # SANITY is about "can you correctly predict what the filesystem would @@ -1572,3 +1606,7 @@ test_lazy_prereq SHA1 ' test_lazy_prereq REBASE_P ' test -z "$GIT_TEST_SKIP_REBASE_P" ' + +test_lazy_prereq FAIL_PREREQS ' + test -n "$GIT_TEST_FAIL_PREREQS" +' |