summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/README12
-rw-r--r--t/helper/test-dir-iterator.c58
-rw-r--r--t/helper/test-example-decorate.c6
-rw-r--r--t/helper/test-hashmap.c9
-rw-r--r--t/helper/test-match-trees.c2
-rw-r--r--t/helper/test-oidmap.c112
-rw-r--r--t/helper/test-tool.c2
-rw-r--r--t/helper/test-tool.h2
-rw-r--r--t/lib-git-daemon.sh7
-rw-r--r--t/lib-git-svn.sh11
-rw-r--r--t/lib-httpd.sh15
-rw-r--r--t/lib-patch-mode.sh12
-rwxr-xr-xt/perf/p5600-clone-reference.sh27
-rwxr-xr-xt/t0000-basic.sh10
-rwxr-xr-xt/t0001-init.sh26
-rwxr-xr-xt/t0007-git-var.sh2
-rwxr-xr-xt/t0011-hashmap.sh9
-rwxr-xr-xt/t0016-oidmap.sh102
-rwxr-xr-xt/t0017-env-helper.sh99
-rwxr-xr-xt/t0061-run-command.sh6
-rwxr-xr-xt/t0066-dir-iterator.sh148
-rwxr-xr-xt/t0205-gettext-poison.sh7
-rwxr-xr-xt/t1090-sparse-checkout-scope.sh14
-rwxr-xr-xt/t1305-config-include.sh60
-rwxr-xr-xt/t2014-checkout-switch.sh (renamed from t/t2014-switch.sh)0
-rwxr-xr-xt/t2020-checkout-detach.sh28
-rwxr-xr-xt/t2060-switch.sh96
-rwxr-xr-xt/t2070-restore.sh98
-rwxr-xr-xt/t2071-restore-patch.sh110
-rwxr-xr-xt/t3200-branch.sh16
-rwxr-xr-xt/t3203-branch-output.sh44
-rwxr-xr-xt/t3206-range-diff.sh124
-rw-r--r--t/t3206/history.export84
-rwxr-xr-xt/t3311-notes-merge-fanout.sh10
-rwxr-xr-xt/t3404-rebase-interactive.sh122
-rwxr-xr-xt/t3418-rebase-continue.sh8
-rwxr-xr-xt/t3420-rebase-autostash.sh15
-rwxr-xr-xt/t3430-rebase-merges.sh18
-rwxr-xr-xt/t3510-cherry-pick-sequence.sh122
-rwxr-xr-xt/t3600-rm.sh13
-rwxr-xr-xt/t3701-add-interactive.sh8
-rwxr-xr-xt/t3903-stash.sh25
-rwxr-xr-xt/t4015-diff-whitespace.sh22
-rwxr-xr-xt/t5310-pack-bitmaps.sh15
-rwxr-xr-xt/t5318-commit-graph.sh10
-rwxr-xr-xt/t5319-multi-pack-index.sh184
-rwxr-xr-xt/t5324-split-commit-graph.sh343
-rwxr-xr-xt/t5504-fetch-receive-strict.sh14
-rwxr-xr-xt/t5510-fetch.sh23
-rwxr-xr-xt/t5512-ls-remote.sh3
-rwxr-xr-xt/t5514-fetch-multiple.sh7
-rwxr-xr-xt/t5541-http-push-smart.sh55
-rwxr-xr-xt/t5551-http-fetch-smart.sh9
-rwxr-xr-xt/t5604-clone-reference.sh133
-rwxr-xr-xt/t5618-alternate-refs.sh60
-rwxr-xr-xt/t5702-protocol-v2.sh10
-rwxr-xr-xt/t5703-upload-pack-ref-in-want.sh4
-rwxr-xr-xt/t5801-remote-helpers.sh18
-rwxr-xr-xt/t5801/git-remote-testgit22
-rwxr-xr-xt/t6000-rev-list-misc.sh20
-rwxr-xr-xt/t6040-tracking-info.sh37
-rwxr-xr-xt/t6200-fmt-merge-msg.sh7
-rwxr-xr-xt/t6300-for-each-ref.sh26
-rwxr-xr-xt/t6302-for-each-ref-filter.sh13
-rwxr-xr-xt/t7004-tag.sh21
-rwxr-xr-xt/t7006-pager.sh2
-rwxr-xr-xt/t7060-wtstatus.sh5
-rwxr-xr-xt/t7064-wtstatus-pv2.sh8
-rwxr-xr-xt/t7201-co.sh2
-rwxr-xr-xt/t7300-clean.sh12
-rwxr-xr-xt/t7407-submodule-foreach.sh7
-rwxr-xr-xt/t7502-commit-porcelain.sh2
-rwxr-xr-xt/t7508-status.sh144
-rwxr-xr-xt/t7512-status-help.sh50
-rwxr-xr-xt/t7513-interpret-trailers.sh71
-rwxr-xr-xt/t7610-mergetool.sh309
-rwxr-xr-xt/t7700-repack.sh10
-rwxr-xr-xt/t7814-grep-recurse-submodules.sh18
-rwxr-xr-xt/t8003-blame-corner-cases.sh36
-rwxr-xr-xt/t8013-blame-ignore-revs.sh274
-rwxr-xr-xt/t8014-blame-ignore-fuzzy.sh437
-rwxr-xr-xt/t9801-git-p4-branch.sh132
-rwxr-xr-xt/t9817-git-p4-exclude.sh51
-rwxr-xr-xt/t9902-completion.sh2
-rwxr-xr-xt/t9903-bash-prompt.sh20
-rw-r--r--t/test-lib-functions.sh196
-rw-r--r--t/test-lib.sh32
87 files changed, 3931 insertions, 644 deletions
diff --git a/t/README b/t/README
index 9747971d58..60d5b77bcc 100644
--- a/t/README
+++ b/t/README
@@ -334,7 +334,7 @@ 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
+GIT_TEST_FAIL_PREREQS=<boolean> fails all prerequisites. This is
useful for discovering issues with the tests where say a later test
implicitly depends on an optional earlier test.
@@ -343,11 +343,11 @@ 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
-prerequisite when adding more strings for translation. See "Testing
-marked strings" in po/README for details.
+GIT_TEST_GETTEXT_POISON=<boolean> turns all strings marked for
+translation into gibberish if true. Used for spotting those tests that
+need to be marked with a C_LOCALE_OUTPUT prerequisite when adding more
+strings for translation. See "Testing marked strings" in po/README for
+details.
GIT_TEST_SPLIT_INDEX=<boolean> forces split-index mode on the whole
test suite. Accept any boolean values that are accepted by git-config.
diff --git a/t/helper/test-dir-iterator.c b/t/helper/test-dir-iterator.c
new file mode 100644
index 0000000000..a5b96cb0dc
--- /dev/null
+++ b/t/helper/test-dir-iterator.c
@@ -0,0 +1,58 @@
+#include "test-tool.h"
+#include "git-compat-util.h"
+#include "strbuf.h"
+#include "iterator.h"
+#include "dir-iterator.h"
+
+/*
+ * usage:
+ * tool-test dir-iterator [--follow-symlinks] [--pedantic] directory_path
+ */
+int cmd__dir_iterator(int argc, const char **argv)
+{
+ struct strbuf path = STRBUF_INIT;
+ struct dir_iterator *diter;
+ unsigned int flags = 0;
+ int iter_status;
+
+ for (++argv, --argc; *argv && starts_with(*argv, "--"); ++argv, --argc) {
+ if (strcmp(*argv, "--follow-symlinks") == 0)
+ flags |= DIR_ITERATOR_FOLLOW_SYMLINKS;
+ else if (strcmp(*argv, "--pedantic") == 0)
+ flags |= DIR_ITERATOR_PEDANTIC;
+ else
+ die("invalid option '%s'", *argv);
+ }
+
+ if (!*argv || argc != 1)
+ die("dir-iterator needs exactly one non-option argument");
+
+ strbuf_add(&path, *argv, strlen(*argv));
+ diter = dir_iterator_begin(path.buf, flags);
+
+ if (!diter) {
+ printf("dir_iterator_begin failure: %d\n", errno);
+ exit(EXIT_FAILURE);
+ }
+
+ while ((iter_status = dir_iterator_advance(diter)) == ITER_OK) {
+ if (S_ISDIR(diter->st.st_mode))
+ printf("[d] ");
+ else if (S_ISREG(diter->st.st_mode))
+ printf("[f] ");
+ else if (S_ISLNK(diter->st.st_mode))
+ printf("[s] ");
+ else
+ printf("[?] ");
+
+ printf("(%s) [%s] %s\n", diter->relative_path, diter->basename,
+ diter->path.buf);
+ }
+
+ if (iter_status != ITER_DONE) {
+ printf("dir_iterator_advance failure\n");
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/t/helper/test-example-decorate.c b/t/helper/test-example-decorate.c
index a20a6161e4..c8a1cde7d2 100644
--- a/t/helper/test-example-decorate.c
+++ b/t/helper/test-example-decorate.c
@@ -26,8 +26,8 @@ int cmd__example_decorate(int argc, const char **argv)
* Add 2 objects, one with a non-NULL decoration and one with a NULL
* decoration.
*/
- one = lookup_unknown_object(one_oid.hash);
- two = lookup_unknown_object(two_oid.hash);
+ one = lookup_unknown_object(&one_oid);
+ two = lookup_unknown_object(&two_oid);
ret = add_decoration(&n, one, &decoration_a);
if (ret)
BUG("when adding a brand-new object, NULL should be returned");
@@ -56,7 +56,7 @@ int cmd__example_decorate(int argc, const char **argv)
ret = lookup_decoration(&n, two);
if (ret != &decoration_b)
BUG("lookup should return added declaration");
- three = lookup_unknown_object(three_oid.hash);
+ three = lookup_unknown_object(&three_oid);
ret = lookup_decoration(&n, three);
if (ret)
BUG("lookup for unknown object should return NULL");
diff --git a/t/helper/test-hashmap.c b/t/helper/test-hashmap.c
index 23d2b172fe..aaf17b0ddf 100644
--- a/t/helper/test-hashmap.c
+++ b/t/helper/test-hashmap.c
@@ -173,14 +173,7 @@ int cmd__hashmap(int argc, const char **argv)
p2 = strtok(NULL, DELIM);
}
- if (!strcmp("hash", cmd) && p1) {
-
- /* print results of different hash functions */
- printf("%u %u %u %u\n",
- strhash(p1), memhash(p1, strlen(p1)),
- strihash(p1), memihash(p1, strlen(p1)));
-
- } else if (!strcmp("add", cmd) && p1 && p2) {
+ if (!strcmp("add", cmd) && p1 && p2) {
/* create entry with key = p1, value = p2 */
entry = alloc_test_entry(hash, p1, p2);
diff --git a/t/helper/test-match-trees.c b/t/helper/test-match-trees.c
index 96857f26ac..b9fd427571 100644
--- a/t/helper/test-match-trees.c
+++ b/t/helper/test-match-trees.c
@@ -20,7 +20,7 @@ int cmd__match_trees(int ac, const char **av)
if (!two)
die("not a tree-ish %s", av[2]);
- shift_tree(&one->object.oid, &two->object.oid, &shifted, -1);
+ shift_tree(the_repository, &one->object.oid, &two->object.oid, &shifted, -1);
printf("shifted: %s\n", oid_to_hex(&shifted));
exit(0);
diff --git a/t/helper/test-oidmap.c b/t/helper/test-oidmap.c
new file mode 100644
index 0000000000..0acf99931e
--- /dev/null
+++ b/t/helper/test-oidmap.c
@@ -0,0 +1,112 @@
+#include "test-tool.h"
+#include "cache.h"
+#include "oidmap.h"
+#include "strbuf.h"
+
+/* key is an oid and value is a name (could be a refname for example) */
+struct test_entry {
+ struct oidmap_entry entry;
+ char name[FLEX_ARRAY];
+};
+
+#define DELIM " \t\r\n"
+
+/*
+ * Read stdin line by line and print result of commands to stdout:
+ *
+ * hash oidkey -> sha1hash(oidkey)
+ * put oidkey namevalue -> NULL / old namevalue
+ * get oidkey -> NULL / namevalue
+ * remove oidkey -> NULL / old namevalue
+ * iterate -> oidkey1 namevalue1\noidkey2 namevalue2\n...
+ *
+ */
+int cmd__oidmap(int argc, const char **argv)
+{
+ struct strbuf line = STRBUF_INIT;
+ struct oidmap map = OIDMAP_INIT;
+
+ setup_git_directory();
+
+ /* init oidmap */
+ oidmap_init(&map, 0);
+
+ /* process commands from stdin */
+ while (strbuf_getline(&line, stdin) != EOF) {
+ char *cmd, *p1 = NULL, *p2 = NULL;
+ struct test_entry *entry;
+ struct object_id oid;
+
+ /* break line into command and up to two parameters */
+ cmd = strtok(line.buf, DELIM);
+ /* ignore empty lines */
+ if (!cmd || *cmd == '#')
+ continue;
+
+ p1 = strtok(NULL, DELIM);
+ if (p1)
+ p2 = strtok(NULL, DELIM);
+
+ if (!strcmp("put", cmd) && p1 && p2) {
+
+ if (get_oid(p1, &oid)) {
+ printf("Unknown oid: %s\n", p1);
+ continue;
+ }
+
+ /* create entry with oid_key = p1, name_value = p2 */
+ FLEX_ALLOC_STR(entry, name, p2);
+ oidcpy(&entry->entry.oid, &oid);
+
+ /* add / replace entry */
+ entry = oidmap_put(&map, entry);
+
+ /* print and free replaced entry, if any */
+ puts(entry ? entry->name : "NULL");
+ free(entry);
+
+ } else if (!strcmp("get", cmd) && p1) {
+
+ if (get_oid(p1, &oid)) {
+ printf("Unknown oid: %s\n", p1);
+ continue;
+ }
+
+ /* lookup entry in oidmap */
+ entry = oidmap_get(&map, &oid);
+
+ /* print result */
+ puts(entry ? entry->name : "NULL");
+
+ } else if (!strcmp("remove", cmd) && p1) {
+
+ if (get_oid(p1, &oid)) {
+ printf("Unknown oid: %s\n", p1);
+ continue;
+ }
+
+ /* remove entry from oidmap */
+ entry = oidmap_remove(&map, &oid);
+
+ /* print result and free entry*/
+ puts(entry ? entry->name : "NULL");
+ free(entry);
+
+ } else if (!strcmp("iterate", cmd)) {
+
+ struct oidmap_iter iter;
+ oidmap_iter_init(&map, &iter);
+ while ((entry = oidmap_iter_next(&iter)))
+ printf("%s %s\n", oid_to_hex(&entry->entry.oid), entry->name);
+
+ } else {
+
+ printf("Unknown command %s\n", cmd);
+
+ }
+ }
+
+ strbuf_release(&line);
+ oidmap_free(&map, 1);
+ return 0;
+}
diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
index 087a8c0cc9..ce7e89028c 100644
--- a/t/helper/test-tool.c
+++ b/t/helper/test-tool.c
@@ -19,6 +19,7 @@ static struct test_cmd cmds[] = {
{ "ctype", cmd__ctype },
{ "date", cmd__date },
{ "delta", cmd__delta },
+ { "dir-iterator", cmd__dir_iterator },
{ "drop-caches", cmd__drop_caches },
{ "dump-cache-tree", cmd__dump_cache_tree },
{ "dump-fsmonitor", cmd__dump_fsmonitor },
@@ -35,6 +36,7 @@ static struct test_cmd cmds[] = {
{ "match-trees", cmd__match_trees },
{ "mergesort", cmd__mergesort },
{ "mktemp", cmd__mktemp },
+ { "oidmap", cmd__oidmap },
{ "online-cpus", cmd__online_cpus },
{ "parse-options", cmd__parse_options },
{ "path-utils", cmd__path_utils },
diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
index 7e703f3038..f805bb39ae 100644
--- a/t/helper/test-tool.h
+++ b/t/helper/test-tool.h
@@ -9,6 +9,7 @@ int cmd__config(int argc, const char **argv);
int cmd__ctype(int argc, const char **argv);
int cmd__date(int argc, const char **argv);
int cmd__delta(int argc, const char **argv);
+int cmd__dir_iterator(int argc, const char **argv);
int cmd__drop_caches(int argc, const char **argv);
int cmd__dump_cache_tree(int argc, const char **argv);
int cmd__dump_fsmonitor(int argc, const char **argv);
@@ -25,6 +26,7 @@ int cmd__lazy_init_name_hash(int argc, const char **argv);
int cmd__match_trees(int argc, const char **argv);
int cmd__mergesort(int argc, const char **argv);
int cmd__mktemp(int argc, const char **argv);
+int cmd__oidmap(int argc, const char **argv);
int cmd__online_cpus(int argc, const char **argv);
int cmd__parse_options(int argc, const char **argv);
int cmd__path_utils(int argc, const char **argv);
diff --git a/t/lib-git-daemon.sh b/t/lib-git-daemon.sh
index 7b3407134e..fb8f887080 100644
--- a/t/lib-git-daemon.sh
+++ b/t/lib-git-daemon.sh
@@ -15,8 +15,7 @@
#
# test_done
-test_tristate GIT_TEST_GIT_DAEMON
-if test "$GIT_TEST_GIT_DAEMON" = false
+if ! git env--helper --type=bool --default=true --exit-code GIT_TEST_GIT_DAEMON
then
skip_all="git-daemon testing disabled (unset GIT_TEST_GIT_DAEMON to enable)"
test_done
@@ -24,7 +23,7 @@ fi
if test_have_prereq !PIPE
then
- test_skip_or_die $GIT_TEST_GIT_DAEMON "file system does not support FIFOs"
+ test_skip_or_die GIT_TEST_GIT_DAEMON "file system does not support FIFOs"
fi
test_set_port LIB_GIT_DAEMON_PORT
@@ -73,7 +72,7 @@ start_git_daemon() {
kill "$GIT_DAEMON_PID"
wait "$GIT_DAEMON_PID"
unset GIT_DAEMON_PID
- test_skip_or_die $GIT_TEST_GIT_DAEMON \
+ test_skip_or_die GIT_TEST_GIT_DAEMON \
"git daemon failed to start"
fi
}
diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh
index c1271d6863..5d4ae629e1 100644
--- a/t/lib-git-svn.sh
+++ b/t/lib-git-svn.sh
@@ -69,14 +69,12 @@ svn_cmd () {
maybe_start_httpd () {
loc=${1-svn}
- test_tristate GIT_SVN_TEST_HTTPD
- case $GIT_SVN_TEST_HTTPD in
- true)
+ if git env--helper --type=bool --default=false --exit-code GIT_TEST_HTTPD
+ then
. "$TEST_DIRECTORY"/lib-httpd.sh
LIB_HTTPD_SVN="$loc"
start_httpd
- ;;
- esac
+ fi
}
convert_to_rev_db () {
@@ -106,8 +104,7 @@ EOF
}
require_svnserve () {
- test_tristate GIT_TEST_SVNSERVE
- if ! test "$GIT_TEST_SVNSERVE" = true
+ if ! git env--helper --type=bool --default=false --exit-code GIT_TEST_SVNSERVE
then
skip_all='skipping svnserve test. (set $GIT_TEST_SVNSERVE to enable)'
test_done
diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh
index b3cc62bd36..0d985758c6 100644
--- a/t/lib-httpd.sh
+++ b/t/lib-httpd.sh
@@ -41,15 +41,14 @@ then
test_done
fi
-test_tristate GIT_TEST_HTTPD
-if test "$GIT_TEST_HTTPD" = false
+if ! git env--helper --type=bool --default=true --exit-code GIT_TEST_HTTPD
then
skip_all="Network testing disabled (unset GIT_TEST_HTTPD to enable)"
test_done
fi
if ! test_have_prereq NOT_ROOT; then
- test_skip_or_die $GIT_TEST_HTTPD \
+ test_skip_or_die GIT_TEST_HTTPD \
"Cannot run httpd tests as root"
fi
@@ -95,7 +94,7 @@ GIT_TRACE=$GIT_TRACE; export GIT_TRACE
if ! test -x "$LIB_HTTPD_PATH"
then
- test_skip_or_die $GIT_TEST_HTTPD "no web server found at '$LIB_HTTPD_PATH'"
+ test_skip_or_die GIT_TEST_HTTPD "no web server found at '$LIB_HTTPD_PATH'"
fi
HTTPD_VERSION=$($LIB_HTTPD_PATH -v | \
@@ -107,19 +106,19 @@ then
then
if ! test $HTTPD_VERSION -ge 2
then
- test_skip_or_die $GIT_TEST_HTTPD \
+ test_skip_or_die GIT_TEST_HTTPD \
"at least Apache version 2 is required"
fi
if ! test -d "$DEFAULT_HTTPD_MODULE_PATH"
then
- test_skip_or_die $GIT_TEST_HTTPD \
+ test_skip_or_die GIT_TEST_HTTPD \
"Apache module directory not found"
fi
LIB_HTTPD_MODULE_PATH="$DEFAULT_HTTPD_MODULE_PATH"
fi
else
- test_skip_or_die $GIT_TEST_HTTPD \
+ test_skip_or_die GIT_TEST_HTTPD \
"Could not identify web server at '$LIB_HTTPD_PATH'"
fi
@@ -184,7 +183,7 @@ start_httpd() {
if test $? -ne 0
then
cat "$HTTPD_ROOT_PATH"/error.log >&4 2>/dev/null
- test_skip_or_die $GIT_TEST_HTTPD "web server setup failed"
+ test_skip_or_die GIT_TEST_HTTPD "web server setup failed"
fi
}
diff --git a/t/lib-patch-mode.sh b/t/lib-patch-mode.sh
index 06c3c91762..cfd76bf987 100644
--- a/t/lib-patch-mode.sh
+++ b/t/lib-patch-mode.sh
@@ -2,28 +2,40 @@
. ./test-lib.sh
+# set_state <path> <worktree-content> <index-content>
+#
+# Prepare the content for path in worktree and the index as specified.
set_state () {
echo "$3" > "$1" &&
git add "$1" &&
echo "$2" > "$1"
}
+# save_state <path>
+#
+# Save index/worktree content of <path> in the files _worktree_<path>
+# and _index_<path>
save_state () {
noslash="$(echo "$1" | tr / _)" &&
cat "$1" > _worktree_"$noslash" &&
git show :"$1" > _index_"$noslash"
}
+# set_and_save_state <path> <worktree-content> <index-content>
set_and_save_state () {
set_state "$@" &&
save_state "$1"
}
+# verify_state <path> <expected-worktree-content> <expected-index-content>
verify_state () {
test "$(cat "$1")" = "$2" &&
test "$(git show :"$1")" = "$3"
}
+# verify_saved_state <path>
+#
+# Call verify_state with expected contents from the last save_state
verify_saved_state () {
noslash="$(echo "$1" | tr / _)" &&
verify_state "$1" "$(cat _worktree_"$noslash")" "$(cat _index_"$noslash")"
diff --git a/t/perf/p5600-clone-reference.sh b/t/perf/p5600-clone-reference.sh
new file mode 100755
index 0000000000..68fed66347
--- /dev/null
+++ b/t/perf/p5600-clone-reference.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+test_description='speed of clone --reference'
+. ./perf-lib.sh
+
+test_perf_default_repo
+
+test_expect_success 'create shareable repository' '
+ git clone --bare . shared.git
+'
+
+test_expect_success 'advance base repository' '
+ # Do not use test_commit here; its test_tick will
+ # use some ancient hard-coded date. The resulting clock
+ # skew will cause pack-objects to traverse in a very
+ # sub-optimal order, skewing the results.
+ echo content >new-file-that-does-not-exist &&
+ git add new-file-that-does-not-exist &&
+ git commit -m "new commit"
+'
+
+test_perf 'clone --reference' '
+ rm -rf dst.git &&
+ git clone --no-local --bare --reference shared.git . dst.git
+'
+
+test_done
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index 31de7e90f3..e89438e619 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 -z "$GIT_TEST_FAIL_PREREQS" -a $haveit$donthaveit != yesyes
+if test -z "$GIT_TEST_FAIL_PREREQS_INTERNAL" -a $haveit$donthaveit != yesyes
then
say "bug in test framework: prerequisite tags do not work reliably"
exit 1
@@ -747,7 +747,7 @@ donthaveiteither=yes
test_expect_success DONTHAVEIT,HAVEIT 'unmet prerequisites causes test to be skipped' '
donthaveiteither=no
'
-if test -z "$GIT_TEST_FAIL_PREREQS" -a $haveit$donthaveit$donthaveiteither != yesyesyes
+if test -z "$GIT_TEST_FAIL_PREREQS_INTERNAL" -a $haveit$donthaveit$donthaveiteither != yesyesyes
then
say "bug in test framework: multiple prerequisite tags do not work reliably"
exit 1
@@ -763,7 +763,7 @@ test_expect_success !LAZY_TRUE 'missing lazy prereqs skip tests' '
donthavetrue=no
'
-if test -z "$GIT_TEST_FAIL_PREREQS" -a "$havetrue$donthavetrue" != yesyes
+if test -z "$GIT_TEST_FAIL_PREREQS_INTERNAL" -a "$havetrue$donthavetrue" != yesyes
then
say 'bug in test framework: lazy prerequisites do not work'
exit 1
@@ -779,7 +779,7 @@ test_expect_success LAZY_FALSE 'missing negative lazy prereqs will skip' '
havefalse=no
'
-if test -z "$GIT_TEST_FAIL_PREREQS" -a "$nothavefalse$havefalse" != yesyes
+if test -z "$GIT_TEST_FAIL_PREREQS_INTERNAL" -a "$nothavefalse$havefalse" != yesyes
then
say 'bug in test framework: negative lazy prerequisites do not work'
exit 1
@@ -790,7 +790,7 @@ test_expect_success 'tests clean up after themselves' '
test_when_finished clean=yes
'
-if test -z "$GIT_TEST_FAIL_PREREQS" -a $clean != yes
+if test -z "$GIT_TEST_FAIL_PREREQS_INTERNAL" -a $clean != yes
then
say "bug in test framework: basic cleanup command does not work reliably"
exit 1
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 0276d14a0b..26f8206326 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -311,8 +311,8 @@ test_expect_success 'init prefers command line to GIT_DIR' '
test_expect_success 'init with separate gitdir' '
rm -rf newdir &&
git init --separate-git-dir realgitdir newdir &&
- echo "gitdir: $(pwd)/realgitdir" >expected &&
- test_cmp expected newdir/.git &&
+ newdir_git="$(cat newdir/.git)" &&
+ test_cmp_fspath "$(pwd)/realgitdir" "${newdir_git#gitdir: }" &&
test_path_is_dir realgitdir/refs
'
@@ -361,12 +361,9 @@ test_expect_success 're-init on .git file' '
'
test_expect_success 're-init to update git link' '
- (
- cd newdir &&
- git init --separate-git-dir ../surrealgitdir
- ) &&
- echo "gitdir: $(pwd)/surrealgitdir" >expected &&
- test_cmp expected newdir/.git &&
+ git -C newdir init --separate-git-dir ../surrealgitdir &&
+ newdir_git="$(cat newdir/.git)" &&
+ test_cmp_fspath "$(pwd)/surrealgitdir" "${newdir_git#gitdir: }" &&
test_path_is_dir surrealgitdir/refs &&
test_path_is_missing realgitdir/refs
'
@@ -374,12 +371,9 @@ test_expect_success 're-init to update git link' '
test_expect_success 're-init to move gitdir' '
rm -rf newdir realgitdir surrealgitdir &&
git init newdir &&
- (
- cd newdir &&
- git init --separate-git-dir ../realgitdir
- ) &&
- echo "gitdir: $(pwd)/realgitdir" >expected &&
- test_cmp expected newdir/.git &&
+ git -C newdir init --separate-git-dir ../realgitdir &&
+ newdir_git="$(cat newdir/.git)" &&
+ test_cmp_fspath "$(pwd)/realgitdir" "${newdir_git#gitdir: }" &&
test_path_is_dir realgitdir/refs
'
@@ -473,8 +467,8 @@ test_expect_success MINGW 'redirect std handles' '
GIT_REDIRECT_STDOUT=output.txt \
GIT_REDIRECT_STDERR="2>&1" \
git rev-parse --git-dir --verify refs/invalid &&
- printf ".git\nfatal: Needed a single revision\n" >expect &&
- test_cmp expect output.txt
+ grep "^\\.git\$" output.txt &&
+ grep "Needed a single revision" output.txt
'
test_done
diff --git a/t/t0007-git-var.sh b/t/t0007-git-var.sh
index 5868a87352..1f600e2cae 100755
--- a/t/t0007-git-var.sh
+++ b/t/t0007-git-var.sh
@@ -17,7 +17,7 @@ test_expect_success 'get GIT_COMMITTER_IDENT' '
test_cmp expect actual
'
-test_expect_success !AUTOIDENT 'requested identites are strict' '
+test_expect_success !FAIL_PREREQS,!AUTOIDENT 'requested identites are strict' '
(
sane_unset GIT_COMMITTER_NAME &&
sane_unset GIT_COMMITTER_EMAIL &&
diff --git a/t/t0011-hashmap.sh b/t/t0011-hashmap.sh
index 3f1f505e89..9c96b3e3b1 100755
--- a/t/t0011-hashmap.sh
+++ b/t/t0011-hashmap.sh
@@ -9,15 +9,6 @@ test_hashmap() {
test_cmp expect actual
}
-test_expect_success 'hash functions' '
-
-test_hashmap "hash key1" "2215982743 2215982743 116372151 116372151" &&
-test_hashmap "hash key2" "2215982740 2215982740 116372148 116372148" &&
-test_hashmap "hash fooBarFrotz" "1383912807 1383912807 3189766727 3189766727" &&
-test_hashmap "hash foobarfrotz" "2862305959 2862305959 3189766727 3189766727"
-
-'
-
test_expect_success 'put' '
test_hashmap "put key1 value1
diff --git a/t/t0016-oidmap.sh b/t/t0016-oidmap.sh
new file mode 100755
index 0000000000..bbe719e950
--- /dev/null
+++ b/t/t0016-oidmap.sh
@@ -0,0 +1,102 @@
+#!/bin/sh
+
+test_description='test oidmap'
+. ./test-lib.sh
+
+# This purposefully is very similar to t0011-hashmap.sh
+
+test_oidmap () {
+ echo "$1" | test-tool oidmap $3 >actual &&
+ echo "$2" >expect &&
+ test_cmp expect actual
+}
+
+
+test_expect_success 'setup' '
+
+ test_commit one &&
+ test_commit two &&
+ test_commit three &&
+ test_commit four
+
+'
+
+test_expect_success 'put' '
+
+test_oidmap "put one 1
+put two 2
+put invalidOid 4
+put three 3" "NULL
+NULL
+Unknown oid: invalidOid
+NULL"
+
+'
+
+test_expect_success 'replace' '
+
+test_oidmap "put one 1
+put two 2
+put three 3
+put invalidOid 4
+put two deux
+put one un" "NULL
+NULL
+NULL
+Unknown oid: invalidOid
+2
+1"
+
+'
+
+test_expect_success 'get' '
+
+test_oidmap "put one 1
+put two 2
+put three 3
+get two
+get four
+get invalidOid
+get one" "NULL
+NULL
+NULL
+2
+NULL
+Unknown oid: invalidOid
+1"
+
+'
+
+test_expect_success 'remove' '
+
+test_oidmap "put one 1
+put two 2
+put three 3
+remove one
+remove two
+remove invalidOid
+remove four" "NULL
+NULL
+NULL
+1
+2
+Unknown oid: invalidOid
+NULL"
+
+'
+
+test_expect_success 'iterate' '
+
+test_oidmap "put one 1
+put two 2
+put three 3
+iterate" "NULL
+NULL
+NULL
+$(git rev-parse two) 2
+$(git rev-parse one) 1
+$(git rev-parse three) 3"
+
+'
+
+test_done
diff --git a/t/t0017-env-helper.sh b/t/t0017-env-helper.sh
new file mode 100755
index 0000000000..c1ecf6aeac
--- /dev/null
+++ b/t/t0017-env-helper.sh
@@ -0,0 +1,99 @@
+#!/bin/sh
+
+test_description='test env--helper'
+
+. ./test-lib.sh
+
+
+test_expect_success 'env--helper usage' '
+ test_must_fail git env--helper &&
+ test_must_fail git env--helper --type=bool &&
+ test_must_fail git env--helper --type=ulong &&
+ test_must_fail git env--helper --type=bool &&
+ test_must_fail git env--helper --type=bool --default &&
+ test_must_fail git env--helper --type=bool --default= &&
+ test_must_fail git env--helper --defaultxyz
+'
+
+test_expect_success 'env--helper bad default values' '
+ test_must_fail git env--helper --type=bool --default=1xyz MISSING &&
+ test_must_fail git env--helper --type=ulong --default=1xyz MISSING
+'
+
+test_expect_success 'env--helper --type=bool' '
+ # Test various --default bool values
+ echo true >expected &&
+ git env--helper --type=bool --default=1 MISSING >actual &&
+ test_cmp expected actual &&
+ git env--helper --type=bool --default=yes MISSING >actual &&
+ test_cmp expected actual &&
+ git env--helper --type=bool --default=true MISSING >actual &&
+ test_cmp expected actual &&
+ echo false >expected &&
+ test_must_fail git env--helper --type=bool --default=0 MISSING >actual &&
+ test_cmp expected actual &&
+ test_must_fail git env--helper --type=bool --default=no MISSING >actual &&
+ test_cmp expected actual &&
+ test_must_fail git env--helper --type=bool --default=false MISSING >actual &&
+ test_cmp expected actual &&
+
+ # No output with --exit-code
+ git env--helper --type=bool --default=true --exit-code MISSING >actual.out 2>actual.err &&
+ test_must_be_empty actual.out &&
+ test_must_be_empty actual.err &&
+ test_must_fail git env--helper --type=bool --default=false --exit-code MISSING >actual.out 2>actual.err &&
+ test_must_be_empty actual.out &&
+ test_must_be_empty actual.err &&
+
+ # Existing variable
+ EXISTS=true git env--helper --type=bool --default=false --exit-code EXISTS >actual.out 2>actual.err &&
+ test_must_be_empty actual.out &&
+ test_must_be_empty actual.err &&
+ test_must_fail \
+ env EXISTS=false \
+ git env--helper --type=bool --default=true --exit-code EXISTS >actual.out 2>actual.err &&
+ test_must_be_empty actual.out &&
+ test_must_be_empty actual.err
+'
+
+test_expect_success 'env--helper --type=ulong' '
+ echo 1234567890 >expected &&
+ git env--helper --type=ulong --default=1234567890 MISSING >actual.out 2>actual.err &&
+ test_cmp expected actual.out &&
+ test_must_be_empty actual.err &&
+
+ echo 0 >expected &&
+ test_must_fail git env--helper --type=ulong --default=0 MISSING >actual &&
+ test_cmp expected actual &&
+
+ git env--helper --type=ulong --default=1234567890 --exit-code MISSING >actual.out 2>actual.err &&
+ test_must_be_empty actual.out &&
+ test_must_be_empty actual.err &&
+
+ EXISTS=1234567890 git env--helper --type=ulong --default=0 EXISTS --exit-code >actual.out 2>actual.err &&
+ test_must_be_empty actual.out &&
+ test_must_be_empty actual.err &&
+
+ echo 1234567890 >expected &&
+ EXISTS=1234567890 git env--helper --type=ulong --default=0 EXISTS >actual.out 2>actual.err &&
+ test_cmp expected actual.out &&
+ test_must_be_empty actual.err
+'
+
+test_expect_success 'env--helper reads config thanks to trace2' '
+ mkdir home &&
+ git config -f home/.gitconfig include.path cycle &&
+ git config -f home/cycle include.path .gitconfig &&
+
+ test_must_fail \
+ env HOME="$(pwd)/home" GIT_TEST_GETTEXT_POISON=false \
+ git config -l 2>err &&
+ grep "exceeded maximum include depth" err &&
+
+ test_must_fail \
+ env HOME="$(pwd)/home" GIT_TEST_GETTEXT_POISON=true \
+ git -C cycle env--helper --type=bool --default=0 --exit-code GIT_TEST_GETTEXT_POISON 2>err &&
+ grep "# GETTEXT POISON #" err
+'
+
+test_done
diff --git a/t/t0061-run-command.sh b/t/t0061-run-command.sh
index ebc49561ac..015fac8b5d 100755
--- a/t/t0061-run-command.sh
+++ b/t/t0061-run-command.sh
@@ -210,4 +210,10 @@ test_expect_success MINGW 'verify curlies are quoted properly' '
test_cmp expect actual
'
+test_expect_success MINGW 'can spawn with argv[0] containing spaces' '
+ cp "$GIT_BUILD_DIR/t/helper/test-fake-ssh$X" ./ &&
+ test_must_fail "$PWD/test-fake-ssh$X" 2>err &&
+ grep TRASH_DIRECTORY err
+'
+
test_done
diff --git a/t/t0066-dir-iterator.sh b/t/t0066-dir-iterator.sh
new file mode 100755
index 0000000000..9354d3f1ed
--- /dev/null
+++ b/t/t0066-dir-iterator.sh
@@ -0,0 +1,148 @@
+#!/bin/sh
+
+test_description='Test the dir-iterator functionality'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ mkdir -p dir &&
+ mkdir -p dir/a/b/c/ &&
+ >dir/b &&
+ >dir/c &&
+ mkdir -p dir/d/e/d/ &&
+ >dir/a/b/c/d &&
+ >dir/a/e &&
+ >dir/d/e/d/a &&
+
+ mkdir -p dir2/a/b/c/ &&
+ >dir2/a/b/c/d
+'
+
+test_expect_success 'dir-iterator should iterate through all files' '
+ cat >expected-iteration-sorted-output <<-EOF &&
+ [d] (a) [a] ./dir/a
+ [d] (a/b) [b] ./dir/a/b
+ [d] (a/b/c) [c] ./dir/a/b/c
+ [d] (d) [d] ./dir/d
+ [d] (d/e) [e] ./dir/d/e
+ [d] (d/e/d) [d] ./dir/d/e/d
+ [f] (a/b/c/d) [d] ./dir/a/b/c/d
+ [f] (a/e) [e] ./dir/a/e
+ [f] (b) [b] ./dir/b
+ [f] (c) [c] ./dir/c
+ [f] (d/e/d/a) [a] ./dir/d/e/d/a
+ EOF
+
+ test-tool dir-iterator ./dir >out &&
+ sort out >./actual-iteration-sorted-output &&
+
+ test_cmp expected-iteration-sorted-output actual-iteration-sorted-output
+'
+
+test_expect_success 'dir-iterator should list files in the correct order' '
+ cat >expected-pre-order-output <<-EOF &&
+ [d] (a) [a] ./dir2/a
+ [d] (a/b) [b] ./dir2/a/b
+ [d] (a/b/c) [c] ./dir2/a/b/c
+ [f] (a/b/c/d) [d] ./dir2/a/b/c/d
+ EOF
+
+ test-tool dir-iterator ./dir2 >actual-pre-order-output &&
+
+ test_cmp expected-pre-order-output actual-pre-order-output
+'
+
+test_expect_success 'begin should fail upon inexistent paths' '
+ test_must_fail test-tool dir-iterator ./inexistent-path \
+ >actual-inexistent-path-output &&
+ echo "dir_iterator_begin failure: 2" >expected-inexistent-path-output &&
+ test_cmp expected-inexistent-path-output actual-inexistent-path-output
+'
+
+test_expect_success 'begin should fail upon non directory paths' '
+ test_must_fail test-tool dir-iterator ./dir/b >actual-non-dir-output &&
+ echo "dir_iterator_begin failure: 20" >expected-non-dir-output &&
+ test_cmp expected-non-dir-output actual-non-dir-output
+'
+
+test_expect_success POSIXPERM,SANITY 'advance should not fail on errors by default' '
+ cat >expected-no-permissions-output <<-EOF &&
+ [d] (a) [a] ./dir3/a
+ EOF
+
+ mkdir -p dir3/a &&
+ >dir3/a/b &&
+ chmod 0 dir3/a &&
+
+ test-tool dir-iterator ./dir3 >actual-no-permissions-output &&
+ test_cmp expected-no-permissions-output actual-no-permissions-output &&
+ chmod 755 dir3/a &&
+ rm -rf dir3
+'
+
+test_expect_success POSIXPERM,SANITY 'advance should fail on errors, w/ pedantic flag' '
+ cat >expected-no-permissions-pedantic-output <<-EOF &&
+ [d] (a) [a] ./dir3/a
+ dir_iterator_advance failure
+ EOF
+
+ mkdir -p dir3/a &&
+ >dir3/a/b &&
+ chmod 0 dir3/a &&
+
+ test_must_fail test-tool dir-iterator --pedantic ./dir3 \
+ >actual-no-permissions-pedantic-output &&
+ test_cmp expected-no-permissions-pedantic-output \
+ actual-no-permissions-pedantic-output &&
+ chmod 755 dir3/a &&
+ rm -rf dir3
+'
+
+test_expect_success SYMLINKS 'setup dirs with symlinks' '
+ mkdir -p dir4/a &&
+ mkdir -p dir4/b/c &&
+ >dir4/a/d &&
+ ln -s d dir4/a/e &&
+ ln -s ../b dir4/a/f &&
+
+ mkdir -p dir5/a/b &&
+ mkdir -p dir5/a/c &&
+ ln -s ../c dir5/a/b/d &&
+ ln -s ../ dir5/a/b/e &&
+ ln -s ../../ dir5/a/b/f
+'
+
+test_expect_success SYMLINKS 'dir-iterator should not follow symlinks by default' '
+ cat >expected-no-follow-sorted-output <<-EOF &&
+ [d] (a) [a] ./dir4/a
+ [d] (b) [b] ./dir4/b
+ [d] (b/c) [c] ./dir4/b/c
+ [f] (a/d) [d] ./dir4/a/d
+ [s] (a/e) [e] ./dir4/a/e
+ [s] (a/f) [f] ./dir4/a/f
+ EOF
+
+ test-tool dir-iterator ./dir4 >out &&
+ sort out >actual-no-follow-sorted-output &&
+
+ test_cmp expected-no-follow-sorted-output actual-no-follow-sorted-output
+'
+
+test_expect_success SYMLINKS 'dir-iterator should follow symlinks w/ follow flag' '
+ cat >expected-follow-sorted-output <<-EOF &&
+ [d] (a) [a] ./dir4/a
+ [d] (a/f) [f] ./dir4/a/f
+ [d] (a/f/c) [c] ./dir4/a/f/c
+ [d] (b) [b] ./dir4/b
+ [d] (b/c) [c] ./dir4/b/c
+ [f] (a/d) [d] ./dir4/a/d
+ [f] (a/e) [e] ./dir4/a/e
+ EOF
+
+ test-tool dir-iterator --follow-symlinks ./dir4 >out &&
+ sort out >actual-follow-sorted-output &&
+
+ test_cmp expected-follow-sorted-output actual-follow-sorted-output
+'
+
+test_done
diff --git a/t/t0205-gettext-poison.sh b/t/t0205-gettext-poison.sh
index a06269f38a..f9fa16ad83 100755
--- a/t/t0205-gettext-poison.sh
+++ b/t/t0205-gettext-poison.sh
@@ -5,7 +5,7 @@
test_description='Gettext Shell poison'
-GIT_TEST_GETTEXT_POISON=YesPlease
+GIT_TEST_GETTEXT_POISON=true
export GIT_TEST_GETTEXT_POISON
. ./lib-gettext.sh
@@ -31,4 +31,9 @@ test_expect_success 'eval_gettext: our eval_gettext() fallback has poison semant
test_cmp expect actual
'
+test_expect_success "gettext: invalid GIT_TEST_GETTEXT_POISON value doesn't infinitely loop" "
+ test_must_fail env GIT_TEST_GETTEXT_POISON=xyz git version 2>error &&
+ grep \"fatal: bad numeric config value 'xyz' for 'GIT_TEST_GETTEXT_POISON': invalid unit\" error
+"
+
test_done
diff --git a/t/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/t1305-config-include.sh b/t/t1305-config-include.sh
index 579a86b7f8..d20b4d150d 100755
--- a/t/t1305-config-include.sh
+++ b/t/t1305-config-include.sh
@@ -309,21 +309,53 @@ test_expect_success SYMLINKS 'conditional include, gitdir matching symlink, icas
)
'
+test_expect_success 'conditional include, onbranch' '
+ echo "[includeIf \"onbranch:foo-branch\"]path=bar9" >>.git/config &&
+ echo "[test]nine=9" >.git/bar9 &&
+ git checkout -b master &&
+ test_must_fail git config test.nine &&
+ git checkout -b foo-branch &&
+ echo 9 >expect &&
+ git config test.nine >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'conditional include, onbranch, wildcard' '
+ echo "[includeIf \"onbranch:?oo-*/**\"]path=bar10" >>.git/config &&
+ echo "[test]ten=10" >.git/bar10 &&
+ git checkout -b not-foo-branch/a &&
+ test_must_fail git config test.ten &&
+
+ echo 10 >expect &&
+ git checkout -b foo-branch/a/b/c &&
+ git config test.ten >actual &&
+ test_cmp expect actual &&
+
+ git checkout -b moo-bar/a &&
+ git config test.ten >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'conditional include, onbranch, implicit /** for /' '
+ echo "[includeIf \"onbranch:foo-dir/\"]path=bar11" >>.git/config &&
+ echo "[test]eleven=11" >.git/bar11 &&
+ git checkout -b not-foo-dir/a &&
+ test_must_fail git config test.eleven &&
+
+ echo 11 >expect &&
+ git checkout -b foo-dir/a/b/c &&
+ git config test.eleven >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'include cycles are detected' '
- cat >.gitconfig <<-\EOF &&
- [test]value = gitconfig
- [include]path = cycle
- EOF
- cat >cycle <<-\EOF &&
- [test]value = cycle
- [include]path = .gitconfig
- EOF
- cat >expect <<-\EOF &&
- gitconfig
- cycle
- EOF
- test_must_fail git config --get-all test.value 2>stderr &&
- test_i18ngrep "exceeded maximum include depth" stderr
+ git init --bare cycle &&
+ git -C cycle config include.path cycle &&
+ git config -f cycle/cycle include.path config &&
+ test_must_fail \
+ env GIT_TEST_GETTEXT_POISON=false \
+ git -C cycle config --get-all test.value 2>stderr &&
+ grep "exceeded maximum include depth" stderr
'
test_done
diff --git a/t/t2014-switch.sh b/t/t2014-checkout-switch.sh
index ccfb147113..ccfb147113 100755
--- a/t/t2014-switch.sh
+++ b/t/t2014-checkout-switch.sh
diff --git a/t/t2020-checkout-detach.sh b/t/t2020-checkout-detach.sh
index 1fa670625c..b748db9946 100755
--- a/t/t2020-checkout-detach.sh
+++ b/t/t2020-checkout-detach.sh
@@ -195,16 +195,22 @@ test_expect_success 'describe_detached_head prints no SHA-1 ellipsis when not as
# The first detach operation is more chatty than the following ones.
cat >1st_detach <<-EOF &&
- Note: checking out 'HEAD^'.
+ Note: switching to 'HEAD^'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
- state without impacting any branches by performing another checkout.
+ state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
- do so (now or later) by using -b with the checkout command again. Example:
+ do so (now or later) by using -c with the switch command. Example:
- git checkout -b <new-branch-name>
+ git switch -c <new-branch-name>
+
+ Or undo this operation with:
+
+ git switch -
+
+ Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at \$commit three
EOF
@@ -271,16 +277,22 @@ test_expect_success 'describe_detached_head does print SHA-1 ellipsis when asked
# The first detach operation is more chatty than the following ones.
cat >1st_detach <<-EOF &&
- Note: checking out 'HEAD^'.
+ Note: switching to 'HEAD^'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
- state without impacting any branches by performing another checkout.
+ state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
- do so (now or later) by using -b with the checkout command again. Example:
+ do so (now or later) by using -c with the switch command. Example:
+
+ git switch -c <new-branch-name>
+
+ Or undo this operation with:
+
+ git switch -
- git checkout -b <new-branch-name>
+ Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at \$commit... three
EOF
diff --git a/t/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/t3200-branch.sh b/t/t3200-branch.sh
index e9d7084d19..411a70b0ce 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -206,18 +206,22 @@ test_expect_success 'git branch -M baz bam should succeed when baz is checked ou
git worktree add -f bazdir2 baz &&
git branch -M baz bam &&
test $(git -C bazdir rev-parse --abbrev-ref HEAD) = bam &&
- test $(git -C bazdir2 rev-parse --abbrev-ref HEAD) = bam
+ test $(git -C bazdir2 rev-parse --abbrev-ref HEAD) = bam &&
+ rm -r bazdir bazdir2 &&
+ git worktree prune
'
test_expect_success 'git branch -M baz bam should succeed within a worktree in which baz is checked out' '
git checkout -b baz &&
- git worktree add -f bazdir3 baz &&
+ git worktree add -f bazdir baz &&
(
- cd bazdir3 &&
+ cd bazdir &&
git branch -M baz bam &&
test $(git rev-parse --abbrev-ref HEAD) = bam
) &&
- test $(git rev-parse --abbrev-ref HEAD) = bam
+ test $(git rev-parse --abbrev-ref HEAD) = bam &&
+ rm -r bazdir &&
+ git worktree prune
'
test_expect_success 'git branch -M master should work when master is checked out' '
@@ -804,7 +808,9 @@ test_expect_success 'test deleting branch without config' '
test_expect_success 'deleting currently checked out branch fails' '
git worktree add -b my7 my7 &&
test_must_fail git -C my7 branch -d my7 &&
- test_must_fail git branch -d my7
+ test_must_fail git branch -d my7 &&
+ rm -r my7 &&
+ git worktree prune
'
test_expect_success 'test --track without .fetch entries' '
diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh
index be55148930..71818b90f0 100755
--- a/t/t3203-branch-output.sh
+++ b/t/t3203-branch-output.sh
@@ -136,10 +136,13 @@ test_expect_success 'git branch `--show-current` works properly with worktrees'
branch-two
EOF
git checkout branch-one &&
- git worktree add worktree branch-two &&
+ test_when_finished "
+ git worktree remove worktree_dir
+ " &&
+ git worktree add worktree_dir branch-two &&
{
git branch --show-current &&
- git -C worktree branch --show-current
+ git -C worktree_dir branch --show-current
} >actual &&
test_cmp expect actual
'
@@ -284,6 +287,24 @@ test_expect_success 'git branch --format option' '
test_i18ncmp expect actual
'
+test_expect_success 'worktree colors correct' '
+ cat >expect <<-EOF &&
+ * <GREEN>(HEAD detached from fromtag)<RESET>
+ ambiguous<RESET>
+ branch-one<RESET>
+ + <CYAN>branch-two<RESET>
+ master<RESET>
+ ref-to-branch<RESET> -> branch-one
+ ref-to-remote<RESET> -> origin/branch-one
+ EOF
+ git worktree add worktree_dir branch-two &&
+ git branch --color >actual.raw &&
+ rm -r worktree_dir &&
+ git worktree prune &&
+ test_decode_color <actual.raw >actual &&
+ test_i18ncmp expect actual
+'
+
test_expect_success "set up color tests" '
echo "<RED>master<RESET>" >expect.color &&
echo "master" >expect.bare &&
@@ -308,4 +329,23 @@ test_expect_success '--color overrides auto-color' '
test_cmp expect.color actual
'
+test_expect_success 'verbose output lists worktree path' '
+ one=$(git rev-parse --short HEAD) &&
+ two=$(git rev-parse --short master) &&
+ cat >expect <<-EOF &&
+ * (HEAD detached from fromtag) $one one
+ ambiguous $one one
+ branch-one $two two
+ + branch-two $one ($(pwd)/worktree_dir) one
+ master $two two
+ ref-to-branch $two two
+ ref-to-remote $two two
+ EOF
+ git worktree add worktree_dir branch-two &&
+ git branch -vv >actual &&
+ rm -r worktree_dir &&
+ git worktree prune &&
+ test_i18ncmp expect actual
+'
+
test_done
diff --git a/t/t3206-range-diff.sh b/t/t3206-range-diff.sh
index 048feaf6dd..ec548654ce 100755
--- a/t/t3206-range-diff.sh
+++ b/t/t3206-range-diff.sh
@@ -99,7 +99,7 @@ test_expect_success 'changed commit' '
1: 4de457d = 1: a4b3333 s/5/A/
2: fccce22 = 2: f51d370 s/4/A/
3: 147e64e ! 3: 0559556 s/11/B/
- @@ -10,7 +10,7 @@
+ @@ file: A
9
10
-11
@@ -109,8 +109,8 @@ test_expect_success 'changed commit' '
13
14
4: a63e992 ! 4: d966c5c s/12/B/
- @@ -8,7 +8,7 @@
- @@
+ @@ file
+ @@ file: A
9
10
- B
@@ -158,7 +158,7 @@ test_expect_success 'changed commit with sm config' '
1: 4de457d = 1: a4b3333 s/5/A/
2: fccce22 = 2: f51d370 s/4/A/
3: 147e64e ! 3: 0559556 s/11/B/
- @@ -10,7 +10,7 @@
+ @@ file: A
9
10
-11
@@ -168,8 +168,8 @@ test_expect_success 'changed commit with sm config' '
13
14
4: a63e992 ! 4: d966c5c s/12/B/
- @@ -8,7 +8,7 @@
- @@
+ @@ file
+ @@ file: A
9
10
- B
@@ -181,6 +181,92 @@ test_expect_success 'changed commit with sm config' '
test_cmp expected actual
'
+test_expect_success 'renamed file' '
+ git range-diff --no-color --submodule=log topic...renamed-file >actual &&
+ sed s/Z/\ /g >expected <<-EOF &&
+ 1: 4de457d = 1: f258d75 s/5/A/
+ 2: fccce22 ! 2: 017b62d s/4/A/
+ @@ Metadata
+ ZAuthor: Thomas Rast <trast@inf.ethz.ch>
+ Z
+ Z ## Commit message ##
+ - s/4/A/
+ + s/4/A/ + rename file
+ Z
+ - ## file ##
+ + ## file => renamed-file ##
+ Z@@
+ Z 1
+ Z 2
+ 3: 147e64e ! 3: 3ce7af6 s/11/B/
+ @@ Metadata
+ Z ## Commit message ##
+ Z s/11/B/
+ Z
+ - ## file ##
+ -@@ file: A
+ + ## renamed-file ##
+ +@@ renamed-file: A
+ Z 8
+ Z 9
+ Z 10
+ 4: a63e992 ! 4: 1e6226b s/12/B/
+ @@ Metadata
+ Z ## Commit message ##
+ Z s/12/B/
+ Z
+ - ## file ##
+ -@@ file: A
+ + ## renamed-file ##
+ +@@ renamed-file: A
+ Z 9
+ Z 10
+ Z B
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'file added and later removed' '
+ git range-diff --no-color --submodule=log topic...added-removed >actual &&
+ sed s/Z/\ /g >expected <<-EOF &&
+ 1: 4de457d = 1: 096b1ba s/5/A/
+ 2: fccce22 ! 2: d92e698 s/4/A/
+ @@ Metadata
+ ZAuthor: Thomas Rast <trast@inf.ethz.ch>
+ Z
+ Z ## Commit message ##
+ - s/4/A/
+ + s/4/A/ + new-file
+ Z
+ Z ## file ##
+ Z@@
+ @@ file
+ Z A
+ Z 6
+ Z 7
+ +
+ + ## new-file (new) ##
+ 3: 147e64e ! 3: 9a1db4d s/11/B/
+ @@ Metadata
+ ZAuthor: Thomas Rast <trast@inf.ethz.ch>
+ Z
+ Z ## Commit message ##
+ - s/11/B/
+ + s/11/B/ + remove file
+ Z
+ Z ## file ##
+ Z@@ file: A
+ @@ file: A
+ Z 12
+ Z 13
+ Z 14
+ +
+ + ## new-file (deleted) ##
+ 4: a63e992 = 4: fea3b5c s/12/B/
+ EOF
+ test_cmp expected actual
+'
+
test_expect_success 'no commits on one side' '
git commit --amend -m "new message" &&
git range-diff master HEAD@{1} HEAD
@@ -191,15 +277,15 @@ test_expect_success 'changed message' '
sed s/Z/\ /g >expected <<-EOF &&
1: 4de457d = 1: f686024 s/5/A/
2: fccce22 ! 2: 4ab067d s/4/A/
- @@ -2,6 +2,8 @@
- Z
+ @@ Metadata
+ Z ## Commit message ##
Z s/4/A/
Z
+ Also a silly comment here!
+
- Z diff --git a/file b/file
- Z --- a/file
- Z +++ b/file
+ Z ## file ##
+ Z@@
+ Z 1
3: 147e64e = 3: b9cb956 s/11/B/
4: a63e992 = 4: 8add5f1 s/12/B/
EOF
@@ -210,17 +296,17 @@ test_expect_success 'dual-coloring' '
sed -e "s|^:||" >expect <<-\EOF &&
:<YELLOW>1: a4b3333 = 1: f686024 s/5/A/<RESET>
:<RED>2: f51d370 <RESET><YELLOW>!<RESET><GREEN> 2: 4ab067d<RESET><YELLOW> s/4/A/<RESET>
- : <REVERSE><CYAN>@@ -2,6 +2,8 @@<RESET>
- : <RESET>
+ : <REVERSE><CYAN>@@<RESET> <RESET>Metadata<RESET>
+ : ## Commit message ##<RESET>
: s/4/A/<RESET>
: <RESET>
: <REVERSE><GREEN>+<RESET><BOLD> Also a silly comment here!<RESET>
: <REVERSE><GREEN>+<RESET>
- : diff --git a/file b/file<RESET>
- : --- a/file<RESET>
- : +++ b/file<RESET>
+ : ## file ##<RESET>
+ : <CYAN> @@<RESET>
+ : 1<RESET>
:<RED>3: 0559556 <RESET><YELLOW>!<RESET><GREEN> 3: b9cb956<RESET><YELLOW> s/11/B/<RESET>
- : <REVERSE><CYAN>@@ -10,7 +10,7 @@<RESET>
+ : <REVERSE><CYAN>@@<RESET> <RESET>file: A<RESET>
: 9<RESET>
: 10<RESET>
: <RED> -11<RESET>
@@ -230,8 +316,8 @@ test_expect_success 'dual-coloring' '
: 13<RESET>
: 14<RESET>
:<RED>4: d966c5c <RESET><YELLOW>!<RESET><GREEN> 4: 8add5f1<RESET><YELLOW> s/12/B/<RESET>
- : <REVERSE><CYAN>@@ -8,7 +8,7 @@<RESET>
- : <CYAN> @@<RESET>
+ : <REVERSE><CYAN>@@<RESET> <RESET>file<RESET>
+ : <CYAN> @@ file: A<RESET>
: 9<RESET>
: 10<RESET>
: <REVERSE><RED>-<RESET><FAINT> BB<RESET>
diff --git a/t/t3206/history.export b/t/t3206/history.export
index b8ffff0940..7bb3814962 100644
--- a/t/t3206/history.export
+++ b/t/t3206/history.export
@@ -22,8 +22,8 @@ data 51
19
20
-reset refs/heads/removed
-commit refs/heads/removed
+reset refs/heads/renamed-file
+commit refs/heads/renamed-file
mark :2
author Thomas Rast <trast@inf.ethz.ch> 1374424921 +0200
committer Thomas Rast <trast@inf.ethz.ch> 1374484724 +0200
@@ -599,6 +599,82 @@ s/12/B/
from :46
M 100644 :28 file
-reset refs/heads/removed
-from :47
+commit refs/heads/added-removed
+mark :48
+author Thomas Rast <trast@inf.ethz.ch> 1374485014 +0200
+committer Thomas Gummerer <t.gummerer@gmail.com> 1556574151 +0100
+data 7
+s/5/A/
+from :2
+M 100644 :3 file
+
+blob
+mark :49
+data 0
+
+commit refs/heads/added-removed
+mark :50
+author Thomas Rast <trast@inf.ethz.ch> 1374485024 +0200
+committer Thomas Gummerer <t.gummerer@gmail.com> 1556574177 +0100
+data 18
+s/4/A/ + new-file
+from :48
+M 100644 :5 file
+M 100644 :49 new-file
+
+commit refs/heads/added-removed
+mark :51
+author Thomas Rast <trast@inf.ethz.ch> 1374485036 +0200
+committer Thomas Gummerer <t.gummerer@gmail.com> 1556574177 +0100
+data 22
+s/11/B/ + remove file
+from :50
+M 100644 :7 file
+D new-file
+
+commit refs/heads/added-removed
+mark :52
+author Thomas Rast <trast@inf.ethz.ch> 1374485044 +0200
+committer Thomas Gummerer <t.gummerer@gmail.com> 1556574177 +0100
+data 8
+s/12/B/
+from :51
+M 100644 :9 file
+
+commit refs/heads/renamed-file
+mark :53
+author Thomas Rast <trast@inf.ethz.ch> 1374485014 +0200
+committer Thomas Gummerer <t.gummerer@gmail.com> 1556574309 +0100
+data 7
+s/5/A/
+from :2
+M 100644 :3 file
+
+commit refs/heads/renamed-file
+mark :54
+author Thomas Rast <trast@inf.ethz.ch> 1374485024 +0200
+committer Thomas Gummerer <t.gummerer@gmail.com> 1556574312 +0100
+data 21
+s/4/A/ + rename file
+from :53
+D file
+M 100644 :5 renamed-file
+
+commit refs/heads/renamed-file
+mark :55
+author Thomas Rast <trast@inf.ethz.ch> 1374485036 +0200
+committer Thomas Gummerer <t.gummerer@gmail.com> 1556574319 +0100
+data 8
+s/11/B/
+from :54
+M 100644 :7 renamed-file
+
+commit refs/heads/renamed-file
+mark :56
+author Thomas Rast <trast@inf.ethz.ch> 1374485044 +0200
+committer Thomas Gummerer <t.gummerer@gmail.com> 1556574319 +0100
+data 8
+s/12/B/
+from :55
+M 100644 :9 renamed-file
diff --git a/t/t3311-notes-merge-fanout.sh b/t/t3311-notes-merge-fanout.sh
index 93516ef67c..37151a3adc 100755
--- a/t/t3311-notes-merge-fanout.sh
+++ b/t/t3311-notes-merge-fanout.sh
@@ -114,12 +114,12 @@ cp expect_log_x expect_log_y
test_expect_success 'Add a few hundred commits w/notes to trigger fanout (x -> y)' '
git update-ref refs/notes/y refs/notes/x &&
git config core.notesRef refs/notes/y &&
- i=5 &&
- while test $i -lt $num
+ test_commit_bulk --start=6 --id=commit $((num - 5)) &&
+ i=0 &&
+ while test $i -lt $((num - 5))
do
- i=$(($i + 1)) &&
- test_commit "commit$i" >/dev/null &&
- git notes add -m "notes for commit$i" || return 1
+ git notes add -m "notes for commit$i" HEAD~$i || return 1
+ i=$((i + 1))
done &&
test "$(git rev-parse refs/notes/y)" != "$(git rev-parse refs/notes/x)" &&
# Expected number of commits and notes
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 1723e1a858..461dd539ff 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -75,11 +75,10 @@ test_expect_success 'rebase --keep-empty' '
test_line_count = 6 actual
'
-cat > expect <<EOF
-error: nothing to do
-EOF
-
test_expect_success 'rebase -i with empty HEAD' '
+ cat >expect <<-\EOF &&
+ error: nothing to do
+ EOF
set_fake_editor &&
test_must_fail env FAKE_LINES="1 exec_true" git rebase -i HEAD^ >actual 2>&1 &&
test_i18ncmp expect actual
@@ -237,25 +236,23 @@ test_expect_success 'exchange two commits' '
test G = $(git cat-file commit HEAD | sed -ne \$p)
'
-cat > expect << EOF
-diff --git a/file1 b/file1
-index f70f10e..fd79235 100644
---- a/file1
-+++ b/file1
-@@ -1 +1 @@
--A
-+G
-EOF
-
-cat > expect2 << EOF
-<<<<<<< HEAD
-D
-=======
-G
->>>>>>> 5d18e54... G
-EOF
-
test_expect_success 'stop on conflicting pick' '
+ cat >expect <<-\EOF &&
+ diff --git a/file1 b/file1
+ index f70f10e..fd79235 100644
+ --- a/file1
+ +++ b/file1
+ @@ -1 +1 @@
+ -A
+ +G
+ EOF
+ cat >expect2 <<-\EOF &&
+ <<<<<<< HEAD
+ D
+ =======
+ G
+ >>>>>>> 5d18e54... G
+ EOF
git tag new-branch1 &&
set_fake_editor &&
test_must_fail git rebase -i master &&
@@ -495,15 +492,14 @@ test_expect_success 'commit message retained after conflict' '
git branch -D conflict-squash
'
-cat > expect-squash-fixup << EOF
-B
-
-D
+test_expect_success C_LOCALE_OUTPUT 'squash and fixup generate correct log messages' '
+ cat >expect-squash-fixup <<-\EOF &&
+ B
-ONCE
-EOF
+ D
-test_expect_success C_LOCALE_OUTPUT 'squash and fixup generate correct log messages' '
+ ONCE
+ EOF
git checkout -b squash-fixup E &&
base=$(git rev-parse HEAD~4) &&
set_fake_editor &&
@@ -799,13 +795,12 @@ test_expect_success 'rebase -i can copy notes' '
test "a note" = "$(git notes show HEAD)"
'
-cat >expect <<EOF
-an earlier note
-
-a note
-EOF
-
test_expect_success 'rebase -i can copy notes over a fixup' '
+ cat >expect <<-\EOF &&
+ an earlier note
+
+ a note
+ EOF
git reset --hard n3 &&
git notes add -m"an earlier note" n2 &&
set_fake_editor &&
@@ -1031,7 +1026,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 &&
@@ -1304,52 +1299,37 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = ignore' '
actual
'
-cat >expect <<EOF
-Warning: some commits may have been dropped accidentally.
-Dropped commits (newer to older):
- - $(git rev-list --pretty=oneline --abbrev-commit -1 master)
-To avoid this message, use "drop" to explicitly remove a commit.
-
-Use 'git config rebase.missingCommitsCheck' to change the level of warnings.
-The possible behaviours are: ignore, warn, error.
-
-Rebasing (1/4)
-Rebasing (2/4)
-Rebasing (3/4)
-Rebasing (4/4)
-Successfully rebased and updated refs/heads/missing-commit.
-EOF
-
-cr_to_nl () {
- tr '\015' '\012'
-}
-
test_expect_success 'rebase -i respects rebase.missingCommitsCheck = warn' '
+ cat >expect <<-EOF &&
+ Warning: some commits may have been dropped accidentally.
+ Dropped commits (newer to older):
+ - $(git rev-list --pretty=oneline --abbrev-commit -1 master)
+ To avoid this message, use "drop" to explicitly remove a commit.
+ EOF
test_config rebase.missingCommitsCheck warn &&
rebase_setup_and_clean missing-commit &&
set_fake_editor &&
FAKE_LINES="1 2 3 4" \
git rebase -i --root 2>actual.2 &&
- cr_to_nl <actual.2 >actual &&
+ head -n4 actual.2 >actual &&
test_i18ncmp expect actual &&
test D = $(git cat-file commit HEAD | sed -ne \$p)
'
-cat >expect <<EOF
-Warning: some commits may have been dropped accidentally.
-Dropped commits (newer to older):
- - $(git rev-list --pretty=oneline --abbrev-commit -1 master)
- - $(git rev-list --pretty=oneline --abbrev-commit -1 master~2)
-To avoid this message, use "drop" to explicitly remove a commit.
-
-Use 'git config rebase.missingCommitsCheck' to change the level of warnings.
-The possible behaviours are: ignore, warn, error.
-
-You can fix this with 'git rebase --edit-todo' and then run 'git rebase --continue'.
-Or you can abort the rebase with 'git rebase --abort'.
-EOF
-
test_expect_success 'rebase -i respects rebase.missingCommitsCheck = error' '
+ cat >expect <<-EOF &&
+ Warning: some commits may have been dropped accidentally.
+ Dropped commits (newer to older):
+ - $(git rev-list --pretty=oneline --abbrev-commit -1 master)
+ - $(git rev-list --pretty=oneline --abbrev-commit -1 master~2)
+ To avoid this message, use "drop" to explicitly remove a commit.
+
+ Use '\''git config rebase.missingCommitsCheck'\'' to change the level of warnings.
+ The possible behaviours are: ignore, warn, error.
+
+ You can fix this with '\''git rebase --edit-todo'\'' and then run '\''git rebase --continue'\''.
+ Or you can abort the rebase with '\''git rebase --abort'\''.
+ EOF
test_config rebase.missingCommitsCheck error &&
rebase_setup_and_clean missing-commit &&
set_fake_editor &&
diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh
index bdaa511bb0..4eff14dae5 100755
--- a/t/t3418-rebase-continue.sh
+++ b/t/t3418-rebase-continue.sh
@@ -265,4 +265,12 @@ test_expect_success '--reschedule-failed-exec' '
test_i18ngrep "has been rescheduled" err
'
+test_expect_success 'rebase.reschedulefailedexec only affects `rebase -i`' '
+ test_config rebase.reschedulefailedexec true &&
+ test_must_fail git rebase -x false HEAD^ &&
+ grep "^exec false" .git/rebase-merge/git-rebase-todo &&
+ git rebase --abort &&
+ git rebase HEAD^
+'
+
test_done
diff --git a/t/t3420-rebase-autostash.sh b/t/t3420-rebase-autostash.sh
index 2d1094e483..b8f4d03467 100755
--- a/t/t3420-rebase-autostash.sh
+++ b/t/t3420-rebase-autostash.sh
@@ -30,7 +30,8 @@ test_expect_success setup '
echo conflicting-change >file2 &&
git add . &&
test_tick &&
- git commit -m "related commit"
+ git commit -m "related commit" &&
+ remove_progress_re="$(printf "s/.*\\r//")"
'
create_expected_success_am () {
@@ -48,7 +49,7 @@ create_expected_success_interactive () {
q_to_cr >expected <<-EOF
$(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
HEAD is now at $(git rev-parse --short feature-branch) third commit
- Rebasing (1/2)QRebasing (2/2)QApplied autostash.
+ Applied autostash.
Successfully rebased and updated refs/heads/rebased-feature-branch.
EOF
}
@@ -67,10 +68,10 @@ create_expected_failure_am () {
}
create_expected_failure_interactive () {
- q_to_cr >expected <<-EOF
+ cat >expected <<-EOF
$(grep "^Created autostash: [0-9a-f][0-9a-f]*\$" actual)
HEAD is now at $(git rev-parse --short feature-branch) third commit
- Rebasing (1/2)QRebasing (2/2)QApplying autostash resulted in conflicts.
+ Applying autostash resulted in conflicts.
Your changes are safe in the stash.
You can run "git stash pop" or "git stash drop" at any time.
Successfully rebased and updated refs/heads/rebased-feature-branch.
@@ -109,7 +110,8 @@ testrebase () {
suffix=interactive
fi &&
create_expected_success_$suffix &&
- test_i18ncmp expected actual
+ sed "$remove_progress_re" <actual >actual2 &&
+ test_i18ncmp expected actual2
'
test_expect_success "rebase$type: dirty index, non-conflicting rebase" '
@@ -209,7 +211,8 @@ testrebase () {
suffix=interactive
fi &&
create_expected_failure_$suffix &&
- test_i18ncmp expected actual
+ sed "$remove_progress_re" <actual >actual2 &&
+ test_i18ncmp expected actual2
'
}
diff --git a/t/t3430-rebase-merges.sh b/t/t3430-rebase-merges.sh
index 2315649f43..7b6c4847ad 100755
--- a/t/t3430-rebase-merges.sh
+++ b/t/t3430-rebase-merges.sh
@@ -237,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 &&
diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh
index 941d5026da..793bcc7fe3 100755
--- a/t/t3510-cherry-pick-sequence.sh
+++ b/t/t3510-cherry-pick-sequence.sh
@@ -93,6 +93,128 @@ test_expect_success 'cherry-pick cleans up sequencer state upon success' '
test_path_is_missing .git/sequencer
'
+test_expect_success 'cherry-pick --skip requires cherry-pick in progress' '
+ pristine_detach initial &&
+ test_must_fail git cherry-pick --skip
+'
+
+test_expect_success 'revert --skip requires revert in progress' '
+ pristine_detach initial &&
+ test_must_fail git revert --skip
+'
+
+test_expect_success 'cherry-pick --skip to skip commit' '
+ pristine_detach initial &&
+ test_must_fail git cherry-pick anotherpick &&
+ test_must_fail git revert --skip &&
+ git cherry-pick --skip &&
+ test_cmp_rev initial HEAD &&
+ test_path_is_missing .git/CHERRY_PICK_HEAD
+'
+
+test_expect_success 'revert --skip to skip commit' '
+ pristine_detach anotherpick &&
+ test_must_fail git revert anotherpick~1 &&
+ test_must_fail git cherry-pick --skip &&
+ git revert --skip &&
+ test_cmp_rev anotherpick HEAD
+'
+
+test_expect_success 'skip "empty" commit' '
+ pristine_detach picked &&
+ test_commit dummy foo d &&
+ test_must_fail git cherry-pick anotherpick &&
+ git cherry-pick --skip &&
+ test_cmp_rev dummy HEAD
+'
+
+test_expect_success 'skip a commit and check if rest of sequence is correct' '
+ pristine_detach initial &&
+ echo e >expect &&
+ cat >expect.log <<-EOF &&
+ OBJID
+ :100644 100644 OBJID OBJID M foo
+ OBJID
+ :100644 100644 OBJID OBJID M foo
+ OBJID
+ :100644 100644 OBJID OBJID M unrelated
+ OBJID
+ :000000 100644 OBJID OBJID A foo
+ :000000 100644 OBJID OBJID A unrelated
+ EOF
+ test_must_fail git cherry-pick base..yetanotherpick &&
+ test_must_fail git cherry-pick --skip &&
+ echo d >foo &&
+ git add foo &&
+ git cherry-pick --continue &&
+ {
+ git rev-list HEAD |
+ git diff-tree --root --stdin |
+ sed "s/$OID_REGEX/OBJID/g"
+ } >actual.log &&
+ test_cmp expect foo &&
+ test_cmp expect.log actual.log
+'
+
+test_expect_success 'check advice when we move HEAD by committing' '
+ pristine_detach initial &&
+ cat >expect <<-EOF &&
+ error: there is nothing to skip
+ hint: have you committed already?
+ hint: try "git cherry-pick --continue"
+ fatal: cherry-pick failed
+ EOF
+ test_must_fail git cherry-pick base..yetanotherpick &&
+ echo c >foo &&
+ git commit -a &&
+ test_path_is_missing .git/CHERRY_PICK_HEAD &&
+ test_must_fail git cherry-pick --skip 2>advice &&
+ test_i18ncmp expect advice
+'
+
+test_expect_success 'selectively advise --skip while launching another sequence' '
+ pristine_detach initial &&
+ cat >expect <<-EOF &&
+ error: cherry-pick is already in progress
+ hint: try "git cherry-pick (--continue | --skip | --abort | --quit)"
+ fatal: cherry-pick failed
+ EOF
+ test_must_fail git cherry-pick picked..yetanotherpick &&
+ test_must_fail git cherry-pick picked..yetanotherpick 2>advice &&
+ test_i18ncmp expect advice &&
+ cat >expect <<-EOF &&
+ error: cherry-pick is already in progress
+ hint: try "git cherry-pick (--continue | --abort | --quit)"
+ fatal: cherry-pick failed
+ EOF
+ git reset --merge &&
+ test_must_fail git cherry-pick picked..yetanotherpick 2>advice &&
+ test_i18ncmp expect advice
+'
+
+test_expect_success 'allow skipping commit but not abort for a new history' '
+ pristine_detach initial &&
+ cat >expect <<-EOF &&
+ error: cannot abort from a branch yet to be born
+ fatal: cherry-pick failed
+ EOF
+ git checkout --orphan new_disconnected &&
+ git reset --hard &&
+ test_must_fail git cherry-pick anotherpick &&
+ test_must_fail git cherry-pick --abort 2>advice &&
+ git cherry-pick --skip &&
+ test_i18ncmp expect advice
+'
+
+test_expect_success 'allow skipping stopped cherry-pick because of untracked file modifications' '
+ pristine_detach initial &&
+ git rm --cached unrelated &&
+ git commit -m "untrack unrelated" &&
+ test_must_fail git cherry-pick initial base &&
+ test_path_is_missing .git/CHERRY_PICK_HEAD &&
+ git cherry-pick --skip
+'
+
test_expect_success '--quit does not complain when no cherry-pick is in progress' '
pristine_detach initial &&
git cherry-pick --quit
diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index 85ae7dc1e4..66282a720e 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -252,6 +252,19 @@ test_expect_success 'choking "git rm" should not let it die with cruft' '
test_path_is_missing .git/index.lock
'
+test_expect_success 'Resolving by removal is not a warning-worthy event' '
+ git reset -q --hard &&
+ test_when_finished "rm -f .git/index.lock msg && git reset -q --hard" &&
+ blob=$(echo blob | git hash-object -w --stdin) &&
+ for stage in 1 2 3
+ do
+ echo "100644 $blob $stage blob"
+ done | git update-index --index-info &&
+ git rm blob >msg 2>&1 &&
+ test_i18ngrep ! "needs merge" msg &&
+ test_must_fail git ls-files -s --error-unmatch blob
+'
+
test_expect_success 'rm removes subdirectories recursively' '
mkdir -p dir/subdir/subsubdir &&
echo content >dir/subdir/subsubdir/file &&
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 ea30d5f6a0..b8e337893f 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -708,6 +708,24 @@ test_expect_success 'invalid ref of the form "n", n >= N' '
git stash drop
'
+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 &&
@@ -1216,4 +1234,11 @@ test_expect_success 'stash works when user.name and user.email are not set' '
)
'
+test_expect_success 'stash --keep-index with file deleted in index does not resurrect it on disk' '
+ test_commit to-remove to-remove &&
+ git rm to-remove &&
+ git stash --keep-index &&
+ test_path_is_missing to-remove
+'
+
test_done
diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index ab4670d236..6b087df3dc 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -2008,4 +2008,26 @@ test_expect_success 'compare mixed whitespace delta across moved blocks' '
test_cmp expected actual
'
+# Note that the "6" in the expected hunk header below is funny, since we only
+# show 5 lines (the missing one was blank and thus ignored). This is how
+# --ignore-blank-lines behaves even without --function-context, and this test
+# is just checking the interaction of the two features. Don't take it as an
+# endorsement of that output.
+test_expect_success 'combine --ignore-blank-lines with --function-context' '
+ test_write_lines 1 "" 2 3 4 5 >a &&
+ test_write_lines 1 2 3 4 >b &&
+ test_must_fail git diff --no-index \
+ --ignore-blank-lines --function-context a b >actual.raw &&
+ sed -n "/@@/,\$p" <actual.raw >actual &&
+ cat <<-\EOF >expect &&
+ @@ -1,6 +1,4 @@
+ 1
+ 2
+ 3
+ 4
+ -5
+ EOF
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh
index a26c8ba9a2..6640329ebf 100755
--- a/t/t5310-pack-bitmaps.sh
+++ b/t/t5310-pack-bitmaps.sh
@@ -21,15 +21,9 @@ has_any () {
}
test_expect_success 'setup repo with moderate-sized history' '
- for i in $(test_seq 1 10)
- do
- test_commit $i
- done &&
+ test_commit_bulk --id=file 100 &&
git checkout -b other HEAD~5 &&
- for i in $(test_seq 1 10)
- do
- test_commit side-$i
- done &&
+ test_commit_bulk --id=side 10 &&
git checkout master &&
bitmaptip=$(git rev-parse master) &&
blob=$(echo tagged-blob | git hash-object -w --stdin) &&
@@ -106,10 +100,7 @@ test_expect_success 'clone from bitmapped repository' '
'
test_expect_success 'setup further non-bitmapped commits' '
- for i in $(test_seq 1 10)
- do
- test_commit further-$i
- done
+ test_commit_bulk --id=further 10
'
rev_list_tests 'partial bitmap'
diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh
index 840ad4d8ac..22cb9d6643 100755
--- a/t/t5318-commit-graph.sh
+++ b/t/t5318-commit-graph.sh
@@ -20,7 +20,15 @@ test_expect_success 'verify graph with no graph file' '
test_expect_success 'write graph with no packs' '
cd "$TRASH_DIRECTORY/full" &&
git commit-graph write --object-dir . &&
- test_path_is_file info/commit-graph
+ test_path_is_missing info/commit-graph
+'
+
+test_expect_success 'close with correct error on bad input' '
+ 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' '
diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh
index 1ebf19ec3c..c72ca04399 100755
--- a/t/t5319-multi-pack-index.sh
+++ b/t/t5319-multi-pack-index.sh
@@ -363,4 +363,188 @@ test_expect_success 'verify incorrect 64-bit offset' '
"incorrect object offset"
'
+test_expect_success 'setup expire tests' '
+ mkdir dup &&
+ (
+ cd dup &&
+ git init &&
+ test-tool genrandom "data" 4096 >large_file.txt &&
+ git update-index --add large_file.txt &&
+ for i in $(test_seq 1 20)
+ do
+ test_commit $i
+ done &&
+ git branch A HEAD &&
+ git branch B HEAD~8 &&
+ git branch C HEAD~13 &&
+ git branch D HEAD~16 &&
+ git branch E HEAD~18 &&
+ git pack-objects --revs .git/objects/pack/pack-A <<-EOF &&
+ refs/heads/A
+ ^refs/heads/B
+ EOF
+ git pack-objects --revs .git/objects/pack/pack-B <<-EOF &&
+ refs/heads/B
+ ^refs/heads/C
+ EOF
+ git pack-objects --revs .git/objects/pack/pack-C <<-EOF &&
+ refs/heads/C
+ ^refs/heads/D
+ EOF
+ git pack-objects --revs .git/objects/pack/pack-D <<-EOF &&
+ refs/heads/D
+ ^refs/heads/E
+ EOF
+ git pack-objects --revs .git/objects/pack/pack-E <<-EOF &&
+ refs/heads/E
+ EOF
+ git multi-pack-index write &&
+ cp -r .git/objects/pack .git/objects/pack-backup
+ )
+'
+
+test_expect_success 'expire does not remove any packs' '
+ (
+ cd dup &&
+ ls .git/objects/pack >expect &&
+ git multi-pack-index expire &&
+ ls .git/objects/pack >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'expire removes unreferenced packs' '
+ (
+ cd dup &&
+ git pack-objects --revs .git/objects/pack/pack-combined <<-EOF &&
+ refs/heads/A
+ ^refs/heads/C
+ EOF
+ git multi-pack-index write &&
+ ls .git/objects/pack | grep -v -e pack-[AB] >expect &&
+ git multi-pack-index expire &&
+ ls .git/objects/pack >actual &&
+ test_cmp expect actual &&
+ ls .git/objects/pack/ | grep idx >expect-idx &&
+ test-tool read-midx .git/objects | grep idx >actual-midx &&
+ test_cmp expect-idx actual-midx &&
+ git multi-pack-index verify &&
+ git fsck
+ )
+'
+
+test_expect_success 'repack with minimum size does not alter existing packs' '
+ (
+ cd dup &&
+ rm -rf .git/objects/pack &&
+ mv .git/objects/pack-backup .git/objects/pack &&
+ touch -m -t 201901010000 .git/objects/pack/pack-D* &&
+ touch -m -t 201901010001 .git/objects/pack/pack-C* &&
+ touch -m -t 201901010002 .git/objects/pack/pack-B* &&
+ touch -m -t 201901010003 .git/objects/pack/pack-A* &&
+ ls .git/objects/pack >expect &&
+ MINSIZE=$(test-tool path-utils file-size .git/objects/pack/*pack | sort -n | head -n 1) &&
+ git multi-pack-index repack --batch-size=$MINSIZE &&
+ ls .git/objects/pack >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'repack creates a new pack' '
+ (
+ cd dup &&
+ ls .git/objects/pack/*idx >idx-list &&
+ test_line_count = 5 idx-list &&
+ THIRD_SMALLEST_SIZE=$(test-tool path-utils file-size .git/objects/pack/*pack | sort -n | head -n 3 | tail -n 1) &&
+ BATCH_SIZE=$(($THIRD_SMALLEST_SIZE + 1)) &&
+ git multi-pack-index repack --batch-size=$BATCH_SIZE &&
+ ls .git/objects/pack/*idx >idx-list &&
+ test_line_count = 6 idx-list &&
+ test-tool read-midx .git/objects | grep idx >midx-list &&
+ test_line_count = 6 midx-list
+ )
+'
+
+test_expect_success 'expire removes repacked packs' '
+ (
+ cd dup &&
+ ls -al .git/objects/pack/*pack &&
+ ls -S .git/objects/pack/*pack | head -n 4 >expect &&
+ git multi-pack-index expire &&
+ ls -S .git/objects/pack/*pack >actual &&
+ test_cmp expect actual &&
+ test-tool read-midx .git/objects | grep idx >midx-list &&
+ test_line_count = 4 midx-list
+ )
+'
+
+test_expect_success 'expire works when adding new packs' '
+ (
+ cd dup &&
+ git pack-objects --revs .git/objects/pack/pack-combined <<-EOF &&
+ refs/heads/A
+ ^refs/heads/B
+ EOF
+ git pack-objects --revs .git/objects/pack/pack-combined <<-EOF &&
+ refs/heads/B
+ ^refs/heads/C
+ EOF
+ git pack-objects --revs .git/objects/pack/pack-combined <<-EOF &&
+ refs/heads/C
+ ^refs/heads/D
+ EOF
+ git multi-pack-index write &&
+ git pack-objects --revs .git/objects/pack/a-pack <<-EOF &&
+ refs/heads/D
+ ^refs/heads/E
+ EOF
+ git multi-pack-index write &&
+ git pack-objects --revs .git/objects/pack/z-pack <<-EOF &&
+ refs/heads/E
+ EOF
+ git multi-pack-index expire &&
+ ls .git/objects/pack/ | grep idx >expect &&
+ test-tool read-midx .git/objects | grep idx >actual &&
+ test_cmp expect actual &&
+ git multi-pack-index verify
+ )
+'
+
+test_expect_success 'expire respects .keep files' '
+ (
+ cd dup &&
+ git pack-objects --revs .git/objects/pack/pack-all <<-EOF &&
+ refs/heads/A
+ EOF
+ git multi-pack-index write &&
+ PACKA=$(ls .git/objects/pack/a-pack*\.pack | sed s/\.pack\$//) &&
+ touch $PACKA.keep &&
+ git multi-pack-index expire &&
+ ls -S .git/objects/pack/a-pack* | grep $PACKA >a-pack-files &&
+ test_line_count = 3 a-pack-files &&
+ test-tool read-midx .git/objects | grep idx >midx-list &&
+ test_line_count = 2 midx-list
+ )
+'
+
+test_expect_success 'repack --batch-size=0 repacks everything' '
+ (
+ cd dup &&
+ rm .git/objects/pack/*.keep &&
+ ls .git/objects/pack/*idx >idx-list &&
+ test_line_count = 2 idx-list &&
+ git multi-pack-index repack --batch-size=0 &&
+ ls .git/objects/pack/*idx >idx-list &&
+ test_line_count = 3 idx-list &&
+ test-tool read-midx .git/objects | grep idx >midx-list &&
+ test_line_count = 3 midx-list &&
+ git multi-pack-index expire &&
+ ls -al .git/objects/pack/*idx >idx-list &&
+ test_line_count = 1 idx-list &&
+ git multi-pack-index repack --batch-size=0 &&
+ ls -al .git/objects/pack/*idx >new-idx-list &&
+ test_cmp idx-list new-idx-list
+ )
+'
+
test_done
diff --git a/t/t5324-split-commit-graph.sh b/t/t5324-split-commit-graph.sh
new file mode 100755
index 0000000000..03f45a1ed9
--- /dev/null
+++ b/t/t5324-split-commit-graph.sh
@@ -0,0 +1,343 @@
+#!/bin/sh
+
+test_description='split commit graph'
+. ./test-lib.sh
+
+GIT_TEST_COMMIT_GRAPH=0
+
+test_expect_success 'setup repo' '
+ git init &&
+ git config core.commitGraph true &&
+ infodir=".git/objects/info" &&
+ graphdir="$infodir/commit-graphs" &&
+ test_oid_init
+'
+
+graph_read_expect() {
+ NUM_BASE=0
+ if test ! -z $2
+ then
+ NUM_BASE=$2
+ fi
+ cat >expect <<- EOF
+ header: 43475048 1 1 3 $NUM_BASE
+ num_commits: $1
+ chunks: oid_fanout oid_lookup commit_metadata
+ EOF
+ git commit-graph read >output &&
+ test_cmp expect output
+}
+
+test_expect_success 'create commits and write commit-graph' '
+ for i in $(test_seq 3)
+ do
+ test_commit $i &&
+ git branch commits/$i || return 1
+ done &&
+ git commit-graph write --reachable &&
+ test_path_is_file $infodir/commit-graph &&
+ graph_read_expect 3
+'
+
+graph_git_two_modes() {
+ git -c core.commitGraph=true $1 >output
+ git -c core.commitGraph=false $1 >expect
+ test_cmp expect output
+}
+
+graph_git_behavior() {
+ MSG=$1
+ BRANCH=$2
+ COMPARE=$3
+ test_expect_success "check normal git operations: $MSG" '
+ graph_git_two_modes "log --oneline $BRANCH" &&
+ graph_git_two_modes "log --topo-order $BRANCH" &&
+ graph_git_two_modes "log --graph $COMPARE..$BRANCH" &&
+ graph_git_two_modes "branch -vv" &&
+ graph_git_two_modes "merge-base -a $BRANCH $COMPARE"
+ '
+}
+
+graph_git_behavior 'graph exists' commits/3 commits/1
+
+verify_chain_files_exist() {
+ for hash in $(cat $1/commit-graph-chain)
+ do
+ test_path_is_file $1/graph-$hash.graph || return 1
+ done
+}
+
+test_expect_success 'add more commits, and write a new base graph' '
+ git reset --hard commits/1 &&
+ for i in $(test_seq 4 5)
+ do
+ test_commit $i &&
+ git branch commits/$i || return 1
+ done &&
+ git reset --hard commits/2 &&
+ for i in $(test_seq 6 10)
+ do
+ test_commit $i &&
+ git branch commits/$i || return 1
+ done &&
+ git reset --hard commits/2 &&
+ git merge commits/4 &&
+ git branch merge/1 &&
+ git reset --hard commits/4 &&
+ git merge commits/6 &&
+ git branch merge/2 &&
+ git commit-graph write --reachable &&
+ graph_read_expect 12
+'
+
+test_expect_success 'fork and fail to base a chain on a commit-graph file' '
+ test_when_finished rm -rf fork &&
+ git clone . fork &&
+ (
+ cd fork &&
+ rm .git/objects/info/commit-graph &&
+ echo "$(pwd)/../.git/objects" >.git/objects/info/alternates &&
+ test_commit new-commit &&
+ git commit-graph write --reachable --split &&
+ test_path_is_file $graphdir/commit-graph-chain &&
+ test_line_count = 1 $graphdir/commit-graph-chain &&
+ verify_chain_files_exist $graphdir
+ )
+'
+
+test_expect_success 'add three more commits, write a tip graph' '
+ git reset --hard commits/3 &&
+ git merge merge/1 &&
+ git merge commits/5 &&
+ git merge merge/2 &&
+ git branch merge/3 &&
+ git commit-graph write --reachable --split &&
+ test_path_is_missing $infodir/commit-graph &&
+ test_path_is_file $graphdir/commit-graph-chain &&
+ ls $graphdir/graph-*.graph >graph-files &&
+ test_line_count = 2 graph-files &&
+ verify_chain_files_exist $graphdir
+'
+
+graph_git_behavior 'split commit-graph: merge 3 vs 2' merge/3 merge/2
+
+test_expect_success 'add one commit, write a tip graph' '
+ test_commit 11 &&
+ git branch commits/11 &&
+ git commit-graph write --reachable --split &&
+ test_path_is_missing $infodir/commit-graph &&
+ test_path_is_file $graphdir/commit-graph-chain &&
+ ls $graphdir/graph-*.graph >graph-files &&
+ test_line_count = 3 graph-files &&
+ verify_chain_files_exist $graphdir
+'
+
+graph_git_behavior 'three-layer commit-graph: commit 11 vs 6' commits/11 commits/6
+
+test_expect_success 'add one commit, write a merged graph' '
+ test_commit 12 &&
+ git branch commits/12 &&
+ git commit-graph write --reachable --split &&
+ test_path_is_file $graphdir/commit-graph-chain &&
+ test_line_count = 2 $graphdir/commit-graph-chain &&
+ ls $graphdir/graph-*.graph >graph-files &&
+ test_line_count = 2 graph-files &&
+ verify_chain_files_exist $graphdir
+'
+
+graph_git_behavior 'merged commit-graph: commit 12 vs 6' commits/12 commits/6
+
+test_expect_success 'create fork and chain across alternate' '
+ git clone . fork &&
+ (
+ cd fork &&
+ git config core.commitGraph true &&
+ rm -rf $graphdir &&
+ echo "$(pwd)/../.git/objects" >.git/objects/info/alternates &&
+ test_commit 13 &&
+ git branch commits/13 &&
+ git commit-graph write --reachable --split &&
+ test_path_is_file $graphdir/commit-graph-chain &&
+ test_line_count = 3 $graphdir/commit-graph-chain &&
+ ls $graphdir/graph-*.graph >graph-files &&
+ test_line_count = 1 graph-files &&
+ git -c core.commitGraph=true rev-list HEAD >expect &&
+ git -c core.commitGraph=false rev-list HEAD >actual &&
+ test_cmp expect actual &&
+ test_commit 14 &&
+ git commit-graph write --reachable --split --object-dir=.git/objects/ &&
+ test_line_count = 3 $graphdir/commit-graph-chain &&
+ ls $graphdir/graph-*.graph >graph-files &&
+ test_line_count = 1 graph-files
+ )
+'
+
+graph_git_behavior 'alternate: commit 13 vs 6' commits/13 commits/6
+
+test_expect_success 'test merge stragety constants' '
+ git clone . merge-2 &&
+ (
+ cd merge-2 &&
+ git config core.commitGraph true &&
+ test_line_count = 2 $graphdir/commit-graph-chain &&
+ test_commit 14 &&
+ git commit-graph write --reachable --split --size-multiple=2 &&
+ test_line_count = 3 $graphdir/commit-graph-chain
+
+ ) &&
+ git clone . merge-10 &&
+ (
+ cd merge-10 &&
+ git config core.commitGraph true &&
+ test_line_count = 2 $graphdir/commit-graph-chain &&
+ test_commit 14 &&
+ git commit-graph write --reachable --split --size-multiple=10 &&
+ test_line_count = 1 $graphdir/commit-graph-chain &&
+ ls $graphdir/graph-*.graph >graph-files &&
+ test_line_count = 1 graph-files
+ ) &&
+ git clone . merge-10-expire &&
+ (
+ cd merge-10-expire &&
+ git config core.commitGraph true &&
+ test_line_count = 2 $graphdir/commit-graph-chain &&
+ test_commit 15 &&
+ git commit-graph write --reachable --split --size-multiple=10 --expire-time=1980-01-01 &&
+ test_line_count = 1 $graphdir/commit-graph-chain &&
+ ls $graphdir/graph-*.graph >graph-files &&
+ test_line_count = 3 graph-files
+ ) &&
+ git clone --no-hardlinks . max-commits &&
+ (
+ cd max-commits &&
+ git config core.commitGraph true &&
+ test_line_count = 2 $graphdir/commit-graph-chain &&
+ test_commit 16 &&
+ test_commit 17 &&
+ git commit-graph write --reachable --split --max-commits=1 &&
+ test_line_count = 1 $graphdir/commit-graph-chain &&
+ ls $graphdir/graph-*.graph >graph-files &&
+ test_line_count = 1 graph-files
+ )
+'
+
+test_expect_success 'remove commit-graph-chain file after flattening' '
+ git clone . flatten &&
+ (
+ cd flatten &&
+ test_line_count = 2 $graphdir/commit-graph-chain &&
+ git commit-graph write --reachable &&
+ test_path_is_missing $graphdir/commit-graph-chain &&
+ ls $graphdir >graph-files &&
+ test_line_count = 0 graph-files
+ )
+'
+
+corrupt_file() {
+ file=$1
+ pos=$2
+ data="${3:-\0}"
+ chmod a+w "$file" &&
+ printf "$data" | dd of="$file" bs=1 seek="$pos" conv=notrunc
+}
+
+test_expect_success 'verify hashes along chain, even in shallow' '
+ git clone --no-hardlinks . verify &&
+ (
+ cd verify &&
+ git commit-graph verify &&
+ base_file=$graphdir/graph-$(head -n 1 $graphdir/commit-graph-chain).graph &&
+ corrupt_file "$base_file" 1760 "\01" &&
+ test_must_fail git commit-graph verify --shallow 2>test_err &&
+ grep -v "^+" test_err >err &&
+ test_i18ngrep "incorrect checksum" err
+ )
+'
+
+test_expect_success 'verify --shallow does not check base contents' '
+ git clone --no-hardlinks . verify-shallow &&
+ (
+ cd verify-shallow &&
+ git commit-graph verify &&
+ base_file=$graphdir/graph-$(head -n 1 $graphdir/commit-graph-chain).graph &&
+ corrupt_file "$base_file" 1000 "\01" &&
+ git commit-graph verify --shallow &&
+ test_must_fail git commit-graph verify 2>test_err &&
+ grep -v "^+" test_err >err &&
+ test_i18ngrep "incorrect checksum" err
+ )
+'
+
+test_expect_success 'warn on base graph chunk incorrect' '
+ git clone --no-hardlinks . base-chunk &&
+ (
+ cd base-chunk &&
+ git commit-graph verify &&
+ base_file=$graphdir/graph-$(tail -n 1 $graphdir/commit-graph-chain).graph &&
+ corrupt_file "$base_file" 1376 "\01" &&
+ git commit-graph verify --shallow 2>test_err &&
+ grep -v "^+" test_err >err &&
+ test_i18ngrep "commit-graph chain does not match" err
+ )
+'
+
+test_expect_success 'verify after commit-graph-chain corruption' '
+ git clone --no-hardlinks . verify-chain &&
+ (
+ cd verify-chain &&
+ corrupt_file "$graphdir/commit-graph-chain" 60 "G" &&
+ git commit-graph verify 2>test_err &&
+ grep -v "^+" test_err >err &&
+ test_i18ngrep "invalid commit-graph chain" err &&
+ corrupt_file "$graphdir/commit-graph-chain" 60 "A" &&
+ git commit-graph verify 2>test_err &&
+ grep -v "^+" test_err >err &&
+ test_i18ngrep "unable to find all commit-graph files" err
+ )
+'
+
+test_expect_success 'verify across alternates' '
+ git clone --no-hardlinks . verify-alt &&
+ (
+ cd verify-alt &&
+ rm -rf $graphdir &&
+ altdir="$(pwd)/../.git/objects" &&
+ echo "$altdir" >.git/objects/info/alternates &&
+ git commit-graph verify --object-dir="$altdir/" &&
+ test_commit extra &&
+ git commit-graph write --reachable --split &&
+ tip_file=$graphdir/graph-$(tail -n 1 $graphdir/commit-graph-chain).graph &&
+ corrupt_file "$tip_file" 100 "\01" &&
+ test_must_fail git commit-graph verify --shallow 2>test_err &&
+ grep -v "^+" test_err >err &&
+ test_i18ngrep "commit-graph has incorrect fanout value" err
+ )
+'
+
+test_expect_success 'add octopus merge' '
+ git reset --hard commits/10 &&
+ git merge commits/3 commits/4 &&
+ git branch merge/octopus &&
+ git commit-graph write --reachable --split &&
+ git commit-graph verify &&
+ test_line_count = 3 $graphdir/commit-graph-chain
+'
+
+graph_git_behavior 'graph exists' merge/octopus commits/12
+
+test_expect_success 'split across alternate where alternate is not split' '
+ git commit-graph write --reachable &&
+ test_path_is_file .git/objects/info/commit-graph &&
+ cp .git/objects/info/commit-graph . &&
+ git clone --no-hardlinks . alt-split &&
+ (
+ cd alt-split &&
+ echo "$(pwd)"/../.git/objects >.git/objects/info/alternates &&
+ test_commit 18 &&
+ git commit-graph write --reachable --split &&
+ test_line_count = 1 $graphdir/commit-graph-chain
+ ) &&
+ test_cmp commit-graph .git/objects/info/commit-graph
+'
+
+test_done
diff --git a/t/t5504-fetch-receive-strict.sh b/t/t5504-fetch-receive-strict.sh
index 7bc706873c..fdfe179b11 100755
--- a/t/t5504-fetch-receive-strict.sh
+++ b/t/t5504-fetch-receive-strict.sh
@@ -164,9 +164,9 @@ test_expect_success 'fsck with unsorted skipList' '
test_expect_success 'fsck with invalid or bogus skipList input' '
git -c fsck.skipList=/dev/null -c fsck.missingEmail=ignore fsck &&
test_must_fail git -c fsck.skipList=does-not-exist -c fsck.missingEmail=ignore fsck 2>err &&
- test_i18ngrep "Could not open skip list: does-not-exist" err &&
+ test_i18ngrep "could not open.*: does-not-exist" err &&
test_must_fail git -c fsck.skipList=.git/config -c fsck.missingEmail=ignore fsck 2>err &&
- test_i18ngrep "Invalid SHA-1: \[core\]" err
+ test_i18ngrep "invalid object name: \[core\]" err
'
test_expect_success 'fsck with other accepted skipList input (comments & empty lines)' '
@@ -193,7 +193,7 @@ test_expect_success 'fsck no garbage output from comments & empty lines errors'
test_expect_success 'fsck with invalid abbreviated skipList input' '
echo $commit | test_copy_bytes 20 >SKIP.abbreviated &&
test_must_fail git -c fsck.skipList=SKIP.abbreviated fsck 2>err-abbreviated &&
- test_i18ngrep "^fatal: Invalid SHA-1: " err-abbreviated
+ test_i18ngrep "^fatal: invalid object name: " err-abbreviated
'
test_expect_success 'fsck with exhaustive accepted skipList input (various types of comments etc.)' '
@@ -226,10 +226,10 @@ test_expect_success 'push with receive.fsck.skipList' '
test_must_fail git push --porcelain dst bogus &&
git --git-dir=dst/.git config receive.fsck.skipList does-not-exist &&
test_must_fail git push --porcelain dst bogus 2>err &&
- test_i18ngrep "Could not open skip list: does-not-exist" err &&
+ test_i18ngrep "could not open.*: does-not-exist" err &&
git --git-dir=dst/.git config receive.fsck.skipList config &&
test_must_fail git push --porcelain dst bogus 2>err &&
- test_i18ngrep "Invalid SHA-1: \[core\]" err &&
+ test_i18ngrep "invalid object name: \[core\]" err &&
git --git-dir=dst/.git config receive.fsck.skipList SKIP &&
git push --porcelain dst bogus
@@ -255,10 +255,10 @@ test_expect_success 'fetch with fetch.fsck.skipList' '
test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec &&
git --git-dir=dst/.git config fetch.fsck.skipList does-not-exist &&
test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec 2>err &&
- test_i18ngrep "Could not open skip list: does-not-exist" err &&
+ test_i18ngrep "could not open.*: does-not-exist" err &&
git --git-dir=dst/.git config fetch.fsck.skipList dst/.git/config &&
test_must_fail git --git-dir=dst/.git fetch "file://$(pwd)" $refspec 2>err &&
- test_i18ngrep "Invalid SHA-1: \[core\]" err &&
+ test_i18ngrep "invalid object name: \[core\]" err &&
git --git-dir=dst/.git config fetch.fsck.skipList dst/.git/SKIP &&
git --git-dir=dst/.git fetch "file://$(pwd)" $refspec
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index e98d90dd9b..139f7106f7 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -978,4 +978,27 @@ test_expect_success '--negotiation-tip limits "have" lines sent with HTTP protoc
check_negotiation_tip
'
+test_expect_success '--no-show-forced-updates' '
+ mkdir forced-updates &&
+ (
+ cd forced-updates &&
+ git init &&
+ test_commit 1 &&
+ test_commit 2
+ ) &&
+ git clone forced-updates forced-update-clone &&
+ git clone forced-updates no-forced-update-clone &&
+ git -C forced-updates reset --hard HEAD~1 &&
+ (
+ cd forced-update-clone &&
+ git fetch --show-forced-updates origin 2>output &&
+ test_i18ngrep "(forced update)" output
+ ) &&
+ (
+ cd no-forced-update-clone &&
+ git fetch --no-show-forced-updates origin 2>output &&
+ ! test_i18ngrep "(forced update)" output
+ )
+'
+
test_done
diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh
index e3c4a48c85..43e1d8d4d2 100755
--- a/t/t5512-ls-remote.sh
+++ b/t/t5512-ls-remote.sh
@@ -267,8 +267,7 @@ test_expect_success 'ls-remote --symref omits filtered-out matches' '
'
test_lazy_prereq GIT_DAEMON '
- test_tristate GIT_TEST_GIT_DAEMON &&
- test "$GIT_TEST_GIT_DAEMON" != false
+ git env--helper --type=bool --default=true --exit-code GIT_TEST_GIT_DAEMON
'
# This test spawns a daemon, so run it only if the user would be OK with
diff --git a/t/t5514-fetch-multiple.sh b/t/t5514-fetch-multiple.sh
index 0030c92e1a..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/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh
index 8ef8763e06..b86ddb60f2 100755
--- a/t/t5541-http-push-smart.sh
+++ b/t/t5541-http-push-smart.sh
@@ -177,6 +177,55 @@ test_expect_success 'push (chunked)' '
test $HEAD = $(git rev-parse --verify HEAD))
'
+test_expect_success 'push --atomic also prevents branch creation, reports collateral' '
+ # Setup upstream repo - empty for now
+ d=$HTTPD_DOCUMENT_ROOT_PATH/atomic-branches.git &&
+ git init --bare "$d" &&
+ test_config -C "$d" http.receivepack true &&
+ up="$HTTPD_URL"/smart/atomic-branches.git &&
+
+ # Tell "$up" about two branches for now
+ test_commit atomic1 &&
+ test_commit atomic2 &&
+ git branch collateral &&
+ git push "$up" master collateral &&
+
+ # collateral is a valid push, but should be failed by atomic push
+ git checkout collateral &&
+ test_commit collateral1 &&
+
+ # Make master incompatible with upstream to provoke atomic
+ git checkout master &&
+ git reset --hard HEAD^ &&
+
+ # Add a new branch which should be failed by atomic push. This is a
+ # regression case.
+ git branch atomic &&
+
+ # --atomic should cause entire push to be rejected
+ test_must_fail git push --atomic "$up" master atomic collateral 2>output &&
+
+ # the new branch should not have been created upstream
+ test_must_fail git -C "$d" show-ref --verify refs/heads/atomic &&
+
+ # upstream should still reflect atomic2, the last thing we pushed
+ # successfully
+ git rev-parse atomic2 >expected &&
+ # on master...
+ git -C "$d" rev-parse refs/heads/master >actual &&
+ test_cmp expected actual &&
+ # ...and collateral.
+ git -C "$d" rev-parse refs/heads/collateral >actual &&
+ test_cmp expected actual &&
+
+ # the failed refs should be indicated to the user
+ grep "^ ! .*rejected.* master -> master" output &&
+
+ # the collateral failure refs should be indicated to the user
+ grep "^ ! .*rejected.* atomic -> atomic .*atomic push failed" output &&
+ grep "^ ! .*rejected.* collateral -> collateral .*atomic push failed" output
+'
+
test_expect_success 'push --all can push to empty repo' '
d=$HTTPD_DOCUMENT_ROOT_PATH/empty-all.git &&
git init --bare "$d" &&
@@ -213,7 +262,7 @@ test_expect_success TTY 'push shows progress when stderr is a tty' '
cd "$ROOT_PATH"/test_repo_clone &&
test_commit noisy &&
test_terminal git push >output 2>&1 &&
- test_i18ngrep "^Writing objects" output
+ test_i18ngrep "Writing objects" output
'
test_expect_success TTY 'push --quiet silences status and progress' '
@@ -228,7 +277,7 @@ test_expect_success TTY 'push --no-progress silences progress but not status' '
test_commit no-progress &&
test_terminal git push --no-progress >output 2>&1 &&
test_i18ngrep "^To http" output &&
- test_i18ngrep ! "^Writing objects" output
+ test_i18ngrep ! "Writing objects" output
'
test_expect_success 'push --progress shows progress to non-tty' '
@@ -236,7 +285,7 @@ test_expect_success 'push --progress shows progress to non-tty' '
test_commit progress &&
git push --progress >output 2>&1 &&
test_i18ngrep "^To http" output &&
- test_i18ngrep "^Writing objects" output
+ test_i18ngrep "Writing objects" output
'
test_expect_success 'http push gives sane defaults to reflog' '
diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
index ac74626a7b..e38e543867 100755
--- a/t/t5551-http-fetch-smart.sh
+++ b/t/t5551-http-fetch-smart.sh
@@ -199,7 +199,7 @@ test_expect_success 'GIT_SMART_HTTP can disable smart http' '
test_expect_success 'invalid Content-Type rejected' '
test_must_fail git clone $HTTPD_URL/broken_smart/repo.git 2>actual &&
- grep "not valid:" actual
+ test_i18ngrep "not valid:" actual
'
test_expect_success 'create namespaced refs' '
@@ -301,11 +301,10 @@ test_expect_success CMDLINE_LIMIT \
)
'
-test_expect_success 'large fetch-pack requests can be split across POSTs' '
+test_expect_success 'large fetch-pack requests can be sent using chunked encoding' '
GIT_TRACE_CURL=true git -c http.postbuffer=65536 \
clone --bare "$HTTPD_URL/smart/repo.git" split.git 2>err &&
- grep "^=> Send header: POST" err >posts &&
- test_line_count = 2 posts
+ grep "^=> Send header: Transfer-Encoding: chunked" err
'
test_expect_success 'test allowreachablesha1inwant' '
@@ -466,7 +465,7 @@ test_expect_success 'GIT_TRACE_CURL_NO_DATA prevents data from being traced' '
test_expect_success 'server-side error detected' '
test_must_fail git clone $HTTPD_URL/error_smart/repo.git 2>actual &&
- grep "server-side error" actual
+ test_i18ngrep "server-side error" actual
'
test_done
diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh
index 4320082b1b..4894237ab8 100755
--- a/t/t5604-clone-reference.sh
+++ b/t/t5604-clone-reference.sh
@@ -221,4 +221,137 @@ test_expect_success 'clone, dissociate from alternates' '
( cd C && git fsck )
'
+test_expect_success 'setup repo with garbage in objects/*' '
+ git init S &&
+ (
+ cd S &&
+ test_commit A &&
+
+ cd .git/objects &&
+ >.some-hidden-file &&
+ >some-file &&
+ mkdir .some-hidden-dir &&
+ >.some-hidden-dir/some-file &&
+ >.some-hidden-dir/.some-dot-file &&
+ mkdir some-dir &&
+ >some-dir/some-file &&
+ >some-dir/.some-dot-file
+ )
+'
+
+test_expect_success 'clone a repo with garbage in objects/*' '
+ for option in --local --no-hardlinks --shared --dissociate
+ do
+ git clone $option S S$option || return 1 &&
+ git -C S$option fsck || return 1
+ done &&
+ find S-* -name "*some*" | sort >actual &&
+ cat >expected <<-EOF &&
+ S--dissociate/.git/objects/.some-hidden-dir
+ S--dissociate/.git/objects/.some-hidden-dir/.some-dot-file
+ S--dissociate/.git/objects/.some-hidden-dir/some-file
+ S--dissociate/.git/objects/.some-hidden-file
+ S--dissociate/.git/objects/some-dir
+ S--dissociate/.git/objects/some-dir/.some-dot-file
+ S--dissociate/.git/objects/some-dir/some-file
+ S--dissociate/.git/objects/some-file
+ S--local/.git/objects/.some-hidden-dir
+ S--local/.git/objects/.some-hidden-dir/.some-dot-file
+ S--local/.git/objects/.some-hidden-dir/some-file
+ S--local/.git/objects/.some-hidden-file
+ S--local/.git/objects/some-dir
+ S--local/.git/objects/some-dir/.some-dot-file
+ S--local/.git/objects/some-dir/some-file
+ S--local/.git/objects/some-file
+ S--no-hardlinks/.git/objects/.some-hidden-dir
+ S--no-hardlinks/.git/objects/.some-hidden-dir/.some-dot-file
+ S--no-hardlinks/.git/objects/.some-hidden-dir/some-file
+ S--no-hardlinks/.git/objects/.some-hidden-file
+ S--no-hardlinks/.git/objects/some-dir
+ S--no-hardlinks/.git/objects/some-dir/.some-dot-file
+ S--no-hardlinks/.git/objects/some-dir/some-file
+ S--no-hardlinks/.git/objects/some-file
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success SYMLINKS 'setup repo with manually symlinked or unknown files at objects/' '
+ git init T &&
+ (
+ cd T &&
+ git config gc.auto 0 &&
+ test_commit A &&
+ git gc &&
+ test_commit B &&
+
+ cd .git/objects &&
+ mv pack packs &&
+ ln -s packs pack &&
+ find ?? -type d >loose-dirs &&
+ last_loose=$(tail -n 1 loose-dirs) &&
+ mv $last_loose a-loose-dir &&
+ ln -s a-loose-dir $last_loose &&
+ first_loose=$(head -n 1 loose-dirs) &&
+ rm -f loose-dirs &&
+
+ cd $first_loose &&
+ obj=$(ls *) &&
+ mv $obj ../an-object &&
+ ln -s ../an-object $obj &&
+
+ cd ../ &&
+ find . -type f | sort >../../../T.objects-files.raw &&
+ find . -type l | sort >../../../T.objects-symlinks.raw &&
+ echo unknown_content >unknown_file
+ ) &&
+ git -C T fsck &&
+ git -C T rev-list --all --objects >T.objects
+'
+
+
+test_expect_success SYMLINKS 'clone repo with symlinked or unknown files at objects/' '
+ for option in --local --no-hardlinks --shared --dissociate
+ do
+ git clone $option T T$option || return 1 &&
+ git -C T$option fsck || return 1 &&
+ git -C T$option rev-list --all --objects >T$option.objects &&
+ test_cmp T.objects T$option.objects &&
+ (
+ cd T$option/.git/objects &&
+ find . -type f | sort >../../../T$option.objects-files.raw &&
+ find . -type l | sort >../../../T$option.objects-symlinks.raw
+ )
+ done &&
+
+ for raw in $(ls T*.raw)
+ do
+ sed -e "s!/../!/Y/!; s![0-9a-f]\{38,\}!Z!" -e "/commit-graph/d" \
+ -e "/multi-pack-index/d" <$raw >$raw.de-sha || return 1
+ done &&
+
+ cat >expected-files <<-EOF &&
+ ./Y/Z
+ ./Y/Z
+ ./a-loose-dir/Z
+ ./an-object
+ ./Y/Z
+ ./info/packs
+ ./pack/pack-Z.idx
+ ./pack/pack-Z.pack
+ ./packs/pack-Z.idx
+ ./packs/pack-Z.pack
+ ./unknown_file
+ EOF
+
+ for option in --local --no-hardlinks --dissociate
+ do
+ test_cmp expected-files T$option.objects-files.raw.de-sha || return 1 &&
+ test_must_be_empty T$option.objects-symlinks.raw.de-sha || return 1
+ done &&
+
+ echo ./info/alternates >expected-files &&
+ test_cmp expected-files T--shared.objects-files.raw &&
+ test_must_be_empty T--shared.objects-symlinks.raw
+'
+
test_done
diff --git a/t/t5618-alternate-refs.sh b/t/t5618-alternate-refs.sh
new file mode 100755
index 0000000000..3353216f09
--- /dev/null
+++ b/t/t5618-alternate-refs.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+test_description='test handling of --alternate-refs traversal'
+. ./test-lib.sh
+
+# Avoid test_commit because we want a specific and known set of refs:
+#
+# base -- one
+# \ \
+# two -- merged
+#
+# where "one" and "two" are on separate refs, and "merged" is available only in
+# the dependent child repository.
+test_expect_success 'set up local refs' '
+ git checkout -b one &&
+ test_tick &&
+ git commit --allow-empty -m base &&
+ test_tick &&
+ git commit --allow-empty -m one &&
+ git checkout -b two HEAD^ &&
+ test_tick &&
+ git commit --allow-empty -m two
+'
+
+# We'll enter the child repository after it's set up since that's where
+# all of the subsequent tests will want to run (and it's easy to forget a
+# "-C child" and get nonsense results).
+test_expect_success 'set up shared clone' '
+ git clone -s . child &&
+ cd child &&
+ git merge origin/one
+'
+
+test_expect_success 'rev-list --alternate-refs' '
+ git rev-list --remotes=origin >expect &&
+ git rev-list --alternate-refs >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'rev-list --not --alternate-refs' '
+ git rev-parse HEAD >expect &&
+ git rev-list HEAD --not --alternate-refs >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'limiting with alternateRefsPrefixes' '
+ test_config core.alternateRefsPrefixes refs/heads/one &&
+ git rev-list origin/one >expect &&
+ git rev-list --alternate-refs >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'log --source shows .alternate marker' '
+ git log --oneline --source --remotes=origin >expect.orig &&
+ sed "s/origin.* /.alternate /" <expect.orig >expect &&
+ git log --oneline --source --alternate-refs >actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
index 5b33f625dd..011b81d4fc 100755
--- a/t/t5702-protocol-v2.sh
+++ b/t/t5702-protocol-v2.sh
@@ -499,10 +499,7 @@ test_expect_success 'upload-pack respects client shallows' '
# Add extra commits to the client so that the whole fetch takes more
# than 1 request (due to negotiation)
- for i in $(test_seq 1 32)
- do
- test_commit -C client c$i
- done &&
+ test_commit_bulk -C client --id=c 32 &&
git -C server checkout -b newbranch base &&
test_commit -C server client_wants &&
@@ -711,10 +708,7 @@ test_expect_success 'when server does not send "ready", expect FLUSH' '
# Create many commits to extend the negotiation phase across multiple
# requests, so that the server does not send "ready" in the first
# request.
- for i in $(test_seq 1 32)
- do
- test_commit -C http_child c$i
- done &&
+ test_commit_bulk -C http_child --id=c 32 &&
# After the acknowledgments section, pretend that a DELIM
# (0001) was sent instead of a FLUSH (0000).
diff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh
index 0951d1bbdc..de4b6106ef 100755
--- a/t/t5703-upload-pack-ref-in-want.sh
+++ b/t/t5703-upload-pack-ref-in-want.sh
@@ -176,7 +176,7 @@ test_expect_success 'setup repos for change-while-negotiating test' '
git clone "http://127.0.0.1:$LIB_HTTPD_PORT/smart/repo" "$LOCAL_PRISTINE" &&
cd "$LOCAL_PRISTINE" &&
git checkout -b side &&
- for i in $(test_seq 1 33); do test_commit s$i; done &&
+ test_commit_bulk --id=s 33 &&
# Add novel commits to upstream
git checkout master &&
@@ -287,7 +287,7 @@ test_expect_success 'setup repos for fetching with ref-in-want tests' '
git clone "file://$REPO" "$LOCAL_PRISTINE" &&
cd "$LOCAL_PRISTINE" &&
git checkout -b side &&
- for i in $(test_seq 1 33); do test_commit s$i; done &&
+ test_commit_bulk --id=s 33 &&
# Add novel commits to upstream
git checkout master &&
diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
index d04f8007e0..2d6c4a281e 100755
--- a/t/t5801-remote-helpers.sh
+++ b/t/t5801-remote-helpers.sh
@@ -126,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
@@ -135,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
'
@@ -145,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
'
@@ -303,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
index 752c763eb6..6b9f0b5dc7 100755
--- a/t/t5801/git-remote-testgit
+++ b/t/t5801/git-remote-testgit
@@ -11,13 +11,15 @@ fi
url=$2
dir="$GIT_DIR/testgit/$alias"
-prefix="refs/testgit/$alias"
-default_refspec="refs/heads/*:${prefix}/heads/*"
+h_refspec="refs/heads/*:refs/testgit/$alias/heads/*"
+t_refspec="refs/tags/*:refs/testgit/$alias/tags/*"
-refspec="${GIT_REMOTE_TESTGIT_REFSPEC-$default_refspec}"
-
-test -z "$refspec" && prefix="refs"
+if test -n "$GIT_REMOTE_TESTGIT_NOREFSPEC"
+then
+ h_refspec=""
+ t_refspec=""
+fi
GIT_DIR="$url/.git"
export GIT_DIR
@@ -40,7 +42,8 @@ do
capabilities)
echo 'import'
echo 'export'
- test -n "$refspec" && echo "refspec $refspec"
+ 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"
@@ -52,7 +55,7 @@ do
echo
;;
list)
- git for-each-ref --format='? %(refname)' 'refs/heads/'
+ git for-each-ref --format='? %(refname)' 'refs/heads/' 'refs/tags/'
head=$(git symbolic-ref HEAD)
echo "@$head HEAD"
echo
@@ -81,10 +84,11 @@ do
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 |
- sed -e "s#refs/heads/#${prefix}/heads/#g"
+ $refs
echo "done"
;;
export)
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/t6040-tracking-info.sh b/t/t6040-tracking-info.sh
index 716283b274..ad1922b999 100755
--- a/t/t6040-tracking-info.sh
+++ b/t/t6040-tracking-info.sh
@@ -38,7 +38,7 @@ test_expect_success setup '
advance h
'
-script='s/^..\(b.\) *[0-9a-f]* \(.*\)$/\1 \2/p'
+t6040_script='s/^..\(b.\) *[0-9a-f]* \(.*\)$/\1 \2/p'
cat >expect <<\EOF
b1 [ahead 1, behind 1] d
b2 [ahead 1, behind 1] d
@@ -53,7 +53,7 @@ test_expect_success 'branch -v' '
cd test &&
git branch -v
) |
- sed -n -e "$script" >actual &&
+ sed -n -e "$t6040_script" >actual &&
test_i18ncmp expect actual
'
@@ -71,7 +71,7 @@ test_expect_success 'branch -vv' '
cd test &&
git branch -vv
) |
- sed -n -e "$script" >actual &&
+ sed -n -e "$t6040_script" >actual &&
test_i18ncmp expect actual
'
@@ -160,6 +160,19 @@ test_expect_success 'status -s -b --no-ahead-behind (diverged from upstream)' '
'
cat >expect <<\EOF
+## b1...origin/master [different]
+EOF
+
+test_expect_success 'status.aheadbehind=false status -s -b (diverged from upstream)' '
+ (
+ cd test &&
+ git checkout b1 >/dev/null &&
+ git -c status.aheadbehind=false status -s -b | head -1
+ ) >actual &&
+ test_i18ncmp expect actual
+'
+
+cat >expect <<\EOF
On branch b1
Your branch and 'origin/master' have diverged,
and have 1 and 1 different commits each, respectively.
@@ -174,6 +187,15 @@ test_expect_success 'status --long --branch' '
test_i18ncmp expect actual
'
+test_expect_success 'status --long --branch' '
+ (
+ cd test &&
+ git checkout b1 >/dev/null &&
+ git -c status.aheadbehind=true status --long -b | head -3
+ ) >actual &&
+ test_i18ncmp expect actual
+'
+
cat >expect <<\EOF
On branch b1
Your branch and 'origin/master' refer to different commits.
@@ -188,6 +210,15 @@ test_expect_success 'status --long --branch --no-ahead-behind' '
test_i18ncmp expect actual
'
+test_expect_success 'status.aheadbehind=false status --long --branch' '
+ (
+ cd test &&
+ git checkout b1 >/dev/null &&
+ git -c status.aheadbehind=false status --long -b | head -2
+ ) >actual &&
+ test_i18ncmp expect actual
+'
+
cat >expect <<\EOF
## b5...brokenbase [gone]
EOF
diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh
index 93f23cfa82..8a72b4c43a 100755
--- a/t/t6200-fmt-merge-msg.sh
+++ b/t/t6200-fmt-merge-msg.sh
@@ -66,12 +66,7 @@ test_expect_success setup '
git commit -a -m "Right #5" &&
git checkout -b long &&
- i=0 &&
- while test $i -lt 30
- do
- test_commit $i one &&
- i=$(($i+1))
- done &&
+ test_commit_bulk --start=0 --message=%s --filename=one 30 &&
git show-branch &&
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index d9235217fc..ab69aa176d 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -346,6 +346,32 @@ test_expect_success 'Verify descending sort' '
'
cat >expected <<\EOF
+refs/tags/testtag
+refs/tags/testtag-2
+EOF
+
+test_expect_success 'exercise patterns with prefixes' '
+ git tag testtag-2 &&
+ test_when_finished "git tag -d testtag-2" &&
+ git for-each-ref --format="%(refname)" \
+ refs/tags/testtag refs/tags/testtag-2 >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
+refs/tags/testtag
+refs/tags/testtag-2
+EOF
+
+test_expect_success 'exercise glob patterns with prefixes' '
+ git tag testtag-2 &&
+ test_when_finished "git tag -d testtag-2" &&
+ git for-each-ref --format="%(refname)" \
+ refs/tags/testtag "refs/tags/testtag-*" >actual &&
+ test_cmp expected actual
+'
+
+cat >expected <<\EOF
'refs/heads/master'
'refs/remotes/origin/master'
'refs/tags/testtag'
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/t7004-tag.sh b/t/t7004-tag.sh
index 6aeeb279a0..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 &&
diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh
index 00e09a375c..7976fa7bcc 100755
--- a/t/t7006-pager.sh
+++ b/t/t7006-pager.sh
@@ -7,6 +7,8 @@ test_description='Test automatic use of a pager.'
. "$TEST_DIRECTORY"/lib-terminal.sh
test_expect_success 'setup' '
+ : squelch advice messages during the transition &&
+ git config --global log.mailmap false &&
sane_unset GIT_PAGER GIT_PAGER_IN_USE &&
test_unconfig core.pager &&
diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index 53cf42fac1..d5218743e9 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -38,7 +38,6 @@ You have unmerged paths.
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
-
deleted by us: foo
no changes added to commit (use "git add" and/or "git commit -a")
@@ -143,7 +142,6 @@ You have unmerged paths.
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
-
both added: conflict.txt
deleted by them: main.txt
@@ -177,7 +175,6 @@ You have unmerged paths.
Unmerged paths:
(use "git add/rm <file>..." as appropriate to mark resolution)
-
both deleted: main.txt
added by them: sub_master.txt
added by us: sub_second.txt
@@ -201,12 +198,10 @@ You have unmerged paths.
(use "git merge --abort" to abort the merge)
Changes to be committed:
-
new file: sub_master.txt
Unmerged paths:
(use "git rm <file>..." to mark resolution)
-
both deleted: main.txt
Untracked files not listed (use -u option to show untracked files)
diff --git a/t/t7064-wtstatus-pv2.sh b/t/t7064-wtstatus-pv2.sh
index 11eccc231a..537787e598 100755
--- a/t/t7064-wtstatus-pv2.sh
+++ b/t/t7064-wtstatus-pv2.sh
@@ -445,6 +445,14 @@ test_expect_success 'verify --[no-]ahead-behind with V2 format' '
EOF
git status --ahead-behind --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual &&
+
+ # Confirm that "status.aheadbehind" DOES NOT work on V2 format.
+ git -c status.aheadbehind=false status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual &&
+
+ # Confirm that "status.aheadbehind" DOES NOT work on V2 format.
+ git -c status.aheadbehind=true status --porcelain=v2 --branch --untracked-files=all >actual &&
test_cmp expect actual
)
'
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 5990299fc9..b696bae5f5 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -249,7 +249,7 @@ test_expect_success 'checkout to detach HEAD (with advice declined)' '
test_expect_success 'checkout to detach HEAD' '
git config advice.detachedHead true &&
git checkout -f renamer && git clean -f &&
- GIT_TEST_GETTEXT_POISON= git checkout renamer^ 2>messages &&
+ GIT_TEST_GETTEXT_POISON=false git checkout renamer^ 2>messages &&
grep "HEAD is now at 7329388" messages &&
test_line_count -gt 1 messages &&
H=$(git rev-parse --verify HEAD) &&
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index 7b36954d63..a2c45d1902 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -669,4 +669,16 @@ test_expect_success 'git clean -d skips untracked dirs containing ignored files'
test_path_is_missing foo/b/bb
'
+test_expect_success MINGW 'handle clean & core.longpaths = false nicely' '
+ test_config core.longpaths false &&
+ a50=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&
+ mkdir -p $a50$a50/$a50$a50/$a50$a50 &&
+ : >"$a50$a50/test.txt" 2>"$a50$a50/$a50$a50/$a50$a50/test.txt" &&
+ # create a temporary outside the working tree to hide from "git clean"
+ test_must_fail git clean -xdf 2>.git/err &&
+ # grepping for a strerror string is unportable but it is OK here with
+ # MINGW prereq
+ test_i18ngrep "too long" .git/err
+'
+
test_done
diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh
index 706ae762e0..6b2aa917e1 100755
--- a/t/t7407-submodule-foreach.sh
+++ b/t/t7407-submodule-foreach.sh
@@ -421,4 +421,11 @@ test_expect_success 'option-like arguments passed to foreach commands are not lo
test_cmp expected actual
'
+test_expect_success 'option-like arguments passed to foreach recurse correctly' '
+ git -C clone2 submodule foreach --recursive "echo be --an-option" >expect &&
+ git -C clone2 submodule foreach --recursive echo be --an-option >actual &&
+ grep -e "--an-option" expect &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t7502-commit-porcelain.sh b/t/t7502-commit-porcelain.sh
index 5733d9cd34..14c92e4c25 100755
--- a/t/t7502-commit-porcelain.sh
+++ b/t/t7502-commit-porcelain.sh
@@ -402,7 +402,7 @@ echo editor started >"$(pwd)/.git/result"
exit 0
EOF
-test_expect_success !AUTOIDENT 'do not fire editor when committer is bogus' '
+test_expect_success !FAIL_PREREQS,!AUTOIDENT 'do not fire editor when committer is bogus' '
>.git/result &&
echo >>negative &&
diff --git a/t/t7508-status.sh b/t/t7508-status.sh
index e1f11293e2..4e676cdce8 100755
--- a/t/t7508-status.sh
+++ b/t/t7508-status.sh
@@ -94,19 +94,16 @@ test_expect_success 'status --column' '
# (use "git pull" to merge the remote branch into yours)
#
# Changes to be committed:
-# (use "git reset HEAD <file>..." to unstage)
-#
+# (use "git restore --staged <file>..." to unstage)
# new file: dir2/added
#
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
-# (use "git checkout -- <file>..." to discard changes in working directory)
-#
+# (use "git restore <file>..." to discard changes in working directory)
# modified: dir1/modified
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
-#
# dir1/untracked dir2/untracked
# dir2/modified untracked
#
@@ -128,19 +125,16 @@ cat >expect <<\EOF
# (use "git pull" to merge the remote branch into yours)
#
# Changes to be committed:
-# (use "git reset HEAD <file>..." to unstage)
-#
+# (use "git restore --staged <file>..." to unstage)
# new file: dir2/added
#
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
-# (use "git checkout -- <file>..." to discard changes in working directory)
-#
+# (use "git restore <file>..." to discard changes in working directory)
# modified: dir1/modified
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
-#
# dir1/untracked
# dir2/modified
# dir2/untracked
@@ -278,24 +272,20 @@ and have 1 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
-
+ (use "git restore --staged <file>..." to unstage)
new file: dir2/added
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: dir1/modified
Untracked files:
(use "git add <file>..." to include in what will be committed)
-
dir2/modified
Ignored files:
(use "git add -f <file>..." to include in what will be committed)
-
.gitignore
dir1/untracked
dir2/untracked
@@ -347,19 +337,16 @@ and have 1 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
-
+ (use "git restore --staged <file>..." to unstage)
new file: dir2/added
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: dir1/modified
Ignored files:
(use "git add -f <file>..." to include in what will be committed)
-
.gitignore
dir1/untracked
dir2/modified
@@ -420,14 +407,12 @@ and have 1 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
-
+ (use "git restore --staged <file>..." to unstage)
new file: dir2/added
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: dir1/modified
Untracked files not listed (use -u option to show untracked files)
@@ -484,19 +469,16 @@ and have 1 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
-
+ (use "git restore --staged <file>..." to unstage)
new file: dir2/added
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: dir1/modified
Untracked files:
(use "git add <file>..." to include in what will be committed)
-
dir1/untracked
dir2/modified
dir2/untracked
@@ -542,19 +524,16 @@ and have 1 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
-
+ (use "git restore --staged <file>..." to unstage)
new file: dir2/added
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: dir1/modified
Untracked files:
(use "git add <file>..." to include in what will be committed)
-
dir1/untracked
dir2/modified
dir2/untracked
@@ -605,19 +584,16 @@ and have 1 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
-
+ (use "git restore --staged <file>..." to unstage)
new file: ../dir2/added
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: modified
Untracked files:
(use "git add <file>..." to include in what will be committed)
-
untracked
../dir2/modified
../dir2/untracked
@@ -676,19 +652,16 @@ and have 1 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
-
+ (use "git restore --staged <file>..." to unstage)
<GREEN>new file: dir2/added<RESET>
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
<RED>modified: dir1/modified<RESET>
Untracked files:
(use "git add <file>..." to include in what will be committed)
-
<BLUE>dir1/untracked<RESET>
<BLUE>dir2/modified<RESET>
<BLUE>dir2/untracked<RESET>
@@ -802,19 +775,16 @@ and have 1 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
-
+ (use "git restore --staged <file>..." to unstage)
new file: dir2/added
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: dir1/modified
Untracked files:
(use "git add <file>..." to include in what will be committed)
-
dir1/untracked
dir2/modified
dir2/untracked
@@ -852,13 +822,11 @@ and have 1 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
-
+ (use "git restore --staged <file>..." to unstage)
modified: dir1/modified
Untracked files:
(use "git add <file>..." to include in what will be committed)
-
dir1/untracked
dir2/
untracked
@@ -896,20 +864,17 @@ and have 1 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
-
+ (use "git restore --staged <file>..." to unstage)
new file: dir2/added
new file: sm
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: dir1/modified
Untracked files:
(use "git add <file>..." to include in what will be committed)
-
dir1/untracked
dir2/modified
dir2/untracked
@@ -956,15 +921,13 @@ and have 1 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
-
+ (use "git restore --staged <file>..." to unstage)
new file: dir2/added
new file: sm
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: dir1/modified
Submodule changes to be committed:
@@ -974,7 +937,6 @@ Submodule changes to be committed:
Untracked files:
(use "git add <file>..." to include in what will be committed)
-
dir1/untracked
dir2/modified
dir2/untracked
@@ -1019,13 +981,11 @@ and have 2 and 2 different commits each, respectively.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: dir1/modified
Untracked files:
(use "git add <file>..." to include in what will be committed)
-
dir1/untracked
dir2/modified
dir2/untracked
@@ -1068,15 +1028,13 @@ and have 2 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
Changes to be committed:
- (use "git reset HEAD^1 <file>..." to unstage)
-
+ (use "git restore --source=HEAD^1 --staged <file>..." to unstage)
new file: dir2/added
new file: sm
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: dir1/modified
Submodule changes to be committed:
@@ -1086,7 +1044,6 @@ Submodule changes to be committed:
Untracked files:
(use "git add <file>..." to include in what will be committed)
-
dir1/untracked
dir2/modified
dir2/untracked
@@ -1123,14 +1080,12 @@ and have 2 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
-
+ (use "git restore --staged <file>..." to unstage)
modified: sm
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: dir1/modified
Submodule changes to be committed:
@@ -1140,7 +1095,6 @@ Submodule changes to be committed:
Untracked files:
(use "git add <file>..." to include in what will be committed)
-
.gitmodules
dir1/untracked
dir2/modified
@@ -1235,15 +1189,13 @@ and have 2 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
-
+ (use "git restore --staged <file>..." to unstage)
modified: sm
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
+ (use "git restore <file>..." to discard changes in working directory)
(commit or discard the untracked or modified content in submodules)
-
modified: dir1/modified
modified: sm (modified content)
@@ -1254,7 +1206,6 @@ Submodule changes to be committed:
Untracked files:
(use "git add <file>..." to include in what will be committed)
-
.gitmodules
dir1/untracked
dir2/modified
@@ -1295,14 +1246,12 @@ and have 2 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
-
+ (use "git restore --staged <file>..." to unstage)
modified: sm
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: dir1/modified
modified: sm (new commits)
@@ -1318,7 +1267,6 @@ Submodules changed but not updated:
Untracked files:
(use "git add <file>..." to include in what will be committed)
-
.gitmodules
dir1/untracked
dir2/modified
@@ -1379,14 +1327,12 @@ cat > expect << EOF
; (use "git pull" to merge the remote branch into yours)
;
; Changes to be committed:
-; (use "git reset HEAD <file>..." to unstage)
-;
+; (use "git restore --staged <file>..." to unstage)
; modified: sm
;
; Changes not staged for commit:
; (use "git add <file>..." to update what will be committed)
-; (use "git checkout -- <file>..." to discard changes in working directory)
-;
+; (use "git restore <file>..." to discard changes in working directory)
; modified: dir1/modified
; modified: sm (new commits)
;
@@ -1402,7 +1348,6 @@ cat > expect << EOF
;
; Untracked files:
; (use "git add <file>..." to include in what will be committed)
-;
; .gitmodules
; dir1/untracked
; dir2/modified
@@ -1431,13 +1376,11 @@ and have 2 and 2 different commits each, respectively.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: dir1/modified
Untracked files:
(use "git add <file>..." to include in what will be committed)
-
.gitmodules
dir1/untracked
dir2/modified
@@ -1458,19 +1401,16 @@ and have 2 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
-
+ (use "git restore --staged <file>..." to unstage)
modified: sm
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: dir1/modified
Untracked files:
(use "git add <file>..." to include in what will be committed)
-
.gitmodules
dir1/untracked
dir2/modified
@@ -1581,14 +1521,12 @@ and have 2 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
-
+ (use "git restore --staged <file>..." to unstage)
modified: sm
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: dir1/modified
Untracked files not listed (use -u option to show untracked files)
diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index c1eb72555d..e01c285cbf 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -33,7 +33,6 @@ You have unmerged paths.
Unmerged paths:
(use "git add <file>..." to mark resolution)
-
both modified: main.txt
no changes added to commit (use "git add" and/or "git commit -a")
@@ -54,7 +53,6 @@ All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
-
modified: main.txt
Untracked files not listed (use -u option to show untracked files)
@@ -85,9 +83,8 @@ You are currently rebasing branch '\''rebase_conflicts'\'' on '\''$ONTO'\''.
(use "git rebase --abort" to check out the original branch)
Unmerged paths:
- (use "git reset HEAD <file>..." to unstage)
+ (use "git restore --staged <file>..." to unstage)
(use "git add <file>..." to mark resolution)
-
both modified: main.txt
no changes added to commit (use "git add" and/or "git commit -a")
@@ -110,8 +107,7 @@ You are currently rebasing branch '\''rebase_conflicts'\'' on '\''$ONTO'\''.
(all conflicts fixed: run "git rebase --continue")
Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
-
+ (use "git restore --staged <file>..." to unstage)
modified: main.txt
Untracked files not listed (use -u option to show untracked files)
@@ -148,9 +144,8 @@ You are currently rebasing branch '\''rebase_i_conflicts_second'\'' on '\''$ONTO
(use "git rebase --abort" to check out the original branch)
Unmerged paths:
- (use "git reset HEAD <file>..." to unstage)
+ (use "git restore --staged <file>..." to unstage)
(use "git add <file>..." to mark resolution)
-
both modified: main.txt
no changes added to commit (use "git add" and/or "git commit -a")
@@ -176,8 +171,7 @@ You are currently rebasing branch '\''rebase_i_conflicts_second'\'' on '\''$ONTO
(all conflicts fixed: run "git rebase --continue")
Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
-
+ (use "git restore --staged <file>..." to unstage)
modified: main.txt
Untracked files not listed (use -u option to show untracked files)
@@ -246,8 +240,7 @@ You are currently splitting a commit while rebasing branch '\''split_commit'\''
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: main.txt
no changes added to commit (use "git add" and/or "git commit -a")
@@ -354,8 +347,7 @@ You are currently splitting a commit while rebasing branch '\''several_edits'\''
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: main.txt
no changes added to commit (use "git add" and/or "git commit -a")
@@ -453,8 +445,7 @@ You are currently splitting a commit while rebasing branch '\''several_edits'\''
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: main.txt
no changes added to commit (use "git add" and/or "git commit -a")
@@ -557,8 +548,7 @@ You are currently splitting a commit while rebasing branch '\''several_edits'\''
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
- (use "git checkout -- <file>..." to discard changes in working directory)
-
+ (use "git restore <file>..." to discard changes in working directory)
modified: main.txt
no changes added to commit (use "git add" and/or "git commit -a")
@@ -747,7 +737,6 @@ You are currently cherry-picking commit $TO_CHERRY_PICK.
Unmerged paths:
(use "git add <file>..." to mark resolution)
-
both modified: main.txt
no changes added to commit (use "git add" and/or "git commit -a")
@@ -771,7 +760,6 @@ You are currently cherry-picking commit $TO_CHERRY_PICK.
(use "git cherry-pick --abort" to cancel the cherry-pick operation)
Changes to be committed:
-
modified: main.txt
Untracked files not listed (use -u option to show untracked files)
@@ -798,6 +786,22 @@ EOF
test_i18ncmp expected actual
'
+test_expect_success 'status shows cherry-pick with invalid oid' '
+ mkdir .git/sequencer &&
+ test_write_lines "pick invalid-oid" >.git/sequencer/todo &&
+ git status --untracked-files=no >actual 2>err &&
+ git cherry-pick --quit &&
+ test_must_be_empty err &&
+ test_i18ncmp expected actual
+'
+
+test_expect_success 'status does not show error if .git/sequencer is a file' '
+ test_when_finished "rm .git/sequencer" &&
+ test_write_lines hello >.git/sequencer &&
+ git status --untracked-files=no 2>err &&
+ test_must_be_empty err
+'
+
test_expect_success 'status showing detached at and from a tag' '
test_commit atag tagging &&
git checkout atag &&
@@ -834,9 +838,8 @@ 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
no changes added to commit (use "git add" and/or "git commit -a")
@@ -855,8 +858,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
Untracked files not listed (use -u option to show untracked files)
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/t7610-mergetool.sh b/t/t7610-mergetool.sh
index 5b61c10a9c..ad288ddc69 100755
--- a/t/t7610-mergetool.sh
+++ b/t/t7610-mergetool.sh
@@ -131,17 +131,21 @@ test_expect_success 'custom mergetool' '
git checkout -b test$test_count branch1 &&
git submodule update -N &&
test_must_fail git merge master &&
- ( yes "" | git mergetool both ) &&
- ( yes "" | git mergetool file1 file1 ) &&
- ( yes "" | git mergetool file2 "spaced name" ) &&
- ( yes "" | git mergetool subdir/file3 ) &&
- ( yes "d" | git mergetool file11 ) &&
- ( yes "d" | git mergetool file12 ) &&
- ( yes "l" | git mergetool submod ) &&
- test "$(cat file1)" = "master updated" &&
- test "$(cat file2)" = "master new" &&
- test "$(cat subdir/file3)" = "master new sub" &&
- test "$(cat submod/bar)" = "branch1 submodule" &&
+ yes "" | git mergetool both &&
+ yes "" | git mergetool file1 file1 &&
+ yes "" | git mergetool file2 "spaced name" &&
+ yes "" | git mergetool subdir/file3 &&
+ yes "d" | git mergetool file11 &&
+ yes "d" | git mergetool file12 &&
+ yes "l" | git mergetool submod &&
+ echo "master updated" >expect &&
+ test_cmp expect file1 &&
+ echo "master new" >expect &&
+ test_cmp expect file2 &&
+ echo "master new sub" >expect &&
+ test_cmp expect subdir/file3 &&
+ echo "branch1 submodule" >expect &&
+ test_cmp expect submod/bar &&
git commit -m "branch1 resolved with mergetool"
'
@@ -153,17 +157,21 @@ test_expect_success 'gui mergetool' '
git checkout -b test$test_count branch1 &&
git submodule update -N &&
test_must_fail git merge master &&
- ( yes "" | git mergetool --gui both ) &&
- ( yes "" | git mergetool -g file1 file1 ) &&
- ( yes "" | git mergetool --gui file2 "spaced name" ) &&
- ( yes "" | git mergetool --gui subdir/file3 ) &&
- ( yes "d" | git mergetool --gui file11 ) &&
- ( yes "d" | git mergetool --gui file12 ) &&
- ( yes "l" | git mergetool --gui submod ) &&
- test "$(cat file1)" = "gui master updated" &&
- test "$(cat file2)" = "gui master new" &&
- test "$(cat subdir/file3)" = "gui master new sub" &&
- test "$(cat submod/bar)" = "branch1 submodule" &&
+ yes "" | git mergetool --gui both &&
+ yes "" | git mergetool -g file1 file1 &&
+ yes "" | git mergetool --gui file2 "spaced name" &&
+ yes "" | git mergetool --gui subdir/file3 &&
+ yes "d" | git mergetool --gui file11 &&
+ yes "d" | git mergetool --gui file12 &&
+ yes "l" | git mergetool --gui submod &&
+ echo "gui master updated" >expect &&
+ test_cmp expect file1 &&
+ echo "gui master new" >expect &&
+ test_cmp expect file2 &&
+ echo "gui master new sub" >expect &&
+ test_cmp expect subdir/file3 &&
+ echo "branch1 submodule" >expect &&
+ test_cmp expect submod/bar &&
git commit -m "branch1 resolved with mergetool"
'
@@ -172,17 +180,21 @@ test_expect_success 'gui mergetool without merge.guitool set falls back to merge
git checkout -b test$test_count branch1 &&
git submodule update -N &&
test_must_fail git merge master &&
- ( yes "" | git mergetool --gui both ) &&
- ( yes "" | git mergetool -g file1 file1 ) &&
- ( yes "" | git mergetool --gui file2 "spaced name" ) &&
- ( yes "" | git mergetool --gui subdir/file3 ) &&
- ( yes "d" | git mergetool --gui file11 ) &&
- ( yes "d" | git mergetool --gui file12 ) &&
- ( yes "l" | git mergetool --gui submod ) &&
- test "$(cat file1)" = "master updated" &&
- test "$(cat file2)" = "master new" &&
- test "$(cat subdir/file3)" = "master new sub" &&
- test "$(cat submod/bar)" = "branch1 submodule" &&
+ yes "" | git mergetool --gui both &&
+ yes "" | git mergetool -g file1 file1 &&
+ yes "" | git mergetool --gui file2 "spaced name" &&
+ yes "" | git mergetool --gui subdir/file3 &&
+ yes "d" | git mergetool --gui file11 &&
+ yes "d" | git mergetool --gui file12 &&
+ yes "l" | git mergetool --gui submod &&
+ echo "master updated" >expect &&
+ test_cmp expect file1 &&
+ echo "master new" >expect &&
+ test_cmp expect file2 &&
+ echo "master new sub" >expect &&
+ test_cmp expect subdir/file3 &&
+ echo "branch1 submodule" >expect &&
+ test_cmp expect submod/bar &&
git commit -m "branch1 resolved with mergetool"
'
@@ -195,19 +207,20 @@ test_expect_success 'mergetool crlf' '
test_config core.autocrlf true &&
git checkout -b test$test_count branch1 &&
test_must_fail git merge master &&
- ( yes "" | git mergetool file1 ) &&
- ( yes "" | git mergetool file2 ) &&
- ( yes "" | git mergetool "spaced name" ) &&
- ( yes "" | git mergetool both ) &&
- ( yes "" | git mergetool subdir/file3 ) &&
- ( yes "d" | git mergetool file11 ) &&
- ( yes "d" | git mergetool file12 ) &&
- ( yes "r" | git mergetool submod ) &&
+ yes "" | git mergetool file1 &&
+ yes "" | git mergetool file2 &&
+ yes "" | git mergetool "spaced name" &&
+ yes "" | git mergetool both &&
+ yes "" | git mergetool subdir/file3 &&
+ yes "d" | git mergetool file11 &&
+ yes "d" | git mergetool file12 &&
+ yes "r" | git mergetool submod &&
test "$(printf x | cat file1 -)" = "$(printf "master updated\r\nx")" &&
test "$(printf x | cat file2 -)" = "$(printf "master new\r\nx")" &&
test "$(printf x | cat subdir/file3 -)" = "$(printf "master new sub\r\nx")" &&
git submodule update -N &&
- test "$(cat submod/bar)" = "master submodule" &&
+ echo "master submodule" >expect &&
+ test_cmp expect submod/bar &&
git commit -m "branch1 resolved with mergetool - autocrlf"
'
@@ -218,8 +231,9 @@ test_expect_success 'mergetool in subdir' '
(
cd subdir &&
test_must_fail git merge master &&
- ( yes "" | git mergetool file3 ) &&
- test "$(cat file3)" = "master new sub"
+ yes "" | git mergetool file3 &&
+ echo "master new sub" >expect &&
+ test_cmp expect file3
)
'
@@ -230,16 +244,19 @@ test_expect_success 'mergetool on file in parent dir' '
(
cd subdir &&
test_must_fail git merge master &&
- ( yes "" | git mergetool file3 ) &&
- ( yes "" | git mergetool ../file1 ) &&
- ( yes "" | git mergetool ../file2 ../spaced\ name ) &&
- ( yes "" | git mergetool ../both ) &&
- ( yes "d" | git mergetool ../file11 ) &&
- ( yes "d" | git mergetool ../file12 ) &&
- ( yes "l" | git mergetool ../submod ) &&
- test "$(cat ../file1)" = "master updated" &&
- test "$(cat ../file2)" = "master new" &&
- test "$(cat ../submod/bar)" = "branch1 submodule" &&
+ yes "" | git mergetool file3 &&
+ yes "" | git mergetool ../file1 &&
+ yes "" | git mergetool ../file2 ../spaced\ name &&
+ yes "" | git mergetool ../both &&
+ yes "d" | git mergetool ../file11 &&
+ yes "d" | git mergetool ../file12 &&
+ yes "l" | git mergetool ../submod &&
+ echo "master updated" >expect &&
+ test_cmp expect ../file1 &&
+ echo "master new" >expect &&
+ test_cmp expect ../file2 &&
+ echo "branch1 submodule" >expect &&
+ test_cmp expect ../submod/bar &&
git commit -m "branch1 resolved with mergetool - subdir"
)
'
@@ -250,9 +267,9 @@ test_expect_success 'mergetool skips autoresolved' '
git submodule update -N &&
test_must_fail git merge master &&
test -n "$(git ls-files -u)" &&
- ( yes "d" | git mergetool file11 ) &&
- ( yes "d" | git mergetool file12 ) &&
- ( yes "l" | git mergetool submod ) &&
+ yes "d" | git mergetool file11 &&
+ yes "d" | git mergetool file12 &&
+ yes "l" | git mergetool submod &&
output="$(git mergetool --no-prompt)" &&
test "$output" = "No files need merging"
'
@@ -264,13 +281,17 @@ test_expect_success 'mergetool merges all from subdir (rerere disabled)' '
(
cd subdir &&
test_must_fail git merge master &&
- ( yes "r" | git mergetool ../submod ) &&
- ( yes "d" "d" | git mergetool --no-prompt ) &&
- test "$(cat ../file1)" = "master updated" &&
- test "$(cat ../file2)" = "master new" &&
- test "$(cat file3)" = "master new sub" &&
+ yes "r" | git mergetool ../submod &&
+ yes "d" "d" | git mergetool --no-prompt &&
+ echo "master updated" >expect &&
+ test_cmp expect ../file1 &&
+ echo "master new" >expect &&
+ test_cmp expect ../file2 &&
+ echo "master new sub" >expect &&
+ test_cmp expect file3 &&
( cd .. && git submodule update -N ) &&
- test "$(cat ../submod/bar)" = "master submodule" &&
+ echo "master submodule" >expect &&
+ test_cmp expect ../submod/bar &&
git commit -m "branch2 resolved by mergetool from subdir"
)
'
@@ -283,13 +304,17 @@ test_expect_success 'mergetool merges all from subdir (rerere enabled)' '
(
cd subdir &&
test_must_fail git merge master &&
- ( yes "r" | git mergetool ../submod ) &&
- ( yes "d" "d" | git mergetool --no-prompt ) &&
- test "$(cat ../file1)" = "master updated" &&
- test "$(cat ../file2)" = "master new" &&
- test "$(cat file3)" = "master new sub" &&
+ yes "r" | git mergetool ../submod &&
+ yes "d" "d" | git mergetool --no-prompt &&
+ echo "master updated" >expect &&
+ test_cmp expect ../file1 &&
+ echo "master new" >expect &&
+ test_cmp expect ../file2 &&
+ echo "master new sub" >expect &&
+ test_cmp expect file3 &&
( cd .. && git submodule update -N ) &&
- test "$(cat ../submod/bar)" = "master submodule" &&
+ echo "master submodule" >expect &&
+ test_cmp expect ../submod/bar &&
git commit -m "branch2 resolved by mergetool from subdir"
)
'
@@ -301,8 +326,8 @@ test_expect_success 'mergetool skips resolved paths when rerere is active' '
git checkout -b test$test_count branch1 &&
git submodule update -N &&
test_must_fail git merge master &&
- ( yes "l" | git mergetool --no-prompt submod ) &&
- ( yes "d" "d" | git mergetool --no-prompt ) &&
+ yes "l" | git mergetool --no-prompt submod &&
+ yes "d" "d" | git mergetool --no-prompt &&
git submodule update -N &&
output="$(yes "n" | git mergetool --no-prompt)" &&
test "$output" = "No files need merging"
@@ -343,9 +368,10 @@ test_expect_success 'mergetool takes partial path' '
git submodule update -N &&
test_must_fail git merge master &&
- ( yes "" | git mergetool subdir ) &&
+ yes "" | git mergetool subdir &&
- test "$(cat subdir/file3)" = "master new sub"
+ echo "master new sub" >expect &&
+ test_cmp expect subdir/file3
'
test_expect_success 'mergetool delete/delete conflict' '
@@ -410,14 +436,16 @@ test_expect_success 'deleted vs modified submodule' '
git checkout -b test$test_count.a test$test_count &&
test_must_fail git merge master &&
test -n "$(git ls-files -u)" &&
- ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) &&
- ( yes "" | git mergetool both ) &&
- ( yes "d" | git mergetool file11 file12 ) &&
- ( yes "r" | git mergetool submod ) &&
+ yes "" | git mergetool file1 file2 spaced\ name subdir/file3 &&
+ yes "" | git mergetool both &&
+ yes "d" | git mergetool file11 file12 &&
+ yes "r" | git mergetool submod &&
rmdir submod && mv submod-movedaside submod &&
- test "$(cat submod/bar)" = "branch1 submodule" &&
+ echo "branch1 submodule" >expect &&
+ test_cmp expect submod/bar &&
git submodule update -N &&
- test "$(cat submod/bar)" = "master submodule" &&
+ echo "master submodule" >expect &&
+ test_cmp expect submod/bar &&
output="$(git mergetool --no-prompt)" &&
test "$output" = "No files need merging" &&
git commit -m "Merge resolved by keeping module" &&
@@ -427,10 +455,10 @@ test_expect_success 'deleted vs modified submodule' '
git submodule update -N &&
test_must_fail git merge master &&
test -n "$(git ls-files -u)" &&
- ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) &&
- ( yes "" | git mergetool both ) &&
- ( yes "d" | git mergetool file11 file12 ) &&
- ( yes "l" | git mergetool submod ) &&
+ yes "" | git mergetool file1 file2 spaced\ name subdir/file3 &&
+ yes "" | git mergetool both &&
+ yes "d" | git mergetool file11 file12 &&
+ yes "l" | git mergetool submod &&
test ! -e submod &&
output="$(git mergetool --no-prompt)" &&
test "$output" = "No files need merging" &&
@@ -441,10 +469,10 @@ test_expect_success 'deleted vs modified submodule' '
git submodule update -N &&
test_must_fail git merge test$test_count &&
test -n "$(git ls-files -u)" &&
- ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) &&
- ( yes "" | git mergetool both ) &&
- ( yes "d" | git mergetool file11 file12 ) &&
- ( yes "r" | git mergetool submod ) &&
+ yes "" | git mergetool file1 file2 spaced\ name subdir/file3 &&
+ yes "" | git mergetool both &&
+ yes "d" | git mergetool file11 file12 &&
+ yes "r" | git mergetool submod &&
test ! -e submod &&
test -d submod.orig &&
git submodule update -N &&
@@ -457,13 +485,15 @@ test_expect_success 'deleted vs modified submodule' '
git submodule update -N &&
test_must_fail git merge test$test_count &&
test -n "$(git ls-files -u)" &&
- ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) &&
- ( yes "" | git mergetool both ) &&
- ( yes "d" | git mergetool file11 file12 ) &&
- ( yes "l" | git mergetool submod ) &&
- test "$(cat submod/bar)" = "master submodule" &&
- git submodule update -N &&
- test "$(cat submod/bar)" = "master submodule" &&
+ yes "" | git mergetool file1 file2 spaced\ name subdir/file3 &&
+ yes "" | git mergetool both &&
+ yes "d" | git mergetool file11 file12 &&
+ yes "l" | git mergetool submod &&
+ echo "master submodule" >expect &&
+ test_cmp expect submod/bar &&
+ git submodule update -N &&
+ echo "master submodule" >expect &&
+ test_cmp expect submod/bar &&
output="$(git mergetool --no-prompt)" &&
test "$output" = "No files need merging" &&
git commit -m "Merge resolved by keeping module"
@@ -481,14 +511,16 @@ test_expect_success 'file vs modified submodule' '
git checkout -b test$test_count.a branch1 &&
test_must_fail git merge master &&
test -n "$(git ls-files -u)" &&
- ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) &&
- ( yes "" | git mergetool both ) &&
- ( yes "d" | git mergetool file11 file12 ) &&
- ( yes "r" | git mergetool submod ) &&
+ yes "" | git mergetool file1 file2 spaced\ name subdir/file3 &&
+ yes "" | git mergetool both &&
+ yes "d" | git mergetool file11 file12 &&
+ yes "r" | git mergetool submod &&
rmdir submod && mv submod-movedaside submod &&
- test "$(cat submod/bar)" = "branch1 submodule" &&
+ echo "branch1 submodule" >expect &&
+ test_cmp expect submod/bar &&
git submodule update -N &&
- test "$(cat submod/bar)" = "master submodule" &&
+ echo "master submodule" >expect &&
+ test_cmp expect submod/bar &&
output="$(git mergetool --no-prompt)" &&
test "$output" = "No files need merging" &&
git commit -m "Merge resolved by keeping module" &&
@@ -497,12 +529,13 @@ test_expect_success 'file vs modified submodule' '
git checkout -b test$test_count.b test$test_count &&
test_must_fail git merge master &&
test -n "$(git ls-files -u)" &&
- ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) &&
- ( yes "" | git mergetool both ) &&
- ( yes "d" | git mergetool file11 file12 ) &&
- ( yes "l" | git mergetool submod ) &&
+ yes "" | git mergetool file1 file2 spaced\ name subdir/file3 &&
+ yes "" | git mergetool both &&
+ yes "d" | git mergetool file11 file12 &&
+ yes "l" | git mergetool submod &&
git submodule update -N &&
- test "$(cat submod)" = "not a submodule" &&
+ echo "not a submodule" >expect &&
+ test_cmp expect submod &&
output="$(git mergetool --no-prompt)" &&
test "$output" = "No files need merging" &&
git commit -m "Merge resolved by keeping file" &&
@@ -513,13 +546,14 @@ test_expect_success 'file vs modified submodule' '
git submodule update -N &&
test_must_fail git merge test$test_count &&
test -n "$(git ls-files -u)" &&
- ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) &&
- ( yes "" | git mergetool both ) &&
- ( yes "d" | git mergetool file11 file12 ) &&
- ( yes "r" | git mergetool submod ) &&
+ yes "" | git mergetool file1 file2 spaced\ name subdir/file3 &&
+ yes "" | git mergetool both &&
+ yes "d" | git mergetool file11 file12 &&
+ yes "r" | git mergetool submod &&
test -d submod.orig &&
git submodule update -N &&
- test "$(cat submod)" = "not a submodule" &&
+ echo "not a submodule" >expect &&
+ test_cmp expect submod &&
output="$(git mergetool --no-prompt)" &&
test "$output" = "No files need merging" &&
git commit -m "Merge resolved by keeping file" &&
@@ -529,13 +563,15 @@ test_expect_success 'file vs modified submodule' '
git submodule update -N &&
test_must_fail git merge test$test_count &&
test -n "$(git ls-files -u)" &&
- ( yes "" | git mergetool file1 file2 spaced\ name subdir/file3 ) &&
- ( yes "" | git mergetool both ) &&
- ( yes "d" | git mergetool file11 file12 ) &&
- ( yes "l" | git mergetool submod ) &&
- test "$(cat submod/bar)" = "master submodule" &&
- git submodule update -N &&
- test "$(cat submod/bar)" = "master submodule" &&
+ yes "" | git mergetool file1 file2 spaced\ name subdir/file3 &&
+ yes "" | git mergetool both &&
+ yes "d" | git mergetool file11 file12 &&
+ yes "l" | git mergetool submod &&
+ echo "master submodule" >expect &&
+ test_cmp expect submod/bar &&
+ git submodule update -N &&
+ echo "master submodule" >expect &&
+ test_cmp expect submod/bar &&
output="$(git mergetool --no-prompt)" &&
test "$output" = "No files need merging" &&
git commit -m "Merge resolved by keeping module"
@@ -587,19 +623,23 @@ test_expect_success 'submodule in subdirectory' '
test_must_fail git merge test$test_count.a &&
(
cd subdir &&
- ( yes "l" | git mergetool subdir_module )
+ yes "l" | git mergetool subdir_module
) &&
- test "$(cat subdir/subdir_module/file15)" = "test$test_count.b" &&
+ echo "test$test_count.b" >expect &&
+ test_cmp expect subdir/subdir_module/file15 &&
git submodule update -N &&
- test "$(cat subdir/subdir_module/file15)" = "test$test_count.b" &&
+ echo "test$test_count.b" >expect &&
+ test_cmp expect subdir/subdir_module/file15 &&
git reset --hard &&
git submodule update -N &&
test_must_fail git merge test$test_count.a &&
- ( yes "r" | git mergetool subdir/subdir_module ) &&
- test "$(cat subdir/subdir_module/file15)" = "test$test_count.b" &&
+ yes "r" | git mergetool subdir/subdir_module &&
+ echo "test$test_count.b" >expect &&
+ test_cmp expect subdir/subdir_module/file15 &&
git submodule update -N &&
- test "$(cat subdir/subdir_module/file15)" = "test$test_count.a" &&
+ echo "test$test_count.a" >expect &&
+ test_cmp expect subdir/subdir_module/file15 &&
git commit -m "branch1 resolved with mergetool"
'
@@ -615,22 +655,25 @@ test_expect_success 'directory vs modified submodule' '
test_must_fail git merge master &&
test -n "$(git ls-files -u)" &&
- ( yes "l" | git mergetool submod ) &&
- test "$(cat submod/file16)" = "not a submodule" &&
+ yes "l" | git mergetool submod &&
+ echo "not a submodule" >expect &&
+ test_cmp expect submod/file16 &&
rm -rf submod.orig &&
git reset --hard &&
test_must_fail git merge master &&
test -n "$(git ls-files -u)" &&
test ! -e submod.orig &&
- ( yes "r" | git mergetool submod ) &&
+ yes "r" | git mergetool submod &&
test -d submod.orig &&
- test "$(cat submod.orig/file16)" = "not a submodule" &&
+ echo "not a submodule" >expect &&
+ test_cmp expect submod.orig/file16 &&
rm -r submod.orig &&
mv submod-movedaside/.git submod &&
( cd submod && git clean -f && git reset --hard ) &&
git submodule update -N &&
- test "$(cat submod/bar)" = "master submodule" &&
+ echo "master submodule" >expect &&
+ test_cmp expect submod/bar &&
git reset --hard &&
rm -rf submod-movedaside &&
@@ -638,17 +681,19 @@ test_expect_success 'directory vs modified submodule' '
git submodule update -N &&
test_must_fail git merge test$test_count &&
test -n "$(git ls-files -u)" &&
- ( yes "l" | git mergetool submod ) &&
+ yes "l" | git mergetool submod &&
git submodule update -N &&
- test "$(cat submod/bar)" = "master submodule" &&
+ echo "master submodule" >expect &&
+ test_cmp expect submod/bar &&
git reset --hard &&
git submodule update -N &&
test_must_fail git merge test$test_count &&
test -n "$(git ls-files -u)" &&
test ! -e submod.orig &&
- ( yes "r" | git mergetool submod ) &&
- test "$(cat submod/file16)" = "not a submodule" &&
+ yes "r" | git mergetool submod &&
+ echo "not a submodule" >expect &&
+ test_cmp expect submod/file16 &&
git reset --hard master &&
( cd submod && git clean -f && git reset --hard ) &&
diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh
index 86d05160a3..0e9af832c9 100755
--- a/t/t7700-repack.sh
+++ b/t/t7700-repack.sh
@@ -239,4 +239,14 @@ test_expect_success 'bitmaps can be disabled on bare repos' '
test -z "$bitmap"
'
+test_expect_success 'no bitmaps created if .keep files present' '
+ pack=$(ls bare.git/objects/pack/*.pack) &&
+ test_path_is_file "$pack" &&
+ keep=${pack%.pack}.keep &&
+ >"$keep" &&
+ git -C bare.git repack -ad &&
+ find bare.git/objects/pack/ -type f -name "*.bitmap" >actual &&
+ test_must_be_empty actual
+'
+
test_done
diff --git a/t/t7814-grep-recurse-submodules.sh b/t/t7814-grep-recurse-submodules.sh
index 134a694516..a11366b4ce 100755
--- a/t/t7814-grep-recurse-submodules.sh
+++ b/t/t7814-grep-recurse-submodules.sh
@@ -14,12 +14,14 @@ test_expect_success 'setup directory structure and submodule' '
echo "(3|4)" >b/b &&
git add a b &&
git commit -m "add a and b" &&
+ test_tick &&
git init submodule &&
echo "(1|2)d(3|4)" >submodule/a &&
git -C submodule add a &&
git -C submodule commit -m "add a" &&
git submodule add ./submodule &&
- git commit -m "added submodule"
+ git commit -m "added submodule" &&
+ test_tick
'
test_expect_success 'grep correctly finds patterns in a submodule' '
@@ -65,11 +67,14 @@ test_expect_success 'grep and nested submodules' '
echo "(1|2)d(3|4)" >submodule/sub/a &&
git -C submodule/sub add a &&
git -C submodule/sub commit -m "add a" &&
+ test_tick &&
git -C submodule submodule add ./sub &&
git -C submodule add sub &&
git -C submodule commit -m "added sub" &&
+ test_tick &&
git add submodule &&
git commit -m "updated submodule" &&
+ test_tick &&
cat >expect <<-\EOF &&
a:(1|2)d(3|4)
@@ -179,15 +184,18 @@ test_expect_success !MINGW 'grep recurse submodule colon in name' '
echo "(1|2)d(3|4)" >"parent/fi:le" &&
git -C parent add "fi:le" &&
git -C parent commit -m "add fi:le" &&
+ test_tick &&
git init "su:b" &&
test_when_finished "rm -rf su:b" &&
echo "(1|2)d(3|4)" >"su:b/fi:le" &&
git -C "su:b" add "fi:le" &&
git -C "su:b" commit -m "add fi:le" &&
+ test_tick &&
git -C parent submodule add "../su:b" "su:b" &&
git -C parent commit -m "add submodule" &&
+ test_tick &&
cat >expect <<-\EOF &&
fi:le:(1|2)d(3|4)
@@ -210,15 +218,18 @@ test_expect_success 'grep history with moved submoules' '
echo "(1|2)d(3|4)" >parent/file &&
git -C parent add file &&
git -C parent commit -m "add file" &&
+ test_tick &&
git init sub &&
test_when_finished "rm -rf sub" &&
echo "(1|2)d(3|4)" >sub/file &&
git -C sub add file &&
git -C sub commit -m "add file" &&
+ test_tick &&
git -C parent submodule add ../sub dir/sub &&
git -C parent commit -m "add submodule" &&
+ test_tick &&
cat >expect <<-\EOF &&
dir/sub/file:(1|2)d(3|4)
@@ -229,6 +240,7 @@ test_expect_success 'grep history with moved submoules' '
git -C parent mv dir/sub sub-moved &&
git -C parent commit -m "moved submodule" &&
+ test_tick &&
cat >expect <<-\EOF &&
file:(1|2)d(3|4)
@@ -251,6 +263,7 @@ test_expect_success 'grep using relative path' '
echo "(1|2)d(3|4)" >sub/file &&
git -C sub add file &&
git -C sub commit -m "add file" &&
+ test_tick &&
git init parent &&
echo "(1|2)d(3|4)" >parent/file &&
@@ -260,6 +273,7 @@ test_expect_success 'grep using relative path' '
git -C parent add src/file2 &&
git -C parent submodule add ../sub &&
git -C parent commit -m "add files and submodule" &&
+ test_tick &&
# From top works
cat >expect <<-\EOF &&
@@ -293,6 +307,7 @@ test_expect_success 'grep from a subdir' '
echo "(1|2)d(3|4)" >sub/file &&
git -C sub add file &&
git -C sub commit -m "add file" &&
+ test_tick &&
git init parent &&
mkdir parent/src &&
@@ -301,6 +316,7 @@ test_expect_success 'grep from a subdir' '
git -C parent submodule add ../sub src/sub &&
git -C parent submodule add ../sub sub &&
git -C parent commit -m "add files and submodules" &&
+ test_tick &&
# Verify grep from root works
cat >expect <<-\EOF &&
diff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh
index c92a47b6d5..1c5fb1d1f8 100755
--- a/t/t8003-blame-corner-cases.sh
+++ b/t/t8003-blame-corner-cases.sh
@@ -275,4 +275,40 @@ test_expect_success 'blame file with CRLF core.autocrlf=true' '
grep "A U Thor" actual
'
+# Tests the splitting and merging of blame entries in blame_coalesce().
+# The output of blame is the same, regardless of whether blame_coalesce() runs
+# or not, so we'd likely only notice a problem if blame crashes or assigned
+# blame to the "splitting" commit ('SPLIT' below).
+test_expect_success 'blame coalesce' '
+ cat >giraffe <<-\EOF &&
+ ABC
+ DEF
+ EOF
+ git add giraffe &&
+ git commit -m "original file" &&
+ oid=$(git rev-parse HEAD) &&
+
+ cat >giraffe <<-\EOF &&
+ ABC
+ SPLIT
+ DEF
+ EOF
+ git add giraffe &&
+ git commit -m "interior SPLIT line" &&
+
+ cat >giraffe <<-\EOF &&
+ ABC
+ DEF
+ EOF
+ git add giraffe &&
+ git commit -m "same contents as original" &&
+
+ cat >expect <<-EOF &&
+ $oid 1) ABC
+ $oid 2) DEF
+ EOF
+ git -c core.abbrev=40 blame -s giraffe >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t8013-blame-ignore-revs.sh b/t/t8013-blame-ignore-revs.sh
new file mode 100755
index 0000000000..36dc31eb39
--- /dev/null
+++ b/t/t8013-blame-ignore-revs.sh
@@ -0,0 +1,274 @@
+#!/bin/sh
+
+test_description='ignore revisions when blaming'
+. ./test-lib.sh
+
+# Creates:
+# A--B--X
+# A added line 1 and B added line 2. X makes changes to those lines. Sanity
+# check that X is blamed for both lines.
+test_expect_success setup '
+ test_commit A file line1 &&
+
+ echo line2 >>file &&
+ git add file &&
+ test_tick &&
+ git commit -m B &&
+ git tag B &&
+
+ test_write_lines line-one line-two >file &&
+ git add file &&
+ test_tick &&
+ git commit -m X &&
+ git tag X &&
+
+ git blame --line-porcelain file >blame_raw &&
+
+ grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual &&
+ git rev-parse X >expect &&
+ test_cmp expect actual &&
+
+ grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual &&
+ git rev-parse X >expect &&
+ test_cmp expect actual
+ '
+
+# Ignore X, make sure A is blamed for line 1 and B for line 2.
+test_expect_success ignore_rev_changing_lines '
+ git blame --line-porcelain --ignore-rev X file >blame_raw &&
+
+ grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual &&
+ git rev-parse A >expect &&
+ test_cmp expect actual &&
+
+ grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual &&
+ git rev-parse B >expect &&
+ test_cmp expect actual
+ '
+
+# For ignored revs that have added 'unblamable' lines, attribute those to the
+# ignored commit.
+# A--B--X--Y
+# Where Y changes lines 1 and 2, and adds lines 3 and 4. The added lines ought
+# to have nothing in common with "line-one" or "line-two", to keep any
+# heuristics from matching them with any lines in the parent.
+test_expect_success ignore_rev_adding_unblamable_lines '
+ test_write_lines line-one-change line-two-changed y3 y4 >file &&
+ git add file &&
+ test_tick &&
+ git commit -m Y &&
+ git tag Y &&
+
+ git rev-parse Y >expect &&
+ git blame --line-porcelain file --ignore-rev Y >blame_raw &&
+
+ grep -E "^[0-9a-f]+ [0-9]+ 3" blame_raw | sed -e "s/ .*//" >actual &&
+ test_cmp expect actual &&
+
+ grep -E "^[0-9a-f]+ [0-9]+ 4" blame_raw | sed -e "s/ .*//" >actual &&
+ test_cmp expect actual
+ '
+
+# Ignore X and Y, both in separate files. Lines 1 == A, 2 == B.
+test_expect_success ignore_revs_from_files '
+ git rev-parse X >ignore_x &&
+ git rev-parse Y >ignore_y &&
+ git blame --line-porcelain file --ignore-revs-file ignore_x --ignore-revs-file ignore_y >blame_raw &&
+
+ grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual &&
+ git rev-parse A >expect &&
+ test_cmp expect actual &&
+
+ grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual &&
+ git rev-parse B >expect &&
+ test_cmp expect actual
+ '
+
+# Ignore X from the config option, Y from a file.
+test_expect_success ignore_revs_from_configs_and_files '
+ git config --add blame.ignoreRevsFile ignore_x &&
+ git blame --line-porcelain file --ignore-revs-file ignore_y >blame_raw &&
+
+ grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual &&
+ git rev-parse A >expect &&
+ test_cmp expect actual &&
+
+ grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual &&
+ git rev-parse B >expect &&
+ test_cmp expect actual
+ '
+
+# Override blame.ignoreRevsFile (ignore_x) with an empty string. X should be
+# blamed now for lines 1 and 2, since we are no longer ignoring X.
+test_expect_success override_ignore_revs_file '
+ git blame --line-porcelain file --ignore-revs-file "" --ignore-revs-file ignore_y >blame_raw &&
+ git rev-parse X >expect &&
+
+ grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual &&
+ test_cmp expect actual &&
+
+ grep -E "^[0-9a-f]+ [0-9]+ 2" blame_raw | sed -e "s/ .*//" >actual &&
+ test_cmp expect actual
+ '
+test_expect_success bad_files_and_revs '
+ test_must_fail git blame file --ignore-rev NOREV 2>err &&
+ test_i18ngrep "cannot find revision NOREV to ignore" err &&
+
+ test_must_fail git blame file --ignore-revs-file NOFILE 2>err &&
+ test_i18ngrep "could not open.*: NOFILE" err &&
+
+ echo NOREV >ignore_norev &&
+ test_must_fail git blame file --ignore-revs-file ignore_norev 2>err &&
+ test_i18ngrep "invalid object name: NOREV" err
+ '
+
+# For ignored revs that have added 'unblamable' lines, mark those lines with a
+# '*'
+# A--B--X--Y
+# Lines 3 and 4 are from Y and unblamable. This was set up in
+# ignore_rev_adding_unblamable_lines.
+test_expect_success mark_unblamable_lines '
+ git config --add blame.markUnblamableLines true &&
+
+ git blame --ignore-rev Y file >blame_raw &&
+ echo "*" >expect &&
+
+ sed -n "3p" blame_raw | cut -c1 >actual &&
+ test_cmp expect actual &&
+
+ sed -n "4p" blame_raw | cut -c1 >actual &&
+ test_cmp expect actual
+ '
+
+# Commit Z will touch the first two lines. Y touched all four.
+# A--B--X--Y--Z
+# The blame output when ignoring Z should be:
+# ?Y ... 1)
+# ?Y ... 2)
+# Y ... 3)
+# Y ... 4)
+# We're checking only the first character
+test_expect_success mark_ignored_lines '
+ git config --add blame.markIgnoredLines true &&
+
+ test_write_lines line-one-Z line-two-Z y3 y4 >file &&
+ git add file &&
+ test_tick &&
+ git commit -m Z &&
+ git tag Z &&
+
+ git blame --ignore-rev Z file >blame_raw &&
+ echo "?" >expect &&
+
+ sed -n "1p" blame_raw | cut -c1 >actual &&
+ test_cmp expect actual &&
+
+ sed -n "2p" blame_raw | cut -c1 >actual &&
+ test_cmp expect actual &&
+
+ sed -n "3p" blame_raw | cut -c1 >actual &&
+ ! test_cmp expect actual &&
+
+ sed -n "4p" blame_raw | cut -c1 >actual &&
+ ! test_cmp expect actual
+ '
+
+# For ignored revs that added 'unblamable' lines and more recent commits changed
+# the blamable lines, mark the unblamable lines with a
+# '*'
+# A--B--X--Y--Z
+# Lines 3 and 4 are from Y and unblamable, as set up in
+# ignore_rev_adding_unblamable_lines. Z changed lines 1 and 2.
+test_expect_success mark_unblamable_lines_intermediate '
+ git config --add blame.markUnblamableLines true &&
+
+ git blame --ignore-rev Y file >blame_raw 2>stderr &&
+ echo "*" >expect &&
+
+ sed -n "3p" blame_raw | cut -c1 >actual &&
+ test_cmp expect actual &&
+
+ sed -n "4p" blame_raw | cut -c1 >actual &&
+ test_cmp expect actual
+ '
+
+# The heuristic called by guess_line_blames() tries to find the size of a
+# blame_entry 'e' in the parent's address space. Those calculations need to
+# check for negative or zero values for when a blame entry is completely outside
+# the window of the parent's version of a file.
+#
+# This happens when one commit adds several lines (commit B below). A later
+# commit (C) changes one line in the middle of B's change. Commit C gets blamed
+# for its change, and that breaks up B's change into multiple blame entries.
+# When processing B, one of the blame_entries is outside A's window (which was
+# zero - it had no lines added on its side of the diff).
+#
+# A--B--C, ignore B to test the ignore heuristic's boundary checks.
+test_expect_success ignored_chunk_negative_parent_size '
+ rm -rf .git/ &&
+ git init &&
+
+ test_write_lines L1 L2 L7 L8 L9 >file &&
+ git add file &&
+ test_tick &&
+ git commit -m A &&
+ git tag A &&
+
+ test_write_lines L1 L2 L3 L4 L5 L6 L7 L8 L9 >file &&
+ git add file &&
+ test_tick &&
+ git commit -m B &&
+ git tag B &&
+
+ test_write_lines L1 L2 L3 L4 xxx L6 L7 L8 L9 >file &&
+ git add file &&
+ test_tick &&
+ git commit -m C &&
+ git tag C &&
+
+ git blame file --ignore-rev B >blame_raw
+ '
+
+# Resetting the repo and creating:
+#
+# A--B--M
+# \ /
+# C-+
+#
+# 'A' creates a file. B changes line 1, and C changes line 9. M merges.
+test_expect_success ignore_merge '
+ rm -rf .git/ &&
+ git init &&
+
+ test_write_lines L1 L2 L3 L4 L5 L6 L7 L8 L9 >file &&
+ git add file &&
+ test_tick &&
+ git commit -m A &&
+ git tag A &&
+
+ test_write_lines BB L2 L3 L4 L5 L6 L7 L8 L9 >file &&
+ git add file &&
+ test_tick &&
+ git commit -m B &&
+ git tag B &&
+
+ git reset --hard A &&
+ test_write_lines L1 L2 L3 L4 L5 L6 L7 L8 CC >file &&
+ git add file &&
+ test_tick &&
+ git commit -m C &&
+ git tag C &&
+
+ test_merge M B &&
+ git blame --line-porcelain file --ignore-rev M >blame_raw &&
+
+ grep -E "^[0-9a-f]+ [0-9]+ 1" blame_raw | sed -e "s/ .*//" >actual &&
+ git rev-parse B >expect &&
+ test_cmp expect actual &&
+
+ grep -E "^[0-9a-f]+ [0-9]+ 9" blame_raw | sed -e "s/ .*//" >actual &&
+ git rev-parse C >expect &&
+ test_cmp expect actual
+ '
+
+test_done
diff --git a/t/t8014-blame-ignore-fuzzy.sh b/t/t8014-blame-ignore-fuzzy.sh
new file mode 100755
index 0000000000..6e61882b6f
--- /dev/null
+++ b/t/t8014-blame-ignore-fuzzy.sh
@@ -0,0 +1,437 @@
+#!/bin/sh
+
+test_description='git blame ignore fuzzy heuristic'
+. ./test-lib.sh
+
+pick_author='s/^[0-9a-f^]* *(\([^ ]*\) .*/\1/'
+
+# Each test is composed of 4 variables:
+# titleN - the test name
+# aN - the initial content
+# bN - the final content
+# expectedN - the line numbers from aN that we expect git blame
+# on bN to identify, or "Final" if bN itself should
+# be identified as the origin of that line.
+
+# We start at test 2 because setup will show as test 1
+title2="Regression test for partially overlapping search ranges"
+cat <<EOF >a2
+1
+2
+3
+abcdef
+5
+6
+7
+ijkl
+9
+10
+11
+pqrs
+13
+14
+15
+wxyz
+17
+18
+19
+EOF
+cat <<EOF >b2
+abcde
+ijk
+pqr
+wxy
+EOF
+cat <<EOF >expected2
+4
+8
+12
+16
+EOF
+
+title3="Combine 3 lines into 2"
+cat <<EOF >a3
+if ((maxgrow==0) ||
+ ( single_line_field && (field->dcols < maxgrow)) ||
+ (!single_line_field && (field->drows < maxgrow)))
+EOF
+cat <<EOF >b3
+if ((maxgrow == 0) || (single_line_field && (field->dcols < maxgrow)) ||
+ (!single_line_field && (field->drows < maxgrow))) {
+EOF
+cat <<EOF >expected3
+2
+3
+EOF
+
+title4="Add curly brackets"
+cat <<EOF >a4
+ if (rows) *rows = field->rows;
+ if (cols) *cols = field->cols;
+ if (frow) *frow = field->frow;
+ if (fcol) *fcol = field->fcol;
+EOF
+cat <<EOF >b4
+ if (rows) {
+ *rows = field->rows;
+ }
+ if (cols) {
+ *cols = field->cols;
+ }
+ if (frow) {
+ *frow = field->frow;
+ }
+ if (fcol) {
+ *fcol = field->fcol;
+ }
+EOF
+cat <<EOF >expected4
+1
+1
+Final
+2
+2
+Final
+3
+3
+Final
+4
+4
+Final
+EOF
+
+
+title5="Combine many lines and change case"
+cat <<EOF >a5
+for(row=0,pBuffer=field->buf;
+ row<height;
+ row++,pBuffer+=width )
+{
+ if ((len = (int)( After_End_Of_Data( pBuffer, width ) - pBuffer )) > 0)
+ {
+ wmove( win, row, 0 );
+ waddnstr( win, pBuffer, len );
+EOF
+cat <<EOF >b5
+for (Row = 0, PBuffer = field->buf; Row < Height; Row++, PBuffer += Width) {
+ if ((Len = (int)(afterEndOfData(PBuffer, Width) - PBuffer)) > 0) {
+ wmove(win, Row, 0);
+ waddnstr(win, PBuffer, Len);
+EOF
+cat <<EOF >expected5
+1
+5
+7
+8
+EOF
+
+title6="Rename and combine lines"
+cat <<EOF >a6
+bool need_visual_update = ((form != (FORM *)0) &&
+ (form->status & _POSTED) &&
+ (form->current==field));
+
+if (need_visual_update)
+ Synchronize_Buffer(form);
+
+if (single_line_field)
+{
+ growth = field->cols * amount;
+ if (field->maxgrow)
+ growth = Minimum(field->maxgrow - field->dcols,growth);
+ field->dcols += growth;
+ if (field->dcols == field->maxgrow)
+EOF
+cat <<EOF >b6
+bool NeedVisualUpdate = ((Form != (FORM *)0) && (Form->status & _POSTED) &&
+ (Form->current == field));
+
+if (NeedVisualUpdate) {
+ synchronizeBuffer(Form);
+}
+
+if (SingleLineField) {
+ Growth = field->cols * amount;
+ if (field->maxgrow) {
+ Growth = Minimum(field->maxgrow - field->dcols, Growth);
+ }
+ field->dcols += Growth;
+ if (field->dcols == field->maxgrow) {
+EOF
+cat <<EOF >expected6
+1
+3
+4
+5
+6
+Final
+7
+8
+10
+11
+12
+Final
+13
+14
+EOF
+
+# Both lines match identically so position must be used to tie-break.
+title7="Same line twice"
+cat <<EOF >a7
+abc
+abc
+EOF
+cat <<EOF >b7
+abcd
+abcd
+EOF
+cat <<EOF >expected7
+1
+2
+EOF
+
+title8="Enforce line order"
+cat <<EOF >a8
+abcdef
+ghijkl
+ab
+EOF
+cat <<EOF >b8
+ghijk
+abcd
+EOF
+cat <<EOF >expected8
+2
+3
+EOF
+
+title9="Expand lines and rename variables"
+cat <<EOF >a9
+int myFunction(int ArgumentOne, Thing *ArgTwo, Blah XuglyBug) {
+ Squiggle FabulousResult = squargle(ArgumentOne, *ArgTwo,
+ XuglyBug) + EwwwGlobalWithAReallyLongNameYepTooLong;
+ return FabulousResult * 42;
+}
+EOF
+cat <<EOF >b9
+int myFunction(int argument_one, Thing *arg_asdfgh,
+ Blah xugly_bug) {
+ Squiggle fabulous_result = squargle(argument_one,
+ *arg_asdfgh, xugly_bug)
+ + g_ewww_global_with_a_really_long_name_yep_too_long;
+ return fabulous_result * 42;
+}
+EOF
+cat <<EOF >expected9
+1
+1
+2
+3
+3
+4
+5
+EOF
+
+title10="Two close matches versus one less close match"
+cat <<EOF >a10
+abcdef
+abcdef
+ghijkl
+EOF
+cat <<EOF >b10
+gh
+abcdefx
+EOF
+cat <<EOF >expected10
+Final
+2
+EOF
+
+# The first line of b matches best with the last line of a, but the overall
+# match is better if we match it with the the first line of a.
+title11="Piggy in the middle"
+cat <<EOF >a11
+abcdefg
+ijklmn
+abcdefgh
+EOF
+cat <<EOF >b11
+abcdefghx
+ijklm
+EOF
+cat <<EOF >expected11
+1
+2
+EOF
+
+title12="No trailing newline"
+printf "abc\ndef" >a12
+printf "abx\nstu" >b12
+cat <<EOF >expected12
+1
+Final
+EOF
+
+title13="Reorder includes"
+cat <<EOF >a13
+#include "c.h"
+#include "b.h"
+#include "a.h"
+#include "e.h"
+#include "d.h"
+EOF
+cat <<EOF >b13
+#include "a.h"
+#include "b.h"
+#include "c.h"
+#include "d.h"
+#include "e.h"
+EOF
+cat <<EOF >expected13
+3
+2
+1
+5
+4
+EOF
+
+last_test=13
+
+test_expect_success setup '
+ for i in $(test_seq 2 $last_test)
+ do
+ # Append each line in a separate commit to make it easy to
+ # check which original line the blame output relates to.
+
+ line_count=0 &&
+ while IFS= read line
+ do
+ line_count=$((line_count+1)) &&
+ echo "$line" >>"$i" &&
+ git add "$i" &&
+ test_tick &&
+ GIT_AUTHOR_NAME="$line_count" git commit -m "$line_count"
+ done <"a$i"
+ done &&
+
+ for i in $(test_seq 2 $last_test)
+ do
+ # Overwrite the files with the final content.
+ cp b$i $i &&
+ git add $i
+ done &&
+ test_tick &&
+
+ # Commit the final content all at once so it can all be
+ # referred to with the same commit ID.
+ GIT_AUTHOR_NAME=Final git commit -m Final &&
+
+ IGNOREME=$(git rev-parse HEAD)
+'
+
+for i in $(test_seq 2 $last_test); do
+ eval title="\$title$i"
+ test_expect_success "$title" \
+ "git blame -M9 --ignore-rev $IGNOREME $i >output &&
+ sed -e \"$pick_author\" output >actual &&
+ test_cmp expected$i actual"
+done
+
+# This invoked a null pointer dereference when the chunk callback was called
+# with a zero length parent chunk and there were no more suspects.
+test_expect_success 'Diff chunks with no suspects' '
+ test_write_lines xy1 A B C xy1 >file &&
+ git add file &&
+ test_tick &&
+ GIT_AUTHOR_NAME=1 git commit -m 1 &&
+
+ test_write_lines xy2 A B xy2 C xy2 >file &&
+ git add file &&
+ test_tick &&
+ GIT_AUTHOR_NAME=2 git commit -m 2 &&
+ REV_2=$(git rev-parse HEAD) &&
+
+ test_write_lines xy3 A >file &&
+ git add file &&
+ test_tick &&
+ GIT_AUTHOR_NAME=3 git commit -m 3 &&
+ REV_3=$(git rev-parse HEAD) &&
+
+ test_write_lines 1 1 >expected &&
+
+ git blame --ignore-rev $REV_2 --ignore-rev $REV_3 file >output &&
+ sed -e "$pick_author" output >actual &&
+
+ test_cmp expected actual
+ '
+
+test_expect_success 'position matching' '
+ test_write_lines abc def >file2 &&
+ git add file2 &&
+ test_tick &&
+ GIT_AUTHOR_NAME=1 git commit -m 1 &&
+
+ test_write_lines abc def abc def >file2 &&
+ git add file2 &&
+ test_tick &&
+ GIT_AUTHOR_NAME=2 git commit -m 2 &&
+
+ test_write_lines abcx defx abcx defx >file2 &&
+ git add file2 &&
+ test_tick &&
+ GIT_AUTHOR_NAME=3 git commit -m 3 &&
+ REV_3=$(git rev-parse HEAD) &&
+
+ test_write_lines abcy defy abcx defx >file2 &&
+ git add file2 &&
+ test_tick &&
+ GIT_AUTHOR_NAME=4 git commit -m 4 &&
+ REV_4=$(git rev-parse HEAD) &&
+
+ test_write_lines 1 1 2 2 >expected &&
+
+ git blame --ignore-rev $REV_3 --ignore-rev $REV_4 file2 >output &&
+ sed -e "$pick_author" output >actual &&
+
+ test_cmp expected actual
+ '
+
+# This fails if each blame entry is processed independently instead of
+# processing each diff change in full.
+test_expect_success 'preserve order' '
+ test_write_lines bcde >file3 &&
+ git add file3 &&
+ test_tick &&
+ GIT_AUTHOR_NAME=1 git commit -m 1 &&
+
+ test_write_lines bcde fghij >file3 &&
+ git add file3 &&
+ test_tick &&
+ GIT_AUTHOR_NAME=2 git commit -m 2 &&
+
+ test_write_lines bcde fghij abcd >file3 &&
+ git add file3 &&
+ test_tick &&
+ GIT_AUTHOR_NAME=3 git commit -m 3 &&
+
+ test_write_lines abcdx fghijx bcdex >file3 &&
+ git add file3 &&
+ test_tick &&
+ GIT_AUTHOR_NAME=4 git commit -m 4 &&
+ REV_4=$(git rev-parse HEAD) &&
+
+ test_write_lines abcdx fghijy bcdex >file3 &&
+ git add file3 &&
+ test_tick &&
+ GIT_AUTHOR_NAME=5 git commit -m 5 &&
+ REV_5=$(git rev-parse HEAD) &&
+
+ test_write_lines 1 2 3 >expected &&
+
+ git blame --ignore-rev $REV_4 --ignore-rev $REV_5 file3 >output &&
+ sed -e "$pick_author" output >actual &&
+
+ test_cmp expected actual
+ '
+
+test_done
diff --git a/t/t9801-git-p4-branch.sh b/t/t9801-git-p4-branch.sh
index 38d6b9043b..67ff2711f5 100755
--- a/t/t9801-git-p4-branch.sh
+++ b/t/t9801-git-p4-branch.sh
@@ -411,6 +411,46 @@ test_expect_failure 'git p4 clone file subset branch' '
)
'
+# Check that excluded files are omitted during import
+test_expect_success 'git p4 clone complex branches with excluded files' '
+ test_when_finished cleanup_git &&
+ test_create_repo "$git" &&
+ (
+ cd "$git" &&
+ git config git-p4.branchList branch1:branch2 &&
+ git config --add git-p4.branchList branch1:branch3 &&
+ git config --add git-p4.branchList branch1:branch4 &&
+ git config --add git-p4.branchList branch1:branch5 &&
+ git config --add git-p4.branchList branch1:branch6 &&
+ git p4 clone --dest=. --detect-branches -//depot/branch1/file2 -//depot/branch2/file2 -//depot/branch3/file2 -//depot/branch4/file2 -//depot/branch5/file2 -//depot/branch6/file2 //depot@all &&
+ git log --all --graph --decorate --stat &&
+ git reset --hard p4/depot/branch1 &&
+ test_path_is_file file1 &&
+ test_path_is_missing file2 &&
+ test_path_is_file file3 &&
+ git reset --hard p4/depot/branch2 &&
+ test_path_is_file file1 &&
+ test_path_is_missing file2 &&
+ test_path_is_missing file3 &&
+ git reset --hard p4/depot/branch3 &&
+ test_path_is_file file1 &&
+ test_path_is_missing file2 &&
+ test_path_is_missing file3 &&
+ git reset --hard p4/depot/branch4 &&
+ test_path_is_file file1 &&
+ test_path_is_missing file2 &&
+ test_path_is_file file3 &&
+ git reset --hard p4/depot/branch5 &&
+ test_path_is_file file1 &&
+ test_path_is_missing file2 &&
+ test_path_is_file file3 &&
+ git reset --hard p4/depot/branch6 &&
+ test_path_is_file file1 &&
+ test_path_is_missing file2 &&
+ test_path_is_missing file3
+ )
+'
+
# From a report in http://stackoverflow.com/questions/11893688
# where --use-client-spec caused branch prefixes not to be removed;
# every file in git appeared into a subdirectory of the branch name.
@@ -610,4 +650,96 @@ test_expect_success 'Update a file in git side and submit to P4 using client vie
)
'
+test_expect_success 'restart p4d (case folding enabled)' '
+ stop_and_cleanup_p4d &&
+ start_p4d -C1
+'
+
+#
+# 1: //depot/main/mf1
+# 2: integrate //depot/main/... -> //depot/branch1/...
+# 3: //depot/main/mf2
+# 4: //depot/BRANCH1/B1f3
+# 5: //depot/branch1/b1f4
+#
+test_expect_success !CASE_INSENSITIVE_FS 'basic p4 branches for case folding' '
+ (
+ cd "$cli" &&
+ mkdir -p main &&
+
+ echo mf1 >main/mf1 &&
+ p4 add main/mf1 &&
+ p4 submit -d "main/mf1" &&
+
+ p4 integrate //depot/main/... //depot/branch1/... &&
+ p4 submit -d "integrate main to branch1" &&
+
+ echo mf2 >main/mf2 &&
+ p4 add main/mf2 &&
+ p4 submit -d "main/mf2" &&
+
+ mkdir BRANCH1 &&
+ echo B1f3 >BRANCH1/B1f3 &&
+ p4 add BRANCH1/B1f3 &&
+ p4 submit -d "BRANCH1/B1f3" &&
+
+ echo b1f4 >branch1/b1f4 &&
+ p4 add branch1/b1f4 &&
+ p4 submit -d "branch1/b1f4"
+ )
+'
+
+# Check that files are properly split across branches when ignorecase is set
+test_expect_success !CASE_INSENSITIVE_FS 'git p4 clone, branchList branch definition, ignorecase' '
+ test_when_finished cleanup_git &&
+ test_create_repo "$git" &&
+ (
+ cd "$git" &&
+ git config git-p4.branchList main:branch1 &&
+ git config --type=bool core.ignoreCase true &&
+ git p4 clone --dest=. --detect-branches //depot@all &&
+
+ git log --all --graph --decorate --stat &&
+
+ git reset --hard p4/master &&
+ test_path_is_file mf1 &&
+ test_path_is_file mf2 &&
+ test_path_is_missing B1f3 &&
+ test_path_is_missing b1f4 &&
+
+ git reset --hard p4/depot/branch1 &&
+ test_path_is_file mf1 &&
+ test_path_is_missing mf2 &&
+ test_path_is_file B1f3 &&
+ test_path_is_file b1f4
+ )
+'
+
+# Check that files are properly split across branches when ignorecase is set, use-client-spec case
+test_expect_success !CASE_INSENSITIVE_FS 'git p4 clone with client-spec, branchList branch definition, ignorecase' '
+ client_view "//depot/... //client/..." &&
+ test_when_finished cleanup_git &&
+ test_create_repo "$git" &&
+ (
+ cd "$git" &&
+ git config git-p4.branchList main:branch1 &&
+ git config --type=bool core.ignoreCase true &&
+ git p4 clone --dest=. --use-client-spec --detect-branches //depot@all &&
+
+ git log --all --graph --decorate --stat &&
+
+ git reset --hard p4/master &&
+ test_path_is_file mf1 &&
+ test_path_is_file mf2 &&
+ test_path_is_missing B1f3 &&
+ test_path_is_missing b1f4 &&
+
+ git reset --hard p4/depot/branch1 &&
+ test_path_is_file mf1 &&
+ test_path_is_missing mf2 &&
+ test_path_is_file B1f3 &&
+ test_path_is_file b1f4
+ )
+'
+
test_done
diff --git a/t/t9817-git-p4-exclude.sh b/t/t9817-git-p4-exclude.sh
index 96d25f0c02..ec3d937c6a 100755
--- a/t/t9817-git-p4-exclude.sh
+++ b/t/t9817-git-p4-exclude.sh
@@ -22,7 +22,9 @@ test_expect_success 'create exclude repo' '
mkdir -p wanted discard &&
echo wanted >wanted/foo &&
echo discard >discard/foo &&
- p4 add wanted/foo discard/foo &&
+ echo discard_file >discard_file &&
+ echo discard_file_not >discard_file_not &&
+ p4 add wanted/foo discard/foo discard_file discard_file_not &&
p4 submit -d "initial revision"
)
'
@@ -33,7 +35,9 @@ test_expect_success 'check the repo was created correctly' '
(
cd "$git" &&
test_path_is_file wanted/foo &&
- test_path_is_file discard/foo
+ test_path_is_file discard/foo &&
+ test_path_is_file discard_file &&
+ test_path_is_file discard_file_not
)
'
@@ -43,7 +47,21 @@ test_expect_success 'clone, excluding part of repo' '
(
cd "$git" &&
test_path_is_file wanted/foo &&
- test_path_is_missing discard/foo
+ test_path_is_missing discard/foo &&
+ test_path_is_file discard_file &&
+ test_path_is_file discard_file_not
+ )
+'
+
+test_expect_success 'clone, excluding single file, no trailing /' '
+ test_when_finished cleanup_git &&
+ git p4 clone -//depot/discard_file --dest="$git" //depot/...@all &&
+ (
+ cd "$git" &&
+ test_path_is_file wanted/foo &&
+ test_path_is_file discard/foo &&
+ test_path_is_missing discard_file &&
+ test_path_is_file discard_file_not
)
'
@@ -52,15 +70,38 @@ test_expect_success 'clone, then sync with exclude' '
git p4 clone -//depot/discard/... --dest="$git" //depot/...@all &&
(
cd "$cli" &&
- p4 edit wanted/foo discard/foo &&
+ p4 edit wanted/foo discard/foo discard_file_not &&
date >>wanted/foo &&
date >>discard/foo &&
+ date >>discard_file_not &&
p4 submit -d "updating" &&
cd "$git" &&
git p4 sync -//depot/discard/... &&
test_path_is_file wanted/foo &&
- test_path_is_missing discard/foo
+ test_path_is_missing discard/foo &&
+ test_path_is_file discard_file &&
+ test_path_is_file discard_file_not
+ )
+'
+
+test_expect_success 'clone, then sync with exclude, no trailing /' '
+ test_when_finished cleanup_git &&
+ git p4 clone -//depot/discard/... -//depot/discard_file --dest="$git" //depot/...@all &&
+ (
+ cd "$cli" &&
+ p4 edit wanted/foo discard/foo discard_file_not &&
+ date >>wanted/foo &&
+ date >>discard/foo &&
+ date >>discard_file_not &&
+ p4 submit -d "updating" &&
+
+ cd "$git" &&
+ git p4 sync -//depot/discard/... -//depot/discard_file &&
+ test_path_is_file wanted/foo &&
+ test_path_is_missing discard/foo &&
+ test_path_is_missing discard_file &&
+ test_path_is_file discard_file_not
)
'
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 43cf313a1c..75512c3403 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -1706,7 +1706,7 @@ test_expect_success 'sourcing the completion script clears cached commands' '
'
test_expect_success 'sourcing the completion script clears cached merge strategies' '
- GIT_TEST_GETTEXT_POISON= &&
+ GIT_TEST_GETTEXT_POISON=false &&
__git_compute_merge_strategies &&
verbose test -n "$__git_merge_strategies" &&
. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh
index 5cadedb2a9..88bc733ad6 100755
--- a/t/t9903-bash-prompt.sh
+++ b/t/t9903-bash-prompt.sh
@@ -211,8 +211,24 @@ test_expect_success 'prompt - merge' '
test_expect_success 'prompt - cherry-pick' '
printf " (master|CHERRY-PICKING)" >expected &&
- test_must_fail git cherry-pick b1 &&
- test_when_finished "git reset --hard" &&
+ test_must_fail git cherry-pick b1 b1^ &&
+ test_when_finished "git cherry-pick --abort" &&
+ __git_ps1 >"$actual" &&
+ test_cmp expected "$actual" &&
+ git reset --merge &&
+ test_must_fail git rev-parse CHERRY_PICK_HEAD &&
+ __git_ps1 >"$actual" &&
+ test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - revert' '
+ printf " (master|REVERTING)" >expected &&
+ test_must_fail git revert b1^ b1 &&
+ test_when_finished "git revert --abort" &&
+ __git_ps1 >"$actual" &&
+ test_cmp expected "$actual" &&
+ git reset --merge &&
+ test_must_fail git rev-parse REVERT_HEAD &&
__git_ps1 >"$actual" &&
test_cmp expected "$actual"
'
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 7860491660..48bd3b467d 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -233,6 +233,129 @@ test_merge () {
git tag "$1"
}
+# Efficiently create <nr> commits, each with a unique number (from 1 to <nr>
+# by default) in the commit message.
+#
+# Usage: test_commit_bulk [options] <nr>
+# -C <dir>:
+# Run all git commands in directory <dir>
+# --ref=<n>:
+# ref on which to create commits (default: HEAD)
+# --start=<n>:
+# number commit messages from <n> (default: 1)
+# --message=<msg>:
+# use <msg> as the commit mesasge (default: "commit %s")
+# --filename=<fn>:
+# modify <fn> in each commit (default: %s.t)
+# --contents=<string>:
+# place <string> in each file (default: "content %s")
+# --id=<string>:
+# shorthand to use <string> and %s in message, filename, and contents
+#
+# The message, filename, and contents strings are evaluated by printf, with the
+# first "%s" replaced by the current commit number. So you can do:
+#
+# test_commit_bulk --filename=file --contents="modification %s"
+#
+# to have every commit touch the same file, but with unique content.
+#
+test_commit_bulk () {
+ tmpfile=.bulk-commit.input
+ indir=.
+ ref=HEAD
+ n=1
+ message='commit %s'
+ filename='%s.t'
+ contents='content %s'
+ while test $# -gt 0
+ do
+ case "$1" in
+ -C)
+ indir=$2
+ shift
+ ;;
+ --ref=*)
+ ref=${1#--*=}
+ ;;
+ --start=*)
+ n=${1#--*=}
+ ;;
+ --message=*)
+ message=${1#--*=}
+ ;;
+ --filename=*)
+ filename=${1#--*=}
+ ;;
+ --contents=*)
+ contents=${1#--*=}
+ ;;
+ --id=*)
+ message="${1#--*=} %s"
+ filename="${1#--*=}-%s.t"
+ contents="${1#--*=} %s"
+ ;;
+ -*)
+ BUG "invalid test_commit_bulk option: $1"
+ ;;
+ *)
+ break
+ ;;
+ esac
+ shift
+ done
+ total=$1
+
+ add_from=
+ if git -C "$indir" rev-parse --verify "$ref"
+ then
+ add_from=t
+ fi
+
+ while test "$total" -gt 0
+ do
+ test_tick &&
+ echo "commit $ref"
+ printf 'author %s <%s> %s\n' \
+ "$GIT_AUTHOR_NAME" \
+ "$GIT_AUTHOR_EMAIL" \
+ "$GIT_AUTHOR_DATE"
+ printf 'committer %s <%s> %s\n' \
+ "$GIT_COMMITTER_NAME" \
+ "$GIT_COMMITTER_EMAIL" \
+ "$GIT_COMMITTER_DATE"
+ echo "data <<EOF"
+ printf "$message\n" $n
+ echo "EOF"
+ if test -n "$add_from"
+ then
+ echo "from $ref^0"
+ add_from=
+ fi
+ printf "M 644 inline $filename\n" $n
+ echo "data <<EOF"
+ printf "$contents\n" $n
+ echo "EOF"
+ echo
+ n=$((n + 1))
+ total=$((total - 1))
+ done >"$tmpfile"
+
+ git -C "$indir" \
+ -c fastimport.unpacklimit=0 \
+ fast-import <"$tmpfile" || return 1
+
+ # This will be left in place on failure, which may aid debugging.
+ rm -f "$tmpfile"
+
+ # If we updated HEAD, then be nice and update the index and working
+ # tree, too.
+ if test "$ref" = "HEAD"
+ then
+ git -C "$indir" checkout -f HEAD || return 1
+ fi
+
+}
+
# This function helps systems where core.filemode=false is set.
# Use it instead of plain 'chmod +x' to set or unset the executable bit
# of a file in the working directory and add it to the index.
@@ -309,7 +432,7 @@ test_unset_prereq () {
}
test_set_prereq () {
- if test -n "$GIT_TEST_FAIL_PREREQS"
+ if test -n "$GIT_TEST_FAIL_PREREQS_INTERNAL"
then
case "$1" in
# The "!" case is handled below with
@@ -908,6 +1031,21 @@ test_cmp_rev () {
fi
}
+# Compare paths respecting core.ignoreCase
+test_cmp_fspath () {
+ if test "x$1" = "x$2"
+ then
+ return 0
+ fi
+
+ if test true != "$(git config --get --type=bool core.ignorecase)"
+ then
+ return 1
+ fi
+
+ test "x$(echo "$1" | tr A-Z a-z)" = "x$(echo "$2" | tr A-Z a-z)"
+}
+
# Print a sequence of integers in increasing order, either with
# two arguments (start and end):
#
@@ -1035,62 +1173,20 @@ perl () {
command "$PERL_PATH" "$@" 2>&7
} 7>&2 2>&4
-# Is the value one of the various ways to spell a boolean true/false?
-test_normalize_bool () {
- git -c magic.variable="$1" config --bool magic.variable 2>/dev/null
-}
-
-# Given a variable $1, normalize the value of it to one of "true",
-# "false", or "auto" and store the result to it.
-#
-# test_tristate GIT_TEST_HTTPD
-#
-# A variable set to an empty string is set to 'false'.
-# A variable set to 'false' or 'auto' keeps its value.
-# Anything else is set to 'true'.
-# An unset variable defaults to 'auto'.
-#
-# The last rule is to allow people to set the variable to an empty
-# string and export it to decline testing the particular feature
-# for versions both before and after this change. We used to treat
-# both unset and empty variable as a signal for "do not test" and
-# took any non-empty string as "please test".
-
-test_tristate () {
- if eval "test x\"\${$1+isset}\" = xisset"
- then
- # explicitly set
- eval "
- case \"\$$1\" in
- '') $1=false ;;
- auto) ;;
- *) $1=\$(test_normalize_bool \$$1 || echo true) ;;
- esac
- "
- else
- eval "$1=auto"
- fi
-}
-
# Exit the test suite, either by skipping all remaining tests or by
-# exiting with an error. If "$1" is "auto", we then we assume we were
-# opportunistically trying to set up some tests and we skip. If it is
-# "true", then we report a failure.
+# exiting with an error. If our prerequisite variable $1 falls back
+# on a default assume we were opportunistically trying to set up some
+# tests and we skip. If it is explicitly "true", then we report a failure.
#
# The error/skip message should be given by $2.
#
test_skip_or_die () {
- case "$1" in
- auto)
+ if ! git env--helper --type=bool --default=false --exit-code $1
+ then
skip_all=$2
test_done
- ;;
- true)
- error "$2"
- ;;
- *)
- error "BUG: test tristate is '$1' (real error: $2)"
- esac
+ fi
+ error "$2"
}
# The following mingw_* functions obey POSIX shell syntax, but are actually
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 4b346467df..30b07e310f 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -386,7 +386,6 @@ unset VISUAL EMAIL LANGUAGE COLUMNS $("$PERL_PATH" -e '
my @env = keys %ENV;
my $ok = join("|", qw(
TRACE
- TR2_
DEBUG
TEST
.*_TEST
@@ -1389,6 +1388,25 @@ yes () {
done
}
+# The GIT_TEST_FAIL_PREREQS code hooks into test_set_prereq(), and
+# thus needs to be set up really early, and set an internal variable
+# for convenience so the hot test_set_prereq() codepath doesn't need
+# to call "git env--helper". Only do that work if needed by seeing if
+# GIT_TEST_FAIL_PREREQS is set at all.
+GIT_TEST_FAIL_PREREQS_INTERNAL=
+if test -n "$GIT_TEST_FAIL_PREREQS"
+then
+ if git env--helper --type=bool --default=0 --exit-code GIT_TEST_FAIL_PREREQS
+ then
+ GIT_TEST_FAIL_PREREQS_INTERNAL=true
+ test_set_prereq FAIL_PREREQS
+ fi
+else
+ test_lazy_prereq FAIL_PREREQS '
+ git env--helper --type=bool --default=0 --exit-code GIT_TEST_FAIL_PREREQS
+ '
+fi
+
# Fix some commands on Windows
uname_s=$(uname -s)
case $uname_s in
@@ -1443,11 +1461,9 @@ then
unset GIT_TEST_GETTEXT_POISON_ORIG
fi
-# Can we rely on git's output in the C locale?
-if test -z "$GIT_TEST_GETTEXT_POISON"
-then
- test_set_prereq C_LOCALE_OUTPUT
-fi
+test_lazy_prereq C_LOCALE_OUTPUT '
+ ! git env--helper --type=bool --default=0 --exit-code GIT_TEST_GETTEXT_POISON
+'
if test -z "$GIT_TEST_CHECK_CACHE_TREE"
then
@@ -1607,7 +1623,3 @@ 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"
-'