aboutsummaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/README2
-rw-r--r--t/helper/test-config.c39
-rw-r--r--t/helper/test-dump-split-index.c2
-rw-r--r--t/helper/test-parse-options.c2
-rw-r--r--t/helper/test-submodule-config.c2
-rw-r--r--t/lib-git-svn.sh91
-rw-r--r--t/lib-httpd.sh9
-rw-r--r--t/lib-httpd/apache.conf4
-rw-r--r--t/lib-rebase.sh1
-rw-r--r--t/perf/README12
-rwxr-xr-xt/perf/p0003-delta-base-cache.sh31
-rwxr-xr-xt/perf/p3400-rebase.sh36
-rwxr-xr-xt/perf/p4211-line-log.sh6
-rwxr-xr-xt/perf/p5303-many-packs.sh87
-rwxr-xr-xt/perf/p5310-pack-bitmaps.sh14
-rw-r--r--t/perf/perf-lib.sh5
-rwxr-xr-xt/t0001-init.sh9
-rwxr-xr-xt/t0008-ignores.sh4
-rwxr-xr-xt/t0012-help.sh52
-rwxr-xr-xt/t0027-auto-crlf.sh6
-rwxr-xr-xt/t1006-cat-file.sh2
-rwxr-xr-xt/t1007-hash-object.sh43
-rwxr-xr-xt/t1011-read-tree-sparse-checkout.sh2
-rwxr-xr-xt/t1300-repo-config.sh8
-rwxr-xr-xt/t1301-shared-repo.sh41
-rwxr-xr-xt/t1302-repo-version.sh32
-rwxr-xr-xt/t1307-config-blob.sh5
-rwxr-xr-xt/t1308-config-set.sh39
-rwxr-xr-xt/t1350-config-hooks-path.sh6
-rwxr-xr-xt/t1400-update-ref.sh43
-rwxr-xr-xt/t1401-symbolic-ref.sh21
-rwxr-xr-xt/t1404-update-ref-df-conflicts.sh107
-rwxr-xr-xt/t1404-update-ref-errors.sh407
-rwxr-xr-xt/t1430-bad-ref-name.sh2
-rwxr-xr-xt/t1450-fsck.sh22
-rwxr-xr-xt/t1506-rev-parse-diagnosis.sh2
-rwxr-xr-xt/t2010-checkout-ambiguous.sh2
-rwxr-xr-xt/t2018-checkout-branch.sh2
-rwxr-xr-xt/t2025-worktree-add.sh16
-rwxr-xr-xt/t2028-worktree-move.sh62
-rwxr-xr-xt/t3101-ls-tree-dirname.sh2
-rwxr-xr-xt/t3200-branch.sh15
-rwxr-xr-xt/t3201-branch-contains.sh2
-rwxr-xr-xt/t3310-notes-merge-manual-resolve.sh8
-rwxr-xr-xt/t3320-notes-merge-worktrees.sh4
-rwxr-xr-xt/t3400-rebase.sh4
-rwxr-xr-xt/t3404-rebase-interactive.sh26
-rwxr-xr-xt/t3415-rebase-autosquash.sh33
-rwxr-xr-xt/t3420-rebase-autostash.sh4
-rwxr-xr-xt/t3700-add.sh65
-rwxr-xr-xt/t4012-diff-binary.sh4
-rwxr-xr-xt/t4013-diff-various.sh6
-rw-r--r--t/t4013/diff.diff_--line-prefix=abc_master_master^_side29
-rw-r--r--t/t4013/diff.diff_--line-prefix_--cached_--_file015
-rwxr-xr-xt/t4014-format-patch.sh81
-rwxr-xr-xt/t4018-diff-funcname.sh1
-rw-r--r--t/t4018/css-brace-in-col-15
-rw-r--r--t/t4018/css-colon-eol4
-rw-r--r--t/t4018/css-colon-selector5
-rw-r--r--t/t4018/css-common4
-rw-r--r--t/t4018/css-long-selector-list6
-rw-r--r--t/t4018/css-prop-sans-indent5
-rw-r--r--t/t4018/css-short-selector-list4
-rw-r--r--t/t4018/css-trailing-space5
-rwxr-xr-xt/t4021-format-patch-numbered.sh17
-rwxr-xr-xt/t4026-color.sh9
-rwxr-xr-xt/t4034-diff-words.sh1
-rw-r--r--t/t4034/css/expect16
-rw-r--r--t/t4034/css/post10
-rw-r--r--t/t4034/css/pre10
-rwxr-xr-xt/t4053-diff-no-index.sh38
-rwxr-xr-xt/t4059-diff-submodule-not-initialized.sh127
-rwxr-xr-xt/t4060-diff-submodule-option-diff-format.sh749
-rwxr-xr-xt/t4150-am.sh20
-rwxr-xr-xt/t4153-am-resume-override-opts.sh2
-rwxr-xr-xt/t4201-shortlog.sh6
-rwxr-xr-xt/t4202-log.sh355
-rwxr-xr-xt/t4204-patch-id.sh14
-rwxr-xr-xt/t4207-log-decoration-colors.sh2
-rwxr-xr-xt/t4208-log-magic-pathspec.sh4
-rwxr-xr-xt/t4211-line-log.sh7
-rwxr-xr-xt/t4254-am-corrupt.sh2
-rwxr-xr-xt/t5000-tar-tree.sh74
-rw-r--r--t/t5000/19f9c8273ec45a8938e6999cb59b3ff66739902abin0 -> 2048 bytes
-rw-r--r--t/t5000/huge-and-future.tarbin0 -> 2048 bytes
-rwxr-xr-xt/t5100-mailinfo.sh31
-rw-r--r--t/t5100/0001mboxrd4
-rw-r--r--t/t5100/0002mboxrd5
-rw-r--r--t/t5100/sample.mboxrd19
-rwxr-xr-xt/t5305-include-tag.sh94
-rwxr-xr-xt/t5310-pack-bitmaps.sh108
-rwxr-xr-xt/t5505-remote.sh2
-rwxr-xr-xt/t5510-fetch.sh32
-rwxr-xr-xt/t5512-ls-remote.sh40
-rwxr-xr-xt/t5520-pull.sh50
-rwxr-xr-xt/t5523-push-upstream.sh12
-rwxr-xr-xt/t5526-fetch-submodules.sh35
-rwxr-xr-xt/t5536-fetch-conflicts.sh4
-rwxr-xr-xt/t5541-http-push-smart.sh14
-rwxr-xr-xt/t5544-pack-objects-hook.sh62
-rwxr-xr-xt/t5545-push-options.sh103
-rwxr-xr-xt/t5546-receive-limits.sh55
-rwxr-xr-xt/t5550-http-fetch-dumb.sh18
-rwxr-xr-xt/t5551-http-fetch-smart.sh15
-rwxr-xr-xt/t5614-clone-submodules.sh52
-rwxr-xr-xt/t6007-rev-list-cherry-pick-file.sh21
-rwxr-xr-xt/t6018-rev-list-glob.sh2
-rwxr-xr-xt/t6026-merge-attr.sh2
-rwxr-xr-xt/t6030-bisect-porcelain.sh28
-rwxr-xr-xt/t6301-for-each-ref-errors.sh10
-rwxr-xr-xt/t7001-mv.sh8
-rwxr-xr-xt/t7004-tag.sh9
-rwxr-xr-xt/t7006-pager.sh13
-rwxr-xr-xt/t7060-wtstatus.sh21
-rwxr-xr-xt/t7063-status-untracked-cache.sh2
-rwxr-xr-xt/t7064-wtstatus-pv2.sh593
-rwxr-xr-xt/t7102-reset.sh4
-rwxr-xr-xt/t7201-co.sh2
-rwxr-xr-xt/t7400-submodule-basic.sh2
-rwxr-xr-xt/t7403-submodule-sync.sh4
-rwxr-xr-xt/t7406-submodule-update.sh80
-rwxr-xr-xt/t7408-submodule-reference.sh185
-rwxr-xr-xt/t7411-submodule-config.sh2
-rwxr-xr-xt/t7508-status.sh4
-rwxr-xr-xt/t7510-signed-commit.sh7
-rwxr-xr-xt/t7607-merge-overwrite.sh2
-rwxr-xr-xt/t7701-repack-unpack-unreachable.sh28
-rwxr-xr-xt/t7810-grep.sh2
-rwxr-xr-xt/t8002-blame.sh5
-rwxr-xr-xt/t8010-cat-file-filters.sh64
-rwxr-xr-xt/t9003-help-autocorrect.sh4
-rwxr-xr-xt/t9100-git-svn-basic.sh23
-rwxr-xr-xt/t9115-git-svn-dcommit-funky-renames.sh7
-rwxr-xr-xt/t9118-git-svn-funky-branch-names.sh2
-rwxr-xr-xt/t9120-git-svn-clone-with-percent-escapes.sh2
-rwxr-xr-xt/t9142-git-svn-shallow-clone.sh2
-rwxr-xr-xt/t9158-git-svn-mergeinfo.sh2
-rwxr-xr-xt/t9160-git-svn-preserve-empty-dirs.sh1
-rwxr-xr-xt/t9300-fast-import.sh25
-rwxr-xr-xt/t9302-fast-import-unpack-limit.sh105
-rwxr-xr-xt/t9401-git-cvsserver-crlf.sh2
-rwxr-xr-xt/t9801-git-p4-branch.sh4
-rwxr-xr-xt/t9903-bash-prompt.sh2
-rw-r--r--t/test-lib-functions.sh18
-rw-r--r--t/test-lib.sh9
145 files changed, 4569 insertions, 572 deletions
diff --git a/t/README b/t/README
index 76a0daa3a..0f764c0ae 100644
--- a/t/README
+++ b/t/README
@@ -265,7 +265,7 @@ right, so this:
$ sh ./t9200-git-cvsexport-commit.sh --run='1-4 !3'
will run tests 1, 2, and 4. Items that comes later have higher
-precendence. It means that this:
+precedence. It means that this:
$ sh ./t9200-git-cvsexport-commit.sh --run='!3 1-4'
diff --git a/t/helper/test-config.c b/t/helper/test-config.c
index d143cd722..83a4f2ab8 100644
--- a/t/helper/test-config.c
+++ b/t/helper/test-config.c
@@ -25,6 +25,9 @@
* ascending order of priority from a config_set
* constructed from files entered as arguments.
*
+ * iterate -> iterate over all values using git_config(), and print some
+ * data for each
+ *
* Examples:
*
* To print the value with highest priority for key "foo.bAr Baz.rock":
@@ -32,6 +35,36 @@
*
*/
+static const char *scope_name(enum config_scope scope)
+{
+ switch (scope) {
+ case CONFIG_SCOPE_SYSTEM:
+ return "system";
+ case CONFIG_SCOPE_GLOBAL:
+ return "global";
+ case CONFIG_SCOPE_REPO:
+ return "repo";
+ case CONFIG_SCOPE_CMDLINE:
+ return "cmdline";
+ default:
+ return "unknown";
+ }
+}
+static int iterate_cb(const char *var, const char *value, void *data)
+{
+ static int nr;
+
+ if (nr++)
+ putchar('\n');
+
+ printf("key=%s\n", var);
+ printf("value=%s\n", value ? value : "(null)");
+ printf("origin=%s\n", current_config_origin_type());
+ printf("name=%s\n", current_config_name());
+ printf("scope=%s\n", scope_name(current_config_scope()));
+
+ return 0;
+}
int cmd_main(int argc, const char **argv)
{
@@ -39,6 +72,9 @@ int cmd_main(int argc, const char **argv)
const char *v;
const struct string_list *strptr;
struct config_set cs;
+
+ setup_git_directory();
+
git_configset_init(&cs);
if (argc < 2) {
@@ -134,6 +170,9 @@ int cmd_main(int argc, const char **argv)
printf("Value not found for \"%s\"\n", argv[2]);
goto exit1;
}
+ } else if (!strcmp(argv[1], "iterate")) {
+ git_config(iterate_cb, NULL);
+ goto exit0;
}
die("%s: Please check the syntax and the function name", argv[0]);
diff --git a/t/helper/test-dump-split-index.c b/t/helper/test-dump-split-index.c
index d1689248b..e44430b69 100644
--- a/t/helper/test-dump-split-index.c
+++ b/t/helper/test-dump-split-index.c
@@ -23,7 +23,7 @@ int cmd_main(int ac, const char **av)
for (i = 0; i < the_index.cache_nr; i++) {
struct cache_entry *ce = the_index.cache[i];
printf("%06o %s %d\t%s\n", ce->ce_mode,
- sha1_to_hex(ce->sha1), ce_stage(ce), ce->name);
+ oid_to_hex(&ce->oid), ce_stage(ce), ce->name);
}
printf("replacements:");
if (si->replace_bitmap)
diff --git a/t/helper/test-parse-options.c b/t/helper/test-parse-options.c
index d51d29251..a01430c24 100644
--- a/t/helper/test-parse-options.c
+++ b/t/helper/test-parse-options.c
@@ -12,7 +12,7 @@ static int dry_run = 0, quiet = 0;
static char *string = NULL;
static char *file = NULL;
static int ambiguous;
-static struct string_list list;
+static struct string_list list = STRING_LIST_INIT_NODUP;
static struct {
int called;
diff --git a/t/helper/test-submodule-config.c b/t/helper/test-submodule-config.c
index 2a50217bf..2f144d539 100644
--- a/t/helper/test-submodule-config.c
+++ b/t/helper/test-submodule-config.c
@@ -49,7 +49,7 @@ int cmd_main(int argc, const char **argv)
path_or_name = arg[1];
if (commit[0] == '\0')
- hashcpy(commit_sha1, null_sha1);
+ hashclr(commit_sha1);
else if (get_sha1(commit, commit_sha1) < 0)
die_usage(argc, argv, "Commit not found.");
diff --git a/t/lib-git-svn.sh b/t/lib-git-svn.sh
index fb8823224..688313ed5 100644
--- a/t/lib-git-svn.sh
+++ b/t/lib-git-svn.sh
@@ -65,81 +65,22 @@ svn_cmd () {
svn "$orig_svncmd" --config-dir "$svnconf" "$@"
}
-prepare_httpd () {
- for d in \
- "$SVN_HTTPD_PATH" \
- /usr/sbin/apache2 \
- /usr/sbin/httpd \
- ; do
- if test -f "$d"
- then
- SVN_HTTPD_PATH="$d"
- break
- fi
- done
- if test -z "$SVN_HTTPD_PATH"
- then
- echo >&2 '*** error: Apache not found'
- return 1
- fi
- for d in \
- "$SVN_HTTPD_MODULE_PATH" \
- /usr/lib/apache2/modules \
- /usr/libexec/apache2 \
- ; do
- if test -d "$d"
- then
- SVN_HTTPD_MODULE_PATH="$d"
- break
- fi
- done
- if test -z "$SVN_HTTPD_MODULE_PATH"
- then
- echo >&2 '*** error: Apache module dir not found'
- return 1
- fi
- if test ! -f "$SVN_HTTPD_MODULE_PATH/mod_dav_svn.so"
- then
- echo >&2 '*** error: Apache module "mod_dav_svn" not found'
- return 1
- fi
-
- repo_base_path="${1-svn}"
- mkdir "$GIT_DIR"/logs
-
- cat > "$GIT_DIR/httpd.conf" <<EOF
-ServerName "git svn test"
-ServerRoot "$GIT_DIR"
-DocumentRoot "$GIT_DIR"
-PidFile "$GIT_DIR/httpd.pid"
-LockFile logs/accept.lock
-Listen 127.0.0.1:$SVN_HTTPD_PORT
-LoadModule dav_module $SVN_HTTPD_MODULE_PATH/mod_dav.so
-LoadModule dav_svn_module $SVN_HTTPD_MODULE_PATH/mod_dav_svn.so
-<Location /$repo_base_path>
- DAV svn
- SVNPath "$rawsvnrepo"
-</Location>
-EOF
-}
-
-start_httpd () {
- if test -z "$SVN_HTTPD_PORT"
- then
- echo >&2 'SVN_HTTPD_PORT is not defined!'
- return
- fi
-
- prepare_httpd "$1" || return 1
-
- "$SVN_HTTPD_PATH" -f "$GIT_DIR"/httpd.conf -k start
- svnrepo="http://127.0.0.1:$SVN_HTTPD_PORT/$repo_base_path"
-}
-
-stop_httpd () {
- test -z "$SVN_HTTPD_PORT" && return
- test ! -f "$GIT_DIR/httpd.conf" && return
- "$SVN_HTTPD_PATH" -f "$GIT_DIR"/httpd.conf -k stop
+maybe_start_httpd () {
+ loc=${1-svn}
+
+ test_tristate GIT_SVN_TEST_HTTPD
+ case $GIT_SVN_TEST_HTTPD in
+ true)
+ . "$TEST_DIRECTORY"/lib-httpd.sh
+ LIB_HTTPD_SVN="$loc"
+ start_httpd
+ ;;
+ *)
+ stop_httpd () {
+ : noop
+ }
+ ;;
+ esac
}
convert_to_rev_db () {
diff --git a/t/lib-httpd.sh b/t/lib-httpd.sh
index f9f3e5fd8..435a37465 100644
--- a/t/lib-httpd.sh
+++ b/t/lib-httpd.sh
@@ -24,7 +24,7 @@
# LIB_HTTPD_MODULE_PATH web server modules path
# LIB_HTTPD_PORT listening port
# LIB_HTTPD_DAV enable DAV
-# LIB_HTTPD_SVN enable SVN
+# LIB_HTTPD_SVN enable SVN at given location (e.g. "svn")
# LIB_HTTPD_SSL enable SSL
#
# Copyright (c) 2008 Clemens Buchacher <drizzd@aon.at>
@@ -162,8 +162,10 @@ prepare_httpd() {
if test -n "$LIB_HTTPD_SVN"
then
HTTPD_PARA="$HTTPD_PARA -DSVN"
- rawsvnrepo="$HTTPD_ROOT_PATH/svnrepo"
- svnrepo="http://127.0.0.1:$LIB_HTTPD_PORT/svn"
+ LIB_HTTPD_SVNPATH="$rawsvnrepo"
+ svnrepo="http://127.0.0.1:$LIB_HTTPD_PORT/"
+ svnrepo="$svnrepo$LIB_HTTPD_SVN"
+ export LIB_HTTPD_SVN LIB_HTTPD_SVNPATH
fi
fi
}
@@ -180,6 +182,7 @@ start_httpd() {
if test $? -ne 0
then
trap 'die' EXIT
+ cat "$HTTPD_ROOT_PATH"/error.log >&4 2>/dev/null
test_skip_or_die $GIT_TEST_HTTPD "web server setup failed"
fi
}
diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
index 018a83a5a..c3e631394 100644
--- a/t/lib-httpd/apache.conf
+++ b/t/lib-httpd/apache.conf
@@ -208,8 +208,8 @@ RewriteRule ^/half-auth-complete/ - [E=AUTHREQUIRED:yes]
<IfDefine SVN>
LoadModule dav_svn_module modules/mod_dav_svn.so
- <Location /svn>
+ <Location /${LIB_HTTPD_SVN}>
DAV svn
- SVNPath svnrepo
+ SVNPath "${LIB_HTTPD_SVNPATH}"
</Location>
</IfDefine>
diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh
index 9a96e1566..25a77ee5c 100644
--- a/t/lib-rebase.sh
+++ b/t/lib-rebase.sh
@@ -29,6 +29,7 @@ set_fake_editor () {
*/COMMIT_EDITMSG)
test -z "$EXPECT_HEADER_COUNT" ||
test "$EXPECT_HEADER_COUNT" = "$(sed -n '1s/^# This is a combination of \(.*\) commits\./\1/p' < "$1")" ||
+ test "# # GETTEXT POISON #" = "$(sed -n '1p' < "$1")" ||
exit
test -z "$FAKE_COMMIT_MESSAGE" || echo "$FAKE_COMMIT_MESSAGE" > "$1"
test -z "$FAKE_COMMIT_AMEND" || echo "$FAKE_COMMIT_AMEND" >> "$1"
diff --git a/t/perf/README b/t/perf/README
index 8848c1461..49ea4349b 100644
--- a/t/perf/README
+++ b/t/perf/README
@@ -115,8 +115,16 @@ After that you will want to use some of the following:
At least one of the first two is required!
-You can use test_expect_success as usual. For actual performance
-tests, use
+You can use test_expect_success as usual. In both test_expect_success
+and in test_perf, running "git" points to the version that is being
+perf-tested. The $MODERN_GIT variable points to the git wrapper for the
+currently checked-out version (i.e., the one that matches the t/perf
+scripts you are running). This is useful if your setup uses commands
+that only work with newer versions of git than what you might want to
+test (but obviously your new commands must still create a state that can
+be used by the older version of git you are testing).
+
+For actual performance tests, use
test_perf 'descriptive string' '
command1 &&
diff --git a/t/perf/p0003-delta-base-cache.sh b/t/perf/p0003-delta-base-cache.sh
new file mode 100755
index 000000000..62369eaaf
--- /dev/null
+++ b/t/perf/p0003-delta-base-cache.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+test_description='Test operations that emphasize the delta base cache.
+
+We look at both "log --raw", which should put only trees into the delta cache,
+and "log -Sfoo --raw", which should look at both trees and blobs.
+
+Any effects will be emphasized if the test repository is fully packed (loose
+objects obviously do not use the delta base cache at all). It is also
+emphasized if the pack has long delta chains (e.g., as produced by "gc
+--aggressive"), though cache is still quite noticeable even with the default
+depth of 50.
+
+The setting of core.deltaBaseCacheLimit in the source repository is also
+relevant (depending on the size of your test repo), so be sure it is consistent
+between runs.
+'
+. ./perf-lib.sh
+
+test_perf_large_repo
+
+# puts mostly trees into the delta base cache
+test_perf 'log --raw' '
+ git log --raw >/dev/null
+'
+
+test_perf 'log -S' '
+ git log --raw -Sfoo >/dev/null
+'
+
+test_done
diff --git a/t/perf/p3400-rebase.sh b/t/perf/p3400-rebase.sh
new file mode 100755
index 000000000..b3e7d525d
--- /dev/null
+++ b/t/perf/p3400-rebase.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+test_description='Tests rebase performance'
+. ./perf-lib.sh
+
+test_perf_default_repo
+
+test_expect_success 'setup' '
+ git checkout -f -b base &&
+ git checkout -b to-rebase &&
+ git checkout -b upstream &&
+ for i in $(seq 100)
+ do
+ # simulate huge diffs
+ echo change$i >unrelated-file$i &&
+ seq 1000 >>unrelated-file$i &&
+ git add unrelated-file$i &&
+ test_tick &&
+ git commit -m commit$i unrelated-file$i &&
+ echo change$i >unrelated-file$i &&
+ seq 1000 | tac >>unrelated-file$i &&
+ git add unrelated-file$i &&
+ test_tick &&
+ git commit -m commit$i-reverse unrelated-file$i ||
+ break
+ done &&
+ git checkout to-rebase &&
+ test_commit our-patch interesting-file
+'
+
+test_perf 'rebase on top of a lot of unrelated changes' '
+ git rebase --onto upstream HEAD^ &&
+ git rebase --onto base HEAD^
+'
+
+test_done
diff --git a/t/perf/p4211-line-log.sh b/t/perf/p4211-line-log.sh
index 3d074b0e4..b7ff68d4f 100755
--- a/t/perf/p4211-line-log.sh
+++ b/t/perf/p4211-line-log.sh
@@ -23,11 +23,11 @@ test_perf 'git log --follow (baseline for -M)' '
git log --oneline --follow -- "$file" >/dev/null
'
-test_perf 'git log -L' '
- git log -L 1:"$file" >/dev/null
+test_perf 'git log -L (renames off)' '
+ git log --no-renames -L 1:"$file" >/dev/null
'
-test_perf 'git log -M -L' '
+test_perf 'git log -L (renames on)' '
git log -M -L 1:"$file" >/dev/null
'
diff --git a/t/perf/p5303-many-packs.sh b/t/perf/p5303-many-packs.sh
new file mode 100755
index 000000000..377985194
--- /dev/null
+++ b/t/perf/p5303-many-packs.sh
@@ -0,0 +1,87 @@
+#!/bin/sh
+
+test_description='performance with large numbers of packs'
+. ./perf-lib.sh
+
+test_perf_large_repo
+
+# A real many-pack situation would probably come from having a lot of pushes
+# over time. We don't know how big each push would be, but we can fake it by
+# just walking the first-parent chain and having every 5 commits be their own
+# "push". This isn't _entirely_ accurate, as real pushes would have some
+# duplicate objects due to thin-pack fixing, but it's a reasonable
+# approximation.
+#
+# And then all of the rest of the objects can go in a single packfile that
+# represents the state before any of those pushes (actually, we'll generate
+# that first because in such a setup it would be the oldest pack, and we sort
+# the packs by reverse mtime inside git).
+repack_into_n () {
+ rm -rf staging &&
+ mkdir staging &&
+
+ git rev-list --first-parent HEAD |
+ sed -n '1~5p' |
+ head -n "$1" |
+ perl -e 'print reverse <>' \
+ >pushes
+
+ # create base packfile
+ head -n 1 pushes |
+ git pack-objects --delta-base-offset --revs staging/pack
+
+ # and then incrementals between each pair of commits
+ last= &&
+ while read rev
+ do
+ if test -n "$last"; then
+ {
+ echo "$rev" &&
+ echo "^$last"
+ } |
+ git pack-objects --delta-base-offset --revs \
+ staging/pack || return 1
+ fi
+ last=$rev
+ done <pushes &&
+
+ # and install the whole thing
+ rm -f .git/objects/pack/* &&
+ mv staging/* .git/objects/pack/
+}
+
+# Pretend we just have a single branch and no reflogs, and that everything is
+# in objects/pack; that makes our fake pack-building via repack_into_n()
+# much simpler.
+test_expect_success 'simplify reachability' '
+ tip=$(git rev-parse --verify HEAD) &&
+ git for-each-ref --format="option no-deref%0adelete %(refname)" |
+ git update-ref --stdin &&
+ rm -rf .git/logs &&
+ git update-ref refs/heads/master $tip &&
+ git symbolic-ref HEAD refs/heads/master &&
+ git repack -ad
+'
+
+for nr_packs in 1 50 1000
+do
+ test_expect_success "create $nr_packs-pack scenario" '
+ repack_into_n $nr_packs
+ '
+
+ test_perf "rev-list ($nr_packs)" '
+ git rev-list --objects --all >/dev/null
+ '
+
+ # This simulates the interesting part of the repack, which is the
+ # actual pack generation, without smudging the on-disk setup
+ # between trials.
+ test_perf "repack ($nr_packs)" '
+ git pack-objects --keep-true-parents \
+ --honor-pack-keep --non-empty --all \
+ --reflog --indexed-objects --delta-base-offset \
+ --stdout </dev/null >/dev/null
+ '
+done
+
+test_done
diff --git a/t/perf/p5310-pack-bitmaps.sh b/t/perf/p5310-pack-bitmaps.sh
index de2a224a3..bb91dbb17 100755
--- a/t/perf/p5310-pack-bitmaps.sh
+++ b/t/perf/p5310-pack-bitmaps.sh
@@ -32,6 +32,14 @@ test_perf 'simulated fetch' '
} | git pack-objects --revs --stdout >/dev/null
'
+test_perf 'pack to file' '
+ git pack-objects --all pack1 </dev/null >/dev/null
+'
+
+test_perf 'pack to file (bitmap)' '
+ git pack-objects --use-bitmap-index --all pack1b </dev/null >/dev/null
+'
+
test_expect_success 'create partial bitmap state' '
# pick a commit to represent the repo tip in the past
cutoff=$(git rev-list HEAD~100 -1) &&
@@ -53,8 +61,12 @@ test_expect_success 'create partial bitmap state' '
git update-ref HEAD $orig_tip
'
-test_perf 'partial bitmap' '
+test_perf 'clone (partial bitmap)' '
git pack-objects --stdout --all </dev/null >/dev/null
'
+test_perf 'pack to file (partial bitmap)' '
+ git pack-objects --use-bitmap-index --all pack2b </dev/null >/dev/null
+'
+
test_done
diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh
index 773f955d4..46f08ee08 100644
--- a/t/perf/perf-lib.sh
+++ b/t/perf/perf-lib.sh
@@ -52,6 +52,9 @@ TEST_NO_MALLOC_CHECK=t
# need to export them for test_perf subshells
export TEST_DIRECTORY TRASH_DIRECTORY GIT_BUILD_DIR GIT_TEST_CMP
+MODERN_GIT=$GIT_BUILD_DIR/bin-wrappers/git
+export MODERN_GIT
+
perf_results_dir=$TEST_OUTPUT_DIRECTORY/test-results
mkdir -p "$perf_results_dir"
rm -f "$perf_results_dir"/$(basename "$0" .sh).subtests
@@ -81,7 +84,7 @@ test_perf_create_repo_from () {
repo="$1"
source="$2"
source_git="$(git -C "$source" rev-parse --git-dir)"
- objects_dir="$(git -C "$source" rev-parse --git-path objects)"
+ objects_dir="$("$MODERN_GIT" -C "$source" rev-parse --git-path objects)"
mkdir -p "$repo/.git"
(
cd "$source" &&
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index a6fdd5ef3..8ffbbea4d 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -384,4 +384,13 @@ test_expect_success MINGW 'bare git dir not hidden' '
! is_hidden newdir
'
+test_expect_success 'remote init from does not use config from cwd' '
+ rm -rf newdir &&
+ test_config core.logallrefupdates true &&
+ git init newdir &&
+ echo true >expect &&
+ git -C newdir config --bool core.logallrefupdates >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh
index b425f3a0d..d27f438bf 100755
--- a/t/t0008-ignores.sh
+++ b/t/t0008-ignores.sh
@@ -34,7 +34,7 @@ expect_from_stdin () {
test_stderr () {
expected="$1"
expect_in stderr "$1" &&
- test_cmp "$HOME/expected-stderr" "$HOME/stderr"
+ test_i18ncmp "$HOME/expected-stderr" "$HOME/stderr"
}
broken_c_unquote () {
@@ -47,7 +47,7 @@ broken_c_unquote_verbose () {
stderr_contains () {
regexp="$1"
- if grep "$regexp" "$HOME/stderr"
+ if test_i18ngrep "$regexp" "$HOME/stderr"
then
return 0
else
diff --git a/t/t0012-help.sh b/t/t0012-help.sh
new file mode 100755
index 000000000..8faba2e8b
--- /dev/null
+++ b/t/t0012-help.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+test_description='help'
+
+. ./test-lib.sh
+
+configure_help () {
+ test_config help.format html &&
+
+ # Unless the path has "://" in it, Git tries to make sure
+ # the documentation directory locally exists. Avoid it as
+ # we are only interested in seeing an attempt to correctly
+ # invoke a help browser in this test.
+ test_config help.htmlpath test://html &&
+
+ # Name a custom browser
+ test_config browser.test.cmd ./test-browser &&
+ test_config help.browser test
+}
+
+test_expect_success "setup" '
+ # Just write out which page gets requested
+ write_script test-browser <<-\EOF
+ echo "$*" >test-browser.log
+ EOF
+'
+
+test_expect_success "works for commands and guides by default" '
+ configure_help &&
+ git help status &&
+ echo "test://html/git-status.html" >expect &&
+ test_cmp expect test-browser.log &&
+ git help revisions &&
+ echo "test://html/gitrevisions.html" >expect &&
+ test_cmp expect test-browser.log
+'
+
+test_expect_success "--exclude-guides does not work for guides" '
+ >test-browser.log &&
+ test_must_fail git help --exclude-guides revisions &&
+ test_must_be_empty test-browser.log
+'
+
+test_expect_success "--help does not work for guides" "
+ cat <<-EOF >expect &&
+ git: 'revisions' is not a git command. See 'git --help'.
+ EOF
+ test_must_fail git revisions --help 2>actual &&
+ test_i18ncmp expect actual
+"
+
+test_done
diff --git a/t/t0027-auto-crlf.sh b/t/t0027-auto-crlf.sh
index 2860d2d08..90db54c9f 100755
--- a/t/t0027-auto-crlf.sh
+++ b/t/t0027-auto-crlf.sh
@@ -119,8 +119,7 @@ commit_chk_wrnNNO () {
fname=${pfx}_$f.txt &&
cp $f $fname &&
printf Z >>"$fname" &&
- git -c core.autocrlf=$crlf add $fname 2>/dev/null &&
- git -c core.autocrlf=$crlf commit -m "commit_$fname" $fname >"${pfx}_$f.err" 2>&1
+ git -c core.autocrlf=$crlf add $fname 2>"${pfx}_$f.err"
done
test_expect_success "commit NNO files crlf=$crlf attr=$attr LF" '
@@ -417,7 +416,8 @@ commit_chk_wrnNNO "text" "" false "$WILC" "$WICL" "$WAMIX" "$WILC
commit_chk_wrnNNO "text" "" true LF_CRLF "" LF_CRLF LF_CRLF ""
commit_chk_wrnNNO "text" "" input "" CRLF_LF CRLF_LF "" CRLF_LF
-test_expect_success 'create files cleanup' '
+test_expect_success 'commit NNO and cleanup' '
+ git commit -m "commit files on top of NNO" &&
rm -f *.txt &&
git -c core.autocrlf=false reset --hard
'
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index 4f38078ff..b19f33269 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -231,7 +231,7 @@ $tag_content
| git cat-file --batch)"
'
-test_expect_success "--batch-check for an emtpy line" '
+test_expect_success "--batch-check for an empty line" '
test " missing" = "$(echo | git cat-file --batch-check)"
'
diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh
index 7d2baa15b..acca9ac56 100755
--- a/t/t1007-hash-object.sh
+++ b/t/t1007-hash-object.sh
@@ -101,7 +101,7 @@ test_expect_success 'git hash-object --stdin file1 <file0 first operates on file
test "$obname1" = "$obname1new"
'
-test_expect_success 'check that appropriate filter is invoke when --path is used' '
+test_expect_success 'set up crlf tests' '
echo fooQ | tr Q "\\015" >file0 &&
cp file0 file1 &&
echo "file0 -crlf" >.gitattributes &&
@@ -109,7 +109,10 @@ test_expect_success 'check that appropriate filter is invoke when --path is used
git config core.autocrlf true &&
file0_sha=$(git hash-object file0) &&
file1_sha=$(git hash-object file1) &&
- test "$file0_sha" != "$file1_sha" &&
+ test "$file0_sha" != "$file1_sha"
+'
+
+test_expect_success 'check that appropriate filter is invoke when --path is used' '
path1_sha=$(git hash-object --path=file1 file0) &&
path0_sha=$(git hash-object --path=file0 file1) &&
test "$file0_sha" = "$path0_sha" &&
@@ -117,38 +120,30 @@ test_expect_success 'check that appropriate filter is invoke when --path is used
path1_sha=$(cat file0 | git hash-object --path=file1 --stdin) &&
path0_sha=$(cat file1 | git hash-object --path=file0 --stdin) &&
test "$file0_sha" = "$path0_sha" &&
- test "$file1_sha" = "$path1_sha" &&
- git config --unset core.autocrlf
+ test "$file1_sha" = "$path1_sha"
+'
+
+test_expect_success 'gitattributes also work in a subdirectory' '
+ mkdir subdir &&
+ (
+ cd subdir &&
+ subdir_sha0=$(git hash-object ../file0) &&
+ subdir_sha1=$(git hash-object ../file1) &&
+ test "$file0_sha" = "$subdir_sha0" &&
+ test "$file1_sha" = "$subdir_sha1"
+ )
'
test_expect_success 'check that --no-filters option works' '
- echo fooQ | tr Q "\\015" >file0 &&
- cp file0 file1 &&
- echo "file0 -crlf" >.gitattributes &&
- echo "file1 crlf" >>.gitattributes &&
- git config core.autocrlf true &&
- file0_sha=$(git hash-object file0) &&
- file1_sha=$(git hash-object file1) &&
- test "$file0_sha" != "$file1_sha" &&
nofilters_file1=$(git hash-object --no-filters file1) &&
test "$file0_sha" = "$nofilters_file1" &&
nofilters_file1=$(cat file1 | git hash-object --stdin) &&
- test "$file0_sha" = "$nofilters_file1" &&
- git config --unset core.autocrlf
+ test "$file0_sha" = "$nofilters_file1"
'
test_expect_success 'check that --no-filters option works with --stdin-paths' '
- echo fooQ | tr Q "\\015" >file0 &&
- cp file0 file1 &&
- echo "file0 -crlf" >.gitattributes &&
- echo "file1 crlf" >>.gitattributes &&
- git config core.autocrlf true &&
- file0_sha=$(git hash-object file0) &&
- file1_sha=$(git hash-object file1) &&
- test "$file0_sha" != "$file1_sha" &&
nofilters_file1=$(echo "file1" | git hash-object --stdin-paths --no-filters) &&
- test "$file0_sha" = "$nofilters_file1" &&
- git config --unset core.autocrlf
+ test "$file0_sha" = "$nofilters_file1"
'
pop_repo
diff --git a/t/t1011-read-tree-sparse-checkout.sh b/t/t1011-read-tree-sparse-checkout.sh
index 81e85e08d..c167f606c 100755
--- a/t/t1011-read-tree-sparse-checkout.sh
+++ b/t/t1011-read-tree-sparse-checkout.sh
@@ -247,7 +247,7 @@ error: The following untracked working tree files would be overwritten by checko
Please move or remove them before you switch branches.
Aborting
EOF
- test_cmp expected actual
+ test_i18ncmp expected actual
'
test_expect_success 'checkout without --ignore-skip-worktree-bits' '
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index d934a2441..923bfc5a2 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -886,7 +886,7 @@ test_expect_success !MINGW 'get --path copes with unset $HOME' '
git config --get --path path.normal >>result &&
git config --get --path path.trailingtilde >>result
) &&
- grep "[Ff]ailed to expand.*~/" msg &&
+ test_i18ngrep "[Ff]ailed to expand.*~/" msg &&
test_cmp expect result
'
@@ -1126,7 +1126,7 @@ test_expect_success 'barf on syntax error' '
key garbage
EOF
test_must_fail git config --get section.key >actual 2>error &&
- grep " line 3 " error
+ test_i18ngrep " line 3 " error
'
test_expect_success 'barf on incomplete section header' '
@@ -1136,7 +1136,7 @@ test_expect_success 'barf on incomplete section header' '
key = value
EOF
test_must_fail git config --get section.key >actual 2>error &&
- grep " line 2 " error
+ test_i18ngrep " line 2 " error
'
test_expect_success 'barf on incomplete string' '
@@ -1146,7 +1146,7 @@ test_expect_success 'barf on incomplete string' '
key = "value string
EOF
test_must_fail git config --get section.key >actual 2>error &&
- grep " line 3 " error
+ test_i18ngrep " line 3 " error
'
test_expect_success 'urlmatch' '
diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh
index ac1087540..1312004f8 100755
--- a/t/t1301-shared-repo.sh
+++ b/t/t1301-shared-repo.sh
@@ -172,4 +172,45 @@ test_expect_success POSIXPERM 'forced modes' '
}" actual)"
'
+test_expect_success POSIXPERM 'remote init does not use config from cwd' '
+ git config core.sharedrepository 0666 &&
+ umask 0022 &&
+ git init --bare child.git &&
+ echo "-rw-r--r--" >expect &&
+ modebits child.git/config >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success POSIXPERM 're-init respects core.sharedrepository (local)' '
+ git config core.sharedrepository 0666 &&
+ umask 0022 &&
+ echo whatever >templates/foo &&
+ git init --template=templates &&
+ echo "-rw-rw-rw-" >expect &&
+ modebits .git/foo >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success POSIXPERM 're-init respects core.sharedrepository (remote)' '
+ rm -rf child.git &&
+ umask 0022 &&
+ git init --bare --shared=0666 child.git &&
+ test_path_is_missing child.git/foo &&
+ git init --bare --template=../templates child.git &&
+ echo "-rw-rw-rw-" >expect &&
+ modebits child.git/foo >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success POSIXPERM 'template can set core.sharedrepository' '
+ rm -rf child.git &&
+ umask 0022 &&
+ git config core.sharedrepository 0666 &&
+ cp .git/config templates/config &&
+ git init --bare --template=../templates child.git &&
+ echo "-rw-rw-rw-" >expect &&
+ modebits child.git/HEAD >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh
index 9bcd34969..ce4cff13b 100755
--- a/t/t1302-repo-version.sh
+++ b/t/t1302-repo-version.sh
@@ -25,46 +25,26 @@ test_expect_success 'setup' '
test_expect_success 'gitdir selection on normal repos' '
echo 0 >expect &&
git config core.repositoryformatversion >actual &&
- (
- cd test &&
- git config core.repositoryformatversion >../actual2
- ) &&
+ git -C test config core.repositoryformatversion >actual2 &&
test_cmp expect actual &&
test_cmp expect actual2
'
test_expect_success 'gitdir selection on unsupported repo' '
# Make sure it would stop at test2, not trash
- echo 99 >expect &&
- (
- cd test2 &&
- git config core.repositoryformatversion >../actual
- ) &&
- test_cmp expect actual
+ test_expect_code 1 git -C test2 config core.repositoryformatversion >actual
'
test_expect_success 'gitdir not required mode' '
git apply --stat test.patch &&
- (
- cd test &&
- git apply --stat ../test.patch
- ) &&
- (
- cd test2 &&
- git apply --stat ../test.patch
- )
+ git -C test apply --stat ../test.patch &&
+ git -C test2 apply --stat ../test.patch
'
test_expect_success 'gitdir required mode' '
git apply --check --index test.patch &&
- (
- cd test &&
- git apply --check --index ../test.patch
- ) &&
- (
- cd test2 &&
- test_must_fail git apply --check --index ../test.patch
- )
+ git -C test apply --check --index ../test.patch &&
+ test_must_fail git -C test2 apply --check --index ../test.patch
'
check_allow () {
diff --git a/t/t1307-config-blob.sh b/t/t1307-config-blob.sh
index 3c6791e6b..eed31ffa3 100755
--- a/t/t1307-config-blob.sh
+++ b/t/t1307-config-blob.sh
@@ -61,10 +61,7 @@ test_expect_success 'parse errors in blobs are properly attributed' '
git commit -m broken &&
test_must_fail git config --blob=HEAD:config some.value 2>err &&
-
- # just grep for our token as the exact error message is likely to
- # change or be internationalized
- grep "HEAD:config" err
+ test_i18ngrep "HEAD:config" err
'
test_expect_success 'can parse blob ending with CR' '
diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index 005d66dbe..7655c94c2 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -197,14 +197,14 @@ test_expect_success 'proper error on error in default config files' '
echo "[" >>.git/config &&
echo "fatal: bad config line 34 in file .git/config" >expect &&
test_expect_code 128 test-config get_value foo.bar 2>actual &&
- test_cmp expect actual
+ test_i18ncmp expect actual
'
test_expect_success 'proper error on error in custom config files' '
echo "[" >>syntax-error &&
echo "fatal: bad config line 1 in file syntax-error" >expect &&
test_expect_code 128 test-config configset_get_value foo.bar syntax-error 2>actual &&
- test_cmp expect actual
+ test_i18ncmp expect actual
'
test_expect_success 'check line errors for malformed values' '
@@ -229,4 +229,39 @@ test_expect_success 'error on modifying repo config without repo' '
)
'
+cmdline_config="'foo.bar=from-cmdline'"
+test_expect_success 'iteration shows correct origins' '
+ echo "[foo]bar = from-repo" >.git/config &&
+ echo "[foo]bar = from-home" >.gitconfig &&
+ if test_have_prereq MINGW
+ then
+ # Use Windows path (i.e. *not* $HOME)
+ HOME_GITCONFIG=$(pwd)/.gitconfig
+ else
+ # Do not get fooled by symbolic links, i.e. $HOME != $(pwd)
+ HOME_GITCONFIG=$HOME/.gitconfig
+ fi &&
+ cat >expect <<-EOF &&
+ key=foo.bar
+ value=from-home
+ origin=file
+ name=$HOME_GITCONFIG
+ scope=global
+
+ key=foo.bar
+ value=from-repo
+ origin=file
+ name=.git/config
+ scope=repo
+
+ key=foo.bar
+ value=from-cmdline
+ origin=command line
+ name=
+ scope=cmdline
+ EOF
+ GIT_CONFIG_PARAMETERS=$cmdline_config test-config iterate >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t1350-config-hooks-path.sh b/t/t1350-config-hooks-path.sh
index 5e3fb3a6a..f1f9aee9f 100755
--- a/t/t1350-config-hooks-path.sh
+++ b/t/t1350-config-hooks-path.sh
@@ -34,4 +34,10 @@ test_expect_success 'Check that various forms of specifying core.hooksPath work'
test_cmp expect actual
'
+test_expect_success 'git rev-parse --git-path hooks' '
+ git config core.hooksPath .git/custom-hooks &&
+ git rev-parse --git-path hooks/abc >actual &&
+ test .git/custom-hooks/abc = "$(cat actual)"
+'
+
test_done
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index af1b20dd5..d4fb97706 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -23,7 +23,7 @@ test_expect_success setup '
m=refs/heads/master
n_dir=refs/heads/gu
n=$n_dir/fixes
-outside=foo
+outside=refs/foo
test_expect_success \
"create $m" \
@@ -361,7 +361,7 @@ test_expect_success 'stdin test setup' '
test_expect_success '-z fails without --stdin' '
test_must_fail git update-ref -z $m $m $m 2>err &&
- grep "usage: git update-ref" err
+ test_i18ngrep "usage: git update-ref" err
'
test_expect_success 'stdin works with no input' '
@@ -479,7 +479,7 @@ test_expect_success 'stdin fails with duplicate refs' '
create $a $m
EOF
test_must_fail git update-ref --stdin <stdin 2>err &&
- grep "fatal: Multiple updates for ref '"'"'$a'"'"' not allowed." err
+ grep "fatal: multiple updates for ref '"'"'$a'"'"' not allowed." err
'
test_expect_success 'stdin create ref works' '
@@ -880,7 +880,7 @@ test_expect_success 'stdin -z fails option with unknown name' '
test_expect_success 'stdin -z fails with duplicate refs' '
printf $F "create $a" "$m" "create $b" "$m" "create $a" "$m" >stdin &&
test_must_fail git update-ref -z --stdin <stdin 2>err &&
- grep "fatal: Multiple updates for ref '"'"'$a'"'"' not allowed." err
+ grep "fatal: multiple updates for ref '"'"'$a'"'"' not allowed." err
'
test_expect_success 'stdin -z create ref works' '
@@ -1102,6 +1102,41 @@ test_expect_success 'stdin -z delete refs works with packed and loose refs' '
test_must_fail git rev-parse --verify -q $c
'
+test_expect_success 'fails with duplicate HEAD update' '
+ git branch target1 $A &&
+ git checkout target1 &&
+ cat >stdin <<-EOF &&
+ update refs/heads/target1 $C
+ option no-deref
+ update HEAD $B
+ EOF
+ test_must_fail git update-ref --stdin <stdin 2>err &&
+ grep "fatal: multiple updates for '\''HEAD'\'' (including one via its referent .refs/heads/target1.) are not allowed" err &&
+ echo "refs/heads/target1" >expect &&
+ git symbolic-ref HEAD >actual &&
+ test_cmp expect actual &&
+ echo "$A" >expect &&
+ git rev-parse refs/heads/target1 >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'fails with duplicate ref update via symref' '
+ git branch target2 $A &&
+ git symbolic-ref refs/heads/symref2 refs/heads/target2 &&
+ cat >stdin <<-EOF &&
+ update refs/heads/target2 $C
+ update refs/heads/symref2 $B
+ EOF
+ test_must_fail git update-ref --stdin <stdin 2>err &&
+ grep "fatal: multiple updates for '\''refs/heads/target2'\'' (including one via symref .refs/heads/symref2.) are not allowed" err &&
+ echo "refs/heads/target2" >expect &&
+ git symbolic-ref refs/heads/symref2 >actual &&
+ test_cmp expect actual &&
+ echo "$A" >expect &&
+ git rev-parse refs/heads/target2 >actual &&
+ test_cmp expect actual
+'
+
run_with_limited_open_files () {
(ulimit -n 32 && "$@")
}
diff --git a/t/t1401-symbolic-ref.sh b/t/t1401-symbolic-ref.sh
index ca3fa406c..eec3e90f9 100755
--- a/t/t1401-symbolic-ref.sh
+++ b/t/t1401-symbolic-ref.sh
@@ -33,18 +33,25 @@ test_expect_success 'symbolic-ref refuses bare sha1' '
'
reset_to_sane
-test_expect_success 'symbolic-ref deletes HEAD' '
- git symbolic-ref -d HEAD &&
+test_expect_success 'HEAD cannot be removed' '
+ test_must_fail git symbolic-ref -d HEAD
+'
+
+reset_to_sane
+
+test_expect_success 'symbolic-ref can be deleted' '
+ git symbolic-ref NOTHEAD refs/heads/foo &&
+ git symbolic-ref -d NOTHEAD &&
test_path_is_file .git/refs/heads/foo &&
- test_path_is_missing .git/HEAD
+ test_path_is_missing .git/NOTHEAD
'
reset_to_sane
-test_expect_success 'symbolic-ref deletes dangling HEAD' '
- git symbolic-ref HEAD refs/heads/missing &&
- git symbolic-ref -d HEAD &&
+test_expect_success 'symbolic-ref can delete dangling symref' '
+ git symbolic-ref NOTHEAD refs/heads/missing &&
+ git symbolic-ref -d NOTHEAD &&
test_path_is_missing .git/refs/heads/missing &&
- test_path_is_missing .git/HEAD
+ test_path_is_missing .git/NOTHEAD
'
reset_to_sane
diff --git a/t/t1404-update-ref-df-conflicts.sh b/t/t1404-update-ref-df-conflicts.sh
deleted file mode 100755
index 66bafb5cf..000000000
--- a/t/t1404-update-ref-df-conflicts.sh
+++ /dev/null
@@ -1,107 +0,0 @@
-#!/bin/sh
-
-test_description='Test git update-ref with D/F conflicts'
-. ./test-lib.sh
-
-test_update_rejected () {
- prefix="$1" &&
- before="$2" &&
- pack="$3" &&
- create="$4" &&
- error="$5" &&
- printf "create $prefix/%s $C\n" $before |
- git update-ref --stdin &&
- git for-each-ref $prefix >unchanged &&
- if $pack
- then
- git pack-refs --all
- fi &&
- printf "create $prefix/%s $C\n" $create >input &&
- test_must_fail git update-ref --stdin <input 2>output.err &&
- grep -F "$error" output.err &&
- git for-each-ref $prefix >actual &&
- test_cmp unchanged actual
-}
-
-Q="'"
-
-test_expect_success 'setup' '
-
- git commit --allow-empty -m Initial &&
- C=$(git rev-parse HEAD)
-
-'
-
-test_expect_success 'existing loose ref is a simple prefix of new' '
-
- prefix=refs/1l &&
- test_update_rejected $prefix "a c e" false "b c/x d" \
- "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x$Q"
-
-'
-
-test_expect_success 'existing packed ref is a simple prefix of new' '
-
- prefix=refs/1p &&
- test_update_rejected $prefix "a c e" true "b c/x d" \
- "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x$Q"
-
-'
-
-test_expect_success 'existing loose ref is a deeper prefix of new' '
-
- prefix=refs/2l &&
- test_update_rejected $prefix "a c e" false "b c/x/y d" \
- "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x/y$Q"
-
-'
-
-test_expect_success 'existing packed ref is a deeper prefix of new' '
-
- prefix=refs/2p &&
- test_update_rejected $prefix "a c e" true "b c/x/y d" \
- "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x/y$Q"
-
-'
-
-test_expect_success 'new ref is a simple prefix of existing loose' '
-
- prefix=refs/3l &&
- test_update_rejected $prefix "a c/x e" false "b c d" \
- "$Q$prefix/c/x$Q exists; cannot create $Q$prefix/c$Q"
-
-'
-
-test_expect_success 'new ref is a simple prefix of existing packed' '
-
- prefix=refs/3p &&
- test_update_rejected $prefix "a c/x e" true "b c d" \
- "$Q$prefix/c/x$Q exists; cannot create $Q$prefix/c$Q"
-
-'
-
-test_expect_success 'new ref is a deeper prefix of existing loose' '
-
- prefix=refs/4l &&
- test_update_rejected $prefix "a c/x/y e" false "b c d" \
- "$Q$prefix/c/x/y$Q exists; cannot create $Q$prefix/c$Q"
-
-'
-
-test_expect_success 'new ref is a deeper prefix of existing packed' '
-
- prefix=refs/4p &&
- test_update_rejected $prefix "a c/x/y e" true "b c d" \
- "$Q$prefix/c/x/y$Q exists; cannot create $Q$prefix/c$Q"
-
-'
-
-test_expect_success 'one new ref is a simple prefix of another' '
-
- prefix=refs/5 &&
- test_update_rejected $prefix "a e" false "b c c/x d" \
- "cannot process $Q$prefix/c$Q and $Q$prefix/c/x$Q at the same time"
-
-'
-
-test_done
diff --git a/t/t1404-update-ref-errors.sh b/t/t1404-update-ref-errors.sh
new file mode 100755
index 000000000..c34ece48f
--- /dev/null
+++ b/t/t1404-update-ref-errors.sh
@@ -0,0 +1,407 @@
+#!/bin/sh
+
+test_description='Test git update-ref error handling'
+. ./test-lib.sh
+
+# Create some references, perhaps run pack-refs --all, then try to
+# create some more references. Ensure that the second creation fails
+# with the correct error message.
+# Usage: test_update_rejected <before> <pack> <create> <error>
+# <before> is a ws-separated list of refs to create before the test
+# <pack> (true or false) tells whether to pack the refs before the test
+# <create> is a list of variables to attempt creating
+# <error> is a string to look for in the stderr of update-ref.
+# All references are created in the namespace specified by the current
+# value of $prefix.
+test_update_rejected () {
+ before="$1" &&
+ pack="$2" &&
+ create="$3" &&
+ error="$4" &&
+ printf "create $prefix/%s $C\n" $before |
+ git update-ref --stdin &&
+ git for-each-ref $prefix >unchanged &&
+ if $pack
+ then
+ git pack-refs --all
+ fi &&
+ printf "create $prefix/%s $C\n" $create >input &&
+ test_must_fail git update-ref --stdin <input 2>output.err &&
+ grep -F "$error" output.err &&
+ git for-each-ref $prefix >actual &&
+ test_cmp unchanged actual
+}
+
+Q="'"
+
+test_expect_success 'setup' '
+
+ git commit --allow-empty -m Initial &&
+ C=$(git rev-parse HEAD) &&
+ git commit --allow-empty -m Second &&
+ D=$(git rev-parse HEAD) &&
+ git commit --allow-empty -m Third &&
+ E=$(git rev-parse HEAD)
+'
+
+test_expect_success 'existing loose ref is a simple prefix of new' '
+
+ prefix=refs/1l &&
+ test_update_rejected "a c e" false "b c/x d" \
+ "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x$Q"
+
+'
+
+test_expect_success 'existing packed ref is a simple prefix of new' '
+
+ prefix=refs/1p &&
+ test_update_rejected "a c e" true "b c/x d" \
+ "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x$Q"
+
+'
+
+test_expect_success 'existing loose ref is a deeper prefix of new' '
+
+ prefix=refs/2l &&
+ test_update_rejected "a c e" false "b c/x/y d" \
+ "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x/y$Q"
+
+'
+
+test_expect_success 'existing packed ref is a deeper prefix of new' '
+
+ prefix=refs/2p &&
+ test_update_rejected "a c e" true "b c/x/y d" \
+ "$Q$prefix/c$Q exists; cannot create $Q$prefix/c/x/y$Q"
+
+'
+
+test_expect_success 'new ref is a simple prefix of existing loose' '
+
+ prefix=refs/3l &&
+ test_update_rejected "a c/x e" false "b c d" \
+ "$Q$prefix/c/x$Q exists; cannot create $Q$prefix/c$Q"
+
+'
+
+test_expect_success 'new ref is a simple prefix of existing packed' '
+
+ prefix=refs/3p &&
+ test_update_rejected "a c/x e" true "b c d" \
+ "$Q$prefix/c/x$Q exists; cannot create $Q$prefix/c$Q"
+
+'
+
+test_expect_success 'new ref is a deeper prefix of existing loose' '
+
+ prefix=refs/4l &&
+ test_update_rejected "a c/x/y e" false "b c d" \
+ "$Q$prefix/c/x/y$Q exists; cannot create $Q$prefix/c$Q"
+
+'
+
+test_expect_success 'new ref is a deeper prefix of existing packed' '
+
+ prefix=refs/4p &&
+ test_update_rejected "a c/x/y e" true "b c d" \
+ "$Q$prefix/c/x/y$Q exists; cannot create $Q$prefix/c$Q"
+
+'
+
+test_expect_success 'one new ref is a simple prefix of another' '
+
+ prefix=refs/5 &&
+ test_update_rejected "a e" false "b c c/x d" \
+ "cannot process $Q$prefix/c$Q and $Q$prefix/c/x$Q at the same time"
+
+'
+
+test_expect_success 'empty directory should not fool rev-parse' '
+ prefix=refs/e-rev-parse &&
+ git update-ref $prefix/foo $C &&
+ git pack-refs --all &&
+ mkdir -p .git/$prefix/foo/bar/baz &&
+ echo "$C" >expected &&
+ git rev-parse $prefix/foo >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'empty directory should not fool for-each-ref' '
+ prefix=refs/e-for-each-ref &&
+ git update-ref $prefix/foo $C &&
+ git for-each-ref $prefix >expected &&
+ git pack-refs --all &&
+ mkdir -p .git/$prefix/foo/bar/baz &&
+ git for-each-ref $prefix >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'empty directory should not fool create' '
+ prefix=refs/e-create &&
+ mkdir -p .git/$prefix/foo/bar/baz &&
+ printf "create %s $C\n" $prefix/foo |
+ git update-ref --stdin
+'
+
+test_expect_success 'empty directory should not fool verify' '
+ prefix=refs/e-verify &&
+ git update-ref $prefix/foo $C &&
+ git pack-refs --all &&
+ mkdir -p .git/$prefix/foo/bar/baz &&
+ printf "verify %s $C\n" $prefix/foo |
+ git update-ref --stdin
+'
+
+test_expect_success 'empty directory should not fool 1-arg update' '
+ prefix=refs/e-update-1 &&
+ git update-ref $prefix/foo $C &&
+ git pack-refs --all &&
+ mkdir -p .git/$prefix/foo/bar/baz &&
+ printf "update %s $D\n" $prefix/foo |
+ git update-ref --stdin
+'
+
+test_expect_success 'empty directory should not fool 2-arg update' '
+ prefix=refs/e-update-2 &&
+ git update-ref $prefix/foo $C &&
+ git pack-refs --all &&
+ mkdir -p .git/$prefix/foo/bar/baz &&
+ printf "update %s $D $C\n" $prefix/foo |
+ git update-ref --stdin
+'
+
+test_expect_success 'empty directory should not fool 0-arg delete' '
+ prefix=refs/e-delete-0 &&
+ git update-ref $prefix/foo $C &&
+ git pack-refs --all &&
+ mkdir -p .git/$prefix/foo/bar/baz &&
+ printf "delete %s\n" $prefix/foo |
+ git update-ref --stdin
+'
+
+test_expect_success 'empty directory should not fool 1-arg delete' '
+ prefix=refs/e-delete-1 &&
+ git update-ref $prefix/foo $C &&
+ git pack-refs --all &&
+ mkdir -p .git/$prefix/foo/bar/baz &&
+ printf "delete %s $C\n" $prefix/foo |
+ git update-ref --stdin
+'
+
+# Test various errors when reading the old values of references...
+
+test_expect_success 'missing old value blocks update' '
+ prefix=refs/missing-update &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/foo$Q: unable to resolve reference $Q$prefix/foo$Q
+ EOF
+ printf "%s\n" "update $prefix/foo $E $D" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err
+'
+
+test_expect_success 'incorrect old value blocks update' '
+ prefix=refs/incorrect-update &&
+ git update-ref $prefix/foo $C &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/foo$Q: is at $C but expected $D
+ EOF
+ printf "%s\n" "update $prefix/foo $E $D" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err
+'
+
+test_expect_success 'existing old value blocks create' '
+ prefix=refs/existing-create &&
+ git update-ref $prefix/foo $C &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/foo$Q: reference already exists
+ EOF
+ printf "%s\n" "create $prefix/foo $E" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err
+'
+
+test_expect_success 'incorrect old value blocks delete' '
+ prefix=refs/incorrect-delete &&
+ git update-ref $prefix/foo $C &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/foo$Q: is at $C but expected $D
+ EOF
+ printf "%s\n" "delete $prefix/foo $D" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err
+'
+
+test_expect_success 'missing old value blocks indirect update' '
+ prefix=refs/missing-indirect-update &&
+ git symbolic-ref $prefix/symref $prefix/foo &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/symref$Q: unable to resolve reference $Q$prefix/foo$Q
+ EOF
+ printf "%s\n" "update $prefix/symref $E $D" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err
+'
+
+test_expect_success 'incorrect old value blocks indirect update' '
+ prefix=refs/incorrect-indirect-update &&
+ git symbolic-ref $prefix/symref $prefix/foo &&
+ git update-ref $prefix/foo $C &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/symref$Q: is at $C but expected $D
+ EOF
+ printf "%s\n" "update $prefix/symref $E $D" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err
+'
+
+test_expect_success 'existing old value blocks indirect create' '
+ prefix=refs/existing-indirect-create &&
+ git symbolic-ref $prefix/symref $prefix/foo &&
+ git update-ref $prefix/foo $C &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/symref$Q: reference already exists
+ EOF
+ printf "%s\n" "create $prefix/symref $E" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err
+'
+
+test_expect_success 'incorrect old value blocks indirect delete' '
+ prefix=refs/incorrect-indirect-delete &&
+ git symbolic-ref $prefix/symref $prefix/foo &&
+ git update-ref $prefix/foo $C &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/symref$Q: is at $C but expected $D
+ EOF
+ printf "%s\n" "delete $prefix/symref $D" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err
+'
+
+test_expect_success 'missing old value blocks indirect no-deref update' '
+ prefix=refs/missing-noderef-update &&
+ git symbolic-ref $prefix/symref $prefix/foo &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/symref$Q: reference is missing but expected $D
+ EOF
+ printf "%s\n" "option no-deref" "update $prefix/symref $E $D" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err
+'
+
+test_expect_success 'incorrect old value blocks indirect no-deref update' '
+ prefix=refs/incorrect-noderef-update &&
+ git symbolic-ref $prefix/symref $prefix/foo &&
+ git update-ref $prefix/foo $C &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/symref$Q: is at $C but expected $D
+ EOF
+ printf "%s\n" "option no-deref" "update $prefix/symref $E $D" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err
+'
+
+test_expect_success 'existing old value blocks indirect no-deref create' '
+ prefix=refs/existing-noderef-create &&
+ git symbolic-ref $prefix/symref $prefix/foo &&
+ git update-ref $prefix/foo $C &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/symref$Q: reference already exists
+ EOF
+ printf "%s\n" "option no-deref" "create $prefix/symref $E" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err
+'
+
+test_expect_success 'incorrect old value blocks indirect no-deref delete' '
+ prefix=refs/incorrect-noderef-delete &&
+ git symbolic-ref $prefix/symref $prefix/foo &&
+ git update-ref $prefix/foo $C &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/symref$Q: is at $C but expected $D
+ EOF
+ printf "%s\n" "option no-deref" "delete $prefix/symref $D" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err
+'
+
+test_expect_success 'non-empty directory blocks create' '
+ prefix=refs/ne-create &&
+ mkdir -p .git/$prefix/foo/bar &&
+ : >.git/$prefix/foo/bar/baz.lock &&
+ test_when_finished "rm -f .git/$prefix/foo/bar/baz.lock" &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/foo$Q: there is a non-empty directory $Q.git/$prefix/foo$Q blocking reference $Q$prefix/foo$Q
+ EOF
+ printf "%s\n" "update $prefix/foo $C" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/foo$Q: unable to resolve reference $Q$prefix/foo$Q
+ EOF
+ printf "%s\n" "update $prefix/foo $D $C" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err
+'
+
+test_expect_success 'broken reference blocks create' '
+ prefix=refs/broken-create &&
+ mkdir -p .git/$prefix &&
+ echo "gobbledigook" >.git/$prefix/foo &&
+ test_when_finished "rm -f .git/$prefix/foo" &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/foo$Q: unable to resolve reference $Q$prefix/foo$Q: reference broken
+ EOF
+ printf "%s\n" "update $prefix/foo $C" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/foo$Q: unable to resolve reference $Q$prefix/foo$Q: reference broken
+ EOF
+ printf "%s\n" "update $prefix/foo $D $C" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err
+'
+
+test_expect_success 'non-empty directory blocks indirect create' '
+ prefix=refs/ne-indirect-create &&
+ git symbolic-ref $prefix/symref $prefix/foo &&
+ mkdir -p .git/$prefix/foo/bar &&
+ : >.git/$prefix/foo/bar/baz.lock &&
+ test_when_finished "rm -f .git/$prefix/foo/bar/baz.lock" &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/symref$Q: there is a non-empty directory $Q.git/$prefix/foo$Q blocking reference $Q$prefix/foo$Q
+ EOF
+ printf "%s\n" "update $prefix/symref $C" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/symref$Q: unable to resolve reference $Q$prefix/foo$Q
+ EOF
+ printf "%s\n" "update $prefix/symref $D $C" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err
+'
+
+test_expect_success 'broken reference blocks indirect create' '
+ prefix=refs/broken-indirect-create &&
+ git symbolic-ref $prefix/symref $prefix/foo &&
+ echo "gobbledigook" >.git/$prefix/foo &&
+ test_when_finished "rm -f .git/$prefix/foo" &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/symref$Q: unable to resolve reference $Q$prefix/foo$Q: reference broken
+ EOF
+ printf "%s\n" "update $prefix/symref $C" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err &&
+ cat >expected <<-EOF &&
+ fatal: cannot lock ref $Q$prefix/symref$Q: unable to resolve reference $Q$prefix/foo$Q: reference broken
+ EOF
+ printf "%s\n" "update $prefix/symref $D $C" |
+ test_must_fail git update-ref --stdin 2>output.err &&
+ test_cmp expected output.err
+'
+
+test_done
diff --git a/t/t1430-bad-ref-name.sh b/t/t1430-bad-ref-name.sh
index 25ddab4e9..8937e25e4 100755
--- a/t/t1430-bad-ref-name.sh
+++ b/t/t1430-bad-ref-name.sh
@@ -285,7 +285,7 @@ test_expect_success 'update-ref -d cannot delete non-ref in .git dir' '
echo precious >expect &&
test_must_fail git update-ref -d my-private-file >output 2>error &&
test_must_be_empty output &&
- test_i18ngrep -e "cannot lock .*: unable to resolve reference" error &&
+ test_i18ngrep -e "refusing to update ref with bad name" error &&
test_cmp expect .git/my-private-file
'
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index 7ee8ea004..8f52da277 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -523,4 +523,26 @@ test_expect_success 'fsck --connectivity-only' '
)
'
+remove_loose_object () {
+ sha1="$(git rev-parse "$1")" &&
+ remainder=${sha1#??} &&
+ firsttwo=${sha1%$remainder} &&
+ rm .git/objects/$firsttwo/$remainder
+}
+
+test_expect_success 'fsck --name-objects' '
+ rm -rf name-objects &&
+ git init name-objects &&
+ (
+ cd name-objects &&
+ test_commit julius caesar.t &&
+ test_commit augustus &&
+ test_commit caesar &&
+ remove_loose_object $(git rev-parse julius:caesar.t) &&
+ test_must_fail git fsck --name-objects >out &&
+ tree=$(git rev-parse --verify julius:) &&
+ grep "$tree (\(refs/heads/master\|HEAD\)@{[0-9]*}:" out
+ )
+'
+
test_done
diff --git a/t/t1506-rev-parse-diagnosis.sh b/t/t1506-rev-parse-diagnosis.sh
index 86c2ff255..79a0251ef 100755
--- a/t/t1506-rev-parse-diagnosis.sh
+++ b/t/t1506-rev-parse-diagnosis.sh
@@ -106,7 +106,7 @@ test_expect_success 'incorrect revision id' '
test_must_fail git rev-parse foobar:file.txt 2>error &&
grep "Invalid object name '"'"'foobar'"'"'." error &&
test_must_fail git rev-parse foobar 2> error &&
- grep "unknown revision or path not in the working tree." error
+ test_i18ngrep "unknown revision or path not in the working tree." error
'
test_expect_success 'incorrect file in sha1:path' '
diff --git a/t/t2010-checkout-ambiguous.sh b/t/t2010-checkout-ambiguous.sh
index 87bdf9c96..e76e84afb 100755
--- a/t/t2010-checkout-ambiguous.sh
+++ b/t/t2010-checkout-ambiguous.sh
@@ -49,7 +49,7 @@ test_expect_success 'disambiguate checking out from a tree-ish' '
test_expect_success 'accurate error message with more than one ref' '
test_must_fail git checkout HEAD master -- 2>actual &&
- grep 2 actual &&
+ test_i18ngrep 2 actual &&
test_i18ngrep "one reference expected, 2 given" actual
'
diff --git a/t/t2018-checkout-branch.sh b/t/t2018-checkout-branch.sh
index 274126236..2131fb2a5 100755
--- a/t/t2018-checkout-branch.sh
+++ b/t/t2018-checkout-branch.sh
@@ -124,7 +124,7 @@ test_expect_success 'checkout -b to @{-1} fails with the right branch name' '
git checkout branch2 &&
echo >expect "fatal: A branch named '\''branch1'\'' already exists." &&
test_must_fail git checkout -b @{-1} 2>actual &&
- test_cmp expect actual
+ test_i18ncmp expect actual
'
test_expect_success 'checkout -B to an existing branch resets branch to HEAD' '
diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh
index 3a22fc55f..4bcc335a1 100755
--- a/t/t2025-worktree-add.sh
+++ b/t/t2025-worktree-add.sh
@@ -20,6 +20,22 @@ test_expect_success '"add" an existing empty worktree' '
git worktree add --detach existing_empty master
'
+test_expect_success '"add" using shorthand - fails when no previous branch' '
+ test_must_fail git worktree add existing_short -
+'
+
+test_expect_success '"add" using - shorthand' '
+ git checkout -b newbranch &&
+ echo hello >myworld &&
+ git add myworld &&
+ git commit -m myworld &&
+ git checkout master &&
+ git worktree add short-hand - &&
+ echo refs/heads/newbranch >expect &&
+ git -C short-hand rev-parse --symbolic-full-name HEAD >actual &&
+ test_cmp expect actual
+'
+
test_expect_success '"add" refuses to checkout locked branch' '
test_must_fail git worktree add zere master &&
! test -d zere &&
diff --git a/t/t2028-worktree-move.sh b/t/t2028-worktree-move.sh
new file mode 100755
index 000000000..8298aaf97
--- /dev/null
+++ b/t/t2028-worktree-move.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+
+test_description='test git worktree move, remove, lock and unlock'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ test_commit init &&
+ git worktree add source &&
+ git worktree list --porcelain | grep "^worktree" >actual &&
+ cat <<-EOF >expected &&
+ worktree $(pwd)
+ worktree $(pwd)/source
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'lock main worktree' '
+ test_must_fail git worktree lock .
+'
+
+test_expect_success 'lock linked worktree' '
+ git worktree lock --reason hahaha source &&
+ echo hahaha >expected &&
+ test_cmp expected .git/worktrees/source/locked
+'
+
+test_expect_success 'lock linked worktree from another worktree' '
+ rm .git/worktrees/source/locked &&
+ git worktree add elsewhere &&
+ git -C elsewhere worktree lock --reason hahaha ../source &&
+ echo hahaha >expected &&
+ test_cmp expected .git/worktrees/source/locked
+'
+
+test_expect_success 'lock worktree twice' '
+ test_must_fail git worktree lock source &&
+ echo hahaha >expected &&
+ test_cmp expected .git/worktrees/source/locked
+'
+
+test_expect_success 'lock worktree twice (from the locked worktree)' '
+ test_must_fail git -C source worktree lock . &&
+ echo hahaha >expected &&
+ test_cmp expected .git/worktrees/source/locked
+'
+
+test_expect_success 'unlock main worktree' '
+ test_must_fail git worktree unlock .
+'
+
+test_expect_success 'unlock linked worktree' '
+ git worktree unlock source &&
+ test_path_is_missing .git/worktrees/source/locked
+'
+
+test_expect_success 'unlock worktree twice' '
+ test_must_fail git worktree unlock source &&
+ test_path_is_missing .git/worktrees/source/locked
+'
+
+test_done
diff --git a/t/t3101-ls-tree-dirname.sh b/t/t3101-ls-tree-dirname.sh
index 425d85893..327ded400 100755
--- a/t/t3101-ls-tree-dirname.sh
+++ b/t/t3101-ls-tree-dirname.sh
@@ -16,7 +16,7 @@ This test runs git ls-tree with the following in a tree.
path3/1.txt - a file in a directory
path3/2.txt - a file in a directory
-Test the handling of mulitple directories which have matching file
+Test the handling of multiple directories which have matching file
entries. Also test odd filename and missing entries handling.
'
. ./test-lib.sh
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index f3e3b6cf2..8a833f354 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -79,6 +79,15 @@ test_expect_success 'git branch -m dumps usage' '
test_i18ngrep "branch name required" err
'
+test_expect_success 'git branch -m m broken_symref should work' '
+ test_when_finished "git branch -D broken_symref" &&
+ git branch -l m &&
+ git symbolic-ref refs/heads/broken_symref refs/heads/i_am_broken &&
+ git branch -m m broken_symref &&
+ git reflog exists refs/heads/broken_symref &&
+ test_must_fail git reflog exists refs/heads/i_am_broken
+'
+
test_expect_success 'git branch -m m m/m should work' '
git branch -l m &&
git branch -m m m/m &&
@@ -550,7 +559,7 @@ If you wanted to make '"'master'"' track '"'origin/master'"', do this:
git branch -d origin/master
git branch --set-upstream-to origin/master
EOF
- test_cmp expected actual
+ test_i18ncmp expected actual
'
test_expect_success '--set-upstream with two args only shows the deprecation message' '
@@ -559,7 +568,7 @@ test_expect_success '--set-upstream with two args only shows the deprecation mes
cat >expected <<EOF &&
The --set-upstream flag is deprecated and will be removed. Consider using --track or --set-upstream-to
EOF
- test_cmp expected actual
+ test_i18ncmp expected actual
'
test_expect_success '--set-upstream with one arg only shows the deprecation message if the branch existed' '
@@ -568,7 +577,7 @@ test_expect_success '--set-upstream with one arg only shows the deprecation mess
cat >expected <<EOF &&
The --set-upstream flag is deprecated and will be removed. Consider using --track or --set-upstream-to
EOF
- test_cmp expected actual
+ test_i18ncmp expected actual
'
test_expect_success '--set-upstream-to notices an error to set branch as own upstream' '
diff --git a/t/t3201-branch-contains.sh b/t/t3201-branch-contains.sh
index 912a6635a..7f3ec4724 100755
--- a/t/t3201-branch-contains.sh
+++ b/t/t3201-branch-contains.sh
@@ -156,7 +156,7 @@ test_expect_success 'branch --merged with --verbose' '
* topic 2c939f4 [ahead 1] foo
zzz c77a0a9 second on master
EOF
- test_cmp expect actual
+ test_i18ncmp expect actual
'
test_done
diff --git a/t/t3310-notes-merge-manual-resolve.sh b/t/t3310-notes-merge-manual-resolve.sh
index d5572121d..696743632 100755
--- a/t/t3310-notes-merge-manual-resolve.sh
+++ b/t/t3310-notes-merge-manual-resolve.sh
@@ -178,7 +178,7 @@ test_expect_success 'merge z into m (== y) with default ("manual") resolver => C
git config core.notesRef refs/notes/m &&
test_must_fail git notes merge z >output &&
# Output should point to where to resolve conflicts
- grep -q "\\.git/NOTES_MERGE_WORKTREE" output &&
+ test_i18ngrep "\\.git/NOTES_MERGE_WORKTREE" output &&
# Inspect merge conflicts
ls .git/NOTES_MERGE_WORKTREE >output_conflicts &&
test_cmp expect_conflicts output_conflicts &&
@@ -381,7 +381,7 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol
git config core.notesRef refs/notes/m &&
test_must_fail git notes merge z >output &&
# Output should point to where to resolve conflicts
- grep -q "\\.git/NOTES_MERGE_WORKTREE" output &&
+ test_i18ngrep "\\.git/NOTES_MERGE_WORKTREE" output &&
# Inspect merge conflicts
ls .git/NOTES_MERGE_WORKTREE >output_conflicts &&
test_cmp expect_conflicts output_conflicts &&
@@ -415,7 +415,7 @@ git rev-parse refs/notes/z > pre_merge_z
test_expect_success 'redo merge of z into m (== y) with default ("manual") resolver => Conflicting 3-way merge' '
test_must_fail git notes merge z >output &&
# Output should point to where to resolve conflicts
- grep -q "\\.git/NOTES_MERGE_WORKTREE" output &&
+ test_i18ngrep "\\.git/NOTES_MERGE_WORKTREE" output &&
# Inspect merge conflicts
ls .git/NOTES_MERGE_WORKTREE >output_conflicts &&
test_cmp expect_conflicts output_conflicts &&
@@ -496,7 +496,7 @@ test_expect_success 'redo merge of z into m (== y) with default ("manual") resol
git update-ref refs/notes/m refs/notes/y &&
test_must_fail git notes merge z >output &&
# Output should point to where to resolve conflicts
- grep -q "\\.git/NOTES_MERGE_WORKTREE" output &&
+ test_i18ngrep "\\.git/NOTES_MERGE_WORKTREE" output &&
# Inspect merge conflicts
ls .git/NOTES_MERGE_WORKTREE >output_conflicts &&
test_cmp expect_conflicts output_conflicts &&
diff --git a/t/t3320-notes-merge-worktrees.sh b/t/t3320-notes-merge-worktrees.sh
index 1f71d589f..6e0511596 100755
--- a/t/t3320-notes-merge-worktrees.sh
+++ b/t/t3320-notes-merge-worktrees.sh
@@ -52,7 +52,7 @@ test_expect_success 'merge z into y while mid-merge in another workdir fails' '
cd worktree &&
git config core.notesRef refs/notes/y &&
test_must_fail git notes merge z 2>err &&
- grep "A notes merge into refs/notes/y is already in-progress at" err
+ test_i18ngrep "A notes merge into refs/notes/y is already in-progress at" err
) &&
test_path_is_missing .git/worktrees/worktree/NOTES_MERGE_REF
'
@@ -62,7 +62,7 @@ test_expect_success 'merge z into x while mid-merge on y succeeds' '
cd worktree2 &&
git config core.notesRef refs/notes/x &&
test_must_fail git notes merge z 2>&1 >out &&
- grep "Automatic notes merge failed" out &&
+ test_i18ngrep "Automatic notes merge failed" out &&
grep -v "A notes merge into refs/notes/x is already in-progress in" out
) &&
echo "ref: refs/notes/x" >expect &&
diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh
index 47b568266..f5fd15e55 100755
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
@@ -136,8 +136,8 @@ test_expect_success 'setup: recover' '
test_expect_success 'Show verbose error when HEAD could not be detached' '
>B &&
test_must_fail git rebase topic 2>output.err >output.out &&
- grep "The following untracked working tree files would be overwritten by checkout:" output.err &&
- grep B output.err
+ test_i18ngrep "The following untracked working tree files would be overwritten by checkout:" output.err &&
+ test_i18ngrep B output.err
'
rm -f B
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index c7ea8bacf..597e94e29 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -219,9 +219,9 @@ test_expect_success 'abort with error when new base cannot be checked out' '
git commit -m "remove file in base" &&
set_fake_editor &&
test_must_fail git rebase -i master > output 2>&1 &&
- grep "The following untracked working tree files would be overwritten by checkout:" \
+ test_i18ngrep "The following untracked working tree files would be overwritten by checkout:" \
output &&
- grep "file1" output &&
+ test_i18ngrep "file1" output &&
test_path_is_missing .git/rebase-merge &&
git reset --hard HEAD^
'
@@ -540,7 +540,7 @@ test_expect_success 'clean error after failed "exec"' '
echo "edited again" > file7 &&
git add file7 &&
test_must_fail git rebase --continue 2>error &&
- grep "You have staged changes in your working tree." error
+ test_i18ngrep "You have staged changes in your working tree." error
'
test_expect_success 'rebase a detached HEAD' '
@@ -1060,7 +1060,7 @@ test_expect_success 'todo count' '
EOF
test_set_editor "$(pwd)/dump-raw.sh" &&
git rebase -i HEAD~4 >actual &&
- grep "^# Rebase ..* onto ..* ([0-9]" actual
+ test_i18ngrep "^# Rebase ..* onto ..* ([0-9]" actual
'
test_expect_success 'rebase -i commits that overwrite untracked files (pick)' '
@@ -1160,7 +1160,7 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = ignore' '
FAKE_LINES="1 2 3 4" \
git rebase -i --root 2>actual &&
test D = $(git cat-file commit HEAD | sed -ne \$p) &&
- test_cmp expect actual
+ test_i18ncmp expect actual
'
cat >expect <<EOF
@@ -1181,7 +1181,7 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = warn' '
set_fake_editor &&
FAKE_LINES="1 2 3 4" \
git rebase -i --root 2>actual &&
- test_cmp expect actual &&
+ test_i18ncmp expect actual &&
test D = $(git cat-file commit HEAD | sed -ne \$p)
'
@@ -1205,7 +1205,7 @@ test_expect_success 'rebase -i respects rebase.missingCommitsCheck = error' '
set_fake_editor &&
test_must_fail env FAKE_LINES="1 2 4" \
git rebase -i --root 2>actual &&
- test_cmp expect actual &&
+ test_i18ncmp expect actual &&
cp .git/rebase-merge/git-rebase-todo.backup \
.git/rebase-merge/git-rebase-todo &&
FAKE_LINES="1 2 drop 3 4 drop 5" \
@@ -1228,7 +1228,7 @@ test_expect_success 'static check of bad command' '
set_fake_editor &&
test_must_fail env FAKE_LINES="1 2 3 bad 4 5" \
git rebase -i --root 2>actual &&
- test_cmp expect actual &&
+ test_i18ncmp expect actual &&
FAKE_LINES="1 2 3 drop 4 5" git rebase --edit-todo &&
git rebase --continue &&
test E = $(git cat-file commit HEAD | sed -ne \$p) &&
@@ -1263,7 +1263,7 @@ test_expect_success 'static check of bad SHA-1' '
set_fake_editor &&
test_must_fail env FAKE_LINES="1 2 edit fakesha 3 4 5 #" \
git rebase -i --root 2>actual &&
- test_cmp expect actual &&
+ test_i18ncmp expect actual &&
FAKE_LINES="1 2 4 5 6" git rebase --edit-todo &&
git rebase --continue &&
test E = $(git cat-file commit HEAD | sed -ne \$p)
@@ -1281,4 +1281,12 @@ test_expect_success 'editor saves as CR/LF' '
)
'
+SQ="'"
+test_expect_success 'rebase -i --gpg-sign=<key-id>' '
+ set_fake_editor &&
+ FAKE_LINES="edit 1" git rebase -i --gpg-sign="\"S I Gner\"" HEAD^ \
+ >out 2>err &&
+ test_i18ngrep "$SQ-S\"S I Gner\"$SQ" err
+'
+
test_done
diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh
index 8f53e54ce..48346f1cc 100755
--- a/t/t3415-rebase-autosquash.sh
+++ b/t/t3415-rebase-autosquash.sh
@@ -271,4 +271,37 @@ test_expect_success 'autosquash with custom inst format' '
test 2 = $(git cat-file commit HEAD^ | grep squash | wc -l)
'
+set_backup_editor () {
+ write_script backup-editor.sh <<-\EOF
+ cp "$1" .git/backup-"$(basename "$1")"
+ EOF
+ test_set_editor "$PWD/backup-editor.sh"
+}
+
+test_expect_failure 'autosquash with multiple empty patches' '
+ test_tick &&
+ git commit --allow-empty -m "empty" &&
+ test_tick &&
+ git commit --allow-empty -m "empty2" &&
+ test_tick &&
+ >fixup &&
+ git add fixup &&
+ git commit --fixup HEAD^^ &&
+ (
+ set_backup_editor &&
+ GIT_USE_REBASE_HELPER=false \
+ git rebase -i --force-rebase --autosquash HEAD~4 &&
+ grep empty2 .git/backup-git-rebase-todo
+ )
+'
+
+test_expect_success 'extra spaces after fixup!' '
+ base=$(git rev-parse HEAD) &&
+ test_commit to-fixup &&
+ git commit --allow-empty -m "fixup! to-fixup" &&
+ git rebase -i --autosquash --keep-empty HEAD~2 &&
+ parent=$(git rev-parse HEAD^) &&
+ test $base = $parent
+'
+
test_done
diff --git a/t/t3420-rebase-autostash.sh b/t/t3420-rebase-autostash.sh
index 532ff5cbd..ab8a63e8d 100755
--- a/t/t3420-rebase-autostash.sh
+++ b/t/t3420-rebase-autostash.sh
@@ -179,7 +179,7 @@ testrebase " --interactive" .git/rebase-merge
test_expect_success 'abort rebase -i with --autostash' '
test_when_finished "git reset --hard" &&
- echo uncommited-content >file0 &&
+ echo uncommitted-content >file0 &&
(
write_script abort-editor.sh <<-\EOF &&
echo >"$1"
@@ -188,7 +188,7 @@ test_expect_success 'abort rebase -i with --autostash' '
test_must_fail git rebase -i --autostash HEAD^ &&
rm -f abort-editor.sh
) &&
- echo uncommited-content >expected &&
+ echo uncommitted-content >expected &&
test_cmp expected file0
'
diff --git a/t/t3700-add.sh b/t/t3700-add.sh
index 4865304eb..2978cb9d6 100755
--- a/t/t3700-add.sh
+++ b/t/t3700-add.sh
@@ -7,6 +7,20 @@ test_description='Test of git add, including the -- option.'
. ./test-lib.sh
+# Test the file mode "$1" of the file "$2" in the index.
+test_mode_in_index () {
+ case "$(git ls-files -s "$2")" in
+ "$1 "*" $2")
+ echo pass
+ ;;
+ *)
+ echo fail
+ git ls-files -s "$2"
+ return 1
+ ;;
+ esac
+}
+
test_expect_success \
'Test of git add' \
'touch foo && git add foo'
@@ -25,18 +39,12 @@ test_expect_success \
echo foo >xfoo1 &&
chmod 755 xfoo1 &&
git add xfoo1 &&
- case "$(git ls-files --stage xfoo1)" in
- 100644" "*xfoo1) echo pass;;
- *) echo fail; git ls-files --stage xfoo1; (exit 1);;
- esac'
+ test_mode_in_index 100644 xfoo1'
test_expect_success 'git add: filemode=0 should not get confused by symlink' '
rm -f xfoo1 &&
test_ln_s_add foo xfoo1 &&
- case "$(git ls-files --stage xfoo1)" in
- 120000" "*xfoo1) echo pass;;
- *) echo fail; git ls-files --stage xfoo1; (exit 1);;
- esac
+ test_mode_in_index 120000 xfoo1
'
test_expect_success \
@@ -45,28 +53,19 @@ test_expect_success \
echo foo >xfoo2 &&
chmod 755 xfoo2 &&
git update-index --add xfoo2 &&
- case "$(git ls-files --stage xfoo2)" in
- 100644" "*xfoo2) echo pass;;
- *) echo fail; git ls-files --stage xfoo2; (exit 1);;
- esac'
+ test_mode_in_index 100644 xfoo2'
test_expect_success 'git add: filemode=0 should not get confused by symlink' '
rm -f xfoo2 &&
test_ln_s_add foo xfoo2 &&
- case "$(git ls-files --stage xfoo2)" in
- 120000" "*xfoo2) echo pass;;
- *) echo fail; git ls-files --stage xfoo2; (exit 1);;
- esac
+ test_mode_in_index 120000 xfoo2
'
test_expect_success \
'git update-index --add: Test that executable bit is not used...' \
'git config core.filemode 0 &&
test_ln_s_add xfoo2 xfoo3 && # runs git update-index --add
- case "$(git ls-files --stage xfoo3)" in
- 120000" "*xfoo3) echo pass;;
- *) echo fail; git ls-files --stage xfoo3; (exit 1);;
- esac'
+ test_mode_in_index 120000 xfoo3'
test_expect_success '.gitignore test setup' '
echo "*.ig" >.gitignore &&
@@ -332,34 +331,22 @@ test_expect_success 'git add --dry-run --ignore-missing of non-existing file out
test_i18ncmp expect.err actual.err
'
-test_expect_success 'git add --chmod=+x stages a non-executable file with +x' '
+test_expect_success 'git add --chmod=[+-]x stages correctly' '
+ rm -f foo1 &&
echo foo >foo1 &&
git add --chmod=+x foo1 &&
- case "$(git ls-files --stage foo1)" in
- 100755" "*foo1) echo pass;;
- *) echo fail; git ls-files --stage foo1; (exit 1);;
- esac
-'
-
-test_expect_success 'git add --chmod=-x stages an executable file with -x' '
- echo foo >xfoo1 &&
- chmod 755 xfoo1 &&
- git add --chmod=-x xfoo1 &&
- case "$(git ls-files --stage xfoo1)" in
- 100644" "*xfoo1) echo pass;;
- *) echo fail; git ls-files --stage xfoo1; (exit 1);;
- esac
+ test_mode_in_index 100755 foo1 &&
+ git add --chmod=-x foo1 &&
+ test_mode_in_index 100644 foo1
'
test_expect_success POSIXPERM,SYMLINKS 'git add --chmod=+x with symlinks' '
git config core.filemode 1 &&
git config core.symlinks 1 &&
+ rm -f foo2 &&
echo foo >foo2 &&
git add --chmod=+x foo2 &&
- case "$(git ls-files --stage foo2)" in
- 100755" "*foo2) echo pass;;
- *) echo fail; git ls-files --stage foo2; (exit 1);;
- esac
+ test_mode_in_index 100755 foo2
'
test_done
diff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh
index 643d72915..0a8af76aa 100755
--- a/t/t4012-diff-binary.sh
+++ b/t/t4012-diff-binary.sh
@@ -68,7 +68,7 @@ test_expect_success C_LOCALE_OUTPUT 'apply detecting corrupt patch correctly' '
sed -e "s/-CIT/xCIT/" <output >broken &&
test_must_fail git apply --stat --summary broken 2>detected &&
detected=$(cat detected) &&
- detected=$(expr "$detected" : "fatal.*at line \\([0-9]*\\)\$") &&
+ detected=$(expr "$detected" : "error.*at line \\([0-9]*\\)\$") &&
detected=$(sed -ne "${detected}p" broken) &&
test "$detected" = xCIT
'
@@ -77,7 +77,7 @@ test_expect_success C_LOCALE_OUTPUT 'apply detecting corrupt patch correctly' '
git diff --binary | sed -e "s/-CIT/xCIT/" >broken &&
test_must_fail git apply --stat --summary broken 2>detected &&
detected=$(cat detected) &&
- detected=$(expr "$detected" : "fatal.*at line \\([0-9]*\\)\$") &&
+ detected=$(expr "$detected" : "error.*at line \\([0-9]*\\)\$") &&
detected=$(sed -ne "${detected}p" broken) &&
test "$detected" = xCIT
'
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 94ef5000e..566817e2e 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -306,6 +306,8 @@ diff --no-index --name-status dir2 dir
diff --no-index --name-status -- dir2 dir
diff --no-index dir dir3
diff master master^ side
+# Can't use spaces...
+diff --line-prefix=abc master master^ side
diff --dirstat master~1 master~2
diff --dirstat initial rearrange
diff --dirstat-by-file initial rearrange
@@ -325,6 +327,10 @@ test_expect_success 'diff --cached -- file on unborn branch' '
git diff --cached -- file0 >result &&
test_cmp "$TEST_DIRECTORY/t4013/diff.diff_--cached_--_file0" result
'
+test_expect_success 'diff --line-prefix with spaces' '
+ git diff --line-prefix="| | | " --cached -- file0 >result &&
+ test_cmp "$TEST_DIRECTORY/t4013/diff.diff_--line-prefix_--cached_--_file0" result
+'
test_expect_success 'diff-tree --stdin with log formatting' '
cat >expect <<-\EOF &&
diff --git a/t/t4013/diff.diff_--line-prefix=abc_master_master^_side b/t/t4013/diff.diff_--line-prefix=abc_master_master^_side
new file mode 100644
index 000000000..99f91e7f0
--- /dev/null
+++ b/t/t4013/diff.diff_--line-prefix=abc_master_master^_side
@@ -0,0 +1,29 @@
+$ git diff --line-prefix=abc master master^ side
+abcdiff --cc dir/sub
+abcindex cead32e,7289e35..992913c
+abc--- a/dir/sub
+abc+++ b/dir/sub
+abc@@@ -1,6 -1,4 +1,8 @@@
+abc A
+abc B
+abc +C
+abc +D
+abc +E
+abc +F
+abc+ 1
+abc+ 2
+abcdiff --cc file0
+abcindex b414108,f4615da..10a8a9f
+abc--- a/file0
+abc+++ b/file0
+abc@@@ -1,6 -1,6 +1,9 @@@
+abc 1
+abc 2
+abc 3
+abc +4
+abc +5
+abc +6
+abc+ A
+abc+ B
+abc+ C
+$
diff --git a/t/t4013/diff.diff_--line-prefix_--cached_--_file0 b/t/t4013/diff.diff_--line-prefix_--cached_--_file0
new file mode 100644
index 000000000..f41ba4d36
--- /dev/null
+++ b/t/t4013/diff.diff_--line-prefix_--cached_--_file0
@@ -0,0 +1,15 @@
+| | | diff --git a/file0 b/file0
+| | | new file mode 100644
+| | | index 0000000..10a8a9f
+| | | --- /dev/null
+| | | +++ b/file0
+| | | @@ -0,0 +1,9 @@
+| | | +1
+| | | +2
+| | | +3
+| | | +4
+| | | +5
+| | | +6
+| | | +A
+| | | +B
+| | | +C
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 805dc9012..b0579dd45 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -229,6 +229,46 @@ check_patch () {
grep -e "^Subject:" "$1"
}
+test_expect_success 'format.from=false' '
+
+ git -c format.from=false format-patch --stdout master..side |
+ sed -e "/^\$/q" >patch &&
+ check_patch patch &&
+ ! grep "^From: C O Mitter <committer@example.com>\$" patch
+'
+
+test_expect_success 'format.from=true' '
+
+ git -c format.from=true format-patch --stdout master..side |
+ sed -e "/^\$/q" >patch &&
+ check_patch patch &&
+ grep "^From: C O Mitter <committer@example.com>\$" patch
+'
+
+test_expect_success 'format.from with address' '
+
+ git -c format.from="F R Om <from@example.com>" format-patch --stdout master..side |
+ sed -e "/^\$/q" >patch &&
+ check_patch patch &&
+ grep "^From: F R Om <from@example.com>\$" patch
+'
+
+test_expect_success '--no-from overrides format.from' '
+
+ git -c format.from="F R Om <from@example.com>" format-patch --no-from --stdout master..side |
+ sed -e "/^\$/q" >patch &&
+ check_patch patch &&
+ ! grep "^From: F R Om <from@example.com>\$" patch
+'
+
+test_expect_success '--from overrides format.from' '
+
+ git -c format.from="F R Om <from@example.com>" format-patch --from --stdout master..side |
+ sed -e "/^\$/q" >patch &&
+ check_patch patch &&
+ ! grep "^From: F R Om <from@example.com>\$" patch
+'
+
test_expect_success '--no-to overrides config.to' '
git config --replace-all format.to \
@@ -1565,4 +1605,45 @@ test_expect_success 'format-patch --base overrides format.useAutoBase' '
test_cmp expected actual
'
+test_expect_success 'format-patch --pretty=mboxrd' '
+ sp=" " &&
+ cat >msg <<-INPUT_END &&
+ mboxrd should escape the body
+
+ From could trip up a loose mbox parser
+ >From extra escape for reversibility
+ >>From extra escape for reversibility 2
+ from lower case not escaped
+ Fromm bad speling not escaped
+ From with leading space not escaped
+
+ F
+ From
+ From$sp
+ From $sp
+ From $sp
+ INPUT_END
+
+ cat >expect <<-INPUT_END &&
+ >From could trip up a loose mbox parser
+ >>From extra escape for reversibility
+ >>>From extra escape for reversibility 2
+ from lower case not escaped
+ Fromm bad speling not escaped
+ From with leading space not escaped
+
+ F
+ From
+ From
+ From
+ From
+ INPUT_END
+
+ C=$(git commit-tree HEAD^^{tree} -p HEAD <msg) &&
+ git format-patch --pretty=mboxrd --stdout -1 $C~1..$C >patch &&
+ git grep -h --no-index -A11 \
+ "^>From could trip up a loose mbox parser" patch >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh
index 67373dc44..1795ffc3a 100755
--- a/t/t4018-diff-funcname.sh
+++ b/t/t4018-diff-funcname.sh
@@ -30,6 +30,7 @@ diffpatterns="
bibtex
cpp
csharp
+ css
fortran
fountain
html
diff --git a/t/t4018/css-brace-in-col-1 b/t/t4018/css-brace-in-col-1
new file mode 100644
index 000000000..783157750
--- /dev/null
+++ b/t/t4018/css-brace-in-col-1
@@ -0,0 +1,5 @@
+RIGHT label.control-label
+{
+ margin-top: 10px!important;
+ border : 10px ChangeMe #C6C6C6;
+}
diff --git a/t/t4018/css-colon-eol b/t/t4018/css-colon-eol
new file mode 100644
index 000000000..5a30553d2
--- /dev/null
+++ b/t/t4018/css-colon-eol
@@ -0,0 +1,4 @@
+RIGHT h1 {
+color:
+ChangeMe;
+}
diff --git a/t/t4018/css-colon-selector b/t/t4018/css-colon-selector
new file mode 100644
index 000000000..c6d71fb42
--- /dev/null
+++ b/t/t4018/css-colon-selector
@@ -0,0 +1,5 @@
+RIGHT a:hover {
+ margin-top:
+ 10px!important;
+ border : 10px ChangeMe #C6C6C6;
+}
diff --git a/t/t4018/css-common b/t/t4018/css-common
new file mode 100644
index 000000000..84ed754b3
--- /dev/null
+++ b/t/t4018/css-common
@@ -0,0 +1,4 @@
+RIGHT label.control-label {
+ margin-top: 10px!important;
+ border : 10px ChangeMe #C6C6C6;
+}
diff --git a/t/t4018/css-long-selector-list b/t/t4018/css-long-selector-list
new file mode 100644
index 000000000..7ccd25d9e
--- /dev/null
+++ b/t/t4018/css-long-selector-list
@@ -0,0 +1,6 @@
+p.header,
+label.control-label,
+div ul#RIGHT {
+ margin-top: 10px!important;
+ border : 10px ChangeMe #C6C6C6;
+}
diff --git a/t/t4018/css-prop-sans-indent b/t/t4018/css-prop-sans-indent
new file mode 100644
index 000000000..a9e3c86b3
--- /dev/null
+++ b/t/t4018/css-prop-sans-indent
@@ -0,0 +1,5 @@
+RIGHT, label.control-label {
+margin-top: 10px!important;
+padding: 0;
+border : 10px ChangeMe #C6C6C6;
+}
diff --git a/t/t4018/css-short-selector-list b/t/t4018/css-short-selector-list
new file mode 100644
index 000000000..6a0bdee33
--- /dev/null
+++ b/t/t4018/css-short-selector-list
@@ -0,0 +1,4 @@
+label.control, div ul#RIGHT {
+ margin-top: 10px!important;
+ border : 10px ChangeMe #C6C6C6;
+}
diff --git a/t/t4018/css-trailing-space b/t/t4018/css-trailing-space
new file mode 100644
index 000000000..32b5606c7
--- /dev/null
+++ b/t/t4018/css-trailing-space
@@ -0,0 +1,5 @@
+RIGHT label.control-label {
+ margin:10px;
+ padding:10px;
+ border : 10px ChangeMe #C6C6C6;
+}
diff --git a/t/t4021-format-patch-numbered.sh b/t/t4021-format-patch-numbered.sh
index 886494b58..9be65fd44 100755
--- a/t/t4021-format-patch-numbered.sh
+++ b/t/t4021-format-patch-numbered.sh
@@ -36,6 +36,11 @@ test_no_numbered() {
test_num_no_numbered $1 2
}
+test_single_cover_letter_numbered() {
+ grep "^Subject: \[PATCH 0/1\]" $1 &&
+ grep "^Subject: \[PATCH 1/1\]" $1
+}
+
test_single_numbered() {
grep "^Subject: \[PATCH 1/1\]" $1
}
@@ -121,4 +126,16 @@ test_expect_success '--start-number && --numbered' '
grep "^Subject: \[PATCH 3/3\]" patch8
'
+test_expect_success 'single patch with cover-letter defaults to numbers' '
+ git format-patch --cover-letter --stdout HEAD~1 >patch9.single &&
+ test_single_cover_letter_numbered patch9.single
+'
+
+test_expect_success 'Use --no-numbered and --cover-letter single patch' '
+ git format-patch --no-numbered --stdout --cover-letter HEAD~1 >patch10 &&
+ test_no_numbered patch10
+'
+
+
+
test_done
diff --git a/t/t4026-color.sh b/t/t4026-color.sh
index 2b32c4fbe..ec78c5e3a 100755
--- a/t/t4026-color.sh
+++ b/t/t4026-color.sh
@@ -50,14 +50,19 @@ test_expect_success 'attr negation' '
color "nobold nodim noul noblink noreverse" "[22;24;25;27m"
'
+test_expect_success '"no-" variant of negation' '
+ color "no-bold no-blink" "[22;25m"
+'
+
test_expect_success 'long color specification' '
color "254 255 bold dim ul blink reverse" "[1;2;4;5;7;38;5;254;48;5;255m"
'
test_expect_success 'absurdly long color specification' '
color \
- "#ffffff #ffffff bold nobold dim nodim ul noul blink noblink reverse noreverse" \
- "[1;2;4;5;7;22;24;25;27;38;2;255;255;255;48;2;255;255;255m"
+ "#ffffff #ffffff bold nobold dim nodim italic noitalic
+ ul noul blink noblink reverse noreverse strike nostrike" \
+ "[1;2;3;4;5;7;9;22;23;24;25;27;29;38;2;255;255;255;48;2;255;255;255m"
'
test_expect_success '0-7 are aliases for basic ANSI color names' '
diff --git a/t/t4034-diff-words.sh b/t/t4034-diff-words.sh
index f2f55fc51..912df9122 100755
--- a/t/t4034-diff-words.sh
+++ b/t/t4034-diff-words.sh
@@ -302,6 +302,7 @@ test_language_driver ada
test_language_driver bibtex
test_language_driver cpp
test_language_driver csharp
+test_language_driver css
test_language_driver fortran
test_language_driver html
test_language_driver java
diff --git a/t/t4034/css/expect b/t/t4034/css/expect
new file mode 100644
index 000000000..ed10393bd
--- /dev/null
+++ b/t/t4034/css/expect
@@ -0,0 +1,16 @@
+<BOLD>diff --git a/pre b/post<RESET>
+<BOLD>index b8ae0bb..fe500b7 100644<RESET>
+<BOLD>--- a/pre<RESET>
+<BOLD>+++ b/post<RESET>
+<CYAN>@@ -1,10 +1,10 @@<RESET>
+.<RED>class-form<RESET><GREEN>other-form<RESET> label.control-label {
+ margin-top: <RED>10<RESET><GREEN>15<RESET>px!important;
+ border : 10px <RED>dashed<RESET><GREEN>dotted<RESET> #C6C6C6;
+}<RESET>
+<RED>#CCCCCC<RESET><GREEN>#CCCCCB<RESET>
+10em<RESET>
+<RED>padding-bottom<RESET><GREEN>margin-left<RESET>
+150<RED>px<RESET><GREEN>em<RESET>
+10px
+<RED>!important<RESET>
+<RED>div<RESET><GREEN>li<RESET>.class#id
diff --git a/t/t4034/css/post b/t/t4034/css/post
new file mode 100644
index 000000000..fe500b7a4
--- /dev/null
+++ b/t/t4034/css/post
@@ -0,0 +1,10 @@
+.other-form label.control-label {
+ margin-top: 15px!important;
+ border : 10px dotted #C6C6C6;
+}
+#CCCCCB
+10em
+margin-left
+150em
+10px
+li.class#id
diff --git a/t/t4034/css/pre b/t/t4034/css/pre
new file mode 100644
index 000000000..b8ae0bb48
--- /dev/null
+++ b/t/t4034/css/pre
@@ -0,0 +1,10 @@
+.class-form label.control-label {
+ margin-top: 10px!important;
+ border : 10px dashed #C6C6C6;
+}
+#CCCCCC
+10em
+padding-bottom
+150px
+10px!important
+div.class#id
diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh
index 6eb83211b..453e6c35e 100755
--- a/t/t4053-diff-no-index.sh
+++ b/t/t4053-diff-no-index.sh
@@ -89,4 +89,42 @@ test_expect_success 'turning a file into a directory' '
)
'
+test_expect_success 'diff from repo subdir shows real paths (explicit)' '
+ echo "diff --git a/../../non/git/a b/../../non/git/b" >expect &&
+ test_expect_code 1 \
+ git -C repo/sub \
+ diff --no-index ../../non/git/a ../../non/git/b >actual &&
+ head -n 1 <actual >actual.head &&
+ test_cmp expect actual.head
+'
+
+test_expect_success 'diff from repo subdir shows real paths (implicit)' '
+ echo "diff --git a/../../non/git/a b/../../non/git/b" >expect &&
+ test_expect_code 1 \
+ git -C repo/sub \
+ diff ../../non/git/a ../../non/git/b >actual &&
+ head -n 1 <actual >actual.head &&
+ test_cmp expect actual.head
+'
+
+test_expect_success 'diff --no-index from repo subdir respects config (explicit)' '
+ echo "diff --git ../../non/git/a ../../non/git/b" >expect &&
+ test_config -C repo diff.noprefix true &&
+ test_expect_code 1 \
+ git -C repo/sub \
+ diff --no-index ../../non/git/a ../../non/git/b >actual &&
+ head -n 1 <actual >actual.head &&
+ test_cmp expect actual.head
+'
+
+test_expect_success 'diff --no-index from repo subdir respects config (implicit)' '
+ echo "diff --git ../../non/git/a ../../non/git/b" >expect &&
+ test_config -C repo diff.noprefix true &&
+ test_expect_code 1 \
+ git -C repo/sub \
+ diff ../../non/git/a ../../non/git/b >actual &&
+ head -n 1 <actual >actual.head &&
+ test_cmp expect actual.head
+'
+
test_done
diff --git a/t/t4059-diff-submodule-not-initialized.sh b/t/t4059-diff-submodule-not-initialized.sh
new file mode 100755
index 000000000..cd70fd519
--- /dev/null
+++ b/t/t4059-diff-submodule-not-initialized.sh
@@ -0,0 +1,127 @@
+#!/bin/sh
+#
+# Copyright (c) 2016 Jacob Keller, based on t4041 by Jens Lehmann
+#
+
+test_description='Test for submodule diff on non-checked out submodule
+
+This test tries to verify that add_submodule_odb works when the submodule was
+initialized previously but the checkout has since been removed.
+'
+
+. ./test-lib.sh
+
+# Tested non-UTF-8 encoding
+test_encoding="ISO8859-1"
+
+# String "added" in German (translated with Google Translate), encoded in UTF-8,
+# used in sample commit log messages in add_file() function below.
+added=$(printf "hinzugef\303\274gt")
+
+add_file () {
+ (
+ cd "$1" &&
+ shift &&
+ for name
+ do
+ echo "$name" >"$name" &&
+ git add "$name" &&
+ test_tick &&
+ # "git commit -m" would break MinGW, as Windows refuse to pass
+ # $test_encoding encoded parameter to git.
+ echo "Add $name ($added $name)" | iconv -f utf-8 -t $test_encoding |
+ git -c "i18n.commitEncoding=$test_encoding" commit -F -
+ done >/dev/null &&
+ git rev-parse --short --verify HEAD
+ )
+}
+
+commit_file () {
+ test_tick &&
+ git commit "$@" -m "Commit $*" >/dev/null
+}
+
+test_expect_success 'setup - submodules' '
+ test_create_repo sm2 &&
+ add_file . foo &&
+ add_file sm2 foo1 foo2 &&
+ smhead1=$(git -C sm2 rev-parse --short --verify HEAD)
+'
+
+test_expect_success 'setup - git submodule add' '
+ git submodule add ./sm2 sm1 &&
+ commit_file sm1 .gitmodules &&
+ git diff-tree -p --no-commit-id --submodule=log HEAD -- sm1 >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 0000000...$smhead1 (new submodule)
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'submodule directory removed' '
+ rm -rf sm1 &&
+ git diff-tree -p --no-commit-id --submodule=log HEAD -- sm1 >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 0000000...$smhead1 (new submodule)
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'setup - submodule multiple commits' '
+ git submodule update --checkout sm1 &&
+ smhead2=$(add_file sm1 foo3 foo4) &&
+ commit_file sm1 &&
+ git diff-tree -p --no-commit-id --submodule=log HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 $smhead1..$smhead2:
+ > Add foo4 ($added foo4)
+ > Add foo3 ($added foo3)
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'submodule removed multiple commits' '
+ rm -rf sm1 &&
+ git diff-tree -p --no-commit-id --submodule=log HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 $smhead1..$smhead2:
+ > Add foo4 ($added foo4)
+ > Add foo3 ($added foo3)
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'submodule not initialized in new clone' '
+ git clone . sm3 &&
+ git -C sm3 diff-tree -p --no-commit-id --submodule=log HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 $smhead1...$smhead2 (not initialized)
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'setup submodule moved' '
+ git submodule update --checkout sm1 &&
+ git mv sm1 sm4 &&
+ commit_file sm4 &&
+ git diff-tree -p --no-commit-id --submodule=log HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm4 0000000...$smhead2 (new submodule)
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'submodule moved then removed' '
+ smhead3=$(add_file sm4 foo6 foo7) &&
+ commit_file sm4 &&
+ rm -rf sm4 &&
+ git diff-tree -p --no-commit-id --submodule=log HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm4 $smhead2..$smhead3:
+ > Add foo7 ($added foo7)
+ > Add foo6 ($added foo6)
+ EOF
+ test_cmp expected actual
+'
+
+test_done
diff --git a/t/t4060-diff-submodule-option-diff-format.sh b/t/t4060-diff-submodule-option-diff-format.sh
new file mode 100755
index 000000000..7e23b55ea
--- /dev/null
+++ b/t/t4060-diff-submodule-option-diff-format.sh
@@ -0,0 +1,749 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Jens Lehmann, based on t7401 by Ping Yin
+# Copyright (c) 2011 Alexey Shumkin (+ non-UTF-8 commit encoding tests)
+# Copyright (c) 2016 Jacob Keller (copy + convert to --submodule=diff)
+#
+
+test_description='Support for diff format verbose submodule difference in git diff
+
+This test tries to verify the sanity of --submodule=diff option of git diff.
+'
+
+. ./test-lib.sh
+
+# Tested non-UTF-8 encoding
+test_encoding="ISO8859-1"
+
+# String "added" in German (translated with Google Translate), encoded in UTF-8,
+# used in sample commit log messages in add_file() function below.
+added=$(printf "hinzugef\303\274gt")
+
+add_file () {
+ (
+ cd "$1" &&
+ shift &&
+ for name
+ do
+ echo "$name" >"$name" &&
+ git add "$name" &&
+ test_tick &&
+ # "git commit -m" would break MinGW, as Windows refuse to pass
+ # $test_encoding encoded parameter to git.
+ echo "Add $name ($added $name)" | iconv -f utf-8 -t $test_encoding |
+ git -c "i18n.commitEncoding=$test_encoding" commit -F -
+ done >/dev/null &&
+ git rev-parse --short --verify HEAD
+ )
+}
+
+commit_file () {
+ test_tick &&
+ git commit "$@" -m "Commit $*" >/dev/null
+}
+
+test_expect_success 'setup repository' '
+ test_create_repo sm1 &&
+ add_file . foo &&
+ head1=$(add_file sm1 foo1 foo2) &&
+ fullhead1=$(git -C sm1 rev-parse --verify HEAD)
+'
+
+test_expect_success 'added submodule' '
+ git add sm1 &&
+ git diff-index -p --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 0000000...$head1 (new submodule)
+ diff --git a/sm1/foo1 b/sm1/foo1
+ new file mode 100644
+ index 0000000..1715acd
+ --- /dev/null
+ +++ b/sm1/foo1
+ @@ -0,0 +1 @@
+ +foo1
+ diff --git a/sm1/foo2 b/sm1/foo2
+ new file mode 100644
+ index 0000000..54b060e
+ --- /dev/null
+ +++ b/sm1/foo2
+ @@ -0,0 +1 @@
+ +foo2
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'added submodule, set diff.submodule' '
+ test_config diff.submodule log &&
+ git add sm1 &&
+ git diff-index -p --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 0000000...$head1 (new submodule)
+ diff --git a/sm1/foo1 b/sm1/foo1
+ new file mode 100644
+ index 0000000..1715acd
+ --- /dev/null
+ +++ b/sm1/foo1
+ @@ -0,0 +1 @@
+ +foo1
+ diff --git a/sm1/foo2 b/sm1/foo2
+ new file mode 100644
+ index 0000000..54b060e
+ --- /dev/null
+ +++ b/sm1/foo2
+ @@ -0,0 +1 @@
+ +foo2
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success '--submodule=short overrides diff.submodule' '
+ test_config diff.submodule log &&
+ git add sm1 &&
+ git diff --submodule=short --cached >actual &&
+ cat >expected <<-EOF &&
+ diff --git a/sm1 b/sm1
+ new file mode 160000
+ index 0000000..$head1
+ --- /dev/null
+ +++ b/sm1
+ @@ -0,0 +1 @@
+ +Subproject commit $fullhead1
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'diff.submodule does not affect plumbing' '
+ test_config diff.submodule log &&
+ git diff-index -p HEAD >actual &&
+ cat >expected <<-EOF &&
+ diff --git a/sm1 b/sm1
+ new file mode 160000
+ index 0000000..$head1
+ --- /dev/null
+ +++ b/sm1
+ @@ -0,0 +1 @@
+ +Subproject commit $fullhead1
+ EOF
+ test_cmp expected actual
+'
+
+commit_file sm1 &&
+head2=$(add_file sm1 foo3)
+
+test_expect_success 'modified submodule(forward)' '
+ git diff-index -p --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 $head1..$head2:
+ diff --git a/sm1/foo3 b/sm1/foo3
+ new file mode 100644
+ index 0000000..c1ec6c6
+ --- /dev/null
+ +++ b/sm1/foo3
+ @@ -0,0 +1 @@
+ +foo3
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'modified submodule(forward)' '
+ git diff --submodule=diff >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 $head1..$head2:
+ diff --git a/sm1/foo3 b/sm1/foo3
+ new file mode 100644
+ index 0000000..c1ec6c6
+ --- /dev/null
+ +++ b/sm1/foo3
+ @@ -0,0 +1 @@
+ +foo3
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'modified submodule(forward) --submodule' '
+ git diff --submodule >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 $head1..$head2:
+ > Add foo3 ($added foo3)
+ EOF
+ test_cmp expected actual
+'
+
+fullhead2=$(cd sm1; git rev-parse --verify HEAD)
+test_expect_success 'modified submodule(forward) --submodule=short' '
+ git diff --submodule=short >actual &&
+ cat >expected <<-EOF &&
+ diff --git a/sm1 b/sm1
+ index $head1..$head2 160000
+ --- a/sm1
+ +++ b/sm1
+ @@ -1 +1 @@
+ -Subproject commit $fullhead1
+ +Subproject commit $fullhead2
+ EOF
+ test_cmp expected actual
+'
+
+commit_file sm1 &&
+head3=$(
+ cd sm1 &&
+ git reset --hard HEAD~2 >/dev/null &&
+ git rev-parse --short --verify HEAD
+)
+
+test_expect_success 'modified submodule(backward)' '
+ git diff-index -p --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 $head2..$head3 (rewind):
+ diff --git a/sm1/foo2 b/sm1/foo2
+ deleted file mode 100644
+ index 54b060e..0000000
+ --- a/sm1/foo2
+ +++ /dev/null
+ @@ -1 +0,0 @@
+ -foo2
+ diff --git a/sm1/foo3 b/sm1/foo3
+ deleted file mode 100644
+ index c1ec6c6..0000000
+ --- a/sm1/foo3
+ +++ /dev/null
+ @@ -1 +0,0 @@
+ -foo3
+ EOF
+ test_cmp expected actual
+'
+
+head4=$(add_file sm1 foo4 foo5)
+test_expect_success 'modified submodule(backward and forward)' '
+ git diff-index -p --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 $head2...$head4:
+ diff --git a/sm1/foo2 b/sm1/foo2
+ deleted file mode 100644
+ index 54b060e..0000000
+ --- a/sm1/foo2
+ +++ /dev/null
+ @@ -1 +0,0 @@
+ -foo2
+ diff --git a/sm1/foo3 b/sm1/foo3
+ deleted file mode 100644
+ index c1ec6c6..0000000
+ --- a/sm1/foo3
+ +++ /dev/null
+ @@ -1 +0,0 @@
+ -foo3
+ diff --git a/sm1/foo4 b/sm1/foo4
+ new file mode 100644
+ index 0000000..a0016db
+ --- /dev/null
+ +++ b/sm1/foo4
+ @@ -0,0 +1 @@
+ +foo4
+ diff --git a/sm1/foo5 b/sm1/foo5
+ new file mode 100644
+ index 0000000..d6f2413
+ --- /dev/null
+ +++ b/sm1/foo5
+ @@ -0,0 +1 @@
+ +foo5
+ EOF
+ test_cmp expected actual
+'
+
+commit_file sm1 &&
+mv sm1 sm1-bak &&
+echo sm1 >sm1 &&
+head5=$(git hash-object sm1 | cut -c1-7) &&
+git add sm1 &&
+rm -f sm1 &&
+mv sm1-bak sm1
+
+test_expect_success 'typechanged submodule(submodule->blob), --cached' '
+ git diff --submodule=diff --cached >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 $head4...0000000 (submodule deleted)
+ diff --git a/sm1/foo1 b/sm1/foo1
+ deleted file mode 100644
+ index 1715acd..0000000
+ --- a/sm1/foo1
+ +++ /dev/null
+ @@ -1 +0,0 @@
+ -foo1
+ diff --git a/sm1/foo4 b/sm1/foo4
+ deleted file mode 100644
+ index a0016db..0000000
+ --- a/sm1/foo4
+ +++ /dev/null
+ @@ -1 +0,0 @@
+ -foo4
+ diff --git a/sm1/foo5 b/sm1/foo5
+ deleted file mode 100644
+ index d6f2413..0000000
+ --- a/sm1/foo5
+ +++ /dev/null
+ @@ -1 +0,0 @@
+ -foo5
+ diff --git a/sm1 b/sm1
+ new file mode 100644
+ index 0000000..9da5fb8
+ --- /dev/null
+ +++ b/sm1
+ @@ -0,0 +1 @@
+ +sm1
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'typechanged submodule(submodule->blob)' '
+ git diff --submodule=diff >actual &&
+ cat >expected <<-EOF &&
+ diff --git a/sm1 b/sm1
+ deleted file mode 100644
+ index 9da5fb8..0000000
+ --- a/sm1
+ +++ /dev/null
+ @@ -1 +0,0 @@
+ -sm1
+ Submodule sm1 0000000...$head4 (new submodule)
+ diff --git a/sm1/foo1 b/sm1/foo1
+ new file mode 100644
+ index 0000000..1715acd
+ --- /dev/null
+ +++ b/sm1/foo1
+ @@ -0,0 +1 @@
+ +foo1
+ diff --git a/sm1/foo4 b/sm1/foo4
+ new file mode 100644
+ index 0000000..a0016db
+ --- /dev/null
+ +++ b/sm1/foo4
+ @@ -0,0 +1 @@
+ +foo4
+ diff --git a/sm1/foo5 b/sm1/foo5
+ new file mode 100644
+ index 0000000..d6f2413
+ --- /dev/null
+ +++ b/sm1/foo5
+ @@ -0,0 +1 @@
+ +foo5
+ EOF
+ test_cmp expected actual
+'
+
+rm -rf sm1 &&
+git checkout-index sm1
+test_expect_success 'typechanged submodule(submodule->blob)' '
+ git diff-index -p --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 $head4...0000000 (submodule deleted)
+ diff --git a/sm1 b/sm1
+ new file mode 100644
+ index 0000000..9da5fb8
+ --- /dev/null
+ +++ b/sm1
+ @@ -0,0 +1 @@
+ +sm1
+ EOF
+ test_cmp expected actual
+'
+
+rm -f sm1 &&
+test_create_repo sm1 &&
+head6=$(add_file sm1 foo6 foo7)
+fullhead6=$(cd sm1; git rev-parse --verify HEAD)
+test_expect_success 'nonexistent commit' '
+ git diff-index -p --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 $head4...$head6 (commits not present)
+ EOF
+ test_cmp expected actual
+'
+
+commit_file
+test_expect_success 'typechanged submodule(blob->submodule)' '
+ git diff-index -p --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ diff --git a/sm1 b/sm1
+ deleted file mode 100644
+ index 9da5fb8..0000000
+ --- a/sm1
+ +++ /dev/null
+ @@ -1 +0,0 @@
+ -sm1
+ Submodule sm1 0000000...$head6 (new submodule)
+ diff --git a/sm1/foo6 b/sm1/foo6
+ new file mode 100644
+ index 0000000..462398b
+ --- /dev/null
+ +++ b/sm1/foo6
+ @@ -0,0 +1 @@
+ +foo6
+ diff --git a/sm1/foo7 b/sm1/foo7
+ new file mode 100644
+ index 0000000..6e9262c
+ --- /dev/null
+ +++ b/sm1/foo7
+ @@ -0,0 +1 @@
+ +foo7
+ EOF
+ test_cmp expected actual
+'
+
+commit_file sm1 &&
+test_expect_success 'submodule is up to date' '
+ git diff-index -p --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'submodule contains untracked content' '
+ echo new > sm1/new-file &&
+ git diff-index -p --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 contains untracked content
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'submodule contains untracked content (untracked ignored)' '
+ git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
+ ! test -s actual
+'
+
+test_expect_success 'submodule contains untracked content (dirty ignored)' '
+ git diff-index -p --ignore-submodules=dirty --submodule=diff HEAD >actual &&
+ ! test -s actual
+'
+
+test_expect_success 'submodule contains untracked content (all ignored)' '
+ git diff-index -p --ignore-submodules=all --submodule=diff HEAD >actual &&
+ ! test -s actual
+'
+
+test_expect_success 'submodule contains untracked and modified content' '
+ echo new > sm1/foo6 &&
+ git diff-index -p --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 contains untracked content
+ Submodule sm1 contains modified content
+ diff --git a/sm1/foo6 b/sm1/foo6
+ index 462398b..3e75765 100644
+ --- a/sm1/foo6
+ +++ b/sm1/foo6
+ @@ -1 +1 @@
+ -foo6
+ +new
+ EOF
+ test_cmp expected actual
+'
+
+# NOT OK
+test_expect_success 'submodule contains untracked and modified content (untracked ignored)' '
+ echo new > sm1/foo6 &&
+ git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 contains modified content
+ diff --git a/sm1/foo6 b/sm1/foo6
+ index 462398b..3e75765 100644
+ --- a/sm1/foo6
+ +++ b/sm1/foo6
+ @@ -1 +1 @@
+ -foo6
+ +new
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'submodule contains untracked and modified content (dirty ignored)' '
+ echo new > sm1/foo6 &&
+ git diff-index -p --ignore-submodules=dirty --submodule=diff HEAD >actual &&
+ ! test -s actual
+'
+
+test_expect_success 'submodule contains untracked and modified content (all ignored)' '
+ echo new > sm1/foo6 &&
+ git diff-index -p --ignore-submodules --submodule=diff HEAD >actual &&
+ ! test -s actual
+'
+
+test_expect_success 'submodule contains modified content' '
+ rm -f sm1/new-file &&
+ git diff-index -p --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 contains modified content
+ diff --git a/sm1/foo6 b/sm1/foo6
+ index 462398b..3e75765 100644
+ --- a/sm1/foo6
+ +++ b/sm1/foo6
+ @@ -1 +1 @@
+ -foo6
+ +new
+ EOF
+ test_cmp expected actual
+'
+
+(cd sm1; git commit -mchange foo6 >/dev/null) &&
+head8=$(cd sm1; git rev-parse --short --verify HEAD) &&
+test_expect_success 'submodule is modified' '
+ git diff-index -p --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 17243c9..$head8:
+ diff --git a/sm1/foo6 b/sm1/foo6
+ index 462398b..3e75765 100644
+ --- a/sm1/foo6
+ +++ b/sm1/foo6
+ @@ -1 +1 @@
+ -foo6
+ +new
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'modified submodule contains untracked content' '
+ echo new > sm1/new-file &&
+ git diff-index -p --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 contains untracked content
+ Submodule sm1 17243c9..$head8:
+ diff --git a/sm1/foo6 b/sm1/foo6
+ index 462398b..3e75765 100644
+ --- a/sm1/foo6
+ +++ b/sm1/foo6
+ @@ -1 +1 @@
+ -foo6
+ +new
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'modified submodule contains untracked content (untracked ignored)' '
+ git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 17243c9..$head8:
+ diff --git a/sm1/foo6 b/sm1/foo6
+ index 462398b..3e75765 100644
+ --- a/sm1/foo6
+ +++ b/sm1/foo6
+ @@ -1 +1 @@
+ -foo6
+ +new
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'modified submodule contains untracked content (dirty ignored)' '
+ git diff-index -p --ignore-submodules=dirty --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 17243c9..cfce562:
+ diff --git a/sm1/foo6 b/sm1/foo6
+ index 462398b..3e75765 100644
+ --- a/sm1/foo6
+ +++ b/sm1/foo6
+ @@ -1 +1 @@
+ -foo6
+ +new
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'modified submodule contains untracked content (all ignored)' '
+ git diff-index -p --ignore-submodules=all --submodule=diff HEAD >actual &&
+ ! test -s actual
+'
+
+test_expect_success 'modified submodule contains untracked and modified content' '
+ echo modification >> sm1/foo6 &&
+ git diff-index -p --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 contains untracked content
+ Submodule sm1 contains modified content
+ Submodule sm1 17243c9..cfce562:
+ diff --git a/sm1/foo6 b/sm1/foo6
+ index 462398b..dfda541 100644
+ --- a/sm1/foo6
+ +++ b/sm1/foo6
+ @@ -1 +1,2 @@
+ -foo6
+ +new
+ +modification
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'modified submodule contains untracked and modified content (untracked ignored)' '
+ echo modification >> sm1/foo6 &&
+ git diff-index -p --ignore-submodules=untracked --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 contains modified content
+ Submodule sm1 17243c9..cfce562:
+ diff --git a/sm1/foo6 b/sm1/foo6
+ index 462398b..e20e2d9 100644
+ --- a/sm1/foo6
+ +++ b/sm1/foo6
+ @@ -1 +1,3 @@
+ -foo6
+ +new
+ +modification
+ +modification
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'modified submodule contains untracked and modified content (dirty ignored)' '
+ echo modification >> sm1/foo6 &&
+ git diff-index -p --ignore-submodules=dirty --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 17243c9..cfce562:
+ diff --git a/sm1/foo6 b/sm1/foo6
+ index 462398b..3e75765 100644
+ --- a/sm1/foo6
+ +++ b/sm1/foo6
+ @@ -1 +1 @@
+ -foo6
+ +new
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'modified submodule contains untracked and modified content (all ignored)' '
+ echo modification >> sm1/foo6 &&
+ git diff-index -p --ignore-submodules --submodule=diff HEAD >actual &&
+ ! test -s actual
+'
+
+# NOT OK
+test_expect_success 'modified submodule contains modified content' '
+ rm -f sm1/new-file &&
+ git diff-index -p --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 contains modified content
+ Submodule sm1 17243c9..cfce562:
+ diff --git a/sm1/foo6 b/sm1/foo6
+ index 462398b..ac466ca 100644
+ --- a/sm1/foo6
+ +++ b/sm1/foo6
+ @@ -1 +1,5 @@
+ -foo6
+ +new
+ +modification
+ +modification
+ +modification
+ +modification
+ EOF
+ test_cmp expected actual
+'
+
+rm -rf sm1
+test_expect_success 'deleted submodule' '
+ git diff-index -p --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 17243c9...0000000 (submodule deleted)
+ EOF
+ test_cmp expected actual
+'
+
+test_create_repo sm2 &&
+head7=$(add_file sm2 foo8 foo9) &&
+git add sm2
+
+test_expect_success 'multiple submodules' '
+ git diff-index -p --submodule=diff HEAD >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 17243c9...0000000 (submodule deleted)
+ Submodule sm2 0000000...a5a65c9 (new submodule)
+ diff --git a/sm2/foo8 b/sm2/foo8
+ new file mode 100644
+ index 0000000..db9916b
+ --- /dev/null
+ +++ b/sm2/foo8
+ @@ -0,0 +1 @@
+ +foo8
+ diff --git a/sm2/foo9 b/sm2/foo9
+ new file mode 100644
+ index 0000000..9c3b4f6
+ --- /dev/null
+ +++ b/sm2/foo9
+ @@ -0,0 +1 @@
+ +foo9
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'path filter' '
+ git diff-index -p --submodule=diff HEAD sm2 >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm2 0000000...a5a65c9 (new submodule)
+ diff --git a/sm2/foo8 b/sm2/foo8
+ new file mode 100644
+ index 0000000..db9916b
+ --- /dev/null
+ +++ b/sm2/foo8
+ @@ -0,0 +1 @@
+ +foo8
+ diff --git a/sm2/foo9 b/sm2/foo9
+ new file mode 100644
+ index 0000000..9c3b4f6
+ --- /dev/null
+ +++ b/sm2/foo9
+ @@ -0,0 +1 @@
+ +foo9
+ EOF
+ test_cmp expected actual
+'
+
+commit_file sm2
+test_expect_success 'given commit' '
+ git diff-index -p --submodule=diff HEAD^ >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 17243c9...0000000 (submodule deleted)
+ Submodule sm2 0000000...a5a65c9 (new submodule)
+ diff --git a/sm2/foo8 b/sm2/foo8
+ new file mode 100644
+ index 0000000..db9916b
+ --- /dev/null
+ +++ b/sm2/foo8
+ @@ -0,0 +1 @@
+ +foo8
+ diff --git a/sm2/foo9 b/sm2/foo9
+ new file mode 100644
+ index 0000000..9c3b4f6
+ --- /dev/null
+ +++ b/sm2/foo9
+ @@ -0,0 +1 @@
+ +foo9
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'setup .git file for sm2' '
+ (cd sm2 &&
+ REAL="$(pwd)/../.real" &&
+ mv .git "$REAL"
+ echo "gitdir: $REAL" >.git)
+'
+
+test_expect_success 'diff --submodule=diff with .git file' '
+ git diff --submodule=diff HEAD^ >actual &&
+ cat >expected <<-EOF &&
+ Submodule sm1 17243c9...0000000 (submodule deleted)
+ Submodule sm2 0000000...a5a65c9 (new submodule)
+ diff --git a/sm2/foo8 b/sm2/foo8
+ new file mode 100644
+ index 0000000..db9916b
+ --- /dev/null
+ +++ b/sm2/foo8
+ @@ -0,0 +1 @@
+ +foo8
+ diff --git a/sm2/foo9 b/sm2/foo9
+ new file mode 100644
+ index 0000000..9c3b4f6
+ --- /dev/null
+ +++ b/sm2/foo9
+ @@ -0,0 +1 @@
+ +foo9
+ EOF
+ test_cmp expected actual
+'
+
+test_done
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index b41bd1726..9ce9424d1 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -957,4 +957,24 @@ test_expect_success 'am -s unexpected trailer block' '
test_cmp expect actual
'
+test_expect_success 'am --patch-format=mboxrd handles mboxrd' '
+ rm -fr .git/rebase-apply &&
+ git checkout -f first &&
+ echo mboxrd >>file &&
+ git add file &&
+ cat >msg <<-\INPUT_END &&
+ mboxrd should escape the body
+
+ From could trip up a loose mbox parser
+ >From extra escape for reversibility
+ INPUT_END
+ git commit -F msg &&
+ git format-patch --pretty=mboxrd --stdout -1 >mboxrd1 &&
+ grep "^>From could trip up a loose mbox parser" mboxrd1 &&
+ git checkout -f first &&
+ git am --patch-format=mboxrd mboxrd1 &&
+ git cat-file commit HEAD | tail -n4 >out &&
+ test_cmp msg out
+'
+
test_done
diff --git a/t/t4153-am-resume-override-opts.sh b/t/t4153-am-resume-override-opts.sh
index 7c013d84d..8ea22d1bc 100755
--- a/t/t4153-am-resume-override-opts.sh
+++ b/t/t4153-am-resume-override-opts.sh
@@ -53,7 +53,7 @@ test_expect_success '--no-quiet overrides --quiet' '
# Applying side1 will be quiet.
test_must_fail git am --quiet side[123].eml >out &&
test_path_is_dir .git/rebase-apply &&
- ! test_i18ngrep "^Applying: " out &&
+ test_i18ngrep ! "^Applying: " out &&
echo side1 >file &&
git add file &&
diff --git a/t/t4201-shortlog.sh b/t/t4201-shortlog.sh
index a9773658f..ae08b5771 100755
--- a/t/t4201-shortlog.sh
+++ b/t/t4201-shortlog.sh
@@ -184,4 +184,10 @@ test_expect_success 'shortlog with revision pseudo options' '
git shortlog --exclude=refs/heads/m* --all
'
+test_expect_success 'shortlog with --output=<file>' '
+ git shortlog --output=shortlog -1 master >output &&
+ test ! -s output &&
+ test_line_count = 3 shortlog
+'
+
test_done
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 0b53e5669..1ccbd5948 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -188,6 +188,16 @@ test_expect_success 'git log --no-walk=sorted <commits> sorts by commit time' '
'
cat > expect << EOF
+=== 804a787 sixth
+=== 394ef78 fifth
+=== 5d31159 fourth
+EOF
+test_expect_success 'git log --line-prefix="=== " --no-walk <commits> sorts by commit time' '
+ git log --line-prefix="=== " --no-walk --oneline 5d31159 804a787 394ef78 > actual &&
+ test_cmp expect actual
+'
+
+cat > expect << EOF
5d31159 fourth
804a787 sixth
394ef78 fifth
@@ -284,6 +294,21 @@ test_expect_success 'simple log --graph' '
test_cmp expect actual
'
+cat > expect <<EOF
+123 * Second
+123 * sixth
+123 * fifth
+123 * fourth
+123 * third
+123 * second
+123 * initial
+EOF
+
+test_expect_success 'simple log --graph --line-prefix="123 "' '
+ git log --graph --line-prefix="123 " --pretty=tformat:%s >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'set up merge history' '
git checkout -b side HEAD~4 &&
test_commit side-1 1 1 &&
@@ -313,6 +338,27 @@ test_expect_success 'log --graph with merge' '
test_cmp expect actual
'
+cat > expect <<\EOF
+| | | * Merge branch 'side'
+| | | |\
+| | | | * side-2
+| | | | * side-1
+| | | * | Second
+| | | * | sixth
+| | | * | fifth
+| | | * | fourth
+| | | |/
+| | | * third
+| | | * second
+| | | * initial
+EOF
+
+test_expect_success 'log --graph --line-prefix="| | | " with merge' '
+ git log --line-prefix="| | | " --graph --date-order --pretty=tformat:%s |
+ sed "s/ *\$//" >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'log --raw --graph -m with merge' '
git log --raw --graph --oneline -m master | head -n 500 >actual &&
grep "initial" actual
@@ -867,6 +913,283 @@ test_expect_success 'log --graph with diff and stats' '
test_i18ncmp expect actual.sanitized
'
+cat >expect <<\EOF
+*** * commit COMMIT_OBJECT_NAME
+*** |\ Merge: MERGE_PARENTS
+*** | | Author: A U Thor <author@example.com>
+*** | |
+*** | | Merge HEADS DESCRIPTION
+*** | |
+*** | * commit COMMIT_OBJECT_NAME
+*** | | Author: A U Thor <author@example.com>
+*** | |
+*** | | reach
+*** | | ---
+*** | | reach.t | 1 +
+*** | | 1 file changed, 1 insertion(+)
+*** | |
+*** | | diff --git a/reach.t b/reach.t
+*** | | new file mode 100644
+*** | | index 0000000..10c9591
+*** | | --- /dev/null
+*** | | +++ b/reach.t
+*** | | @@ -0,0 +1 @@
+*** | | +reach
+*** | |
+*** | \
+*** *-. \ commit COMMIT_OBJECT_NAME
+*** |\ \ \ Merge: MERGE_PARENTS
+*** | | | | Author: A U Thor <author@example.com>
+*** | | | |
+*** | | | | Merge HEADS DESCRIPTION
+*** | | | |
+*** | | * | commit COMMIT_OBJECT_NAME
+*** | | |/ Author: A U Thor <author@example.com>
+*** | | |
+*** | | | octopus-b
+*** | | | ---
+*** | | | octopus-b.t | 1 +
+*** | | | 1 file changed, 1 insertion(+)
+*** | | |
+*** | | | diff --git a/octopus-b.t b/octopus-b.t
+*** | | | new file mode 100644
+*** | | | index 0000000..d5fcad0
+*** | | | --- /dev/null
+*** | | | +++ b/octopus-b.t
+*** | | | @@ -0,0 +1 @@
+*** | | | +octopus-b
+*** | | |
+*** | * | commit COMMIT_OBJECT_NAME
+*** | |/ Author: A U Thor <author@example.com>
+*** | |
+*** | | octopus-a
+*** | | ---
+*** | | octopus-a.t | 1 +
+*** | | 1 file changed, 1 insertion(+)
+*** | |
+*** | | diff --git a/octopus-a.t b/octopus-a.t
+*** | | new file mode 100644
+*** | | index 0000000..11ee015
+*** | | --- /dev/null
+*** | | +++ b/octopus-a.t
+*** | | @@ -0,0 +1 @@
+*** | | +octopus-a
+*** | |
+*** * | commit COMMIT_OBJECT_NAME
+*** |/ Author: A U Thor <author@example.com>
+*** |
+*** | seventh
+*** | ---
+*** | seventh.t | 1 +
+*** | 1 file changed, 1 insertion(+)
+*** |
+*** | diff --git a/seventh.t b/seventh.t
+*** | new file mode 100644
+*** | index 0000000..9744ffc
+*** | --- /dev/null
+*** | +++ b/seventh.t
+*** | @@ -0,0 +1 @@
+*** | +seventh
+*** |
+*** * commit COMMIT_OBJECT_NAME
+*** |\ Merge: MERGE_PARENTS
+*** | | Author: A U Thor <author@example.com>
+*** | |
+*** | | Merge branch 'tangle'
+*** | |
+*** | * commit COMMIT_OBJECT_NAME
+*** | |\ Merge: MERGE_PARENTS
+*** | | | Author: A U Thor <author@example.com>
+*** | | |
+*** | | | Merge branch 'side' (early part) into tangle
+*** | | |
+*** | * | commit COMMIT_OBJECT_NAME
+*** | |\ \ Merge: MERGE_PARENTS
+*** | | | | Author: A U Thor <author@example.com>
+*** | | | |
+*** | | | | Merge branch 'master' (early part) into tangle
+*** | | | |
+*** | * | | commit COMMIT_OBJECT_NAME
+*** | | | | Author: A U Thor <author@example.com>
+*** | | | |
+*** | | | | tangle-a
+*** | | | | ---
+*** | | | | tangle-a | 1 +
+*** | | | | 1 file changed, 1 insertion(+)
+*** | | | |
+*** | | | | diff --git a/tangle-a b/tangle-a
+*** | | | | new file mode 100644
+*** | | | | index 0000000..7898192
+*** | | | | --- /dev/null
+*** | | | | +++ b/tangle-a
+*** | | | | @@ -0,0 +1 @@
+*** | | | | +a
+*** | | | |
+*** * | | | commit COMMIT_OBJECT_NAME
+*** |\ \ \ \ Merge: MERGE_PARENTS
+*** | | | | | Author: A U Thor <author@example.com>
+*** | | | | |
+*** | | | | | Merge branch 'side'
+*** | | | | |
+*** | * | | | commit COMMIT_OBJECT_NAME
+*** | | |_|/ Author: A U Thor <author@example.com>
+*** | |/| |
+*** | | | | side-2
+*** | | | | ---
+*** | | | | 2 | 1 +
+*** | | | | 1 file changed, 1 insertion(+)
+*** | | | |
+*** | | | | diff --git a/2 b/2
+*** | | | | new file mode 100644
+*** | | | | index 0000000..0cfbf08
+*** | | | | --- /dev/null
+*** | | | | +++ b/2
+*** | | | | @@ -0,0 +1 @@
+*** | | | | +2
+*** | | | |
+*** | * | | commit COMMIT_OBJECT_NAME
+*** | | | | Author: A U Thor <author@example.com>
+*** | | | |
+*** | | | | side-1
+*** | | | | ---
+*** | | | | 1 | 1 +
+*** | | | | 1 file changed, 1 insertion(+)
+*** | | | |
+*** | | | | diff --git a/1 b/1
+*** | | | | new file mode 100644
+*** | | | | index 0000000..d00491f
+*** | | | | --- /dev/null
+*** | | | | +++ b/1
+*** | | | | @@ -0,0 +1 @@
+*** | | | | +1
+*** | | | |
+*** * | | | commit COMMIT_OBJECT_NAME
+*** | | | | Author: A U Thor <author@example.com>
+*** | | | |
+*** | | | | Second
+*** | | | | ---
+*** | | | | one | 1 +
+*** | | | | 1 file changed, 1 insertion(+)
+*** | | | |
+*** | | | | diff --git a/one b/one
+*** | | | | new file mode 100644
+*** | | | | index 0000000..9a33383
+*** | | | | --- /dev/null
+*** | | | | +++ b/one
+*** | | | | @@ -0,0 +1 @@
+*** | | | | +case
+*** | | | |
+*** * | | | commit COMMIT_OBJECT_NAME
+*** | |_|/ Author: A U Thor <author@example.com>
+*** |/| |
+*** | | | sixth
+*** | | | ---
+*** | | | a/two | 1 -
+*** | | | 1 file changed, 1 deletion(-)
+*** | | |
+*** | | | diff --git a/a/two b/a/two
+*** | | | deleted file mode 100644
+*** | | | index 9245af5..0000000
+*** | | | --- a/a/two
+*** | | | +++ /dev/null
+*** | | | @@ -1 +0,0 @@
+*** | | | -ni
+*** | | |
+*** * | | commit COMMIT_OBJECT_NAME
+*** | | | Author: A U Thor <author@example.com>
+*** | | |
+*** | | | fifth
+*** | | | ---
+*** | | | a/two | 1 +
+*** | | | 1 file changed, 1 insertion(+)
+*** | | |
+*** | | | diff --git a/a/two b/a/two
+*** | | | new file mode 100644
+*** | | | index 0000000..9245af5
+*** | | | --- /dev/null
+*** | | | +++ b/a/two
+*** | | | @@ -0,0 +1 @@
+*** | | | +ni
+*** | | |
+*** * | | commit COMMIT_OBJECT_NAME
+*** |/ / Author: A U Thor <author@example.com>
+*** | |
+*** | | fourth
+*** | | ---
+*** | | ein | 1 +
+*** | | 1 file changed, 1 insertion(+)
+*** | |
+*** | | diff --git a/ein b/ein
+*** | | new file mode 100644
+*** | | index 0000000..9d7e69f
+*** | | --- /dev/null
+*** | | +++ b/ein
+*** | | @@ -0,0 +1 @@
+*** | | +ichi
+*** | |
+*** * | commit COMMIT_OBJECT_NAME
+*** |/ Author: A U Thor <author@example.com>
+*** |
+*** | third
+*** | ---
+*** | ichi | 1 +
+*** | one | 1 -
+*** | 2 files changed, 1 insertion(+), 1 deletion(-)
+*** |
+*** | diff --git a/ichi b/ichi
+*** | new file mode 100644
+*** | index 0000000..9d7e69f
+*** | --- /dev/null
+*** | +++ b/ichi
+*** | @@ -0,0 +1 @@
+*** | +ichi
+*** | diff --git a/one b/one
+*** | deleted file mode 100644
+*** | index 9d7e69f..0000000
+*** | --- a/one
+*** | +++ /dev/null
+*** | @@ -1 +0,0 @@
+*** | -ichi
+*** |
+*** * commit COMMIT_OBJECT_NAME
+*** | Author: A U Thor <author@example.com>
+*** |
+*** | second
+*** | ---
+*** | one | 2 +-
+*** | 1 file changed, 1 insertion(+), 1 deletion(-)
+*** |
+*** | diff --git a/one b/one
+*** | index 5626abf..9d7e69f 100644
+*** | --- a/one
+*** | +++ b/one
+*** | @@ -1 +1 @@
+*** | -one
+*** | +ichi
+*** |
+*** * commit COMMIT_OBJECT_NAME
+*** Author: A U Thor <author@example.com>
+***
+*** initial
+*** ---
+*** one | 1 +
+*** 1 file changed, 1 insertion(+)
+***
+*** diff --git a/one b/one
+*** new file mode 100644
+*** index 0000000..5626abf
+*** --- /dev/null
+*** +++ b/one
+*** @@ -0,0 +1 @@
+*** +one
+EOF
+
+test_expect_success 'log --line-prefix="*** " --graph with diff and stats' '
+ git log --line-prefix="*** " --no-renames --graph --pretty=short --stat -p >actual &&
+ sanitize_output >actual.sanitized <actual &&
+ test_i18ncmp expect actual.sanitized
+'
+
test_expect_success 'dotdot is a parent directory' '
mkdir -p a/b &&
( echo sixth && echo fifth ) >expect &&
@@ -874,12 +1197,15 @@ test_expect_success 'dotdot is a parent directory' '
test_cmp expect actual
'
-test_expect_success GPG 'log --graph --show-signature' '
+test_expect_success GPG 'setup signed branch' '
test_when_finished "git reset --hard && git checkout master" &&
git checkout -b signed master &&
echo foo >foo &&
git add foo &&
- git commit -S -m signed_commit &&
+ git commit -S -m signed_commit
+'
+
+test_expect_success GPG 'log --graph --show-signature' '
git log --graph --show-signature -n1 signed >actual &&
grep "^| gpg: Signature made" actual &&
grep "^| gpg: Good signature" actual
@@ -904,6 +1230,31 @@ test_expect_success GPG 'log --graph --show-signature for merged tag' '
grep "^| | gpg: Good signature" actual
'
+test_expect_success GPG '--no-show-signature overrides --show-signature' '
+ git log -1 --show-signature --no-show-signature signed >actual &&
+ ! grep "^gpg:" actual
+'
+
+test_expect_success GPG 'log.showsignature=true behaves like --show-signature' '
+ test_config log.showsignature true &&
+ git log -1 signed >actual &&
+ grep "gpg: Signature made" actual &&
+ grep "gpg: Good signature" actual
+'
+
+test_expect_success GPG '--no-show-signature overrides log.showsignature=true' '
+ test_config log.showsignature true &&
+ git log -1 --no-show-signature signed >actual &&
+ ! grep "^gpg:" actual
+'
+
+test_expect_success GPG '--show-signature overrides log.showsignature=false' '
+ test_config log.showsignature false &&
+ git log -1 --show-signature signed >actual &&
+ grep "gpg: Signature made" actual &&
+ grep "gpg: Good signature" actual
+'
+
test_expect_success 'log --graph --no-walk is forbidden' '
test_must_fail git log --graph --no-walk
'
diff --git a/t/t4204-patch-id.sh b/t/t4204-patch-id.sh
index 84a809690..0288c17ec 100755
--- a/t/t4204-patch-id.sh
+++ b/t/t4204-patch-id.sh
@@ -143,6 +143,20 @@ test_expect_success 'patch-id supports git-format-patch MIME output' '
test_cmp patch-id_master patch-id_same
'
+test_expect_success 'patch-id respects config from subdir' '
+ test_config patchid.stable true &&
+ mkdir subdir &&
+
+ # copy these because test_patch_id() looks for them in
+ # the current directory
+ cp bar-then-foo foo-then-bar subdir &&
+
+ (
+ cd subdir &&
+ test_patch_id irrelevant patchid.stable=true
+ )
+'
+
cat >nonl <<\EOF
diff --git i/a w/a
index e69de29..2e65efe 100644
diff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh
index f8008b6a3..b972296f0 100755
--- a/t/t4207-log-decoration-colors.sh
+++ b/t/t4207-log-decoration-colors.sh
@@ -44,7 +44,7 @@ test_expect_success setup '
'
cat >expected <<EOF
-${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD${c_reset}${c_commit} ->\
+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD ->\
${c_reset}${c_branch}master${c_reset}${c_commit},\
${c_reset}${c_tag}tag: v1.0${c_reset}${c_commit},\
${c_reset}${c_tag}tag: B${c_reset}${c_commit})${c_reset} B
diff --git a/t/t4208-log-magic-pathspec.sh b/t/t4208-log-magic-pathspec.sh
index d8f23f488..001343e2f 100755
--- a/t/t4208-log-magic-pathspec.sh
+++ b/t/t4208-log-magic-pathspec.sh
@@ -18,7 +18,7 @@ test_expect_success '"git log :/" should not be ambiguous' '
test_expect_success '"git log :/a" should be ambiguous (applied both rev and worktree)' '
: >a &&
test_must_fail git log :/a 2>error &&
- grep ambiguous error
+ test_i18ngrep ambiguous error
'
test_expect_success '"git log :/a -- " should not be ambiguous' '
@@ -31,7 +31,7 @@ test_expect_success '"git log -- :/a" should not be ambiguous' '
test_expect_success '"git log :" should be ambiguous' '
test_must_fail git log : 2>error &&
- grep ambiguous error
+ test_i18ngrep ambiguous error
'
test_expect_success 'git log -- :' '
diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh
index 4451127eb..9d87777b5 100755
--- a/t/t4211-line-log.sh
+++ b/t/t4211-line-log.sh
@@ -99,4 +99,11 @@ test_expect_success '-L with --first-parent and a merge' '
git log --first-parent -L 1,1:b.c
'
+test_expect_success '-L with --output' '
+ git checkout parallel-change &&
+ git log --output=log -L :main:b.c >output &&
+ test ! -s output &&
+ test_line_count = 70 log
+'
+
test_done
diff --git a/t/t4254-am-corrupt.sh b/t/t4254-am-corrupt.sh
index 85716dd6e..9bd7dd2ba 100755
--- a/t/t4254-am-corrupt.sh
+++ b/t/t4254-am-corrupt.sh
@@ -29,7 +29,7 @@ test_expect_success 'try to apply corrupted patch' '
'
test_expect_success 'compare diagnostic; ensure file is still here' '
- echo "fatal: git diff header lacks filename information (line 4)" >expected &&
+ echo "error: git diff header lacks filename information (line 4)" >expected &&
test_path_is_file f &&
test_cmp expected actual
'
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index 4b68bbafb..80b238734 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -319,4 +319,78 @@ test_expect_success 'catch non-matching pathspec' '
test_must_fail git archive -v HEAD -- "*.abc" >/dev/null
'
+# Pull the size and date of each entry in a tarfile using the system tar.
+#
+# We'll pull out only the year from the date; that avoids any question of
+# timezones impacting the result (as long as we keep our test times away from a
+# year boundary; our reference times are all in August).
+#
+# The output of tar_info is expected to be "<size> <year>", both in decimal. It
+# ignores the return value of tar. We have to do this, because some of our test
+# input is only partial (the real data is 64GB in some cases).
+tar_info () {
+ "$TAR" tvf "$1" |
+ awk '{
+ split($4, date, "-")
+ print $3 " " date[1]
+ }'
+}
+
+# See if our system tar can handle a tar file with huge sizes and dates far in
+# the future, and that we can actually parse its output.
+#
+# The reference file was generated by GNU tar, and the magic time and size are
+# both octal 01000000000001, which overflows normal ustar fields.
+test_lazy_prereq TAR_HUGE '
+ echo "68719476737 4147" >expect &&
+ tar_info "$TEST_DIRECTORY"/t5000/huge-and-future.tar >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success LONG_IS_64BIT 'set up repository with huge blob' '
+ obj_d=19 &&
+ obj_f=f9c8273ec45a8938e6999cb59b3ff66739902a &&
+ obj=${obj_d}${obj_f} &&
+ mkdir -p .git/objects/$obj_d &&
+ cp "$TEST_DIRECTORY"/t5000/$obj .git/objects/$obj_d/$obj_f &&
+ rm -f .git/index &&
+ git update-index --add --cacheinfo 100644,$obj,huge &&
+ git commit -m huge
+'
+
+# We expect git to die with SIGPIPE here (otherwise we
+# would generate the whole 64GB).
+test_expect_success LONG_IS_64BIT 'generate tar with huge size' '
+ {
+ git archive HEAD
+ echo $? >exit-code
+ } | test_copy_bytes 4096 >huge.tar &&
+ echo 141 >expect &&
+ test_cmp expect exit-code
+'
+
+test_expect_success TAR_HUGE,LONG_IS_64BIT 'system tar can read our huge size' '
+ echo 68719476737 >expect &&
+ tar_info huge.tar | cut -d" " -f1 >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success LONG_IS_64BIT 'set up repository with far-future commit' '
+ rm -f .git/index &&
+ echo content >file &&
+ git add file &&
+ GIT_COMMITTER_DATE="@68719476737 +0000" \
+ git commit -m "tempori parendum"
+'
+
+test_expect_success LONG_IS_64BIT 'generate tar with future mtime' '
+ git archive HEAD >future.tar
+'
+
+test_expect_success TAR_HUGE,LONG_IS_64BIT 'system tar can read our future mtime' '
+ echo 4147 >expect &&
+ tar_info future.tar | cut -d" " -f2 >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t5000/19f9c8273ec45a8938e6999cb59b3ff66739902a b/t/t5000/19f9c8273ec45a8938e6999cb59b3ff66739902a
new file mode 100644
index 000000000..5cbe9ec31
--- /dev/null
+++ b/t/t5000/19f9c8273ec45a8938e6999cb59b3ff66739902a
Binary files differ
diff --git a/t/t5000/huge-and-future.tar b/t/t5000/huge-and-future.tar
new file mode 100644
index 000000000..63155e185
--- /dev/null
+++ b/t/t5000/huge-and-future.tar
Binary files differ
diff --git a/t/t5100-mailinfo.sh b/t/t5100-mailinfo.sh
index 85b3df5e3..1a5a54623 100755
--- a/t/t5100-mailinfo.sh
+++ b/t/t5100-mailinfo.sh
@@ -111,4 +111,35 @@ test_expect_success 'mailinfo on message with quoted >From' '
test_cmp "$TEST_DIRECTORY"/t5100/quoted-from.expect quoted-from/msg
'
+test_expect_success 'mailinfo unescapes with --mboxrd' '
+ mkdir mboxrd &&
+ git mailsplit -omboxrd --mboxrd \
+ "$TEST_DIRECTORY"/t5100/sample.mboxrd >last &&
+ test x"$(cat last)" = x2 &&
+ for i in 0001 0002
+ do
+ git mailinfo mboxrd/msg mboxrd/patch \
+ <mboxrd/$i >mboxrd/out &&
+ test_cmp "$TEST_DIRECTORY"/t5100/${i}mboxrd mboxrd/msg
+ done &&
+ sp=" " &&
+ echo "From " >expect &&
+ echo "From " >>expect &&
+ echo >> expect &&
+ cat >sp <<-INPUT_END &&
+ From mboxrd Mon Sep 17 00:00:00 2001
+ From: trailing spacer <sp@example.com>
+ Subject: [PATCH] a commit with trailing space
+
+ From$sp
+ >From$sp
+
+ INPUT_END
+
+ git mailsplit -f2 -omboxrd --mboxrd <sp >last &&
+ test x"$(cat last)" = x1 &&
+ git mailinfo mboxrd/msg mboxrd/patch <mboxrd/0003 &&
+ test_cmp expect mboxrd/msg
+'
+
test_done
diff --git a/t/t5100/0001mboxrd b/t/t5100/0001mboxrd
new file mode 100644
index 000000000..494ec554b
--- /dev/null
+++ b/t/t5100/0001mboxrd
@@ -0,0 +1,4 @@
+From the beginning, mbox should have been mboxrd
+>From escaped
+From not mangled but this line should have been escaped
+
diff --git a/t/t5100/0002mboxrd b/t/t5100/0002mboxrd
new file mode 100644
index 000000000..71343d41f
--- /dev/null
+++ b/t/t5100/0002mboxrd
@@ -0,0 +1,5 @@
+ >From unchanged
+ From also unchanged
+no trailing space, no escaping necessary and '>' was intended:
+>From
+
diff --git a/t/t5100/sample.mboxrd b/t/t5100/sample.mboxrd
new file mode 100644
index 000000000..79ad5ae0e
--- /dev/null
+++ b/t/t5100/sample.mboxrd
@@ -0,0 +1,19 @@
+From mboxrd Mon Sep 17 00:00:00 2001
+From: mboxrd writer <mboxrd@example.com>
+Date: Fri, 9 Jun 2006 00:44:16 -0700
+Subject: [PATCH] a commit with escaped From lines
+
+>From the beginning, mbox should have been mboxrd
+>>From escaped
+From not mangled but this line should have been escaped
+
+From mboxrd Mon Sep 17 00:00:00 2001
+From: mboxrd writer <mboxrd@example.com>
+Date: Fri, 9 Jun 2006 00:44:16 -0700
+Subject: [PATCH 2/2] another with fake From lines
+
+ >From unchanged
+ From also unchanged
+no trailing space, no escaping necessary and '>' was intended:
+>From
+
diff --git a/t/t5305-include-tag.sh b/t/t5305-include-tag.sh
index f314ad507..a5eca210b 100755
--- a/t/t5305-include-tag.sh
+++ b/t/t5305-include-tag.sh
@@ -25,58 +25,94 @@ test_expect_success setup '
} >obj-list
'
-rm -rf clone.git
test_expect_success 'pack without --include-tag' '
- packname_1=$(git pack-objects \
+ packname=$(git pack-objects \
--window=0 \
- test-1 <obj-list)
+ test-no-include <obj-list)
'
test_expect_success 'unpack objects' '
- (
- GIT_DIR=clone.git &&
- export GIT_DIR &&
- git init &&
- git unpack-objects -n <test-1-${packname_1}.pack &&
- git unpack-objects <test-1-${packname_1}.pack
- )
+ rm -rf clone.git &&
+ git init clone.git &&
+ git -C clone.git unpack-objects <test-no-include-${packname}.pack
'
test_expect_success 'check unpacked result (have commit, no tag)' '
git rev-list --objects $commit >list.expect &&
- (
- test_must_fail env GIT_DIR=clone.git git cat-file -e $tag &&
- git rev-list --objects $commit
- ) >list.actual &&
+ test_must_fail git -C clone.git cat-file -e $tag &&
+ git -C clone.git rev-list --objects $commit >list.actual &&
test_cmp list.expect list.actual
'
-rm -rf clone.git
test_expect_success 'pack with --include-tag' '
- packname_1=$(git pack-objects \
+ packname=$(git pack-objects \
--window=0 \
--include-tag \
- test-2 <obj-list)
+ test-include <obj-list)
'
test_expect_success 'unpack objects' '
- (
- GIT_DIR=clone.git &&
- export GIT_DIR &&
- git init &&
- git unpack-objects -n <test-2-${packname_1}.pack &&
- git unpack-objects <test-2-${packname_1}.pack
- )
+ rm -rf clone.git &&
+ git init clone.git &&
+ git -C clone.git unpack-objects <test-include-${packname}.pack
'
test_expect_success 'check unpacked result (have commit, have tag)' '
git rev-list --objects mytag >list.expect &&
- (
- GIT_DIR=clone.git &&
- export GIT_DIR &&
- git rev-list --objects $tag
- ) >list.actual &&
+ git -C clone.git rev-list --objects $tag >list.actual &&
test_cmp list.expect list.actual
'
+# A tag of a tag, where the "inner" tag is not otherwise
+# reachable, and a full peel points to a commit reachable from HEAD.
+test_expect_success 'create hidden inner tag' '
+ test_commit commit &&
+ git tag -m inner inner HEAD &&
+ git tag -m outer outer inner &&
+ git tag -d inner
+'
+
+test_expect_success 'pack explicit outer tag' '
+ packname=$(
+ {
+ echo HEAD &&
+ echo outer
+ } |
+ git pack-objects --revs test-hidden-explicit
+ )
+'
+
+test_expect_success 'unpack objects' '
+ rm -rf clone.git &&
+ git init clone.git &&
+ git -C clone.git unpack-objects <test-hidden-explicit-${packname}.pack
+'
+
+test_expect_success 'check unpacked result (have all objects)' '
+ git -C clone.git rev-list --objects $(git rev-parse outer HEAD)
+'
+
+test_expect_success 'pack implied outer tag' '
+ packname=$(
+ echo HEAD |
+ git pack-objects --revs --include-tag test-hidden-implied
+ )
+'
+
+test_expect_success 'unpack objects' '
+ rm -rf clone.git &&
+ git init clone.git &&
+ git -C clone.git unpack-objects <test-hidden-implied-${packname}.pack
+'
+
+test_expect_success 'check unpacked result (have all objects)' '
+ git -C clone.git rev-list --objects $(git rev-parse outer HEAD)
+'
+
+test_expect_success 'single-branch clone can transfer tag' '
+ rm -rf clone.git &&
+ git clone --no-local --single-branch -b master . clone.git &&
+ git -C clone.git fsck
+'
+
test_done
diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh
index 3893afd68..b4c7a6ff6 100755
--- a/t/t5310-pack-bitmaps.sh
+++ b/t/t5310-pack-bitmaps.sh
@@ -7,6 +7,18 @@ objpath () {
echo ".git/objects/$(echo "$1" | sed -e 's|\(..\)|\1/|')"
}
+# show objects present in pack ($1 should be associated *.idx)
+list_packed_objects () {
+ git show-index <"$1" | cut -d' ' -f2
+}
+
+# has_any pattern-file content-file
+# tests whether content-file has any entry from pattern-file with entries being
+# whole lines.
+has_any () {
+ grep -Ff "$1" "$2"
+}
+
test_expect_success 'setup repo with moderate-sized history' '
for i in $(test_seq 1 10); do
test_commit $i
@@ -16,6 +28,7 @@ test_expect_success 'setup repo with moderate-sized history' '
test_commit side-$i
done &&
git checkout master &&
+ bitmaptip=$(git rev-parse master) &&
blob=$(echo tagged-blob | git hash-object -w --stdin) &&
git tag tagged-blob $blob &&
git config repack.writebitmaps true &&
@@ -118,6 +131,83 @@ test_expect_success 'incremental repack can disable bitmaps' '
git repack -d --no-write-bitmap-index
'
+test_expect_success 'pack-objects respects --local (non-local loose)' '
+ git init --bare alt.git &&
+ echo $(pwd)/alt.git/objects >.git/objects/info/alternates &&
+ echo content1 >file1 &&
+ # non-local loose object which is not present in bitmapped pack
+ altblob=$(GIT_DIR=alt.git git hash-object -w file1) &&
+ # non-local loose object which is also present in bitmapped pack
+ git cat-file blob $blob | GIT_DIR=alt.git git hash-object -w --stdin &&
+ git add file1 &&
+ test_tick &&
+ git commit -m commit_file1 &&
+ echo HEAD | git pack-objects --local --stdout --revs >1.pack &&
+ git index-pack 1.pack &&
+ list_packed_objects 1.idx >1.objects &&
+ printf "%s\n" "$altblob" "$blob" >nonlocal-loose &&
+ ! has_any nonlocal-loose 1.objects
+'
+
+test_expect_success 'pack-objects respects --honor-pack-keep (local non-bitmapped pack)' '
+ echo content2 >file2 &&
+ blob2=$(git hash-object -w file2) &&
+ git add file2 &&
+ test_tick &&
+ git commit -m commit_file2 &&
+ printf "%s\n" "$blob2" "$bitmaptip" >keepobjects &&
+ pack2=$(git pack-objects pack2 <keepobjects) &&
+ mv pack2-$pack2.* .git/objects/pack/ &&
+ >.git/objects/pack/pack2-$pack2.keep &&
+ rm $(objpath $blob2) &&
+ echo HEAD | git pack-objects --honor-pack-keep --stdout --revs >2a.pack &&
+ git index-pack 2a.pack &&
+ list_packed_objects 2a.idx >2a.objects &&
+ ! has_any keepobjects 2a.objects
+'
+
+test_expect_success 'pack-objects respects --local (non-local pack)' '
+ mv .git/objects/pack/pack2-$pack2.* alt.git/objects/pack/ &&
+ echo HEAD | git pack-objects --local --stdout --revs >2b.pack &&
+ git index-pack 2b.pack &&
+ list_packed_objects 2b.idx >2b.objects &&
+ ! has_any keepobjects 2b.objects
+'
+
+test_expect_success 'pack-objects respects --honor-pack-keep (local bitmapped pack)' '
+ ls .git/objects/pack/ | grep bitmap >output &&
+ test_line_count = 1 output &&
+ packbitmap=$(basename $(cat output) .bitmap) &&
+ list_packed_objects .git/objects/pack/$packbitmap.idx >packbitmap.objects &&
+ test_when_finished "rm -f .git/objects/pack/$packbitmap.keep" &&
+ >.git/objects/pack/$packbitmap.keep &&
+ echo HEAD | git pack-objects --honor-pack-keep --stdout --revs >3a.pack &&
+ git index-pack 3a.pack &&
+ list_packed_objects 3a.idx >3a.objects &&
+ ! has_any packbitmap.objects 3a.objects
+'
+
+test_expect_success 'pack-objects respects --local (non-local bitmapped pack)' '
+ mv .git/objects/pack/$packbitmap.* alt.git/objects/pack/ &&
+ test_when_finished "mv alt.git/objects/pack/$packbitmap.* .git/objects/pack/" &&
+ echo HEAD | git pack-objects --local --stdout --revs >3b.pack &&
+ git index-pack 3b.pack &&
+ list_packed_objects 3b.idx >3b.objects &&
+ ! has_any packbitmap.objects 3b.objects
+'
+
+test_expect_success 'pack-objects to file can use bitmap' '
+ # make sure we still have 1 bitmap index from previous tests
+ ls .git/objects/pack/ | grep bitmap >output &&
+ test_line_count = 1 output &&
+ # verify equivalent packs are generated with/without using bitmap index
+ packasha1=$(git pack-objects --no-use-bitmap-index --all packa </dev/null) &&
+ packbsha1=$(git pack-objects --use-bitmap-index --all packb </dev/null) &&
+ list_packed_objects <packa-$packasha1.idx >packa.objects &&
+ list_packed_objects <packb-$packbsha1.idx >packb.objects &&
+ test_cmp packa.objects packb.objects
+'
+
test_expect_success 'full repack, reusing previous bitmaps' '
git repack -ad &&
ls .git/objects/pack/ | grep bitmap >output &&
@@ -143,6 +233,20 @@ test_expect_success 'create objects for missing-HAVE tests' '
EOF
'
+test_expect_success 'pack-objects respects --incremental' '
+ cat >revs2 <<-EOF &&
+ HEAD
+ $commit
+ EOF
+ git pack-objects --incremental --stdout --revs <revs2 >4.pack &&
+ git index-pack 4.pack &&
+ list_packed_objects 4.idx >4.objects &&
+ test_line_count = 4 4.objects &&
+ git rev-list --objects $commit >revlist &&
+ cut -d" " -f1 revlist |sort >objects &&
+ test_cmp 4.objects objects
+'
+
test_expect_success 'pack with missing blob' '
rm $(objpath $blob) &&
git pack-objects --stdout --revs <revs >/dev/null
@@ -158,10 +262,6 @@ test_expect_success 'pack with missing parent' '
git pack-objects --stdout --revs <revs >/dev/null
'
-test_lazy_prereq JGIT '
- type jgit
-'
-
test_expect_success JGIT 'we can read jgit bitmaps' '
git clone . compat-jgit &&
(
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index dd2e6ce34..8198d8eb0 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -1182,7 +1182,7 @@ test_expect_success 'extra args: setup' '
test_extra_arg () {
test_expect_success "extra args: $*" "
test_must_fail git remote $* bogus_extra_arg 2>actual &&
- grep '^usage:' actual
+ test_i18ngrep '^usage:' actual
"
}
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 454d89639..668c54be4 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -644,7 +644,7 @@ test_expect_success 'fetch --prune prints the remotes url' '
git fetch --prune origin 2>&1 | head -n1 >../actual
) &&
echo "From ${D}/." >expect &&
- test_cmp expect actual
+ test_i18ncmp expect actual
'
test_expect_success 'branchname D/F conflict resolved by --prune' '
@@ -688,4 +688,34 @@ test_expect_success 'fetching with auto-gc does not lock up' '
)
'
+test_expect_success C_LOCALE_OUTPUT 'fetch aligned output' '
+ git clone . full-output &&
+ test_commit looooooooooooong-tag &&
+ (
+ cd full-output &&
+ git -c fetch.output=full fetch origin 2>&1 | \
+ grep -e "->" | cut -c 22- >../actual
+ ) &&
+ cat >expect <<-\EOF &&
+ master -> origin/master
+ looooooooooooong-tag -> looooooooooooong-tag
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success C_LOCALE_OUTPUT 'fetch compact output' '
+ git clone . compact &&
+ test_commit extraaa &&
+ (
+ cd compact &&
+ git -c fetch.output=compact fetch origin 2>&1 | \
+ grep -e "->" | cut -c 22- >../actual
+ ) &&
+ cat >expect <<-\EOF &&
+ master -> origin/*
+ extraaa -> *
+ EOF
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh
index 819b9ddd0..befdfeefc 100755
--- a/t/t5512-ls-remote.sh
+++ b/t/t5512-ls-remote.sh
@@ -207,5 +207,45 @@ test_expect_success 'ls-remote --symref omits filtered-out matches' '
test_cmp expect actual
'
+test_lazy_prereq GIT_DAEMON '
+ test_tristate GIT_TEST_GIT_DAEMON &&
+ test "$GIT_TEST_GIT_DAEMON" != false
+'
+
+# This test spawns a daemon, so run it only if the user would be OK with
+# testing with git-daemon.
+test_expect_success PIPE,JGIT,GIT_DAEMON 'indicate no refs in standards-compliant empty remote' '
+ JGIT_DAEMON_PORT=${JGIT_DAEMON_PORT-${this_test#t}} &&
+ JGIT_DAEMON_PID= &&
+ git init --bare empty.git &&
+ >empty.git/git-daemon-export-ok &&
+ mkfifo jgit_daemon_output &&
+ {
+ jgit daemon --port="$JGIT_DAEMON_PORT" . >jgit_daemon_output &
+ JGIT_DAEMON_PID=$!
+ } &&
+ test_when_finished kill "$JGIT_DAEMON_PID" &&
+ {
+ read line &&
+ case $line in
+ Exporting*)
+ ;;
+ *)
+ echo "Expected: Exporting" &&
+ false;;
+ esac &&
+ read line &&
+ case $line in
+ "Listening on"*)
+ ;;
+ *)
+ echo "Expected: Listening on" &&
+ false;;
+ esac
+ } <jgit_daemon_output &&
+ # --exit-code asks the command to exit with 2 when no
+ # matching refs are found.
+ test_expect_code 2 git ls-remote --exit-code git://localhost:$JGIT_DAEMON_PORT/empty.git
+'
test_done
diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
index 739c089d5..551844584 100755
--- a/t/t5520-pull.sh
+++ b/t/t5520-pull.sh
@@ -211,7 +211,7 @@ test_expect_success 'fail if the index has unresolved entries' '
test -n "$(git ls-files -u)" &&
cp file expected &&
test_must_fail git pull . second 2>err &&
- test_i18ngrep "Pull is not possible because you have unmerged files" err &&
+ test_i18ngrep "Pulling is not possible because you have unmerged files." err &&
test_cmp expected file &&
git add file &&
test -z "$(git ls-files -u)" &&
@@ -255,6 +255,38 @@ test_expect_success '--rebase' '
test new = "$(git show HEAD:file2)"
'
+test_expect_success '--rebase with conflicts shows advice' '
+ test_when_finished "git rebase --abort; git checkout -f to-rebase" &&
+ git checkout -b seq &&
+ test_seq 5 >seq.txt &&
+ git add seq.txt &&
+ test_tick &&
+ git commit -m "Add seq.txt" &&
+ echo 6 >>seq.txt &&
+ test_tick &&
+ git commit -m "Append to seq.txt" seq.txt &&
+ git checkout -b with-conflicts HEAD^ &&
+ echo conflicting >>seq.txt &&
+ test_tick &&
+ git commit -m "Create conflict" seq.txt &&
+ test_must_fail git pull --rebase . seq 2>err >out &&
+ test_i18ngrep "When you have resolved this problem" out
+'
+
+test_expect_success 'failed --rebase shows advice' '
+ test_when_finished "git rebase --abort; git checkout -f to-rebase" &&
+ git checkout -b diverging &&
+ test_commit attributes .gitattributes "* text=auto" attrs &&
+ sha1="$(printf "1\\r\\n" | git hash-object -w --stdin)" &&
+ git update-index --cacheinfo 0644 $sha1 file &&
+ git commit -m v1-with-cr &&
+ # force checkout because `git reset --hard` will not leave clean `file`
+ git checkout -f -b fails-to-rebase HEAD^ &&
+ test_commit v2-without-cr file "2" file2-lf &&
+ test_must_fail git pull --rebase . diverging 2>err >out &&
+ test_i18ngrep "When you have resolved this problem" out
+'
+
test_expect_success '--rebase fails with multiple branches' '
git reset --hard before-rebase &&
test_must_fail git pull --rebase . copy master 2>err &&
@@ -341,6 +373,22 @@ test_expect_success 'branch.to-rebase.rebase should override pull.rebase' '
test new = "$(git show HEAD:file2)"
'
+test_expect_success "pull --rebase warns on --verify-signatures" '
+ git reset --hard before-rebase &&
+ git pull --rebase --verify-signatures . copy 2>err &&
+ test "$(git rev-parse HEAD^)" = "$(git rev-parse copy)" &&
+ test new = "$(git show HEAD:file2)" &&
+ test_i18ngrep "ignoring --verify-signatures for rebase" err
+'
+
+test_expect_success "pull --rebase does not warn on --no-verify-signatures" '
+ git reset --hard before-rebase &&
+ git pull --rebase --no-verify-signatures . copy 2>err &&
+ test "$(git rev-parse HEAD^)" = "$(git rev-parse copy)" &&
+ test new = "$(git show HEAD:file2)" &&
+ test_i18ngrep ! "verify-signatures" err
+'
+
# add a feature branch, keep-merge, that is merged into master, so the
# test can try preserving the merge commit (or not) with various
# --rebase flags/pull.rebase settings.
diff --git a/t/t5523-push-upstream.sh b/t/t5523-push-upstream.sh
index 3683df13a..d6981ba30 100755
--- a/t/t5523-push-upstream.sh
+++ b/t/t5523-push-upstream.sh
@@ -75,7 +75,7 @@ test_expect_success TTY 'progress messages go to tty' '
ensure_fresh_upstream &&
test_terminal git push -u upstream master >out 2>err &&
- grep "Writing objects" err
+ test_i18ngrep "Writing objects" err
'
test_expect_success 'progress messages do not go to non-tty' '
@@ -83,7 +83,7 @@ test_expect_success 'progress messages do not go to non-tty' '
# skip progress messages, since stderr is non-tty
git push -u upstream master >out 2>err &&
- ! grep "Writing objects" err
+ test_i18ngrep ! "Writing objects" err
'
test_expect_success 'progress messages go to non-tty (forced)' '
@@ -91,22 +91,22 @@ test_expect_success 'progress messages go to non-tty (forced)' '
# force progress messages to stderr, even though it is non-tty
git push -u --progress upstream master >out 2>err &&
- grep "Writing objects" err
+ test_i18ngrep "Writing objects" err
'
test_expect_success TTY 'push -q suppresses progress' '
ensure_fresh_upstream &&
test_terminal git push -u -q upstream master >out 2>err &&
- ! grep "Writing objects" err
+ test_i18ngrep ! "Writing objects" err
'
test_expect_success TTY 'push --no-progress suppresses progress' '
ensure_fresh_upstream &&
test_terminal git push -u --no-progress upstream master >out 2>err &&
- ! grep "Unpacking objects" err &&
- ! grep "Writing objects" err
+ test_i18ngrep ! "Unpacking objects" err &&
+ test_i18ngrep ! "Writing objects" err
'
test_expect_success TTY 'quiet push' '
diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh
index 954d0e43f..f3b0a8d30 100755
--- a/t/t5526-fetch-submodules.sh
+++ b/t/t5526-fetch-submodules.sh
@@ -485,4 +485,39 @@ test_expect_success 'fetching submodules respects parallel settings' '
)
'
+test_expect_success 'fetching submodule into a broken repository' '
+ # Prepare src and src/sub nested in it
+ git init src &&
+ (
+ cd src &&
+ git init sub &&
+ git -C sub commit --allow-empty -m "initial in sub" &&
+ git submodule add -- ./sub sub &&
+ git commit -m "initial in top"
+ ) &&
+
+ # Clone the old-fashoned way
+ git clone src dst &&
+ git -C dst clone ../src/sub sub &&
+
+ # Make sure that old-fashoned layout is still supported
+ git -C dst status &&
+
+ # "diff" would find no change
+ git -C dst diff --exit-code &&
+
+ # Recursive-fetch works fine
+ git -C dst fetch --recurse-submodules &&
+
+ # Break the receiving submodule
+ rm -f dst/sub/.git/HEAD &&
+
+ # NOTE: without the fix the following tests will recurse forever!
+ # They should terminate with an error.
+
+ test_must_fail git -C dst status &&
+ test_must_fail git -C dst diff &&
+ test_must_fail git -C dst fetch --recurse-submodules
+'
+
test_done
diff --git a/t/t5536-fetch-conflicts.sh b/t/t5536-fetch-conflicts.sh
index 6c5d3a4ce..2e42cf331 100755
--- a/t/t5536-fetch-conflicts.sh
+++ b/t/t5536-fetch-conflicts.sh
@@ -22,8 +22,8 @@ verify_stderr () {
cat >expected &&
# We're not interested in the error
# "fatal: The remote end hung up unexpectedly":
- grep -E '^(fatal|warning):' <error | grep -v 'hung up' >actual | sort &&
- test_cmp expected actual
+ test_i18ngrep -E '^(fatal|warning):' <error | grep -v 'hung up' >actual | sort &&
+ test_i18ncmp expected actual
}
test_expect_success 'setup' '
diff --git a/t/t5541-http-push-smart.sh b/t/t5541-http-push-smart.sh
index 9593fc17f..d38bf3247 100755
--- a/t/t5541-http-push-smart.sh
+++ b/t/t5541-http-push-smart.sh
@@ -74,7 +74,7 @@ test_expect_success 'push to remote repository (standard)' '
test_tick &&
git commit -m path2 &&
HEAD=$(git rev-parse --verify HEAD) &&
- GIT_CURL_VERBOSE=1 git push -v -v 2>err &&
+ GIT_TRACE_CURL=true git push -v -v 2>err &&
! grep "Expect: 100-continue" err &&
grep "POST git-receive-pack ([0-9]* bytes)" err &&
(cd "$HTTPD_DOCUMENT_ROOT_PATH"/test_repo.git &&
@@ -119,7 +119,7 @@ test_expect_success 'rejected update prints status' '
git commit -m dev2 &&
test_must_fail git push origin dev2 2>act &&
sed -e "/^remote: /s/ *$//" <act >cmp &&
- test_cmp exp cmp
+ test_i18ncmp exp cmp
'
rm -f "$HTTPD_DOCUMENT_ROOT_PATH/test_repo.git/hooks/update"
@@ -219,7 +219,7 @@ test_expect_success TTY 'push shows progress when stderr is a tty' '
cd "$ROOT_PATH"/test_repo_clone &&
test_commit noisy &&
test_terminal git push >output 2>&1 &&
- grep "^Writing objects" output
+ test_i18ngrep "^Writing objects" output
'
test_expect_success TTY 'push --quiet silences status and progress' '
@@ -233,16 +233,16 @@ test_expect_success TTY 'push --no-progress silences progress but not status' '
cd "$ROOT_PATH"/test_repo_clone &&
test_commit no-progress &&
test_terminal git push --no-progress >output 2>&1 &&
- grep "^To http" output &&
- ! grep "^Writing objects"
+ test_i18ngrep "^To http" output &&
+ test_i18ngrep ! "^Writing objects"
'
test_expect_success 'push --progress shows progress to non-tty' '
cd "$ROOT_PATH"/test_repo_clone &&
test_commit progress &&
git push --progress >output 2>&1 &&
- grep "^To http" output &&
- grep "^Writing objects" output
+ test_i18ngrep "^To http" output &&
+ test_i18ngrep "^Writing objects" output
'
test_expect_success 'http push gives sane defaults to reflog' '
diff --git a/t/t5544-pack-objects-hook.sh b/t/t5544-pack-objects-hook.sh
new file mode 100755
index 000000000..4357af152
--- /dev/null
+++ b/t/t5544-pack-objects-hook.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+
+test_description='test custom script in place of pack-objects'
+. ./test-lib.sh
+
+test_expect_success 'create some history to fetch' '
+ test_commit one &&
+ test_commit two
+'
+
+test_expect_success 'create debugging hook script' '
+ write_script .git/hook <<-\EOF
+ echo >&2 "hook running"
+ echo "$*" >hook.args
+ cat >hook.stdin
+ "$@" <hook.stdin >hook.stdout
+ cat hook.stdout
+ EOF
+'
+
+clear_hook_results () {
+ rm -rf .git/hook.* dst.git
+}
+
+test_expect_success 'hook runs via global config' '
+ clear_hook_results &&
+ test_config_global uploadpack.packObjectsHook ./hook &&
+ git clone --no-local . dst.git 2>stderr &&
+ grep "hook running" stderr
+'
+
+test_expect_success 'hook outputs are sane' '
+ # check that we recorded a usable pack
+ git index-pack --stdin <.git/hook.stdout &&
+
+ # check that we recorded args and stdin. We do not check
+ # the full argument list or the exact pack contents, as it would make
+ # the test brittle. So just sanity check that we could replay
+ # the packing procedure.
+ grep "^git" .git/hook.args &&
+ $(cat .git/hook.args) <.git/hook.stdin >replay
+'
+
+test_expect_success 'hook runs from -c config' '
+ clear_hook_results &&
+ git clone --no-local \
+ -u "git -c uploadpack.packObjectsHook=./hook upload-pack" \
+ . dst.git 2>stderr &&
+ grep "hook running" stderr
+'
+
+test_expect_success 'hook does not run from repo config' '
+ clear_hook_results &&
+ test_config uploadpack.packObjectsHook "./hook" &&
+ git clone --no-local . dst.git 2>stderr &&
+ ! grep "hook running" stderr &&
+ test_path_is_missing .git/hook.args &&
+ test_path_is_missing .git/hook.stdin &&
+ test_path_is_missing .git/hook.stdout
+'
+
+test_done
diff --git a/t/t5545-push-options.sh b/t/t5545-push-options.sh
new file mode 100755
index 000000000..ea813b938
--- /dev/null
+++ b/t/t5545-push-options.sh
@@ -0,0 +1,103 @@
+#!/bin/sh
+
+test_description='pushing to a repository using push options'
+
+. ./test-lib.sh
+
+mk_repo_pair () {
+ rm -rf workbench upstream &&
+ test_create_repo upstream &&
+ test_create_repo workbench &&
+ (
+ cd upstream &&
+ git config receive.denyCurrentBranch warn &&
+ mkdir -p .git/hooks &&
+ cat >.git/hooks/pre-receive <<-'EOF' &&
+ #!/bin/sh
+ if test -n "$GIT_PUSH_OPTION_COUNT"; then
+ i=0
+ >hooks/pre-receive.push_options
+ while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"; do
+ eval "value=\$GIT_PUSH_OPTION_$i"
+ echo $value >>hooks/pre-receive.push_options
+ i=$((i + 1))
+ done
+ fi
+ EOF
+ chmod u+x .git/hooks/pre-receive
+
+ cat >.git/hooks/post-receive <<-'EOF' &&
+ #!/bin/sh
+ if test -n "$GIT_PUSH_OPTION_COUNT"; then
+ i=0
+ >hooks/post-receive.push_options
+ while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"; do
+ eval "value=\$GIT_PUSH_OPTION_$i"
+ echo $value >>hooks/post-receive.push_options
+ i=$((i + 1))
+ done
+ fi
+ EOF
+ chmod u+x .git/hooks/post-receive
+ ) &&
+ (
+ cd workbench &&
+ git remote add up ../upstream
+ )
+}
+
+# Compare the ref ($1) in upstream with a ref value from workbench ($2)
+# i.e. test_refs second HEAD@{2}
+test_refs () {
+ test $# = 2 &&
+ git -C upstream rev-parse --verify "$1" >expect &&
+ git -C workbench rev-parse --verify "$2" >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success 'one push option works for a single branch' '
+ mk_repo_pair &&
+ git -C upstream config receive.advertisePushOptions true &&
+ (
+ cd workbench &&
+ test_commit one &&
+ git push --mirror up &&
+ test_commit two &&
+ git push --push-option=asdf up master
+ ) &&
+ test_refs master master &&
+ echo "asdf" >expect &&
+ test_cmp expect upstream/.git/hooks/pre-receive.push_options &&
+ test_cmp expect upstream/.git/hooks/post-receive.push_options
+'
+
+test_expect_success 'push option denied by remote' '
+ mk_repo_pair &&
+ git -C upstream config receive.advertisePushOptions false &&
+ (
+ cd workbench &&
+ test_commit one &&
+ git push --mirror up &&
+ test_commit two &&
+ test_must_fail git push --push-option=asdf up master
+ ) &&
+ test_refs master HEAD@{1}
+'
+
+test_expect_success 'two push options work' '
+ mk_repo_pair &&
+ git -C upstream config receive.advertisePushOptions true &&
+ (
+ cd workbench &&
+ test_commit one &&
+ git push --mirror up &&
+ test_commit two &&
+ git push --push-option=asdf --push-option="more structured text" up master
+ ) &&
+ test_refs master master &&
+ printf "asdf\nmore structured text\n" >expect &&
+ test_cmp expect upstream/.git/hooks/pre-receive.push_options &&
+ test_cmp expect upstream/.git/hooks/post-receive.push_options
+'
+
+test_done
diff --git a/t/t5546-receive-limits.sh b/t/t5546-receive-limits.sh
new file mode 100755
index 000000000..10cb0be2b
--- /dev/null
+++ b/t/t5546-receive-limits.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+test_description='check receive input limits'
+. ./test-lib.sh
+
+# Let's run tests with different unpack limits: 1 and 10000
+# When the limit is 1, `git receive-pack` will call `git index-pack`.
+# When the limit is 10000, `git receive-pack` will call `git unpack-objects`.
+
+test_pack_input_limit () {
+ case "$1" in
+ index) unpack_limit=1 ;;
+ unpack) unpack_limit=10000 ;;
+ esac
+
+ test_expect_success 'prepare destination repository' '
+ rm -fr dest &&
+ git --bare init dest
+ '
+
+ test_expect_success "set unpacklimit to $unpack_limit" '
+ git --git-dir=dest config receive.unpacklimit "$unpack_limit"
+ '
+
+ test_expect_success 'setting receive.maxInputSize to 512 rejects push' '
+ git --git-dir=dest config receive.maxInputSize 512 &&
+ test_must_fail git push dest HEAD
+ '
+
+ test_expect_success 'bumping limit to 4k allows push' '
+ git --git-dir=dest config receive.maxInputSize 4k &&
+ git push dest HEAD
+ '
+
+ test_expect_success 'prepare destination repository (again)' '
+ rm -fr dest &&
+ git --bare init dest
+ '
+
+ test_expect_success 'lifting the limit allows push' '
+ git --git-dir=dest config receive.maxInputSize 0 &&
+ git push dest HEAD
+ '
+}
+
+test_expect_success "create known-size (1024 bytes) commit" '
+ test-genrandom foo 1024 >one-k &&
+ git add one-k &&
+ test_commit one-k
+'
+
+test_pack_input_limit index
+test_pack_input_limit unpack
+
+test_done
diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh
index 3484b6f0f..7641417b4 100755
--- a/t/t5550-http-fetch-dumb.sh
+++ b/t/t5550-http-fetch-dumb.sh
@@ -263,15 +263,15 @@ check_language () {
>expect
;;
?*)
- echo "Accept-Language: $1" >expect
+ echo "=> Send header: Accept-Language: $1" >expect
;;
esac &&
- GIT_CURL_VERBOSE=1 \
+ GIT_TRACE_CURL=true \
LANGUAGE=$2 \
git ls-remote "$HTTPD_URL/dumb/repo.git" >output 2>&1 &&
tr -d '\015' <output |
sort -u |
- sed -ne '/^Accept-Language:/ p' >actual &&
+ sed -ne '/^=> Send header: Accept-Language:/ p' >actual &&
test_cmp expect actual
}
@@ -295,8 +295,16 @@ ja;q=0.95, zh;q=0.94, sv;q=0.93, pt;q=0.92, nb;q=0.91, *;q=0.90" \
'
test_expect_success 'git client does not send an empty Accept-Language' '
- GIT_CURL_VERBOSE=1 LANGUAGE= git ls-remote "$HTTPD_URL/dumb/repo.git" 2>stderr &&
- ! grep "^Accept-Language:" stderr
+ GIT_TRACE_CURL=true LANGUAGE= git ls-remote "$HTTPD_URL/dumb/repo.git" 2>stderr &&
+ ! grep "^=> Send header: Accept-Language:" stderr
+'
+
+test_expect_success 'remote-http complains cleanly about malformed urls' '
+ # do not actually issue "list" or other commands, as we do not
+ # want to rely on what curl would actually do with such a broken
+ # URL. This is just about making sure we do not segfault during
+ # initialization.
+ test_must_fail git remote-http http::/example.com/repo.git
'
stop_httpd
diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
index 2f375eb94..1ec5b2747 100755
--- a/t/t5551-http-fetch-smart.sh
+++ b/t/t5551-http-fetch-smart.sh
@@ -43,12 +43,21 @@ cat >exp <<EOF
< Content-Type: application/x-git-upload-pack-result
EOF
test_expect_success 'clone http repository' '
- GIT_CURL_VERBOSE=1 git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err &&
+ GIT_TRACE_CURL=true git clone --quiet $HTTPD_URL/smart/repo.git clone 2>err &&
test_cmp file clone/file &&
tr '\''\015'\'' Q <err |
sed -e "
s/Q\$//
/^[*] /d
+ /^== Info:/d
+ /^=> Send header, /d
+ /^=> Send header:$/d
+ /^<= Recv header, /d
+ /^<= Recv header:$/d
+ s/=> Send header: //
+ s/= Recv header://
+ /^<= Recv data/d
+ /^=> Send data/d
/^$/d
/^< $/d
@@ -261,9 +270,9 @@ test_expect_success CMDLINE_LIMIT \
'
test_expect_success 'large fetch-pack requests can be split across POSTs' '
- GIT_CURL_VERBOSE=1 git -c http.postbuffer=65536 \
+ GIT_TRACE_CURL=true git -c http.postbuffer=65536 \
clone --bare "$HTTPD_URL/smart/repo.git" split.git 2>err &&
- grep "^> POST" err >posts &&
+ grep "^=> Send header: POST" err >posts &&
test_line_count = 2 posts
'
diff --git a/t/t5614-clone-submodules.sh b/t/t5614-clone-submodules.sh
index da2a67f65..a87d32965 100755
--- a/t/t5614-clone-submodules.sh
+++ b/t/t5614-clone-submodules.sh
@@ -67,4 +67,56 @@ test_expect_success 'non shallow clone with shallow submodule' '
test_line_count = 1 lines
'
+test_expect_success 'clone follows shallow recommendation' '
+ test_when_finished "rm -rf super_clone" &&
+ git config -f .gitmodules submodule.sub.shallow true &&
+ git add .gitmodules &&
+ git commit -m "recommed shallow for sub" &&
+ git clone --recurse-submodules --no-local "file://$pwd/." super_clone &&
+ (
+ cd super_clone &&
+ git log --oneline >lines &&
+ test_line_count = 4 lines
+ ) &&
+ (
+ cd super_clone/sub &&
+ git log --oneline >lines &&
+ test_line_count = 1 lines
+ )
+'
+
+test_expect_success 'get unshallow recommended shallow submodule' '
+ test_when_finished "rm -rf super_clone" &&
+ git clone --no-local "file://$pwd/." super_clone &&
+ (
+ cd super_clone &&
+ git submodule update --init --no-recommend-shallow &&
+ git log --oneline >lines &&
+ test_line_count = 4 lines
+ ) &&
+ (
+ cd super_clone/sub &&
+ git log --oneline >lines &&
+ test_line_count = 3 lines
+ )
+'
+
+test_expect_success 'clone follows non shallow recommendation' '
+ test_when_finished "rm -rf super_clone" &&
+ git config -f .gitmodules submodule.sub.shallow false &&
+ git add .gitmodules &&
+ git commit -m "recommed non shallow for sub" &&
+ git clone --recurse-submodules --no-local "file://$pwd/." super_clone &&
+ (
+ cd super_clone &&
+ git log --oneline >lines &&
+ test_line_count = 5 lines
+ ) &&
+ (
+ cd super_clone/sub &&
+ git log --oneline >lines &&
+ test_line_count = 3 lines
+ )
+'
+
test_done
diff --git a/t/t6007-rev-list-cherry-pick-file.sh b/t/t6007-rev-list-cherry-pick-file.sh
index 28d4f6b25..1408b608e 100755
--- a/t/t6007-rev-list-cherry-pick-file.sh
+++ b/t/t6007-rev-list-cherry-pick-file.sh
@@ -207,4 +207,25 @@ test_expect_success '--count --left-right' '
test_cmp expect actual
'
+# Corrupt the object store deliberately to make sure
+# the object is not even checked for its existence.
+remove_loose_object () {
+ sha1="$(git rev-parse "$1")" &&
+ remainder=${sha1#??} &&
+ firsttwo=${sha1%$remainder} &&
+ rm .git/objects/$firsttwo/$remainder
+}
+
+test_expect_success '--cherry-pick avoids looking at full diffs' '
+ git checkout -b shy-diff &&
+ test_commit dont-look-at-me &&
+ echo Hello >dont-look-at-me.t &&
+ test_tick &&
+ git commit -m tip dont-look-at-me.t &&
+ git checkout -b mainline HEAD^ &&
+ test_commit to-cherry-pick &&
+ remove_loose_object shy-diff^:dont-look-at-me.t &&
+ git rev-list --cherry-pick ...shy-diff
+'
+
test_done
diff --git a/t/t6018-rev-list-glob.sh b/t/t6018-rev-list-glob.sh
index d00f7db86..381f35ed1 100755
--- a/t/t6018-rev-list-glob.sh
+++ b/t/t6018-rev-list-glob.sh
@@ -257,7 +257,7 @@ test_expect_success 'rev-list accumulates multiple --exclude' '
# "git rev-list<ENTER>" is likely to be a bug in the calling script and may
-# deserve an error message, but do cases where set of refs programatically
+# deserve an error message, but do cases where set of refs programmatically
# given using globbing and/or --stdin need to fail with the same error, or
# are we better off reporting a success with no output? The following few
# tests document the current behaviour to remind us that we might want to
diff --git a/t/t6026-merge-attr.sh b/t/t6026-merge-attr.sh
index dd8f88d18..7a6e33e67 100755
--- a/t/t6026-merge-attr.sh
+++ b/t/t6026-merge-attr.sh
@@ -185,7 +185,9 @@ test_expect_success 'custom merge does not lock index' '
git reset --hard anchor &&
write_script sleep-one-second.sh <<-\EOF &&
sleep 1 &
+ echo $! >sleep.pid
EOF
+ test_when_finished "kill \$(cat sleep.pid)" &&
test_write_lines >.gitattributes \
"* merge=ours" "text merge=sleep-one-second" &&
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index e74662ba5..5e5370feb 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -362,7 +362,7 @@ test_expect_success 'bisect starting with a detached HEAD' '
test_expect_success 'bisect errors out if bad and good are mistaken' '
git bisect reset &&
test_must_fail git bisect start $HASH2 $HASH4 2> rev_list_error &&
- grep "mistook good and bad" rev_list_error &&
+ test_i18ngrep "mistook good and bad" rev_list_error &&
git bisect reset
'
@@ -404,7 +404,7 @@ test_expect_success 'side branch creation' '
test_expect_success 'good merge base when good and bad are siblings' '
git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt &&
- grep "merge base must be tested" my_bisect_log.txt &&
+ test_i18ngrep "merge base must be tested" my_bisect_log.txt &&
grep $HASH4 my_bisect_log.txt &&
git bisect good > my_bisect_log.txt &&
test_must_fail grep "merge base must be tested" my_bisect_log.txt &&
@@ -413,7 +413,7 @@ test_expect_success 'good merge base when good and bad are siblings' '
'
test_expect_success 'skipped merge base when good and bad are siblings' '
git bisect start "$SIDE_HASH7" "$HASH7" > my_bisect_log.txt &&
- grep "merge base must be tested" my_bisect_log.txt &&
+ test_i18ngrep "merge base must be tested" my_bisect_log.txt &&
grep $HASH4 my_bisect_log.txt &&
git bisect skip > my_bisect_log.txt 2>&1 &&
grep "warning" my_bisect_log.txt &&
@@ -423,11 +423,11 @@ test_expect_success 'skipped merge base when good and bad are siblings' '
test_expect_success 'bad merge base when good and bad are siblings' '
git bisect start "$HASH7" HEAD > my_bisect_log.txt &&
- grep "merge base must be tested" my_bisect_log.txt &&
+ test_i18ngrep "merge base must be tested" my_bisect_log.txt &&
grep $HASH4 my_bisect_log.txt &&
test_must_fail git bisect bad > my_bisect_log.txt 2>&1 &&
- grep "merge base $HASH4 is bad" my_bisect_log.txt &&
- grep "fixed between $HASH4 and \[$SIDE_HASH7\]" my_bisect_log.txt &&
+ test_i18ngrep "merge base $HASH4 is bad" my_bisect_log.txt &&
+ test_i18ngrep "fixed between $HASH4 and \[$SIDE_HASH7\]" my_bisect_log.txt &&
git bisect reset
'
@@ -460,9 +460,9 @@ test_expect_success 'many merge bases creation' '
test_expect_success 'good merge bases when good and bad are siblings' '
git bisect start "$B_HASH" "$A_HASH" > my_bisect_log.txt &&
- grep "merge base must be tested" my_bisect_log.txt &&
+ test_i18ngrep "merge base must be tested" my_bisect_log.txt &&
git bisect good > my_bisect_log2.txt &&
- grep "merge base must be tested" my_bisect_log2.txt &&
+ test_i18ngrep "merge base must be tested" my_bisect_log2.txt &&
{
{
grep "$SIDE_HASH5" my_bisect_log.txt &&
@@ -477,14 +477,14 @@ test_expect_success 'good merge bases when good and bad are siblings' '
test_expect_success 'optimized merge base checks' '
git bisect start "$HASH7" "$SIDE_HASH7" > my_bisect_log.txt &&
- grep "merge base must be tested" my_bisect_log.txt &&
+ test_i18ngrep "merge base must be tested" my_bisect_log.txt &&
grep "$HASH4" my_bisect_log.txt &&
git bisect good > my_bisect_log2.txt &&
test -f ".git/BISECT_ANCESTORS_OK" &&
test "$HASH6" = $(git rev-parse --verify HEAD) &&
git bisect bad > my_bisect_log3.txt &&
git bisect good "$A_HASH" > my_bisect_log4.txt &&
- grep "merge base must be tested" my_bisect_log4.txt &&
+ test_i18ngrep "merge base must be tested" my_bisect_log4.txt &&
test_must_fail test -f ".git/BISECT_ANCESTORS_OK"
'
@@ -562,7 +562,7 @@ test_expect_success 'skipping away from skipped commit' '
test_expect_success 'erroring out when using bad path parameters' '
test_must_fail git bisect start $PARA_HASH7 $HASH1 -- foobar 2> error.txt &&
- grep "bad path parameters" error.txt
+ test_i18ngrep "bad path parameters" error.txt
'
test_expect_success 'test bisection on bare repo - --no-checkout specified' '
@@ -721,7 +721,7 @@ git bisect good 3de952f2416b6084f557ec417709eac740c6818c
# first bad commit: [32a594a3fdac2d57cf6d02987e30eec68511498c] Add <4: Ciao for now> into <hello>.
EOF
-test_expect_success 'bisect log: successfull result' '
+test_expect_success 'bisect log: successful result' '
git bisect reset &&
git bisect start $HASH4 $HASH2 &&
git bisect good &&
@@ -803,7 +803,7 @@ test_expect_success 'bisect terms needs 0 or 1 argument' '
test_must_fail git bisect terms 1 2 &&
test_must_fail git bisect terms 2>actual &&
echo "no terms defined" >expected &&
- test_cmp expected actual
+ test_i18ncmp expected actual
'
test_expect_success 'bisect terms shows good/bad after start' '
@@ -875,7 +875,7 @@ test_expect_success 'bisect start --term-* does store terms' '
Your current terms are two for the old state
and one for the new state.
EOF
- test_cmp expected actual &&
+ test_i18ncmp expected actual &&
git bisect terms --term-bad >actual &&
echo one >expected &&
test_cmp expected actual &&
diff --git a/t/t6301-for-each-ref-errors.sh b/t/t6301-for-each-ref-errors.sh
index cdb67a03b..c734ce238 100755
--- a/t/t6301-for-each-ref-errors.sh
+++ b/t/t6301-for-each-ref-errors.sh
@@ -20,8 +20,8 @@ test_expect_success 'Broken refs are reported correctly' '
test_when_finished "rm -f .git/$r" &&
echo "warning: ignoring broken ref $r" >broken-err &&
git for-each-ref >out 2>err &&
- test_cmp full-list out &&
- test_cmp broken-err err
+ test_i18ncmp full-list out &&
+ test_i18ncmp broken-err err
'
test_expect_success 'NULL_SHA1 refs are reported correctly' '
@@ -31,10 +31,10 @@ test_expect_success 'NULL_SHA1 refs are reported correctly' '
echo "warning: ignoring broken ref $r" >zeros-err &&
git for-each-ref >out 2>err &&
test_cmp full-list out &&
- test_cmp zeros-err err &&
+ test_i18ncmp zeros-err err &&
git for-each-ref --format="%(objectname) %(refname)" >brief-out 2>brief-err &&
test_cmp brief-list brief-out &&
- test_cmp zeros-err brief-err
+ test_i18ncmp zeros-err brief-err
'
test_expect_success 'Missing objects are reported correctly' '
@@ -43,7 +43,7 @@ test_expect_success 'Missing objects are reported correctly' '
test_when_finished "rm -f .git/$r" &&
echo "fatal: missing object $MISSING for $r" >missing-err &&
test_must_fail git for-each-ref 2>err &&
- test_cmp missing-err err &&
+ test_i18ncmp missing-err err &&
(
cat brief-list &&
echo "$MISSING $r"
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index 4a2570ed9..e365d1ff7 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -292,8 +292,8 @@ test_expect_success 'setup submodule' '
echo content >file &&
git add file &&
git commit -m "added sub and file" &&
- mkdir -p deep/directory/hierachy &&
- git submodule add ./. deep/directory/hierachy/sub &&
+ mkdir -p deep/directory/hierarchy &&
+ git submodule add ./. deep/directory/hierarchy/sub &&
git commit -m "added another submodule" &&
git branch submodule
'
@@ -485,8 +485,8 @@ test_expect_success 'moving a submodule in nested directories' '
# git status would fail if the update of linking git dir to
# work dir of the submodule failed.
git status &&
- git config -f ../.gitmodules submodule.deep/directory/hierachy/sub.path >../actual &&
- echo "directory/hierachy/sub" >../expect
+ git config -f ../.gitmodules submodule.deep/directory/hierarchy/sub.path >../actual &&
+ echo "directory/hierarchy/sub" >../expect
) &&
test_cmp actual expect
'
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index f9b7d79af..8b0f71a2a 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -1202,10 +1202,17 @@ test_expect_success GPG,RFC1991 \
# try to sign with bad user.signingkey
git config user.signingkey BobTheMouse
test_expect_success GPG \
- 'git tag -s fails if gpg is misconfigured' \
+ 'git tag -s fails if gpg is misconfigured (bad key)' \
'test_must_fail git tag -s -m tail tag-gpg-failure'
git config --unset user.signingkey
+# try to produce invalid signature
+test_expect_success GPG \
+ 'git tag -s fails if gpg is misconfigured (bad signature format)' \
+ 'test_config gpg.program echo &&
+ test_must_fail git tag -s -m tail tag-gpg-failure'
+
+
# try to verify without gpg:
rm -rf gpghome
diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh
index e4fc5c826..c8dc665f2 100755
--- a/t/t7006-pager.sh
+++ b/t/t7006-pager.sh
@@ -49,6 +49,19 @@ test_expect_success TTY 'LESS and LV envvars are set for pagination' '
grep ^LV= pager-env.out
'
+test_expect_success !MINGW,TTY 'LESS and LV envvars set by git-sh-setup' '
+ (
+ sane_unset LESS LV &&
+ PAGER="env >pager-env.out; wc" &&
+ export PAGER &&
+ PATH="$(git --exec-path):$PATH" &&
+ export PATH &&
+ test_terminal sh -c ". git-sh-setup && git_pager"
+ ) &&
+ grep ^LESS= pager-env.out &&
+ grep ^LV= pager-env.out
+'
+
test_expect_success TTY 'some commands do not use a pager' '
rm -f paginated.out &&
test_terminal git rev-list HEAD &&
diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index 4d17363a9..53cf42fac 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -232,4 +232,25 @@ test_expect_success 'status --branch with detached HEAD' '
test_i18ncmp expected actual
'
+## Duplicate the above test and verify --porcelain=v1 arg parsing.
+test_expect_success 'status --porcelain=v1 --branch with detached HEAD' '
+ git reset --hard &&
+ git checkout master^0 &&
+ git status --branch --porcelain=v1 >actual &&
+ cat >expected <<-EOF &&
+ ## HEAD (no branch)
+ ?? .gitconfig
+ ?? actual
+ ?? expect
+ ?? expected
+ ?? mdconflict/
+ EOF
+ test_i18ncmp expected actual
+'
+
+## Verify parser error on invalid --porcelain argument.
+test_expect_success 'status --porcelain=bogus' '
+ test_must_fail git status --porcelain=bogus
+'
+
test_done
diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index 4e1e290a9..0667bd9dd 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -658,7 +658,7 @@ test_expect_success 'test ident field is working' '
cp -R done dthree dtwo four three ../other_worktree &&
GIT_WORK_TREE=../other_worktree git status 2>../err &&
echo "warning: Untracked cache is disabled on this system or location." >../expect &&
- test_cmp ../expect ../err
+ test_i18ncmp ../expect ../err
'
test_done
diff --git a/t/t7064-wtstatus-pv2.sh b/t/t7064-wtstatus-pv2.sh
new file mode 100755
index 000000000..3012a4d7c
--- /dev/null
+++ b/t/t7064-wtstatus-pv2.sh
@@ -0,0 +1,593 @@
+#!/bin/sh
+
+test_description='git status --porcelain=v2
+
+This test exercises porcelain V2 output for git status.'
+
+
+. ./test-lib.sh
+
+
+test_expect_success setup '
+ test_tick &&
+ git config core.autocrlf false &&
+ echo x >file_x &&
+ echo y >file_y &&
+ echo z >file_z &&
+ mkdir dir1 &&
+ echo a >dir1/file_a &&
+ echo b >dir1/file_b
+'
+
+test_expect_success 'before initial commit, nothing added, only untracked' '
+ cat >expect <<-EOF &&
+ # branch.oid (initial)
+ # branch.head master
+ ? actual
+ ? dir1/
+ ? expect
+ ? file_x
+ ? file_y
+ ? file_z
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=normal >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'before initial commit, things added' '
+ git add file_x file_y file_z dir1 &&
+ OID_A=$(git hash-object -t blob -- dir1/file_a) &&
+ OID_B=$(git hash-object -t blob -- dir1/file_b) &&
+ OID_X=$(git hash-object -t blob -- file_x) &&
+ OID_Y=$(git hash-object -t blob -- file_y) &&
+ OID_Z=$(git hash-object -t blob -- file_z) &&
+
+ cat >expect <<-EOF &&
+ # branch.oid (initial)
+ # branch.head master
+ 1 A. N... 000000 100644 100644 $_z40 $OID_A dir1/file_a
+ 1 A. N... 000000 100644 100644 $_z40 $OID_B dir1/file_b
+ 1 A. N... 000000 100644 100644 $_z40 $OID_X file_x
+ 1 A. N... 000000 100644 100644 $_z40 $OID_Y file_y
+ 1 A. N... 000000 100644 100644 $_z40 $OID_Z file_z
+ ? actual
+ ? expect
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'before initial commit, things added (-z)' '
+ lf_to_nul >expect <<-EOF &&
+ # branch.oid (initial)
+ # branch.head master
+ 1 A. N... 000000 100644 100644 $_z40 $OID_A dir1/file_a
+ 1 A. N... 000000 100644 100644 $_z40 $OID_B dir1/file_b
+ 1 A. N... 000000 100644 100644 $_z40 $OID_X file_x
+ 1 A. N... 000000 100644 100644 $_z40 $OID_Y file_y
+ 1 A. N... 000000 100644 100644 $_z40 $OID_Z file_z
+ ? actual
+ ? expect
+ EOF
+
+ git status -z --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'make first commit, comfirm HEAD oid and branch' '
+ git commit -m initial &&
+ H0=$(git rev-parse HEAD) &&
+ cat >expect <<-EOF &&
+ # branch.oid $H0
+ # branch.head master
+ ? actual
+ ? expect
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'after first commit, create unstaged changes' '
+ echo x >>file_x &&
+ OID_X1=$(git hash-object -t blob -- file_x) &&
+ rm file_z &&
+ H0=$(git rev-parse HEAD) &&
+
+ cat >expect <<-EOF &&
+ # branch.oid $H0
+ # branch.head master
+ 1 .M N... 100644 100644 100644 $OID_X $OID_X file_x
+ 1 .D N... 100644 100644 000000 $OID_Z $OID_Z file_z
+ ? actual
+ ? expect
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'after first commit but omit untracked files and branch' '
+ cat >expect <<-EOF &&
+ 1 .M N... 100644 100644 100644 $OID_X $OID_X file_x
+ 1 .D N... 100644 100644 000000 $OID_Z $OID_Z file_z
+ EOF
+
+ git status --porcelain=v2 --untracked-files=no >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'after first commit, stage existing changes' '
+ git add file_x &&
+ git rm file_z &&
+ H0=$(git rev-parse HEAD) &&
+
+ cat >expect <<-EOF &&
+ # branch.oid $H0
+ # branch.head master
+ 1 M. N... 100644 100644 100644 $OID_X $OID_X1 file_x
+ 1 D. N... 100644 000000 000000 $OID_Z $_z40 file_z
+ ? actual
+ ? expect
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'rename causes 2 path lines' '
+ git mv file_y renamed_y &&
+ H0=$(git rev-parse HEAD) &&
+
+ q_to_tab >expect <<-EOF &&
+ # branch.oid $H0
+ # branch.head master
+ 1 M. N... 100644 100644 100644 $OID_X $OID_X1 file_x
+ 1 D. N... 100644 000000 000000 $OID_Z $_z40 file_z
+ 2 R. N... 100644 100644 100644 $OID_Y $OID_Y R100 renamed_yQfile_y
+ ? actual
+ ? expect
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'rename causes 2 path lines (-z)' '
+ H0=$(git rev-parse HEAD) &&
+
+ ## Lines use NUL path separator and line terminator, so double transform here.
+ q_to_nul <<-EOF | lf_to_nul >expect &&
+ # branch.oid $H0
+ # branch.head master
+ 1 M. N... 100644 100644 100644 $OID_X $OID_X1 file_x
+ 1 D. N... 100644 000000 000000 $OID_Z $_z40 file_z
+ 2 R. N... 100644 100644 100644 $OID_Y $OID_Y R100 renamed_yQfile_y
+ ? actual
+ ? expect
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all -z >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'make second commit, confirm clean and new HEAD oid' '
+ git commit -m second &&
+ H1=$(git rev-parse HEAD) &&
+
+ cat >expect <<-EOF &&
+ # branch.oid $H1
+ # branch.head master
+ ? actual
+ ? expect
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'confirm ignored files are not printed' '
+ test_when_finished "rm -f x.ign .gitignore" &&
+ echo x.ign >.gitignore &&
+ echo "ignore me" >x.ign &&
+
+ cat >expect <<-EOF &&
+ ? .gitignore
+ ? actual
+ ? expect
+ EOF
+
+ git status --porcelain=v2 --untracked-files=all >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'ignored files are printed with --ignored' '
+ test_when_finished "rm -f x.ign .gitignore" &&
+ echo x.ign >.gitignore &&
+ echo "ignore me" >x.ign &&
+
+ cat >expect <<-EOF &&
+ ? .gitignore
+ ? actual
+ ? expect
+ ! x.ign
+ EOF
+
+ git status --porcelain=v2 --ignored --untracked-files=all >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'create and commit permanent ignore file' '
+ cat >.gitignore <<-EOF &&
+ actual*
+ expect*
+ EOF
+
+ git add .gitignore &&
+ git commit -m ignore_trash &&
+ H1=$(git rev-parse HEAD) &&
+
+ cat >expect <<-EOF &&
+ # branch.oid $H1
+ # branch.head master
+ EOF
+
+ git status --porcelain=v2 --branch >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'verify --intent-to-add output' '
+ test_when_finished "git rm -f intent1.add intent2.add" &&
+ touch intent1.add &&
+ echo test >intent2.add &&
+
+ git add --intent-to-add intent1.add intent2.add &&
+
+ cat >expect <<-EOF &&
+ 1 AM N... 000000 100644 100644 $_z40 $EMPTY_BLOB intent1.add
+ 1 AM N... 000000 100644 100644 $_z40 $EMPTY_BLOB intent2.add
+ EOF
+
+ git status --porcelain=v2 >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'verify AA (add-add) conflict' '
+ test_when_finished "git reset --hard" &&
+
+ git branch AA_A master &&
+ git checkout AA_A &&
+ echo "Branch AA_A" >conflict.txt &&
+ OID_AA_A=$(git hash-object -t blob -- conflict.txt) &&
+ git add conflict.txt &&
+ git commit -m "branch aa_a" &&
+
+ git branch AA_B master &&
+ git checkout AA_B &&
+ echo "Branch AA_B" >conflict.txt &&
+ OID_AA_B=$(git hash-object -t blob -- conflict.txt) &&
+ git add conflict.txt &&
+ git commit -m "branch aa_b" &&
+
+ git branch AA_M AA_B &&
+ git checkout AA_M &&
+ test_must_fail git merge AA_A &&
+
+ HM=$(git rev-parse HEAD) &&
+
+ cat >expect <<-EOF &&
+ # branch.oid $HM
+ # branch.head AA_M
+ u AA N... 000000 100644 100644 100644 $_z40 $OID_AA_B $OID_AA_A conflict.txt
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'verify UU (edit-edit) conflict' '
+ test_when_finished "git reset --hard" &&
+
+ git branch UU_ANC master &&
+ git checkout UU_ANC &&
+ echo "Ancestor" >conflict.txt &&
+ OID_UU_ANC=$(git hash-object -t blob -- conflict.txt) &&
+ git add conflict.txt &&
+ git commit -m "UU_ANC" &&
+
+ git branch UU_A UU_ANC &&
+ git checkout UU_A &&
+ echo "Branch UU_A" >conflict.txt &&
+ OID_UU_A=$(git hash-object -t blob -- conflict.txt) &&
+ git add conflict.txt &&
+ git commit -m "branch uu_a" &&
+
+ git branch UU_B UU_ANC &&
+ git checkout UU_B &&
+ echo "Branch UU_B" >conflict.txt &&
+ OID_UU_B=$(git hash-object -t blob -- conflict.txt) &&
+ git add conflict.txt &&
+ git commit -m "branch uu_b" &&
+
+ git branch UU_M UU_B &&
+ git checkout UU_M &&
+ test_must_fail git merge UU_A &&
+
+ HM=$(git rev-parse HEAD) &&
+
+ cat >expect <<-EOF &&
+ # branch.oid $HM
+ # branch.head UU_M
+ u UU N... 100644 100644 100644 100644 $OID_UU_ANC $OID_UU_B $OID_UU_A conflict.txt
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'verify upstream fields in branch header' '
+ git checkout master &&
+ test_when_finished "rm -rf sub_repo" &&
+ git clone . sub_repo &&
+ (
+ ## Confirm local master tracks remote master.
+ cd sub_repo &&
+ HUF=$(git rev-parse HEAD) &&
+
+ cat >expect <<-EOF &&
+ # branch.oid $HUF
+ # branch.head master
+ # branch.upstream origin/master
+ # branch.ab +0 -0
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual &&
+
+ ## Test ahead/behind.
+ echo xyz >file_xyz &&
+ git add file_xyz &&
+ git commit -m xyz &&
+
+ HUF=$(git rev-parse HEAD) &&
+
+ cat >expect <<-EOF &&
+ # branch.oid $HUF
+ # branch.head master
+ # branch.upstream origin/master
+ # branch.ab +1 -0
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual &&
+
+ ## Repeat the above but without --branch.
+ cat >expect <<-EOF &&
+ EOF
+
+ git status --porcelain=v2 --untracked-files=all >actual &&
+ test_cmp expect actual &&
+
+ ## Test upstream-gone case. Fake this by pointing origin/master at
+ ## a non-existing commit.
+ OLD=$(git rev-parse origin/master) &&
+ NEW=$_z40 &&
+ mv .git/packed-refs .git/old-packed-refs &&
+ sed "s/$OLD/$NEW/g" <.git/old-packed-refs >.git/packed-refs &&
+
+ HUF=$(git rev-parse HEAD) &&
+
+ cat >expect <<-EOF &&
+ # branch.oid $HUF
+ # branch.head master
+ # branch.upstream origin/master
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'create and add submodule, submodule appears clean (A. S...)' '
+ git checkout master &&
+ git clone . sub_repo &&
+ git clone . super_repo &&
+ ( cd super_repo &&
+ git submodule add ../sub_repo sub1 &&
+
+ ## Confirm stage/add of clean submodule.
+ HMOD=$(git hash-object -t blob -- .gitmodules) &&
+ HSUP=$(git rev-parse HEAD) &&
+ HSUB=$HSUP &&
+
+ cat >expect <<-EOF &&
+ # branch.oid $HSUP
+ # branch.head master
+ # branch.upstream origin/master
+ # branch.ab +0 -0
+ 1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
+ 1 A. S... 000000 160000 160000 $_z40 $HSUB sub1
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'untracked changes in added submodule (AM S..U)' '
+ ( cd super_repo &&
+ ## create untracked file in the submodule.
+ ( cd sub1 &&
+ echo "xxxx" >file_in_sub
+ ) &&
+
+ HMOD=$(git hash-object -t blob -- .gitmodules) &&
+ HSUP=$(git rev-parse HEAD) &&
+ HSUB=$HSUP &&
+
+ cat >expect <<-EOF &&
+ # branch.oid $HSUP
+ # branch.head master
+ # branch.upstream origin/master
+ # branch.ab +0 -0
+ 1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
+ 1 AM S..U 000000 160000 160000 $_z40 $HSUB sub1
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'staged changes in added submodule (AM S.M.)' '
+ ( cd super_repo &&
+ ## stage the changes in the submodule.
+ ( cd sub1 &&
+ git add file_in_sub
+ ) &&
+
+ HMOD=$(git hash-object -t blob -- .gitmodules) &&
+ HSUP=$(git rev-parse HEAD) &&
+ HSUB=$HSUP &&
+
+ cat >expect <<-EOF &&
+ # branch.oid $HSUP
+ # branch.head master
+ # branch.upstream origin/master
+ # branch.ab +0 -0
+ 1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
+ 1 AM S.M. 000000 160000 160000 $_z40 $HSUB sub1
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'staged and unstaged changes in added (AM S.M.)' '
+ ( cd super_repo &&
+ ( cd sub1 &&
+ ## make additional unstaged changes (on the same file) in the submodule.
+ ## This does not cause us to get S.MU (because the submodule does not report
+ ## a "?" line for the unstaged changes).
+ echo "more changes" >>file_in_sub
+ ) &&
+
+ HMOD=$(git hash-object -t blob -- .gitmodules) &&
+ HSUP=$(git rev-parse HEAD) &&
+ HSUB=$HSUP &&
+
+ cat >expect <<-EOF &&
+ # branch.oid $HSUP
+ # branch.head master
+ # branch.upstream origin/master
+ # branch.ab +0 -0
+ 1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
+ 1 AM S.M. 000000 160000 160000 $_z40 $HSUB sub1
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'staged and untracked changes in added submodule (AM S.MU)' '
+ ( cd super_repo &&
+ ( cd sub1 &&
+ ## stage new changes in tracked file.
+ git add file_in_sub &&
+ ## create new untracked file.
+ echo "yyyy" >>another_file_in_sub
+ ) &&
+
+ HMOD=$(git hash-object -t blob -- .gitmodules) &&
+ HSUP=$(git rev-parse HEAD) &&
+ HSUB=$HSUP &&
+
+ cat >expect <<-EOF &&
+ # branch.oid $HSUP
+ # branch.head master
+ # branch.upstream origin/master
+ # branch.ab +0 -0
+ 1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
+ 1 AM S.MU 000000 160000 160000 $_z40 $HSUB sub1
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'commit within the submodule appears as new commit in super (AM SC..)' '
+ ( cd super_repo &&
+ ( cd sub1 &&
+ ## Make a new commit in the submodule.
+ git add file_in_sub &&
+ rm -f another_file_in_sub &&
+ git commit -m "new commit"
+ ) &&
+
+ HMOD=$(git hash-object -t blob -- .gitmodules) &&
+ HSUP=$(git rev-parse HEAD) &&
+ HSUB=$HSUP &&
+
+ cat >expect <<-EOF &&
+ # branch.oid $HSUP
+ # branch.head master
+ # branch.upstream origin/master
+ # branch.ab +0 -0
+ 1 A. N... 000000 100644 100644 $_z40 $HMOD .gitmodules
+ 1 AM SC.. 000000 160000 160000 $_z40 $HSUB sub1
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'stage submodule in super and commit' '
+ ( cd super_repo &&
+ ## Stage the new submodule commit in the super.
+ git add sub1 &&
+ ## Commit the super so that the sub no longer appears as added.
+ git commit -m "super commit" &&
+
+ HSUP=$(git rev-parse HEAD) &&
+
+ cat >expect <<-EOF &&
+ # branch.oid $HSUP
+ # branch.head master
+ # branch.upstream origin/master
+ # branch.ab +1 -0
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'make unstaged changes in existing submodule (.M S.M.)' '
+ ( cd super_repo &&
+ ( cd sub1 &&
+ echo "zzzz" >>file_in_sub
+ ) &&
+
+ HSUP=$(git rev-parse HEAD) &&
+ HSUB=$(cd sub1 && git rev-parse HEAD) &&
+
+ cat >expect <<-EOF &&
+ # branch.oid $HSUP
+ # branch.head master
+ # branch.upstream origin/master
+ # branch.ab +1 -0
+ 1 .M S.M. 160000 160000 160000 $HSUB $HSUB sub1
+ EOF
+
+ git status --porcelain=v2 --branch --untracked-files=all >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_done
diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh
index 98bcfe21a..86f23be34 100755
--- a/t/t7102-reset.sh
+++ b/t/t7102-reset.sh
@@ -66,14 +66,14 @@ test_expect_success 'reset --hard message' '
hex=$(git log -1 --format="%h") &&
git reset --hard > .actual &&
echo HEAD is now at $hex $(commit_msg) > .expected &&
- test_cmp .expected .actual
+ test_i18ncmp .expected .actual
'
test_expect_success 'reset --hard message (ISO8859-1 logoutputencoding)' '
hex=$(git log -1 --format="%h") &&
git -c "i18n.logOutputEncoding=$test_encoding" reset --hard > .actual &&
echo HEAD is now at $hex $(commit_msg $test_encoding) > .expected &&
- test_cmp .expected .actual
+ test_i18ncmp .expected .actual
'
>.diff_expect
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 885923610..d4b217b0e 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -257,7 +257,7 @@ test_expect_success 'checkout to detach HEAD' '
git checkout -f renamer && git clean -f &&
git checkout renamer^ 2>messages &&
test_i18ngrep "HEAD is now at 7329388" messages &&
- test_line_count -gt 1 messages &&
+ (test_line_count -gt 1 messages || test -n "$GETTEXT_POISON") &&
H=$(git rev-parse --verify HEAD) &&
M=$(git show-ref -s --verify refs/heads/master) &&
test "z$H" = "z$M" &&
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index 3570f7bb8..b77cce8e4 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -942,7 +942,7 @@ test_expect_success 'submodule deinit from subdirectory' '
cd sub &&
git submodule deinit ../init >../output
) &&
- grep "\\.\\./init" output &&
+ test_i18ngrep "\\.\\./init" output &&
test -z "$(git config --get-regexp "submodule\.example\.")" &&
test -n "$(git config --get-regexp "submodule\.example2\.")" &&
test -f example2/.git &&
diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh
index 5503ec067..0726799e7 100755
--- a/t/t7403-submodule-sync.sh
+++ b/t/t7403-submodule-sync.sh
@@ -157,7 +157,7 @@ test_expect_success '"git submodule sync" should update submodule URLs - subdire
cd sub &&
git submodule sync >../../output
) &&
- grep "\\.\\./submodule" output &&
+ test_i18ngrep "\\.\\./submodule" output &&
test -d "$(
cd super-clone/submodule &&
git config remote.origin.url
@@ -188,7 +188,7 @@ test_expect_success '"git submodule sync --recursive" should update all submodul
cd sub &&
git submodule sync --recursive >../../output
) &&
- grep "\\.\\./submodule/sub-submodule" output &&
+ test_i18ngrep "\\.\\./submodule/sub-submodule" output &&
test -d "$(
cd super-clone/submodule &&
git config remote.origin.url
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index 5f278799d..64f322c4c 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -136,8 +136,8 @@ test_expect_success 'submodule update --init --recursive from subdirectory' '
cd tmp &&
git submodule update --init --recursive ../super >../../actual 2>../../actual2
) &&
- test_cmp expect actual &&
- test_cmp expect2 actual2
+ test_i18ncmp expect actual &&
+ test_i18ncmp expect2 actual2
'
apos="'";
@@ -209,9 +209,42 @@ test_expect_success 'submodule update --remote should fetch upstream changes' '
)
'
+test_expect_success 'submodule update --remote should fetch upstream changes with .' '
+ (
+ cd super &&
+ git config -f .gitmodules submodule."submodule".branch "." &&
+ git add .gitmodules &&
+ git commit -m "submodules: update from the respective superproject branch"
+ ) &&
+ (
+ cd submodule &&
+ echo line4a >> file &&
+ git add file &&
+ test_tick &&
+ git commit -m "upstream line4a" &&
+ git checkout -b test-branch &&
+ test_commit on-test-branch
+ ) &&
+ (
+ cd super &&
+ git submodule update --remote --force submodule &&
+ git -C submodule log -1 --oneline >actual
+ git -C ../submodule log -1 --oneline master >expect
+ test_cmp expect actual &&
+ git checkout -b test-branch &&
+ git submodule update --remote --force submodule &&
+ git -C submodule log -1 --oneline >actual
+ git -C ../submodule log -1 --oneline test-branch >expect
+ test_cmp expect actual &&
+ git checkout master &&
+ git branch -d test-branch &&
+ git reset --hard HEAD^
+ )
+'
+
test_expect_success 'local config should override .gitmodules branch' '
(cd submodule &&
- git checkout -b test-branch &&
+ git checkout test-branch &&
echo line5 >> file &&
git add file &&
test_tick &&
@@ -370,7 +403,7 @@ test_expect_success 'submodule update - command in .git/config catches failure'
(cd super &&
test_must_fail git submodule update submodule 2>../actual
) &&
- test_cmp actual expect
+ test_i18ncmp actual expect
'
cat << EOF >expect
@@ -388,7 +421,7 @@ test_expect_success 'submodule update - command in .git/config catches failure -
mkdir tmp && cd tmp &&
test_must_fail git submodule update ../submodule 2>../../actual
) &&
- test_cmp actual expect
+ test_i18ncmp actual expect
'
cat << EOF >expect
@@ -408,7 +441,7 @@ test_expect_success 'recursive submodule update - command in .git/config catches
mkdir -p tmp && cd tmp &&
test_must_fail git submodule update --recursive ../super 2>../../actual
) &&
- test_cmp actual expect
+ test_i18ncmp actual expect
'
test_expect_success 'submodule init does not copy command into .git/config' '
@@ -841,16 +874,35 @@ test_expect_success SYMLINKS 'submodule update can handle symbolic links in pwd'
'
test_expect_success 'submodule update clone shallow submodule' '
+ test_when_finished "rm -rf super3" &&
+ first=$(git -C cloned submodule status submodule |cut -c2-41) &&
+ second=$(git -C submodule rev-parse HEAD) &&
+ commit_count=$(git -C submodule rev-list --count $first^..$second) &&
git clone cloned super3 &&
pwd=$(pwd) &&
- (cd super3 &&
- sed -e "s#url = ../#url = file://$pwd/#" <.gitmodules >.gitmodules.tmp &&
- mv -f .gitmodules.tmp .gitmodules &&
- git submodule update --init --depth=3
- (cd submodule &&
- test 1 = $(git log --oneline | wc -l)
- )
-)
+ (
+ cd super3 &&
+ sed -e "s#url = ../#url = file://$pwd/#" <.gitmodules >.gitmodules.tmp &&
+ mv -f .gitmodules.tmp .gitmodules &&
+ git submodule update --init --depth=$commit_count &&
+ test 1 = $(git -C submodule log --oneline | wc -l)
+ )
+'
+
+test_expect_success 'submodule update clone shallow submodule outside of depth' '
+ test_when_finished "rm -rf super3" &&
+ git clone cloned super3 &&
+ pwd=$(pwd) &&
+ (
+ cd super3 &&
+ sed -e "s#url = ../#url = file://$pwd/#" <.gitmodules >.gitmodules.tmp &&
+ mv -f .gitmodules.tmp .gitmodules &&
+ test_must_fail git submodule update --init --depth=1 2>actual &&
+ test_i18ngrep "Direct fetching of that commit failed." actual &&
+ git -C ../submodule config uploadpack.allowReachableSHA1InWant true &&
+ git submodule update --init --depth=1 >actual &&
+ test 1 = $(git -C submodule log --oneline | wc -l)
+ )
'
test_expect_success 'submodule update --recursive drops module name before recursing' '
diff --git a/t/t7408-submodule-reference.sh b/t/t7408-submodule-reference.sh
index eaea19b8f..1c1e289ff 100755
--- a/t/t7408-submodule-reference.sh
+++ b/t/t7408-submodule-reference.sh
@@ -8,74 +8,121 @@ test_description='test clone --reference'
base_dir=$(pwd)
-U=$base_dir/UPLOAD_LOG
-
-test_expect_success 'preparing first repository' \
-'test_create_repo A && cd A &&
-echo first > file1 &&
-git add file1 &&
-git commit -m A-initial'
-
-cd "$base_dir"
-
-test_expect_success 'preparing second repository' \
-'git clone A B && cd B &&
-echo second > file2 &&
-git add file2 &&
-git commit -m B-addition &&
-git repack -a -d &&
-git prune'
-
-cd "$base_dir"
-
-test_expect_success 'preparing superproject' \
-'test_create_repo super && cd super &&
-echo file > file &&
-git add file &&
-git commit -m B-super-initial'
-
-cd "$base_dir"
-
-test_expect_success 'submodule add --reference' \
-'cd super && git submodule add --reference ../B "file://$base_dir/A" sub &&
-git commit -m B-super-added'
-
-cd "$base_dir"
-
-test_expect_success 'after add: existence of info/alternates' \
-'test_line_count = 1 super/.git/modules/sub/objects/info/alternates'
-
-cd "$base_dir"
-
-test_expect_success 'that reference gets used with add' \
-'cd super/sub &&
-echo "0 objects, 0 kilobytes" > expected &&
-git count-objects > current &&
-diff expected current'
-
-cd "$base_dir"
-
-test_expect_success 'cloning superproject' \
-'git clone super super-clone'
-
-cd "$base_dir"
-
-test_expect_success 'update with reference' \
-'cd super-clone && git submodule update --init --reference ../B'
-
-cd "$base_dir"
-
-test_expect_success 'after update: existence of info/alternates' \
-'test_line_count = 1 super-clone/.git/modules/sub/objects/info/alternates'
-
-cd "$base_dir"
-
-test_expect_success 'that reference gets used with update' \
-'cd super-clone/sub &&
-echo "0 objects, 0 kilobytes" > expected &&
-git count-objects > current &&
-diff expected current'
-
-cd "$base_dir"
+test_alternate_is_used () {
+ alternates_file="$1" &&
+ working_dir="$2" &&
+ test_line_count = 1 "$alternates_file" &&
+ echo "0 objects, 0 kilobytes" >expect &&
+ git -C "$working_dir" count-objects >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success 'preparing first repository' '
+ test_create_repo A &&
+ (
+ cd A &&
+ echo first >file1 &&
+ git add file1 &&
+ git commit -m A-initial
+ )
+'
+
+test_expect_success 'preparing second repository' '
+ git clone A B &&
+ (
+ cd B &&
+ echo second >file2 &&
+ git add file2 &&
+ git commit -m B-addition &&
+ git repack -a -d &&
+ git prune
+ )
+'
+
+test_expect_success 'preparing superproject' '
+ test_create_repo super &&
+ (
+ cd super &&
+ echo file >file &&
+ git add file &&
+ git commit -m B-super-initial
+ )
+'
+
+test_expect_success 'submodule add --reference uses alternates' '
+ (
+ cd super &&
+ git submodule add --reference ../B "file://$base_dir/A" sub &&
+ git commit -m B-super-added &&
+ git repack -ad
+ ) &&
+ test_alternate_is_used super/.git/modules/sub/objects/info/alternates super/sub
+'
+
+test_expect_success 'that reference gets used with add' '
+ (
+ cd super/sub &&
+ echo "0 objects, 0 kilobytes" >expected &&
+ git count-objects >current &&
+ diff expected current
+ )
+'
+
+# The tests up to this point, and repositories created by them
+# (A, B, super and super/sub), are about setting up the stage
+# for subsequent tests and meant to be kept throughout the
+# remainder of the test.
+# Tests from here on, if they create their own test repository,
+# are expected to clean after themselves.
+
+test_expect_success 'updating superproject keeps alternates' '
+ test_when_finished "rm -rf super-clone" &&
+ git clone super super-clone &&
+ git -C super-clone submodule update --init --reference ../B &&
+ test_alternate_is_used super-clone/.git/modules/sub/objects/info/alternates super-clone/sub
+'
+
+test_expect_success 'submodules use alternates when cloning a superproject' '
+ test_when_finished "rm -rf super-clone" &&
+ git clone --reference super --recursive super super-clone &&
+ (
+ cd super-clone &&
+ # test superproject has alternates setup correctly
+ test_alternate_is_used .git/objects/info/alternates . &&
+ # test submodule has correct setup
+ test_alternate_is_used .git/modules/sub/objects/info/alternates sub
+ )
+'
+
+test_expect_success 'missing submodule alternate fails clone and submodule update' '
+ test_when_finished "rm -rf super-clone" &&
+ git clone super super2 &&
+ test_must_fail git clone --recursive --reference super2 super2 super-clone &&
+ (
+ cd super-clone &&
+ # test superproject has alternates setup correctly
+ test_alternate_is_used .git/objects/info/alternates . &&
+ # update of the submodule succeeds
+ test_must_fail git submodule update --init &&
+ # and we have no alternates:
+ test_must_fail test_alternate_is_used .git/modules/sub/objects/info/alternates sub &&
+ test_must_fail test_path_is_file sub/file1
+ )
+'
+
+test_expect_success 'ignoring missing submodule alternates passes clone and submodule update' '
+ test_when_finished "rm -rf super-clone" &&
+ git clone --reference-if-able super2 --recursive super2 super-clone &&
+ (
+ cd super-clone &&
+ # test superproject has alternates setup correctly
+ test_alternate_is_used .git/objects/info/alternates . &&
+ # update of the submodule succeeds
+ git submodule update --init &&
+ # and we have no alternates:
+ test_must_fail test_alternate_is_used .git/modules/sub/objects/info/alternates sub &&
+ test_path_is_file sub/file1
+ )
+'
test_done
diff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh
index 400e2b143..47562ce46 100755
--- a/t/t7411-submodule-config.sh
+++ b/t/t7411-submodule-config.sh
@@ -89,7 +89,7 @@ test_expect_success 'error message contains blob reference' '
HEAD b \
HEAD submodule \
2>actual_err &&
- grep "submodule-blob $sha1:.gitmodules" actual_err >/dev/null
+ test_i18ngrep "submodule-blob $sha1:.gitmodules" actual_err >/dev/null
)
'
diff --git a/t/t7508-status.sh b/t/t7508-status.sh
index a42aef831..fb00e6d9b 100755
--- a/t/t7508-status.sh
+++ b/t/t7508-status.sh
@@ -1377,7 +1377,7 @@ EOF
git config --add -f .gitmodules submodule.subname.ignore all &&
git config --add -f .gitmodules submodule.subname.path sm &&
git status > output &&
- test_cmp expect output &&
+ test_i18ncmp expect output &&
git config -f .gitmodules --remove-section submodule.subname
'
@@ -1387,7 +1387,7 @@ test_expect_success '.git/config ignore=all suppresses unstaged submodule summar
git config --add submodule.subname.ignore all &&
git config --add submodule.subname.path sm &&
git status > output &&
- test_cmp expect output &&
+ test_i18ncmp expect output &&
git config --remove-section submodule.subname &&
git config -f .gitmodules --remove-section submodule.subname
'
diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh
index 4177a8609..6e839f548 100755
--- a/t/t7510-signed-commit.sh
+++ b/t/t7510-signed-commit.sh
@@ -210,4 +210,11 @@ test_expect_success GPG 'show lack of signature with custom format' '
test_cmp expect actual
'
+test_expect_success GPG 'log.showsignature behaves like --show-signature' '
+ test_config log.showsignature true &&
+ git show initial >actual &&
+ grep "gpg: Signature made" actual &&
+ grep "gpg: Good signature" actual
+'
+
test_done
diff --git a/t/t7607-merge-overwrite.sh b/t/t7607-merge-overwrite.sh
index 1c5934994..9444d6a9b 100755
--- a/t/t7607-merge-overwrite.sh
+++ b/t/t7607-merge-overwrite.sh
@@ -125,7 +125,7 @@ test_expect_success 'will not overwrite untracked file in leading path' '
cp important sub &&
cp important sub2 &&
test_must_fail git merge sub 2>out &&
- test_cmp out expect &&
+ test_i18ncmp out expect &&
test_path_is_missing .git/MERGE_HEAD &&
test_cmp important sub &&
test_cmp important sub2 &&
diff --git a/t/t7701-repack-unpack-unreachable.sh b/t/t7701-repack-unpack-unreachable.sh
index b66e38386..987573c41 100755
--- a/t/t7701-repack-unpack-unreachable.sh
+++ b/t/t7701-repack-unpack-unreachable.sh
@@ -122,4 +122,32 @@ test_expect_success 'keep packed objects found only in index' '
git cat-file blob :file
'
+test_expect_success 'repack -k keeps unreachable packed objects' '
+ # create packed-but-unreachable object
+ sha1=$(echo unreachable-packed | git hash-object -w --stdin) &&
+ pack=$(echo $sha1 | git pack-objects .git/objects/pack/pack) &&
+ git prune-packed &&
+
+ # -k should keep it
+ git repack -adk &&
+ git cat-file -p $sha1 &&
+
+ # and double check that without -k it would have been removed
+ git repack -ad &&
+ test_must_fail git cat-file -p $sha1
+'
+
+test_expect_success 'repack -k packs unreachable loose objects' '
+ # create loose unreachable object
+ sha1=$(echo would-be-deleted-loose | git hash-object -w --stdin) &&
+ objpath=.git/objects/$(echo $sha1 | sed "s,..,&/,") &&
+ test_path_is_file $objpath &&
+
+ # and confirm that the loose object goes away, but we can
+ # still access it (ergo, it is packed)
+ git repack -adk &&
+ test_path_is_missing $objpath &&
+ git cat-file -p $sha1
+'
+
test_done
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index cf3f9ec63..de2405ccb 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -581,7 +581,7 @@ test_expect_success 'log grep (9)' '
'
test_expect_success 'log grep (9)' '
- git log -g --grep-reflog="commit: third" --author="non-existant" --pretty=tformat:%s >actual &&
+ git log -g --grep-reflog="commit: third" --author="non-existent" --pretty=tformat:%s >actual &&
: >expect &&
test_cmp expect actual
'
diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh
index ff09aced6..ab79de954 100755
--- a/t/t8002-blame.sh
+++ b/t/t8002-blame.sh
@@ -6,6 +6,11 @@ test_description='git blame'
PROG='git blame -c'
. "$TEST_DIRECTORY"/annotate-tests.sh
+test_expect_success 'blame untracked file in empty repo' '
+ >untracked &&
+ test_must_fail git blame untracked
+'
+
PROG='git blame -c -e'
test_expect_success 'blame --show-email' '
check_count \
diff --git a/t/t8010-cat-file-filters.sh b/t/t8010-cat-file-filters.sh
new file mode 100755
index 000000000..d8242e467
--- /dev/null
+++ b/t/t8010-cat-file-filters.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+
+test_description='git cat-file filters support'
+. ./test-lib.sh
+
+test_expect_success 'setup ' '
+ echo "*.txt eol=crlf diff=txt" >.gitattributes &&
+ echo "hello" | append_cr >world.txt &&
+ git add .gitattributes world.txt &&
+ test_tick &&
+ git commit -m "Initial commit"
+'
+
+has_cr () {
+ tr '\015' Q <"$1" | grep Q >/dev/null
+}
+
+test_expect_success 'no filters with `git show`' '
+ git show HEAD:world.txt >actual &&
+ ! has_cr actual
+
+'
+
+test_expect_success 'no filters with cat-file' '
+ git cat-file blob HEAD:world.txt >actual &&
+ ! has_cr actual
+'
+
+test_expect_success 'cat-file --filters converts to worktree version' '
+ git cat-file --filters HEAD:world.txt >actual &&
+ has_cr actual
+'
+
+test_expect_success 'cat-file --filters --path=<path> works' '
+ sha1=$(git rev-parse -q --verify HEAD:world.txt) &&
+ git cat-file --filters --path=world.txt $sha1 >actual &&
+ has_cr actual
+'
+
+test_expect_success 'cat-file --textconv --path=<path> works' '
+ sha1=$(git rev-parse -q --verify HEAD:world.txt) &&
+ test_config diff.txt.textconv "tr A-Za-z N-ZA-Mn-za-m <" &&
+ git cat-file --textconv --path=hello.txt $sha1 >rot13 &&
+ test uryyb = "$(cat rot13 | remove_cr)"
+'
+
+test_expect_success '--path=<path> complains without --textconv/--filters' '
+ sha1=$(git rev-parse -q --verify HEAD:world.txt) &&
+ test_must_fail git cat-file --path=hello.txt blob $sha1 >actual 2>err &&
+ test ! -s actual &&
+ grep "path.*needs.*filters" err
+'
+
+test_expect_success 'cat-file --textconv --batch works' '
+ sha1=$(git rev-parse -q --verify HEAD:world.txt) &&
+ test_config diff.txt.textconv "tr A-Za-z N-ZA-Mn-za-m <" &&
+ printf "%s hello.txt\n%s hello\n" $sha1 $sha1 |
+ git cat-file --textconv --batch >actual &&
+ printf "%s blob 6\nuryyb\r\n\n%s blob 6\nhello\n\n" \
+ $sha1 $sha1 >expect &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t9003-help-autocorrect.sh b/t/t9003-help-autocorrect.sh
index dfe95c923..b1c7919c4 100755
--- a/t/t9003-help-autocorrect.sh
+++ b/t/t9003-help-autocorrect.sh
@@ -31,10 +31,10 @@ test_expect_success 'autocorrect showing candidates' '
git config help.autocorrect 0 &&
test_must_fail git lfg 2>actual &&
- sed -e "1,/^Did you mean this/d" actual | grep lgf &&
+ grep "^ lgf" actual &&
test_must_fail git distimdist 2>actual &&
- sed -e "1,/^Did you mean this/d" actual | grep distimdistim
+ grep "^ distimdistim" actual
'
test_expect_success 'autocorrect running commands' '
diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh
index 28082b134..92a3aa806 100755
--- a/t/t9100-git-svn-basic.sh
+++ b/t/t9100-git-svn-basic.sh
@@ -8,8 +8,6 @@ GIT_SVN_LC_ALL=${LC_ALL:-$LANG}
. ./lib-git-svn.sh
-say 'define NO_SVN_TESTS to skip git svn tests'
-
case "$GIT_SVN_LC_ALL" in
*.UTF-8)
test_set_prereq UTF8
@@ -19,6 +17,27 @@ case "$GIT_SVN_LC_ALL" in
;;
esac
+deepdir=nothing-above
+ceiling=$PWD
+
+test_expect_success 'git svn --version works anywhere' '
+ mkdir -p "$deepdir" && (
+ GIT_CEILING_DIRECTORIES="$ceiling" &&
+ export GIT_CEILING_DIRECTORIES &&
+ cd "$deepdir" &&
+ git svn --version
+ )
+'
+
+test_expect_success 'git svn help works anywhere' '
+ mkdir -p "$deepdir" && (
+ GIT_CEILING_DIRECTORIES="$ceiling" &&
+ export GIT_CEILING_DIRECTORIES &&
+ cd "$deepdir" &&
+ git svn help
+ )
+'
+
test_expect_success \
'initialize git svn' '
mkdir import &&
diff --git a/t/t9115-git-svn-dcommit-funky-renames.sh b/t/t9115-git-svn-dcommit-funky-renames.sh
index a87d3d3fc..64bb49583 100755
--- a/t/t9115-git-svn-dcommit-funky-renames.sh
+++ b/t/t9115-git-svn-dcommit-funky-renames.sh
@@ -8,9 +8,10 @@ test_description='git svn dcommit can commit renames of files with ugly names'
. ./lib-git-svn.sh
test_expect_success 'load repository with strange names' '
- svnadmin load -q "$rawsvnrepo" < "$TEST_DIRECTORY"/t9115/funky-names.dump &&
- start_httpd gtk+
- '
+ svnadmin load -q "$rawsvnrepo" <"$TEST_DIRECTORY"/t9115/funky-names.dump
+'
+
+maybe_start_httpd gtk+
test_expect_success 'init and fetch repository' '
git svn init "$svnrepo" &&
diff --git a/t/t9118-git-svn-funky-branch-names.sh b/t/t9118-git-svn-funky-branch-names.sh
index ecb1fed14..41a026637 100755
--- a/t/t9118-git-svn-funky-branch-names.sh
+++ b/t/t9118-git-svn-funky-branch-names.sh
@@ -32,7 +32,7 @@ test_expect_success 'setup svnrepo' '
"$svnrepo/pr ject/branches/trailing_dotlock.lock" &&
svn_cmd cp -m "reflog" "$svnrepo/pr ject/trunk" \
"$svnrepo/pr ject/branches/not-a@{0}reflog@" &&
- start_httpd
+ maybe_start_httpd
'
# SVN 1.7 will truncate "not-a%40{0]" to just "not-a".
diff --git a/t/t9120-git-svn-clone-with-percent-escapes.sh b/t/t9120-git-svn-clone-with-percent-escapes.sh
index 59465b147..b28a1741e 100755
--- a/t/t9120-git-svn-clone-with-percent-escapes.sh
+++ b/t/t9120-git-svn-clone-with-percent-escapes.sh
@@ -15,7 +15,7 @@ test_expect_success 'setup svnrepo' '
svn_cmd cp -m "tag" "$svnrepo/pr ject/trunk" \
"$svnrepo/pr ject/tags/v1" &&
rm -rf project &&
- start_httpd
+ maybe_start_httpd
'
test_expect_success 'test clone with percent escapes' '
diff --git a/t/t9142-git-svn-shallow-clone.sh b/t/t9142-git-svn-shallow-clone.sh
index e21ee5f66..9ee23be64 100755
--- a/t/t9142-git-svn-shallow-clone.sh
+++ b/t/t9142-git-svn-shallow-clone.sh
@@ -18,7 +18,7 @@ test_expect_success 'setup test repository' '
svn_cmd add foo &&
svn_cmd commit -m "add foo"
) &&
- start_httpd
+ maybe_start_httpd
'
test_expect_success 'clone trunk with "-r HEAD"' '
diff --git a/t/t9158-git-svn-mergeinfo.sh b/t/t9158-git-svn-mergeinfo.sh
index 13f78f268..a875b4510 100755
--- a/t/t9158-git-svn-mergeinfo.sh
+++ b/t/t9158-git-svn-mergeinfo.sh
@@ -7,8 +7,6 @@ test_description='git svn mergeinfo propagation'
. ./lib-git-svn.sh
-say 'define NO_SVN_TESTS to skip git svn tests'
-
test_expect_success 'initialize source svn repo' '
svn_cmd mkdir -m x "$svnrepo"/trunk &&
svn_cmd co "$svnrepo"/trunk "$SVN_TREE" &&
diff --git a/t/t9160-git-svn-preserve-empty-dirs.sh b/t/t9160-git-svn-preserve-empty-dirs.sh
index b4a443460..0ede3cfed 100755
--- a/t/t9160-git-svn-preserve-empty-dirs.sh
+++ b/t/t9160-git-svn-preserve-empty-dirs.sh
@@ -11,7 +11,6 @@ local Git repository with placeholder files.'
. ./lib-git-svn.sh
-say 'define NO_SVN_TESTS to skip git svn tests'
GIT_REPO=git-svn-repo
test_expect_success 'initialize source svn repo containing empty dirs' '
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 4bca35c25..2e0ba3ebd 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -7,23 +7,6 @@ test_description='test git fast-import utility'
. ./test-lib.sh
. "$TEST_DIRECTORY"/diff-lib.sh ;# test-lib chdir's into trash
-# Print $1 bytes from stdin to stdout.
-#
-# This could be written as "head -c $1", but IRIX "head" does not
-# support the -c option.
-head_c () {
- perl -e '
- my $len = $ARGV[1];
- while ($len > 0) {
- my $s;
- my $nread = sysread(STDIN, $s, $len);
- die "cannot read: $!" unless defined($nread);
- print $s;
- $len -= $nread;
- }
- ' - "$1"
-}
-
verify_packs () {
for p in .git/objects/pack/*.pack
do
@@ -52,6 +35,7 @@ echo "$@"'
###
test_expect_success 'empty stream succeeds' '
+ git config fastimport.unpackLimit 0 &&
git fast-import </dev/null
'
@@ -2480,7 +2464,7 @@ test_expect_success PIPE 'R: copy using cat-file' '
read blob_id type size <&3 &&
echo "$blob_id $type $size" >response &&
- head_c $size >blob <&3 &&
+ test_copy_bytes $size >blob <&3 &&
read newline <&3 &&
cat <<-EOF &&
@@ -2523,7 +2507,7 @@ test_expect_success PIPE 'R: print blob mid-commit' '
EOF
read blob_id type size <&3 &&
- head_c $size >actual <&3 &&
+ test_copy_bytes $size >actual <&3 &&
read newline <&3 &&
echo
@@ -2558,7 +2542,7 @@ test_expect_success PIPE 'R: print staged blob within commit' '
echo "cat-blob $to_get" &&
read blob_id type size <&3 &&
- head_c $size >actual <&3 &&
+ test_copy_bytes $size >actual <&3 &&
read newline <&3 &&
echo deleteall
@@ -2690,6 +2674,7 @@ test_expect_success 'R: blob bigger than threshold' '
echo >>input &&
test_create_repo R &&
+ git --git-dir=R/.git config fastimport.unpackLimit 0 &&
git --git-dir=R/.git fast-import --big-file-threshold=1 <input
'
diff --git a/t/t9302-fast-import-unpack-limit.sh b/t/t9302-fast-import-unpack-limit.sh
new file mode 100755
index 000000000..a04de1467
--- /dev/null
+++ b/t/t9302-fast-import-unpack-limit.sh
@@ -0,0 +1,105 @@
+#!/bin/sh
+test_description='test git fast-import unpack limit'
+. ./test-lib.sh
+
+test_expect_success 'create loose objects on import' '
+ test_tick &&
+ cat >input <<-INPUT_END &&
+ commit refs/heads/master
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ initial
+ COMMIT
+
+ done
+ INPUT_END
+
+ git -c fastimport.unpackLimit=2 fast-import --done <input &&
+ git fsck --no-progress &&
+ test $(find .git/objects/?? -type f | wc -l) -eq 2 &&
+ test $(find .git/objects/pack -type f | wc -l) -eq 0
+'
+
+test_expect_success 'bigger packs are preserved' '
+ test_tick &&
+ cat >input <<-INPUT_END &&
+ commit refs/heads/master
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ incremental should create a pack
+ COMMIT
+ from refs/heads/master^0
+
+ commit refs/heads/branch
+ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+ data <<COMMIT
+ branch
+ COMMIT
+
+ done
+ INPUT_END
+
+ git -c fastimport.unpackLimit=2 fast-import --done <input &&
+ git fsck --no-progress &&
+ test $(find .git/objects/?? -type f | wc -l) -eq 2 &&
+ test $(find .git/objects/pack -type f | wc -l) -eq 2
+'
+
+test_expect_success 'lookups after checkpoint works' '
+ hello_id=$(echo hello | git hash-object --stdin -t blob) &&
+ id="$GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE" &&
+ before=$(git rev-parse refs/heads/master^0) &&
+ (
+ cat <<-INPUT_END &&
+ blob
+ mark :1
+ data 6
+ hello
+
+ commit refs/heads/master
+ mark :2
+ committer $id
+ data <<COMMIT
+ checkpoint after this
+ COMMIT
+ from refs/heads/master^0
+ M 100644 :1 hello
+
+ # pre-checkpoint
+ cat-blob :1
+ cat-blob $hello_id
+ checkpoint
+ # post-checkpoint
+ cat-blob :1
+ cat-blob $hello_id
+ INPUT_END
+
+ n=0 &&
+ from=$before &&
+ while test x"$from" = x"$before"
+ do
+ if test $n -gt 30
+ then
+ echo >&2 "checkpoint did not update branch"
+ exit 1
+ else
+ n=$(($n + 1))
+ fi &&
+ sleep 1 &&
+ from=$(git rev-parse refs/heads/master^0)
+ done &&
+ cat <<-INPUT_END &&
+ commit refs/heads/master
+ committer $id
+ data <<COMMIT
+ make sure from "unpacked sha1 reference" works, too
+ COMMIT
+ from $from
+ INPUT_END
+ echo done
+ ) | git -c fastimport.unpackLimit=100 fast-import --done &&
+ test $(find .git/objects/?? -type f | wc -l) -eq 6 &&
+ test $(find .git/objects/pack -type f | wc -l) -eq 2
+'
+
+test_done
diff --git a/t/t9401-git-cvsserver-crlf.sh b/t/t9401-git-cvsserver-crlf.sh
index f324b9f01..84787eee9 100755
--- a/t/t9401-git-cvsserver-crlf.sh
+++ b/t/t9401-git-cvsserver-crlf.sh
@@ -154,7 +154,7 @@ test_expect_success 'adding files' '
echo "more text" > src.c &&
GIT_CONFIG="$git_config" cvs -Q add src.c >cvs.log 2>&1 &&
marked_as . src.c "" &&
- echo "psuedo-binary" > temp.bin
+ echo "pseudo-binary" > temp.bin
) &&
GIT_CONFIG="$git_config" cvs -Q add subdir/temp.bin >cvs.log 2>&1 &&
marked_as subdir temp.bin "-kb" &&
diff --git a/t/t9801-git-p4-branch.sh b/t/t9801-git-p4-branch.sh
index 0aafd0333..6a86d6996 100755
--- a/t/t9801-git-p4-branch.sh
+++ b/t/t9801-git-p4-branch.sh
@@ -300,7 +300,7 @@ test_expect_success 'git p4 clone complex branches' '
test_path_is_file file2 &&
test_path_is_file file3 &&
! grep update file2 &&
- test_path_is_missing .git/git-p4-tmp
+ test_must_fail git show-ref --verify refs/git-p4-tmp
)
'
@@ -352,7 +352,7 @@ test_expect_success 'git p4 sync changes to two branches in the same changelist'
test_path_is_file file2 &&
test_path_is_file file3 &&
! grep update file2 &&
- test_path_is_missing .git/git-p4-tmp
+ test_must_fail git show-ref --verify refs/git-p4-tmp
)
'
diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh
index 0db4469c8..97c9b32c2 100755
--- a/t/t9903-bash-prompt.sh
+++ b/t/t9903-bash-prompt.sh
@@ -177,7 +177,7 @@ test_expect_success 'prompt - interactive rebase' '
git checkout b1 &&
test_when_finished "git checkout master" &&
git rebase -i HEAD^ &&
- test_when_finished "git rebase --abort"
+ test_when_finished "git rebase --abort" &&
__git_ps1 >"$actual" &&
test_cmp expected "$actual"
'
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index ca40a1289..fdaeb3a96 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -81,6 +81,10 @@ test_decode_color () {
'
}
+lf_to_nul () {
+ perl -pe 'y/\012/\000/'
+}
+
nul_to_q () {
perl -pe 'y/\000/Q/'
}
@@ -976,3 +980,17 @@ test_match_signal () {
fi
return 1
}
+
+# Read up to "$1" bytes (or to EOF) from stdin and write them to stdout.
+test_copy_bytes () {
+ perl -e '
+ my $len = $ARGV[1];
+ while ($len > 0) {
+ my $s;
+ my $nread = sysread(STDIN, $s, $len);
+ die "cannot read: $!" unless defined($nread);
+ print $s;
+ $len -= $nread;
+ }
+ ' - "$1"
+}
diff --git a/t/test-lib.sh b/t/test-lib.sh
index d731d66e3..11562bde1 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -89,6 +89,7 @@ unset VISUAL EMAIL LANGUAGE COLUMNS $("$PERL_PATH" -e '
UNZIP
PERF_
CURL_VERBOSE
+ TRACE_CURL
));
my @vars = grep(/^GIT_/ && !/^GIT_($ok)/o, @env);
print join("\n", @vars);
@@ -687,9 +688,9 @@ test_done () {
test_results_dir="$TEST_OUTPUT_DIRECTORY/test-results"
mkdir -p "$test_results_dir"
base=${0##*/}
- test_results_path="$test_results_dir/${base%.sh}-$$.counts"
+ test_results_path="$test_results_dir/${base%.sh}.counts"
- cat >>"$test_results_path" <<-EOF
+ cat >"$test_results_path" <<-EOF
total $test_count
success $test_success
fixed $test_fixed
@@ -1072,6 +1073,10 @@ test_lazy_prereq NOT_ROOT '
test "$uid" != 0
'
+test_lazy_prereq JGIT '
+ type jgit
+'
+
# SANITY is about "can you correctly predict what the filesystem would
# do by only looking at the permission bits of the files and
# directories?" A typical example of !SANITY is running the test