summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/README3
-rw-r--r--t/helper/test-bloom.c2
-rw-r--r--t/helper/test-chmtime.c4
-rw-r--r--t/lib-rebase.sh11
-rwxr-xr-xt/perf/p5303-many-packs.sh36
-rwxr-xr-xt/perf/p7519-fsmonitor.sh4
-rw-r--r--t/perf/perf-lib.sh31
-rwxr-xr-xt/t0003-attributes.sh36
-rwxr-xr-xt/t0008-ignores.sh34
-rwxr-xr-xt/t0021-conversion.sh24
-rwxr-xr-xt/t2021-checkout-overwrite.sh12
-rwxr-xr-xt/t3060-ls-files-with-tree.sh41
-rwxr-xr-xt/t3400-rebase.sh16
-rwxr-xr-xt/t3415-rebase-autosquash.sh30
-rwxr-xr-xt/t3437-rebase-fixup-options.sh211
-rw-r--r--t/t3437/expected-combined-message21
-rw-r--r--t/t3437/expected-squash-message51
-rwxr-xr-xt/t3800-mktag.sh2
-rwxr-xr-xt/t3900-i18n-commit.sh4
-rwxr-xr-xt/t3905-stash-include-untracked.sh108
-rwxr-xr-xt/t4053-diff-no-index.sh60
-rwxr-xr-xt/t4203-mailmap.sh31
-rwxr-xr-xt/t4205-log-pretty-formats.sh35
-rwxr-xr-xt/t5001-archive-attr.sh14
-rwxr-xr-xt/t5300-pack-object.sh141
-rwxr-xr-xt/t5318-commit-graph.sh2
-rwxr-xr-xt/t5324-split-commit-graph.sh4
-rwxr-xr-xt/t5505-remote.sh3
-rwxr-xr-xt/t5606-clone-options.sh10
-rwxr-xr-xt/t5612-clone-refspec.sh1
-rwxr-xr-xt/t6030-bisect-porcelain.sh12
-rwxr-xr-xt/t6114-keep-packs.sh69
-rwxr-xr-xt/t6600-test-reach.sh2
-rwxr-xr-xt/t7003-filter-branch.sh31
-rwxr-xr-xt/t7007-show.sh39
-rwxr-xr-xt/t7500-commit-template-squash-signoff.sh159
-rwxr-xr-xt/t7703-repack-geometric.sh183
-rwxr-xr-xt/t7810-grep.sh3
-rwxr-xr-xt/t9001-send-email.sh32
-rwxr-xr-xt/t9801-git-p4-branch.sh38
40 files changed, 1464 insertions, 86 deletions
diff --git a/t/README b/t/README
index 593d4a4e27..fd9375b146 100644
--- a/t/README
+++ b/t/README
@@ -387,9 +387,6 @@ GIT_TEST_COMMIT_GRAPH=<boolean>, when true, forces the commit-graph to
be written after every 'git commit' command, and overrides the
'core.commitGraph' setting to true.
-GIT_TEST_COMMIT_GRAPH_NO_GDAT=<boolean>, when true, forces the
-commit-graph to be written without generation data chunk.
-
GIT_TEST_COMMIT_GRAPH_CHANGED_PATHS=<boolean>, when true, forces
commit-graph write to compute and write changed path Bloom filters for
every 'git commit-graph write', as if the `--changed-paths` option was
diff --git a/t/helper/test-bloom.c b/t/helper/test-bloom.c
index 46e97b04eb..2a1ae3dae6 100644
--- a/t/helper/test-bloom.c
+++ b/t/helper/test-bloom.c
@@ -69,7 +69,7 @@ int cmd__bloom(int argc, const char **argv)
struct bloom_filter filter;
int i = 2;
filter.len = (settings.bits_per_entry + BITS_PER_WORD - 1) / BITS_PER_WORD;
- filter.data = xcalloc(filter.len, sizeof(unsigned char));
+ CALLOC_ARRAY(filter.data, filter.len);
if (argc - 1 < i)
usage(bloom_usage);
diff --git a/t/helper/test-chmtime.c b/t/helper/test-chmtime.c
index aa22af48c2..524b55ca49 100644
--- a/t/helper/test-chmtime.c
+++ b/t/helper/test-chmtime.c
@@ -109,9 +109,9 @@ int cmd__chmtime(int argc, const char **argv)
uintmax_t mtime;
if (stat(argv[i], &sb) < 0) {
- fprintf(stderr, "Failed to stat %s: %s\n",
+ fprintf(stderr, "Failed to stat %s: %s. Skipping\n",
argv[i], strerror(errno));
- return 1;
+ continue;
}
#ifdef GIT_WINDOWS_NATIVE
diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh
index 172d7459ff..dc75b83451 100644
--- a/t/lib-rebase.sh
+++ b/t/lib-rebase.sh
@@ -4,6 +4,7 @@
#
# - override the commit message with $FAKE_COMMIT_MESSAGE
# - amend the commit message with $FAKE_COMMIT_AMEND
+# - copy the original commit message to a file with $FAKE_MESSAGE_COPY
# - check that non-commit messages have a certain line count with $EXPECT_COUNT
# - check the commit count in the commit message header with $EXPECT_HEADER_COUNT
# - rewrite a rebase -i script as directed by $FAKE_LINES.
@@ -14,10 +15,11 @@
# specified line.
#
# "<cmd> <lineno>" -- add a line with the specified command
-# ("pick", "squash", "fixup", "edit", "reword" or "drop") and the
-# SHA1 taken from the specified line.
+# ("pick", "squash", "fixup"|"fixup_-C"|"fixup_-c", "edit", "reword" or "drop")
+# and the SHA1 taken from the specified line.
#
-# "exec_cmd_with_args" -- add an "exec cmd with args" line.
+# "_" -- add a space, like "fixup_-C" implies "fixup -C" and
+# "exec_cmd_with_args" add an "exec cmd with args" line.
#
# "#" -- Add a comment line.
#
@@ -32,6 +34,7 @@ set_fake_editor () {
exit
test -z "$FAKE_COMMIT_MESSAGE" || echo "$FAKE_COMMIT_MESSAGE" > "$1"
test -z "$FAKE_COMMIT_AMEND" || echo "$FAKE_COMMIT_AMEND" >> "$1"
+ test -z "$FAKE_MESSAGE_COPY" || cat "$1" >"$FAKE_MESSAGE_COPY"
exit
;;
esac
@@ -50,6 +53,8 @@ set_fake_editor () {
action="$line";;
exec_*|x_*|break|b)
echo "$line" | sed 's/_/ /g' >> "$1";;
+ merge_*|fixup_*)
+ action=$(echo "$line" | sed 's/_/ /g');;
"#")
echo '# comment' >> "$1";;
">")
diff --git a/t/perf/p5303-many-packs.sh b/t/perf/p5303-many-packs.sh
index ce0c42cc9f..35c0cbdf49 100755
--- a/t/perf/p5303-many-packs.sh
+++ b/t/perf/p5303-many-packs.sh
@@ -28,11 +28,18 @@ repack_into_n () {
push @commits, $_ if $. % 5 == 1;
}
print reverse @commits;
- ' "$1" >pushes
+ ' "$1" >pushes &&
# create base packfile
- head -n 1 pushes |
- git pack-objects --delta-base-offset --revs staging/pack
+ base_pack=$(
+ head -n 1 pushes |
+ git pack-objects --delta-base-offset --revs staging/pack
+ ) &&
+ test_export base_pack &&
+
+ # create an empty packfile
+ empty_pack=$(git pack-objects staging/pack </dev/null) &&
+ test_export empty_pack &&
# and then incrementals between each pair of commits
last= &&
@@ -49,6 +56,12 @@ repack_into_n () {
last=$rev
done <pushes &&
+ (
+ find staging -type f -name 'pack-*.pack' |
+ xargs -n 1 basename | grep -v "$base_pack" &&
+ printf "^pack-%s.pack\n" $base_pack
+ ) >stdin.packs
+
# and install the whole thing
rm -f .git/objects/pack/* &&
mv staging/* .git/objects/pack/
@@ -91,6 +104,23 @@ do
--reflog --indexed-objects --delta-base-offset \
--stdout </dev/null >/dev/null
'
+
+ test_perf "repack with kept ($nr_packs)" '
+ git pack-objects --keep-true-parents \
+ --keep-pack=pack-$empty_pack.pack \
+ --honor-pack-keep --non-empty --all \
+ --reflog --indexed-objects --delta-base-offset \
+ --stdout </dev/null >/dev/null
+ '
+
+ test_perf "repack with --stdin-packs ($nr_packs)" '
+ git pack-objects \
+ --keep-true-parents \
+ --stdin-packs \
+ --non-empty \
+ --delta-base-offset \
+ --stdout <stdin.packs >/dev/null
+ '
done
# Measure pack loading with 10,000 packs.
diff --git a/t/perf/p7519-fsmonitor.sh b/t/perf/p7519-fsmonitor.sh
index b657564aed..5eb5044a10 100755
--- a/t/perf/p7519-fsmonitor.sh
+++ b/t/perf/p7519-fsmonitor.sh
@@ -216,6 +216,10 @@ test_fsmonitor_suite() {
git diff
'
+ test_perf_w_drop_caches "diff HEAD ($DESC)" '
+ git diff HEAD
+ '
+
test_perf_w_drop_caches "diff -- 0_files ($DESC)" '
git diff -- 1_file
'
diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh
index e385c6896f..601d9f67dd 100644
--- a/t/perf/perf-lib.sh
+++ b/t/perf/perf-lib.sh
@@ -70,6 +70,19 @@ test_perf_do_repo_symlink_config_ () {
test_have_prereq SYMLINKS || git config core.symlinks false
}
+test_perf_copy_repo_contents () {
+ for stuff in "$1"/*
+ do
+ case "$stuff" in
+ */objects|*/hooks|*/config|*/commondir|*/gitdir|*/worktrees)
+ ;;
+ *)
+ cp -R "$stuff" "$repo/.git/" || exit 1
+ ;;
+ esac
+ done
+}
+
test_perf_create_repo_from () {
test "$#" = 2 ||
BUG "not 2 parameters to test-create-repo"
@@ -77,20 +90,20 @@ test_perf_create_repo_from () {
source="$2"
source_git="$("$MODERN_GIT" -C "$source" rev-parse --git-dir)"
objects_dir="$("$MODERN_GIT" -C "$source" rev-parse --git-path objects)"
+ common_dir="$("$MODERN_GIT" -C "$source" rev-parse --git-common-dir)"
mkdir -p "$repo/.git"
(
cd "$source" &&
{ cp -Rl "$objects_dir" "$repo/.git/" 2>/dev/null ||
cp -R "$objects_dir" "$repo/.git/"; } &&
- for stuff in "$source_git"/*; do
- case "$stuff" in
- */objects|*/hooks|*/config|*/commondir)
- ;;
- *)
- cp -R "$stuff" "$repo/.git/" || exit 1
- ;;
- esac
- done
+
+ # common_dir must come first here, since we want source_git to
+ # take precedence and overwrite any overlapping files
+ test_perf_copy_repo_contents "$common_dir"
+ if test "$source_git" != "$common_dir"
+ then
+ test_perf_copy_repo_contents "$source_git"
+ fi
) &&
(
cd "$repo" &&
diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh
index b660593c20..1e4c672b84 100755
--- a/t/t0003-attributes.sh
+++ b/t/t0003-attributes.sh
@@ -4,12 +4,16 @@ test_description=gitattributes
. ./test-lib.sh
-attr_check () {
+attr_check_basic () {
path="$1" expect="$2" git_opts="$3" &&
git $git_opts check-attr test -- "$path" >actual 2>err &&
echo "$path: test: $expect" >expect &&
- test_cmp expect actual &&
+ test_cmp expect actual
+}
+
+attr_check () {
+ attr_check_basic "$@" &&
test_must_be_empty err
}
@@ -331,7 +335,6 @@ test_expect_success 'binary macro expanded by -a' '
test_cmp expect actual
'
-
test_expect_success 'query binary macro directly' '
echo "file binary" >.gitattributes &&
echo file: binary: set >expect &&
@@ -339,4 +342,31 @@ test_expect_success 'query binary macro directly' '
test_cmp expect actual
'
+test_expect_success SYMLINKS 'set up symlink tests' '
+ echo "* test" >attr &&
+ rm -f .gitattributes
+'
+
+test_expect_success SYMLINKS 'symlinks respected in core.attributesFile' '
+ test_when_finished "rm symlink" &&
+ ln -s attr symlink &&
+ test_config core.attributesFile "$(pwd)/symlink" &&
+ attr_check file set
+'
+
+test_expect_success SYMLINKS 'symlinks respected in info/attributes' '
+ test_when_finished "rm .git/info/attributes" &&
+ ln -s ../../attr .git/info/attributes &&
+ attr_check file set
+'
+
+test_expect_success SYMLINKS 'symlinks not respected in-tree' '
+ test_when_finished "rm -rf .gitattributes subdir" &&
+ ln -s attr .gitattributes &&
+ mkdir subdir &&
+ ln -s ../attr subdir/.gitattributes &&
+ attr_check_basic subdir/file unspecified &&
+ test_i18ngrep "unable to access.*gitattributes" err
+'
+
test_done
diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh
index f7abde62f6..a594b4aa7d 100755
--- a/t/t0008-ignores.sh
+++ b/t/t0008-ignores.sh
@@ -865,4 +865,38 @@ test_expect_success 'info/exclude trumps core.excludesfile' '
test_cmp expect actual
'
+test_expect_success SYMLINKS 'set up ignore file for symlink tests' '
+ echo "*" >ignore &&
+ rm -f .gitignore .git/info/exclude
+'
+
+test_expect_success SYMLINKS 'symlinks respected in core.excludesFile' '
+ test_when_finished "rm symlink" &&
+ ln -s ignore symlink &&
+ test_config core.excludesFile "$(pwd)/symlink" &&
+ echo file >expect &&
+ git check-ignore file >actual 2>err &&
+ test_cmp expect actual &&
+ test_must_be_empty err
+'
+
+test_expect_success SYMLINKS 'symlinks respected in info/exclude' '
+ test_when_finished "rm .git/info/exclude" &&
+ ln -s ../../ignore .git/info/exclude &&
+ echo file >expect &&
+ git check-ignore file >actual 2>err &&
+ test_cmp expect actual &&
+ test_must_be_empty err
+'
+
+test_expect_success SYMLINKS 'symlinks not respected in-tree' '
+ test_when_finished "rm .gitignore" &&
+ ln -s ignore .gitignore &&
+ mkdir subdir &&
+ ln -s ignore subdir/.gitignore &&
+ test_must_fail git check-ignore subdir/file >actual 2>err &&
+ test_must_be_empty actual &&
+ test_i18ngrep "unable to access.*gitignore" err
+'
+
test_done
diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh
index a9e10a0c21..b5749f327d 100755
--- a/t/t0021-conversion.sh
+++ b/t/t0021-conversion.sh
@@ -257,6 +257,30 @@ test_expect_success 'required filter clean failure' '
test_must_fail git add test.fc
'
+test_expect_success 'required filter with absent clean field' '
+ test_config filter.absentclean.smudge cat &&
+ test_config filter.absentclean.required true &&
+
+ echo "*.ac filter=absentclean" >.gitattributes &&
+
+ echo test >test.ac &&
+ test_must_fail git add test.ac 2>stderr &&
+ test_i18ngrep "fatal: test.ac: clean filter .absentclean. failed" stderr
+'
+
+test_expect_success 'required filter with absent smudge field' '
+ test_config filter.absentsmudge.clean cat &&
+ test_config filter.absentsmudge.required true &&
+
+ echo "*.as filter=absentsmudge" >.gitattributes &&
+
+ echo test >test.as &&
+ git add test.as &&
+ rm -f test.as &&
+ test_must_fail git checkout -- test.as 2>stderr &&
+ test_i18ngrep "fatal: test.as: smudge filter absentsmudge failed" stderr
+'
+
test_expect_success 'filtering large input to small output should use little memory' '
test_config filter.devnull.clean "cat >/dev/null" &&
test_config filter.devnull.required true &&
diff --git a/t/t2021-checkout-overwrite.sh b/t/t2021-checkout-overwrite.sh
index c2ada7de37..70d69263e6 100755
--- a/t/t2021-checkout-overwrite.sh
+++ b/t/t2021-checkout-overwrite.sh
@@ -51,4 +51,16 @@ test_expect_success SYMLINKS 'the symlink remained' '
test -h a/b
'
+test_expect_success SYMLINKS 'checkout -f must not follow symlinks when removing entries' '
+ git checkout -f start &&
+ mkdir dir &&
+ >dir/f &&
+ git add dir/f &&
+ git commit -m "add dir/f" &&
+ mv dir untracked &&
+ ln -s untracked dir &&
+ git checkout -f HEAD~ &&
+ test_path_is_file untracked/f
+'
+
test_done
diff --git a/t/t3060-ls-files-with-tree.sh b/t/t3060-ls-files-with-tree.sh
index 52ed665fcd..b257c792a4 100755
--- a/t/t3060-ls-files-with-tree.sh
+++ b/t/t3060-ls-files-with-tree.sh
@@ -47,6 +47,12 @@ test_expect_success setup '
git add .
'
+test_expect_success 'usage' '
+ test_expect_code 128 git ls-files --with-tree=HEAD -u &&
+ test_expect_code 128 git ls-files --with-tree=HEAD -s &&
+ test_expect_code 128 git ls-files --recurse-submodules --with-tree=HEAD
+'
+
test_expect_success 'git ls-files --with-tree should succeed from subdir' '
# We have to run from a sub-directory to trigger prune_path
# Then we finally get to run our --with-tree test
@@ -60,4 +66,39 @@ test_expect_success \
'git ls-files --with-tree should add entries from named tree.' \
'test_cmp expected output'
+test_expect_success 'no duplicates in --with-tree output' '
+ git ls-files --with-tree=HEAD >actual &&
+ sort -u actual >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'setup: output in a conflict' '
+ test_create_repo conflict &&
+ test_commit -C conflict BASE file &&
+ test_commit -C conflict A file foo &&
+ git -C conflict reset --hard BASE &&
+ test_commit -C conflict B file bar
+'
+
+test_expect_success 'output in a conflict' '
+ test_must_fail git -C conflict merge A B &&
+ cat >expected <<-\EOF &&
+ file
+ file
+ file
+ file
+ EOF
+ git -C conflict ls-files --with-tree=HEAD >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'output with removed .git/index' '
+ cat >expected <<-\EOF &&
+ file
+ EOF
+ rm conflict/.git/index &&
+ git -C conflict ls-files --with-tree=HEAD >actual &&
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh
index 587b408063..0bb88aa982 100755
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
@@ -388,22 +388,6 @@ test_expect_success 'rebase--merge.sh and --show-current-patch' '
)
'
-test_expect_success 'rebase -c rebase.useBuiltin=false warning' '
- expected="rebase.useBuiltin support has been removed" &&
-
- # Only warn when the legacy rebase is requested...
- test_must_fail git -c rebase.useBuiltin=false rebase 2>err &&
- test_i18ngrep "$expected" err &&
- test_must_fail env GIT_TEST_REBASE_USE_BUILTIN=false git rebase 2>err &&
- test_i18ngrep "$expected" err &&
-
- # ...not when we would have used the built-in anyway
- test_must_fail git -c rebase.useBuiltin=true rebase 2>err &&
- test_must_be_empty err &&
- test_must_fail env GIT_TEST_REBASE_USE_BUILTIN=true git rebase 2>err &&
- test_must_be_empty err
-'
-
test_expect_success 'switch to branch checked out here' '
git checkout main &&
git rebase main main
diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh
index 908016c2f8..78c27496d6 100755
--- a/t/t3415-rebase-autosquash.sh
+++ b/t/t3415-rebase-autosquash.sh
@@ -84,8 +84,7 @@ test_auto_squash () {
echo 1 >file1 &&
git add -u &&
test_tick &&
- git commit -m "squash! first" &&
-
+ git commit -m "squash! first" -m "extra para for first" &&
git tag $1 &&
test_tick &&
git rebase $2 -i HEAD^^^ &&
@@ -142,7 +141,7 @@ test_expect_success 'auto squash that matches 2 commits' '
echo 1 >file1 &&
git add -u &&
test_tick &&
- git commit -m "squash! first" &&
+ git commit -m "squash! first" -m "extra para for first" &&
git tag final-multisquash &&
test_tick &&
git rebase --autosquash -i HEAD~4 &&
@@ -195,7 +194,7 @@ test_expect_success 'auto squash that matches a sha1' '
git add -u &&
test_tick &&
oid=$(git rev-parse --short HEAD^) &&
- git commit -m "squash! $oid" &&
+ git commit -m "squash! $oid" -m "extra para" &&
git tag final-shasquash &&
test_tick &&
git rebase --autosquash -i HEAD^^^ &&
@@ -206,7 +205,8 @@ test_expect_success 'auto squash that matches a sha1' '
git cat-file blob HEAD^:file1 >actual &&
test_cmp expect actual &&
git cat-file commit HEAD^ >commit &&
- grep squash commit >actual &&
+ ! grep "squash" commit &&
+ grep "^extra para" commit >actual &&
test_line_count = 1 actual
'
@@ -216,7 +216,7 @@ test_expect_success 'auto squash that matches longer sha1' '
git add -u &&
test_tick &&
oid=$(git rev-parse --short=11 HEAD^) &&
- git commit -m "squash! $oid" &&
+ git commit -m "squash! $oid" -m "extra para" &&
git tag final-longshasquash &&
test_tick &&
git rebase --autosquash -i HEAD^^^ &&
@@ -227,7 +227,8 @@ test_expect_success 'auto squash that matches longer sha1' '
git cat-file blob HEAD^:file1 >actual &&
test_cmp expect actual &&
git cat-file commit HEAD^ >commit &&
- grep squash commit >actual &&
+ ! grep "squash" commit &&
+ grep "^extra para" commit >actual &&
test_line_count = 1 actual
'
@@ -236,7 +237,7 @@ test_auto_commit_flags () {
echo 1 >file1 &&
git add -u &&
test_tick &&
- git commit --$1 first-commit &&
+ git commit --$1 first-commit -m "extra para for first" &&
git tag final-commit-$1 &&
test_tick &&
git rebase --autosquash -i HEAD^^^ &&
@@ -264,11 +265,11 @@ test_auto_fixup_fixup () {
echo 1 >file1 &&
git add -u &&
test_tick &&
- git commit -m "$1! first" &&
+ git commit -m "$1! first" -m "extra para for first" &&
echo 2 >file1 &&
git add -u &&
test_tick &&
- git commit -m "$1! $2! first" &&
+ git commit -m "$1! $2! first" -m "second extra para for first" &&
git tag "final-$1-$2" &&
test_tick &&
(
@@ -329,12 +330,12 @@ test_expect_success 'autosquash with custom inst format' '
git add -u &&
test_tick &&
oid=$(git rev-parse --short HEAD^) &&
- git commit -m "squash! $oid" &&
+ git commit -m "squash! $oid" -m "extra para for first" &&
echo 1 >file1 &&
git add -u &&
test_tick &&
subject=$(git log -n 1 --format=%s HEAD~2) &&
- git commit -m "squash! $subject" &&
+ git commit -m "squash! $subject" -m "second extra para for first" &&
git tag final-squash-instFmt &&
test_tick &&
git rebase --autosquash -i HEAD~4 &&
@@ -345,8 +346,9 @@ test_expect_success 'autosquash with custom inst format' '
git cat-file blob HEAD^:file1 >actual &&
test_cmp expect actual &&
git cat-file commit HEAD^ >commit &&
- grep squash commit >actual &&
- test_line_count = 2 actual
+ ! grep "squash" commit &&
+ grep first commit >actual &&
+ test_line_count = 3 actual
'
test_expect_success 'autosquash with empty custom instructionFormat' '
diff --git a/t/t3437-rebase-fixup-options.sh b/t/t3437-rebase-fixup-options.sh
new file mode 100755
index 0000000000..d0bdc7ed02
--- /dev/null
+++ b/t/t3437-rebase-fixup-options.sh
@@ -0,0 +1,211 @@
+#!/bin/sh
+#
+# Copyright (c) 2018 Phillip Wood
+#
+
+test_description='git rebase interactive fixup options
+
+This test checks the "fixup [-C|-c]" command of rebase interactive.
+In addition to amending the contents of the commit, "fixup -C"
+replaces the original commit message with the message of the fixup
+commit. "fixup -c" also replaces the original message, but opens the
+editor to allow the user to edit the message before committing. Similar
+to the "fixup" command that works with "fixup!", "fixup -C" works with
+"amend!" upon --autosquash.
+'
+
+. ./test-lib.sh
+
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+EMPTY=""
+
+# test_commit_message <rev> -m <msg>
+# test_commit_message <rev> <path>
+# Verify that the commit message of <rev> matches
+# <msg> or the content of <path>.
+test_commit_message () {
+ git show --no-patch --pretty=format:%B "$1" >actual &&
+ case "$2" in
+ -m)
+ echo "$3" >expect &&
+ test_cmp expect actual ;;
+ *)
+ test_cmp "$2" actual ;;
+ esac
+}
+
+get_author () {
+ rev="$1" &&
+ git log -1 --pretty=format:"%an %ae %at" "$rev"
+}
+
+test_expect_success 'setup' '
+ cat >message <<-EOF &&
+ amend! B
+ $EMPTY
+ new subject
+ $EMPTY
+ new
+ body
+ EOF
+
+ test_commit A A &&
+ test_commit B B &&
+ get_author HEAD >expected-author &&
+ ORIG_AUTHOR_NAME="$GIT_AUTHOR_NAME" &&
+ ORIG_AUTHOR_EMAIL="$GIT_AUTHOR_EMAIL" &&
+ GIT_AUTHOR_NAME="Amend Author" &&
+ GIT_AUTHOR_EMAIL="amend@example.com" &&
+ test_commit "$(cat message)" A A1 A1 &&
+ test_commit A2 A &&
+ test_commit A3 A &&
+ GIT_AUTHOR_NAME="$ORIG_AUTHOR_NAME" &&
+ GIT_AUTHOR_EMAIL="$ORIG_AUTHOR_EMAIL" &&
+ git checkout -b conflicts-branch A &&
+ test_commit conflicts A &&
+
+ set_fake_editor &&
+ git checkout -b branch B &&
+ echo B1 >B &&
+ test_tick &&
+ git commit --fixup=HEAD -a &&
+ git tag B1 &&
+ test_tick &&
+ FAKE_COMMIT_AMEND="edited 1" git commit --fixup=reword:B &&
+ test_tick &&
+ FAKE_COMMIT_AMEND="edited 2" git commit --fixup=reword:HEAD &&
+ echo B2 >B &&
+ test_tick &&
+ FAKE_COMMIT_AMEND="edited squash" git commit --squash=HEAD -a &&
+ git tag B2 &&
+ echo B3 >B &&
+ test_tick &&
+ FAKE_COMMIT_AMEND="edited 3" git commit -a --fixup=amend:HEAD^ &&
+ git tag B3 &&
+
+ GIT_AUTHOR_NAME="Rebase Author" &&
+ GIT_AUTHOR_EMAIL="rebase.author@example.com" &&
+ GIT_COMMITTER_NAME="Rebase Committer" &&
+ GIT_COMMITTER_EMAIL="rebase.committer@example.com"
+'
+
+test_expect_success 'simple fixup -C works' '
+ test_when_finished "test_might_fail git rebase --abort" &&
+ git checkout --detach A2 &&
+ FAKE_LINES="1 fixup_-C 2" git rebase -i B &&
+ test_cmp_rev HEAD^ B &&
+ test_cmp_rev HEAD^{tree} A2^{tree} &&
+ test_commit_message HEAD -m "A2"
+'
+
+test_expect_success 'simple fixup -c works' '
+ test_when_finished "test_might_fail git rebase --abort" &&
+ git checkout --detach A2 &&
+ git log -1 --pretty=format:%B >expected-fixup-message &&
+ test_write_lines "" "Modified A2" >>expected-fixup-message &&
+ FAKE_LINES="1 fixup_-c 2" \
+ FAKE_COMMIT_AMEND="Modified A2" \
+ git rebase -i B &&
+ test_cmp_rev HEAD^ B &&
+ test_cmp_rev HEAD^{tree} A2^{tree} &&
+ test_commit_message HEAD expected-fixup-message
+'
+
+test_expect_success 'fixup -C removes amend! from message' '
+ test_when_finished "test_might_fail git rebase --abort" &&
+ git checkout --detach A1 &&
+ git log -1 --pretty=format:%b >expected-message &&
+ FAKE_LINES="1 fixup_-C 2" git rebase -i A &&
+ test_cmp_rev HEAD^ A &&
+ test_cmp_rev HEAD^{tree} A1^{tree} &&
+ test_commit_message HEAD expected-message &&
+ get_author HEAD >actual-author &&
+ test_cmp expected-author actual-author
+'
+
+test_expect_success 'fixup -C with conflicts gives correct message' '
+ test_when_finished "test_might_fail git rebase --abort" &&
+ git checkout --detach A1 &&
+ git log -1 --pretty=format:%b >expected-message &&
+ test_write_lines "" "edited" >>expected-message &&
+ test_must_fail env FAKE_LINES="1 fixup_-C 2" git rebase -i conflicts &&
+ git checkout --theirs -- A &&
+ git add A &&
+ FAKE_COMMIT_AMEND=edited git rebase --continue &&
+ test_cmp_rev HEAD^ conflicts &&
+ test_cmp_rev HEAD^{tree} A1^{tree} &&
+ test_commit_message HEAD expected-message &&
+ get_author HEAD >actual-author &&
+ test_cmp expected-author actual-author
+'
+
+test_expect_success 'skipping fixup -C after fixup gives correct message' '
+ test_when_finished "test_might_fail git rebase --abort" &&
+ git checkout --detach A3 &&
+ test_must_fail env FAKE_LINES="1 fixup 2 fixup_-C 4" git rebase -i A &&
+ git reset --hard &&
+ FAKE_COMMIT_AMEND=edited git rebase --continue &&
+ test_commit_message HEAD -m "B"
+'
+
+test_expect_success 'sequence of fixup, fixup -C & squash --signoff works' '
+ git checkout --detach B3 &&
+ FAKE_LINES="1 fixup 2 fixup_-C 3 fixup_-C 4 squash 5 fixup_-C 6" \
+ FAKE_COMMIT_AMEND=squashed \
+ FAKE_MESSAGE_COPY=actual-squash-message \
+ git -c commit.status=false rebase -ik --signoff A &&
+ git diff-tree --exit-code --patch HEAD B3 -- &&
+ test_cmp_rev HEAD^ A &&
+ test_i18ncmp "$TEST_DIRECTORY/t3437/expected-squash-message" \
+ actual-squash-message
+'
+
+test_expect_success 'first fixup -C commented out in sequence fixup fixup -C fixup -C' '
+ test_when_finished "test_might_fail git rebase --abort" &&
+ git checkout --detach B2~ &&
+ git log -1 --pretty=format:%b >expected-message &&
+ FAKE_LINES="1 fixup 2 fixup_-C 3 fixup_-C 4" git rebase -i A &&
+ test_cmp_rev HEAD^ A &&
+ test_commit_message HEAD expected-message
+'
+
+test_expect_success 'multiple fixup -c opens editor once' '
+ test_when_finished "test_might_fail git rebase --abort" &&
+ git checkout --detach A3 &&
+ git log -1 --pretty=format:%B >expected-message &&
+ test_write_lines "" "Modified-A3" >>expected-message &&
+ FAKE_COMMIT_AMEND="Modified-A3" \
+ FAKE_LINES="1 fixup_-C 2 fixup_-c 3 fixup_-c 4" \
+ EXPECT_HEADER_COUNT=4 \
+ git rebase -i A &&
+ test_cmp_rev HEAD^ A &&
+ get_author HEAD >actual-author &&
+ test_cmp expected-author actual-author &&
+ test_commit_message HEAD expected-message
+'
+
+test_expect_success 'sequence squash, fixup & fixup -c gives combined message' '
+ test_when_finished "test_might_fail git rebase --abort" &&
+ git checkout --detach A3 &&
+ FAKE_LINES="1 squash 2 fixup 3 fixup_-c 4" \
+ FAKE_MESSAGE_COPY=actual-combined-message \
+ git -c commit.status=false rebase -i A &&
+ test_i18ncmp "$TEST_DIRECTORY/t3437/expected-combined-message" \
+ actual-combined-message &&
+ test_cmp_rev HEAD^ A
+'
+
+test_expect_success 'fixup -C works upon --autosquash with amend!' '
+ git checkout --detach B3 &&
+ FAKE_COMMIT_AMEND=squashed \
+ FAKE_MESSAGE_COPY=actual-squash-message \
+ git -c commit.status=false rebase -ik --autosquash \
+ --signoff A &&
+ git diff-tree --exit-code --patch HEAD B3 -- &&
+ test_cmp_rev HEAD^ A &&
+ test_i18ncmp "$TEST_DIRECTORY/t3437/expected-squash-message" \
+ actual-squash-message
+'
+
+test_done
diff --git a/t/t3437/expected-combined-message b/t/t3437/expected-combined-message
new file mode 100644
index 0000000000..a26cfb2fa9
--- /dev/null
+++ b/t/t3437/expected-combined-message
@@ -0,0 +1,21 @@
+# This is a combination of 4 commits.
+# This is the 1st commit message:
+
+B
+
+# This is the commit message #2:
+
+# amend! B
+
+new subject
+
+new
+body
+
+# The commit message #3 will be skipped:
+
+# A2
+
+# This is the commit message #4:
+
+A3
diff --git a/t/t3437/expected-squash-message b/t/t3437/expected-squash-message
new file mode 100644
index 0000000000..ab2434f90e
--- /dev/null
+++ b/t/t3437/expected-squash-message
@@ -0,0 +1,51 @@
+# This is a combination of 6 commits.
+# The 1st commit message will be skipped:
+
+# B
+#
+# Signed-off-by: Rebase Committer <rebase.committer@example.com>
+
+# The commit message #2 will be skipped:
+
+# fixup! B
+
+# The commit message #3 will be skipped:
+
+# amend! B
+#
+# B
+#
+# edited 1
+#
+# Signed-off-by: Rebase Committer <rebase.committer@example.com>
+
+# This is the commit message #4:
+
+# amend! amend! B
+
+B
+
+edited 1
+
+edited 2
+
+Signed-off-by: Rebase Committer <rebase.committer@example.com>
+
+# This is the commit message #5:
+
+# squash! amend! amend! B
+
+edited squash
+
+# This is the commit message #6:
+
+# amend! amend! amend! B
+
+B
+
+edited 1
+
+edited 2
+
+edited 3
+squashed
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 60a666da59..6275c98523 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -17,7 +17,7 @@ check_verify_failure () {
grep '$2' message &&
if test '$3' != '--no-strict'
then
- test_must_fail git mktag --no-strict <tag.sig 2>message.no-strict &&xb
+ test_must_fail git mktag --no-strict <tag.sig 2>message.no-strict &&
grep '$2' message.no-strict
fi
"
diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh
index d277a9f4b7..bfab245eb3 100755
--- a/t/t3900-i18n-commit.sh
+++ b/t/t3900-i18n-commit.sh
@@ -226,10 +226,6 @@ test_commit_autosquash_multi_encoding () {
git rev-list HEAD >actual &&
test_line_count = 3 actual &&
iconv -f $old -t UTF-8 "$TEST_DIRECTORY"/t3900/$msg >expect &&
- if test $flag = squash; then
- subject="$(head -1 expect)" &&
- printf "\nsquash! %s\n" "$subject" >>expect
- fi &&
git cat-file commit HEAD^ >raw &&
(sed "1,/^$/d" raw | iconv -f $new -t utf-8) >actual &&
test_cmp expect actual
diff --git a/t/t3905-stash-include-untracked.sh b/t/t3905-stash-include-untracked.sh
index 598b17f6d4..8314ab21d4 100755
--- a/t/t3905-stash-include-untracked.sh
+++ b/t/t3905-stash-include-untracked.sh
@@ -297,4 +297,112 @@ test_expect_success 'stash -u with globs' '
test_path_is_missing untracked.txt
'
+test_expect_success 'stash show --include-untracked shows untracked files' '
+ git reset --hard &&
+ git clean -xf &&
+ >untracked &&
+ >tracked &&
+ git add tracked &&
+ empty_blob_oid=$(git rev-parse --short :tracked) &&
+ git stash -u &&
+
+ cat >expect <<-EOF &&
+ tracked | 0
+ untracked | 0
+ 2 files changed, 0 insertions(+), 0 deletions(-)
+ EOF
+ git stash show --include-untracked >actual &&
+ test_cmp expect actual &&
+ git stash show -u >actual &&
+ test_cmp expect actual &&
+ git stash show --no-include-untracked --include-untracked >actual &&
+ test_cmp expect actual &&
+ git stash show --only-untracked --include-untracked >actual &&
+ test_cmp expect actual &&
+ git -c stash.showIncludeUntracked=true stash show >actual &&
+ test_cmp expect actual &&
+
+ cat >expect <<-EOF &&
+ diff --git a/tracked b/tracked
+ new file mode 100644
+ index 0000000..$empty_blob_oid
+ diff --git a/untracked b/untracked
+ new file mode 100644
+ index 0000000..$empty_blob_oid
+ EOF
+ git stash show -p --include-untracked >actual &&
+ test_cmp expect actual &&
+ git stash show --include-untracked -p >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'stash show --only-untracked only shows untracked files' '
+ git reset --hard &&
+ git clean -xf &&
+ >untracked &&
+ >tracked &&
+ git add tracked &&
+ empty_blob_oid=$(git rev-parse --short :tracked) &&
+ git stash -u &&
+
+ cat >expect <<-EOF &&
+ untracked | 0
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+ EOF
+ git stash show --only-untracked >actual &&
+ test_cmp expect actual &&
+ git stash show --no-include-untracked --only-untracked >actual &&
+ test_cmp expect actual &&
+ git stash show --include-untracked --only-untracked >actual &&
+ test_cmp expect actual &&
+
+ cat >expect <<-EOF &&
+ diff --git a/untracked b/untracked
+ new file mode 100644
+ index 0000000..$empty_blob_oid
+ EOF
+ git stash show -p --only-untracked >actual &&
+ test_cmp expect actual &&
+ git stash show --only-untracked -p >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'stash show --no-include-untracked cancels --{include,show}-untracked' '
+ git reset --hard &&
+ git clean -xf &&
+ >untracked &&
+ >tracked &&
+ git add tracked &&
+ git stash -u &&
+
+ cat >expect <<-EOF &&
+ tracked | 0
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+ EOF
+ git stash show --only-untracked --no-include-untracked >actual &&
+ test_cmp expect actual &&
+ git stash show --include-untracked --no-include-untracked >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'stash show --include-untracked errors on duplicate files' '
+ git reset --hard &&
+ git clean -xf &&
+ >tracked &&
+ git add tracked &&
+ tree=$(git write-tree) &&
+ i_commit=$(git commit-tree -p HEAD -m "index on any-branch" "$tree") &&
+ test_when_finished "rm -f untracked_index" &&
+ u_commit=$(
+ GIT_INDEX_FILE="untracked_index" &&
+ export GIT_INDEX_FILE &&
+ git update-index --add tracked &&
+ u_tree=$(git write-tree) &&
+ git commit-tree -m "untracked files on any-branch" "$u_tree"
+ ) &&
+ w_commit=$(git commit-tree -p HEAD -p "$i_commit" -p "$u_commit" -m "WIP on any-branch" "$tree") &&
+ test_must_fail git stash show --include-untracked "$w_commit" 2>err &&
+ test_i18ngrep "worktree and untracked commit have duplicate entries: tracked" err
+'
+
test_done
diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh
index 0168946b63..3feadf0e35 100755
--- a/t/t4053-diff-no-index.sh
+++ b/t/t4053-diff-no-index.sh
@@ -16,6 +16,11 @@ test_expect_success 'setup' '
echo 1 >non/git/b
'
+test_expect_success 'git diff --no-index --exit-code' '
+ git diff --no-index --exit-code a/1 non/git/a &&
+ test_expect_code 1 git diff --no-index --exit-code a/1 a/2
+'
+
test_expect_success 'git diff --no-index directories' '
test_expect_code 1 git diff --no-index a b >cnt &&
test_line_count = 14 cnt
@@ -144,4 +149,59 @@ test_expect_success 'diff --no-index allows external diff' '
test_cmp expect actual
'
+test_expect_success 'diff --no-index normalizes mode: no changes' '
+ echo foo >x &&
+ cp x y &&
+ git diff --no-index x y >out &&
+ test_must_be_empty out
+'
+
+test_expect_success POSIXPERM 'diff --no-index normalizes mode: chmod +x' '
+ chmod +x y &&
+ cat >expected <<-\EOF &&
+ diff --git a/x b/y
+ old mode 100644
+ new mode 100755
+ EOF
+ test_expect_code 1 git diff --no-index x y >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success POSIXPERM 'diff --no-index normalizes: mode not like git mode' '
+ chmod 666 x &&
+ chmod 777 y &&
+ cat >expected <<-\EOF &&
+ diff --git a/x b/y
+ old mode 100644
+ new mode 100755
+ EOF
+ test_expect_code 1 git diff --no-index x y >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success POSIXPERM,SYMLINKS 'diff --no-index normalizes: mode not like git mode (symlink)' '
+ ln -s y z &&
+ X_OID=$(git hash-object --stdin <x) &&
+ Z_OID=$(printf y | git hash-object --stdin) &&
+ cat >expected <<-EOF &&
+ diff --git a/x b/x
+ deleted file mode 100644
+ index $X_OID..$ZERO_OID
+ --- a/x
+ +++ /dev/null
+ @@ -1 +0,0 @@
+ -foo
+ diff --git a/z b/z
+ new file mode 120000
+ index $ZERO_OID..$Z_OID
+ --- /dev/null
+ +++ b/z
+ @@ -0,0 +1 @@
+ +y
+ \ No newline at end of file
+ EOF
+ test_expect_code 1 git -c core.abbrev=no diff --no-index x z >actual &&
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh
index 93caf9a46d..d8e7374234 100755
--- a/t/t4203-mailmap.sh
+++ b/t/t4203-mailmap.sh
@@ -932,4 +932,35 @@ test_expect_success 'find top-level mailmap from subdir' '
test_cmp expect actual
'
+test_expect_success SYMLINKS 'set up symlink tests' '
+ git commit --allow-empty -m foo --author="Orig <orig@example.com>" &&
+ echo "New <new@example.com> <orig@example.com>" >map &&
+ rm -f .mailmap
+'
+
+test_expect_success SYMLINKS 'symlinks respected in mailmap.file' '
+ test_when_finished "rm symlink" &&
+ ln -s map symlink &&
+ git -c mailmap.file="$(pwd)/symlink" log -1 --format=%aE >actual &&
+ echo "new@example.com" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success SYMLINKS 'symlinks respected in non-repo shortlog' '
+ git log -1 >input &&
+ test_when_finished "nongit rm .mailmap" &&
+ nongit ln -sf "$TRASH_DIRECTORY/map" .mailmap &&
+ nongit git shortlog -s <input >actual &&
+ echo " 1 New" >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success SYMLINKS 'symlinks not respected in-tree' '
+ test_when_finished "rm .mailmap" &&
+ ln -s map .mailmap &&
+ git log -1 --format=%aE >actual &&
+ echo "orig@example.com" >expect&&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh
index 85432b80ff..cabdf7d57a 100755
--- a/t/t4205-log-pretty-formats.sh
+++ b/t/t4205-log-pretty-formats.sh
@@ -962,4 +962,39 @@ test_expect_success 'log --pretty=reference is colored appropriately' '
test_cmp expect actual
'
+test_expect_success '%(describe) vs git describe' '
+ git log --format="%H" | while read hash
+ do
+ if desc=$(git describe $hash)
+ then
+ : >expect-contains-good
+ else
+ : >expect-contains-bad
+ fi &&
+ echo "$hash $desc"
+ done >expect &&
+ test_path_exists expect-contains-good &&
+ test_path_exists expect-contains-bad &&
+
+ git log --format="%H %(describe)" >actual 2>err &&
+ test_cmp expect actual &&
+ test_must_be_empty err
+'
+
+test_expect_success '%(describe:match=...) vs git describe --match ...' '
+ test_when_finished "git tag -d tag-match" &&
+ git tag -a -m tagged tag-match&&
+ git describe --match "*-match" >expect &&
+ git log -1 --format="%(describe:match=*-match)" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '%(describe:exclude=...) vs git describe --exclude ...' '
+ test_when_finished "git tag -d tag-exclude" &&
+ git tag -a -m tagged tag-exclude &&
+ git describe --exclude "*-exclude" >expect &&
+ git log -1 --format="%(describe:exclude=*-exclude)" >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh
index e9aa97117a..712ae52299 100755
--- a/t/t5001-archive-attr.sh
+++ b/t/t5001-archive-attr.sh
@@ -128,4 +128,18 @@ test_expect_success 'export-subst' '
test_cmp substfile2 archive/substfile2
'
+test_expect_success 'export-subst expands %(describe) once' '
+ echo "\$Format:%(describe)\$" >substfile3 &&
+ echo "\$Format:%(describe)\$" >>substfile3 &&
+ echo "\$Format:%(describe)${LF}%(describe)\$" >substfile4 &&
+ git add substfile[34] &&
+ git commit -m export-subst-describe &&
+ git tag -m export-subst-describe export-subst-describe &&
+ git archive HEAD >archive-describe.tar &&
+ extract_tar_to_dir archive-describe &&
+ desc=$(git describe) &&
+ grep -F "$desc" archive-describe/substfile[34] >substituted &&
+ test_line_count = 1 substituted
+'
+
test_done
diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh
index d586fdc7a9..2fc5e68250 100755
--- a/t/t5300-pack-object.sh
+++ b/t/t5300-pack-object.sh
@@ -427,7 +427,8 @@ test_expect_success 'index-pack --strict <pack> works in non-repo' '
test_path_is_file foo.idx
'
-test_expect_success !PTHREADS 'index-pack --threads=N or pack.threads=N warns when no pthreads' '
+test_expect_success !PTHREADS,!FAIL_PREREQS \
+ 'index-pack --threads=N or pack.threads=N warns when no pthreads' '
test_must_fail git index-pack --threads=2 2>err &&
grep ^warning: err >warnings &&
test_line_count = 1 warnings &&
@@ -445,7 +446,8 @@ test_expect_success !PTHREADS 'index-pack --threads=N or pack.threads=N warns wh
grep -F "no threads support, ignoring pack.threads" err
'
-test_expect_success !PTHREADS 'pack-objects --threads=N or pack.threads=N warns when no pthreads' '
+test_expect_success !PTHREADS,!FAIL_PREREQS \
+ 'pack-objects --threads=N or pack.threads=N warns when no pthreads' '
git pack-objects --threads=2 --stdout --all </dev/null >/dev/null 2>err &&
grep ^warning: err >warnings &&
test_line_count = 1 warnings &&
@@ -532,4 +534,139 @@ test_expect_success 'prefetch objects' '
test_line_count = 1 donelines
'
+test_expect_success 'setup for --stdin-packs tests' '
+ git init stdin-packs &&
+ (
+ cd stdin-packs &&
+
+ test_commit A &&
+ test_commit B &&
+ test_commit C &&
+
+ for id in A B C
+ do
+ git pack-objects .git/objects/pack/pack-$id \
+ --incremental --revs <<-EOF
+ refs/tags/$id
+ EOF
+ done &&
+
+ ls -la .git/objects/pack
+ )
+'
+
+test_expect_success '--stdin-packs with excluded packs' '
+ (
+ cd stdin-packs &&
+
+ PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
+ PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
+ PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
+
+ git pack-objects test --stdin-packs <<-EOF &&
+ $PACK_A
+ ^$PACK_B
+ $PACK_C
+ EOF
+
+ (
+ git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
+ git show-index <$(ls .git/objects/pack/pack-C-*.idx)
+ ) >expect.raw &&
+ git show-index <$(ls test-*.idx) >actual.raw &&
+
+ cut -d" " -f2 <expect.raw | sort >expect &&
+ cut -d" " -f2 <actual.raw | sort >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success '--stdin-packs is incompatible with --filter' '
+ (
+ cd stdin-packs &&
+ test_must_fail git pack-objects --stdin-packs --stdout \
+ --filter=blob:none </dev/null 2>err &&
+ test_i18ngrep "cannot use --filter with --stdin-packs" err
+ )
+'
+
+test_expect_success '--stdin-packs is incompatible with --revs' '
+ (
+ cd stdin-packs &&
+ test_must_fail git pack-objects --stdin-packs --revs out \
+ </dev/null 2>err &&
+ test_i18ngrep "cannot use internal rev list with --stdin-packs" err
+ )
+'
+
+test_expect_success '--stdin-packs with loose objects' '
+ (
+ cd stdin-packs &&
+
+ PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
+ PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
+ PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
+
+ test_commit D && # loose
+
+ git pack-objects test2 --stdin-packs --unpacked <<-EOF &&
+ $PACK_A
+ ^$PACK_B
+ $PACK_C
+ EOF
+
+ (
+ git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
+ git show-index <$(ls .git/objects/pack/pack-C-*.idx) &&
+ git rev-list --objects --no-object-names \
+ refs/tags/C..refs/tags/D
+
+ ) >expect.raw &&
+ ls -la . &&
+ git show-index <$(ls test2-*.idx) >actual.raw &&
+
+ cut -d" " -f2 <expect.raw | sort >expect &&
+ cut -d" " -f2 <actual.raw | sort >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success '--stdin-packs with broken links' '
+ (
+ cd stdin-packs &&
+
+ # make an unreachable object with a bogus parent
+ git cat-file -p HEAD >commit &&
+ sed "s/$(git rev-parse HEAD^)/$(test_oid zero)/" <commit |
+ git hash-object -w -t commit --stdin >in &&
+
+ git pack-objects .git/objects/pack/pack-D <in &&
+
+ PACK_A="$(basename .git/objects/pack/pack-A-*.pack)" &&
+ PACK_B="$(basename .git/objects/pack/pack-B-*.pack)" &&
+ PACK_C="$(basename .git/objects/pack/pack-C-*.pack)" &&
+ PACK_D="$(basename .git/objects/pack/pack-D-*.pack)" &&
+
+ git pack-objects test3 --stdin-packs --unpacked <<-EOF &&
+ $PACK_A
+ ^$PACK_B
+ $PACK_C
+ $PACK_D
+ EOF
+
+ (
+ git show-index <$(ls .git/objects/pack/pack-A-*.idx) &&
+ git show-index <$(ls .git/objects/pack/pack-C-*.idx) &&
+ git show-index <$(ls .git/objects/pack/pack-D-*.idx) &&
+ git rev-list --objects --no-object-names \
+ refs/tags/C..refs/tags/D
+ ) >expect.raw &&
+ git show-index <$(ls test3-*.idx) >actual.raw &&
+
+ cut -d" " -f2 <expect.raw | sort >expect &&
+ cut -d" " -f2 <actual.raw | sort >actual &&
+ test_cmp expect actual
+ )
+'
+
test_done
diff --git a/t/t5318-commit-graph.sh b/t/t5318-commit-graph.sh
index edeb6d6d31..af88f805aa 100755
--- a/t/t5318-commit-graph.sh
+++ b/t/t5318-commit-graph.sh
@@ -475,7 +475,7 @@ test_expect_success 'lower layers have overflow chunk' '
test_expect_success 'git commit-graph verify' '
cd "$TRASH_DIRECTORY/full" &&
- git rev-parse commits/8 | GIT_TEST_COMMIT_GRAPH_NO_GDAT=1 git commit-graph write --stdin-commits &&
+ git rev-parse commits/8 | git -c commitGraph.generationVersion=1 commit-graph write --stdin-commits &&
git commit-graph verify >output &&
graph_read_expect 9 extra_edges
'
diff --git a/t/t5324-split-commit-graph.sh b/t/t5324-split-commit-graph.sh
index 8e90f3423b..587226ed10 100755
--- a/t/t5324-split-commit-graph.sh
+++ b/t/t5324-split-commit-graph.sh
@@ -489,7 +489,7 @@ test_expect_success 'setup repo for mixed generation commit-graph-chain' '
test_commit $i &&
git branch commits/$i || return 1
done &&
- git commit-graph write --reachable --split &&
+ git -c commitGraph.generationVersion=2 commit-graph write --reachable --split &&
graph_read_expect $NUM_FIRST_LAYER_COMMITS &&
test_line_count = 1 $graphdir/commit-graph-chain &&
for i in $(test_seq $SECOND_LAYER_SEQUENCE_START $SECOND_LAYER_SEQUENCE_END)
@@ -497,7 +497,7 @@ test_expect_success 'setup repo for mixed generation commit-graph-chain' '
test_commit $i &&
git branch commits/$i || return 1
done &&
- GIT_TEST_COMMIT_GRAPH_NO_GDAT=1 git commit-graph write --reachable --split=no-merge &&
+ git -c commitGraph.generationVersion=1 commit-graph write --reachable --split=no-merge &&
test_line_count = 2 $graphdir/commit-graph-chain &&
test-tool read-graph >output &&
cat >expect <<-EOF &&
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 8c462f20ae..c7b392794b 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -594,6 +594,7 @@ test_expect_success 'add --no-tags' '
cd add-no-tags &&
git init &&
git remote add -f --no-tags origin ../one &&
+ grep tagOpt .git/config &&
git tag -l some-tag >../test/output &&
git tag -l foobar-tag >../test/output &&
git config remote.origin.tagopt >>../test/output
@@ -756,6 +757,7 @@ test_expect_success 'rename a remote' '
cd four &&
git config branch.main.pushRemote origin &&
git remote rename origin upstream &&
+ grep "pushRemote" .git/config &&
test -z "$(git for-each-ref refs/remotes/origin)" &&
test "$(git symbolic-ref refs/remotes/upstream/HEAD)" = "refs/remotes/upstream/main" &&
test "$(git rev-parse upstream/main)" = "$(git rev-parse main)" &&
@@ -772,6 +774,7 @@ test_expect_success 'rename a remote renames repo remote.pushDefault' '
cd four.1 &&
git config remote.pushDefault origin &&
git remote rename origin upstream &&
+ grep pushDefault .git/config &&
test "$(git config --local remote.pushDefault)" = "upstream"
)
'
diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh
index 52e5789fb0..428b0aac93 100755
--- a/t/t5606-clone-options.sh
+++ b/t/t5606-clone-options.sh
@@ -104,12 +104,20 @@ test_expect_success 'redirected clone -v does show progress' '
'
+test_expect_success 'clone does not segfault with --bare and core.bare=false' '
+ test_config_global core.bare false &&
+ git clone --bare parent clone-bare &&
+ echo true >expect &&
+ git -C clone-bare rev-parse --is-bare-repository >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'chooses correct default initial branch name' '
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= \
git -c init.defaultBranch=foo init --bare empty &&
test_config -C empty lsrefs.unborn advertise &&
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= \
- git -c init.defaultBranch=up clone empty whats-up &&
+ git -c init.defaultBranch=up -c protocol.version=2 clone empty whats-up &&
test refs/heads/foo = $(git -C whats-up symbolic-ref HEAD) &&
test refs/heads/foo = $(git -C whats-up config branch.foo.merge)
'
diff --git a/t/t5612-clone-refspec.sh b/t/t5612-clone-refspec.sh
index 6a6af7449c..3126cfd7e9 100755
--- a/t/t5612-clone-refspec.sh
+++ b/t/t5612-clone-refspec.sh
@@ -97,6 +97,7 @@ test_expect_success 'by default no tags will be kept updated' '
test_expect_success 'clone with --no-tags' '
(
cd dir_all_no_tags &&
+ grep tagOpt .git/config &&
git fetch &&
git for-each-ref refs/tags >../actual
) &&
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 0ba5a91b4e..32bb66e1ed 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -939,4 +939,16 @@ test_expect_success 'git bisect reset cleans bisection state properly' '
test_path_is_missing ".git/BISECT_START"
'
+test_expect_success 'bisect handles annotated tags' '
+ test_commit commit-one &&
+ git tag -m foo tag-one &&
+ test_commit commit-two &&
+ git tag -m foo tag-two &&
+ git bisect start &&
+ git bisect good tag-one &&
+ git bisect bad tag-two >output &&
+ bad=$(git rev-parse --verify tag-two^{commit}) &&
+ grep "$bad is the first bad commit" output
+'
+
test_done
diff --git a/t/t6114-keep-packs.sh b/t/t6114-keep-packs.sh
new file mode 100755
index 0000000000..9239d8aa46
--- /dev/null
+++ b/t/t6114-keep-packs.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+test_description='rev-list with .keep packs'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ test_commit loose &&
+ test_commit packed &&
+ test_commit kept &&
+
+ KEPT_PACK=$(git pack-objects --revs .git/objects/pack/pack <<-EOF
+ refs/tags/kept
+ ^refs/tags/packed
+ EOF
+ ) &&
+ MISC_PACK=$(git pack-objects --revs .git/objects/pack/pack <<-EOF
+ refs/tags/packed
+ ^refs/tags/loose
+ EOF
+ ) &&
+
+ touch .git/objects/pack/pack-$KEPT_PACK.keep
+'
+
+rev_list_objects () {
+ git rev-list "$@" >out &&
+ sort out
+}
+
+idx_objects () {
+ git show-index <$1 >expect-idx &&
+ cut -d" " -f2 <expect-idx | sort
+}
+
+test_expect_success '--no-kept-objects excludes trees and blobs in .keep packs' '
+ rev_list_objects --objects --all --no-object-names >kept &&
+ rev_list_objects --objects --all --no-object-names --no-kept-objects >no-kept &&
+
+ idx_objects .git/objects/pack/pack-$KEPT_PACK.idx >expect &&
+ comm -3 kept no-kept >actual &&
+
+ test_cmp expect actual
+'
+
+test_expect_success '--no-kept-objects excludes kept non-MIDX object' '
+ test_config core.multiPackIndex true &&
+
+ # Create a pack with just the commit object in pack, and do not mark it
+ # as kept (even though it appears in $KEPT_PACK, which does have a .keep
+ # file).
+ MIDX_PACK=$(git pack-objects .git/objects/pack/pack <<-EOF
+ $(git rev-parse kept)
+ EOF
+ ) &&
+
+ # Write a MIDX containing all packs, but use the version of the commit
+ # at "kept" in a non-kept pack by touching $MIDX_PACK.
+ touch .git/objects/pack/pack-$MIDX_PACK.pack &&
+ git multi-pack-index write &&
+
+ rev_list_objects --objects --no-object-names --no-kept-objects HEAD >actual &&
+ (
+ idx_objects .git/objects/pack/pack-$MISC_PACK.idx &&
+ git rev-list --objects --no-object-names refs/tags/loose
+ ) | sort >expect &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t6600-test-reach.sh b/t/t6600-test-reach.sh
index e2d33a8a4c..3d7a62ddab 100755
--- a/t/t6600-test-reach.sh
+++ b/t/t6600-test-reach.sh
@@ -55,7 +55,7 @@ test_expect_success 'setup' '
git show-ref -s commit-5-5 | git commit-graph write --stdin-commits &&
mv .git/objects/info/commit-graph commit-graph-half &&
chmod u+w commit-graph-half &&
- GIT_TEST_COMMIT_GRAPH_NO_GDAT=1 git commit-graph write --reachable &&
+ git -c commitGraph.generationVersion=1 commit-graph write --reachable &&
mv .git/objects/info/commit-graph commit-graph-no-gdat &&
chmod u+w commit-graph-no-gdat &&
git config core.commitGraph true
diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh
index 1c55695034..1349e5b232 100755
--- a/t/t7003-filter-branch.sh
+++ b/t/t7003-filter-branch.sh
@@ -506,4 +506,35 @@ test_expect_success 'rewrite repository including refs that point at non-commit
! fgrep fatal filter-output
'
+test_expect_success 'filter-branch handles ref deletion' '
+ git switch --orphan empty-commit &&
+ git commit --allow-empty -m "empty commit" &&
+ git tag empty &&
+ git branch to-delete &&
+ git filter-branch -f --prune-empty to-delete >out 2>&1 &&
+ grep "to-delete.*was deleted" out &&
+ test_must_fail git rev-parse --verify to-delete
+'
+
+test_expect_success 'filter-branch handles ref rewrite' '
+ git checkout empty &&
+ test_commit to-drop &&
+ git branch rewrite &&
+ git filter-branch -f \
+ --index-filter "git rm --ignore-unmatch --cached to-drop.t" \
+ rewrite >out 2>&1 &&
+ grep "rewrite.*was rewritten" out &&
+ ! grep -i warning out &&
+ git diff-tree empty rewrite
+'
+
+test_expect_success 'filter-branch handles ancestor rewrite' '
+ test_commit to-exclude &&
+ git branch ancestor &&
+ git filter-branch -f ancestor -- :^to-exclude.t >out 2>&1 &&
+ grep "ancestor.*was rewritten" out &&
+ ! grep -i warning out &&
+ git diff-tree HEAD^ ancestor
+'
+
test_done
diff --git a/t/t7007-show.sh b/t/t7007-show.sh
index 42d3db6246..d6cc69e0f2 100755
--- a/t/t7007-show.sh
+++ b/t/t7007-show.sh
@@ -38,6 +38,45 @@ test_expect_success 'showing two commits' '
test_cmp expect actual.filtered
'
+test_expect_success 'showing a tree' '
+ cat >expected <<-EOF &&
+ tree main1:
+
+ main1.t
+ EOF
+ git show main1: >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'showing two trees' '
+ cat >expected <<-EOF &&
+ tree main1^{tree}
+
+ main1.t
+
+ tree main2^{tree}
+
+ main1.t
+ main2.t
+ EOF
+ git show main1^{tree} main2^{tree} >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'showing a trees is not recursive' '
+ git worktree add not-recursive main1 &&
+ mkdir not-recursive/a &&
+ test_commit -C not-recursive a/file &&
+ cat >expected <<-EOF &&
+ tree HEAD^{tree}
+
+ a/
+ main1.t
+ EOF
+ git -C not-recursive show HEAD^{tree} >actual &&
+ test_cmp expected actual
+'
+
test_expect_success 'showing a range walks (linear)' '
cat >expect <<-EOF &&
commit $(git rev-parse main3)
diff --git a/t/t7500-commit-template-squash-signoff.sh b/t/t7500-commit-template-squash-signoff.sh
index e41ac18e7e..9092db5fdc 100755
--- a/t/t7500-commit-template-squash-signoff.sh
+++ b/t/t7500-commit-template-squash-signoff.sh
@@ -9,6 +9,8 @@ Tests for template, signoff, squash and -F functions.'
. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
commit_msg_is () {
expect=commit_msg_is.expect
actual=commit_msg_is.actual
@@ -279,6 +281,163 @@ test_expect_success 'commit --fixup -m"something" -m"extra"' '
extra"
'
+get_commit_msg () {
+ rev="$1" &&
+ git log -1 --pretty=format:"%B" "$rev"
+}
+
+test_expect_success 'commit --fixup=amend: creates amend! commit' '
+ commit_for_rebase_autosquash_setup &&
+ cat >expected <<-EOF &&
+ amend! $(git log -1 --format=%s HEAD~)
+
+ $(get_commit_msg HEAD~)
+
+ edited
+ EOF
+ (
+ set_fake_editor &&
+ FAKE_COMMIT_AMEND="edited" \
+ git commit --fixup=amend:HEAD~
+ ) &&
+ get_commit_msg HEAD >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success '--fixup=amend: --only ignores staged changes' '
+ commit_for_rebase_autosquash_setup &&
+ cat >expected <<-EOF &&
+ amend! $(git log -1 --format=%s HEAD~)
+
+ $(get_commit_msg HEAD~)
+
+ edited
+ EOF
+ (
+ set_fake_editor &&
+ FAKE_COMMIT_AMEND="edited" \
+ git commit --fixup=amend:HEAD~ --only
+ ) &&
+ get_commit_msg HEAD >actual &&
+ test_cmp expected actual &&
+ test_cmp_rev HEAD@{1}^{tree} HEAD^{tree} &&
+ test_cmp_rev HEAD@{1} HEAD^ &&
+ test_expect_code 1 git diff --cached --exit-code &&
+ git cat-file blob :foo >actual &&
+ test_cmp foo actual
+'
+
+test_expect_success '--fixup=reword: ignores staged changes' '
+ commit_for_rebase_autosquash_setup &&
+ cat >expected <<-EOF &&
+ amend! $(git log -1 --format=%s HEAD~)
+
+ $(get_commit_msg HEAD~)
+
+ edited
+ EOF
+ (
+ set_fake_editor &&
+ FAKE_COMMIT_AMEND="edited" \
+ git commit --fixup=reword:HEAD~
+ ) &&
+ get_commit_msg HEAD >actual &&
+ test_cmp expected actual &&
+ test_cmp_rev HEAD@{1}^{tree} HEAD^{tree} &&
+ test_cmp_rev HEAD@{1} HEAD^ &&
+ test_expect_code 1 git diff --cached --exit-code &&
+ git cat-file blob :foo >actual &&
+ test_cmp foo actual
+'
+
+test_expect_success '--fixup=reword: error out with -m option' '
+ commit_for_rebase_autosquash_setup &&
+ echo "fatal: cannot combine -m with --fixup:reword" >expect &&
+ test_must_fail git commit --fixup=reword:HEAD~ -m "reword commit message" 2>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '--fixup=amend: error out with -m option' '
+ commit_for_rebase_autosquash_setup &&
+ echo "fatal: cannot combine -m with --fixup:amend" >expect &&
+ test_must_fail git commit --fixup=amend:HEAD~ -m "amend commit message" 2>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'consecutive amend! commits remove amend! line from commit msg body' '
+ commit_for_rebase_autosquash_setup &&
+ cat >expected <<-EOF &&
+ amend! amend! $(git log -1 --format=%s HEAD~)
+
+ $(get_commit_msg HEAD~)
+
+ edited 1
+
+ edited 2
+ EOF
+ echo "reword new commit message" >actual &&
+ (
+ set_fake_editor &&
+ FAKE_COMMIT_AMEND="edited 1" \
+ git commit --fixup=reword:HEAD~ &&
+ FAKE_COMMIT_AMEND="edited 2" \
+ git commit --fixup=reword:HEAD
+ ) &&
+ get_commit_msg HEAD >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'deny to create amend! commit if its commit msg body is empty' '
+ commit_for_rebase_autosquash_setup &&
+ echo "Aborting commit due to empty commit message body." >expected &&
+ (
+ set_fake_editor &&
+ test_must_fail env FAKE_COMMIT_MESSAGE="amend! target message subject line" \
+ git commit --fixup=amend:HEAD~ 2>actual
+ ) &&
+ test_cmp expected actual
+'
+
+test_expect_success 'amend! commit allows empty commit msg body with --allow-empty-message' '
+ commit_for_rebase_autosquash_setup &&
+ cat >expected <<-EOF &&
+ amend! $(git log -1 --format=%s HEAD~)
+ EOF
+ (
+ set_fake_editor &&
+ FAKE_COMMIT_MESSAGE="amend! target message subject line" \
+ git commit --fixup=amend:HEAD~ --allow-empty-message &&
+ get_commit_msg HEAD >actual
+ ) &&
+ test_cmp expected actual
+'
+
+test_fixup_reword_opt () {
+ test_expect_success C_LOCALE_OUTPUT "--fixup=reword: incompatible with $1" "
+ echo 'fatal: reword option of --fixup is mutually exclusive with'\
+ '--patch/--interactive/--all/--include/--only' >expect &&
+ test_must_fail git commit --fixup=reword:HEAD~ $1 2>actual &&
+ test_cmp expect actual
+ "
+}
+
+for opt in --all --include --only --interactive --patch
+do
+ test_fixup_reword_opt $opt
+done
+
+test_expect_success '--fixup=reword: give error with pathsec' '
+ commit_for_rebase_autosquash_setup &&
+ echo "fatal: cannot combine reword option of --fixup with path '\''foo'\''" >expect &&
+ test_must_fail git commit --fixup=reword:HEAD~ -- foo 2>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '--fixup=reword: -F give error message' '
+ echo "fatal: Only one of -c/-C/-F/--fixup can be used." >expect &&
+ test_must_fail git commit --fixup=reword:HEAD~ -F msg 2>actual &&
+ test_cmp expect actual
+'
test_expect_success 'commit --squash works with -F' '
commit_for_rebase_autosquash_setup &&
diff --git a/t/t7703-repack-geometric.sh b/t/t7703-repack-geometric.sh
new file mode 100755
index 0000000000..5ccaa440e0
--- /dev/null
+++ b/t/t7703-repack-geometric.sh
@@ -0,0 +1,183 @@
+#!/bin/sh
+
+test_description='git repack --geometric works correctly'
+
+. ./test-lib.sh
+
+GIT_TEST_MULTI_PACK_INDEX=0
+
+objdir=.git/objects
+midx=$objdir/pack/multi-pack-index
+
+test_expect_success '--geometric with no packs' '
+ git init geometric &&
+ test_when_finished "rm -fr geometric" &&
+ (
+ cd geometric &&
+
+ git repack --geometric 2 >out &&
+ test_i18ngrep "Nothing new to pack" out
+ )
+'
+
+test_expect_success '--geometric with one pack' '
+ git init geometric &&
+ test_when_finished "rm -fr geometric" &&
+ (
+ cd geometric &&
+
+ test_commit "base" &&
+ git repack -d &&
+
+ git repack --geometric 2 >out &&
+
+ test_i18ngrep "Nothing new to pack" out
+ )
+'
+
+test_expect_success '--geometric with an intact progression' '
+ git init geometric &&
+ test_when_finished "rm -fr geometric" &&
+ (
+ cd geometric &&
+
+ # These packs already form a geometric progression.
+ test_commit_bulk --start=1 1 && # 3 objects
+ test_commit_bulk --start=2 2 && # 6 objects
+ test_commit_bulk --start=4 4 && # 12 objects
+
+ find $objdir/pack -name "*.pack" | sort >expect &&
+ git repack --geometric 2 -d &&
+ find $objdir/pack -name "*.pack" | sort >actual &&
+
+ test_cmp expect actual
+ )
+'
+
+test_expect_success '--geometric with loose objects' '
+ git init geometric &&
+ test_when_finished "rm -fr geometric" &&
+ (
+ cd geometric &&
+
+ # These packs already form a geometric progression.
+ test_commit_bulk --start=1 1 && # 3 objects
+ test_commit_bulk --start=2 2 && # 6 objects
+ # The loose objects are packed together, breaking the
+ # progression.
+ test_commit loose && # 3 objects
+
+ find $objdir/pack -name "*.pack" | sort >before &&
+ git repack --geometric 2 -d &&
+ find $objdir/pack -name "*.pack" | sort >after &&
+
+ comm -13 before after >new &&
+ comm -23 before after >removed &&
+
+ test_line_count = 1 new &&
+ test_must_be_empty removed &&
+
+ git repack --geometric 2 -d &&
+ find $objdir/pack -name "*.pack" | sort >after &&
+
+ # The progression (3, 3, 6) is combined into one new pack.
+ test_line_count = 1 after
+ )
+'
+
+test_expect_success '--geometric with small-pack rollup' '
+ git init geometric &&
+ test_when_finished "rm -fr geometric" &&
+ (
+ cd geometric &&
+
+ test_commit_bulk --start=1 1 && # 3 objects
+ test_commit_bulk --start=2 1 && # 3 objects
+ find $objdir/pack -name "*.pack" | sort >small &&
+ test_commit_bulk --start=3 4 && # 12 objects
+ test_commit_bulk --start=7 8 && # 24 objects
+ find $objdir/pack -name "*.pack" | sort >before &&
+
+ git repack --geometric 2 -d &&
+
+ # Three packs in total; two of the existing large ones, and one
+ # new one.
+ find $objdir/pack -name "*.pack" | sort >after &&
+ test_line_count = 3 after &&
+ comm -3 small before | tr -d "\t" >large &&
+ grep -qFf large after
+ )
+'
+
+test_expect_success '--geometric with small- and large-pack rollup' '
+ git init geometric &&
+ test_when_finished "rm -fr geometric" &&
+ (
+ cd geometric &&
+
+ # size(small1) + size(small2) > size(medium) / 2
+ test_commit_bulk --start=1 1 && # 3 objects
+ test_commit_bulk --start=2 1 && # 3 objects
+ test_commit_bulk --start=2 3 && # 7 objects
+ test_commit_bulk --start=6 9 && # 27 objects &&
+
+ find $objdir/pack -name "*.pack" | sort >before &&
+
+ git repack --geometric 2 -d &&
+
+ find $objdir/pack -name "*.pack" | sort >after &&
+ comm -12 before after >untouched &&
+
+ # Two packs in total; the largest pack from before running "git
+ # repack", and one new one.
+ test_line_count = 1 untouched &&
+ test_line_count = 2 after
+ )
+'
+
+test_expect_success '--geometric ignores kept packs' '
+ git init geometric &&
+ test_when_finished "rm -fr geometric" &&
+ (
+ cd geometric &&
+
+ test_commit kept && # 3 objects
+ test_commit pack && # 3 objects
+
+ KEPT=$(git pack-objects --revs $objdir/pack/pack <<-EOF
+ refs/tags/kept
+ EOF
+ ) &&
+ PACK=$(git pack-objects --revs $objdir/pack/pack <<-EOF
+ refs/tags/pack
+ ^refs/tags/kept
+ EOF
+ ) &&
+
+ # neither pack contains more than twice the number of objects in
+ # the other, so they should be combined. but, marking one as
+ # .kept on disk will "freeze" it, so the pack structure should
+ # remain unchanged.
+ touch $objdir/pack/pack-$KEPT.keep &&
+
+ find $objdir/pack -name "*.pack" | sort >before &&
+ git repack --geometric 2 -d &&
+ find $objdir/pack -name "*.pack" | sort >after &&
+
+ # both packs should still exist
+ test_path_is_file $objdir/pack/pack-$KEPT.pack &&
+ test_path_is_file $objdir/pack/pack-$PACK.pack &&
+
+ # and no new packs should be created
+ test_cmp before after &&
+
+ # Passing --pack-kept-objects causes packs with a .keep file to
+ # be repacked, too.
+ git repack --geometric 2 -d --pack-kept-objects &&
+
+ find $objdir/pack -name "*.pack" >after &&
+ test_line_count = 1 after
+ )
+'
+
+test_done
diff --git a/t/t7810-grep.sh b/t/t7810-grep.sh
index edfaa9a6d1..5830733f3d 100755
--- a/t/t7810-grep.sh
+++ b/t/t7810-grep.sh
@@ -969,7 +969,8 @@ do
"
done
-test_expect_success !PTHREADS 'grep --threads=N or pack.threads=N warns when no pthreads' '
+test_expect_success !PTHREADS,!FAIL_PREREQS \
+ 'grep --threads=N or pack.threads=N warns when no pthreads' '
git grep --threads=2 Hello hello_world 2>err &&
grep ^warning: err >warnings &&
test_line_count = 1 warnings &&
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 4eee9c3dcb..1a1caf8f2e 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -513,6 +513,38 @@ do
done
+test_expect_success $PREREQ "--validate respects relative core.hooksPath path" '
+ clean_fake_sendmail &&
+ mkdir my-hooks &&
+ test_when_finished "rm my-hooks.ran" &&
+ write_script my-hooks/sendemail-validate <<-\EOF &&
+ >my-hooks.ran
+ exit 1
+ EOF
+ test_config core.hooksPath "my-hooks" &&
+ test_must_fail git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ --validate \
+ longline.patch 2>err &&
+ test_path_is_file my-hooks.ran &&
+ grep "rejected by sendemail-validate" err
+'
+
+test_expect_success $PREREQ "--validate respects absolute core.hooksPath path" '
+ test_config core.hooksPath "$(pwd)/my-hooks" &&
+ test_when_finished "rm my-hooks.ran" &&
+ test_must_fail git send-email \
+ --from="Example <nobody@example.com>" \
+ --to=nobody@example.com \
+ --smtp-server="$(pwd)/fake.sendmail" \
+ --validate \
+ longline.patch 2>err &&
+ test_path_is_file my-hooks.ran &&
+ grep "rejected by sendemail-validate" err
+'
+
for enc in 7bit 8bit quoted-printable base64
do
test_expect_success $PREREQ "--transfer-encoding=$enc produces correct header" '
diff --git a/t/t9801-git-p4-branch.sh b/t/t9801-git-p4-branch.sh
index 56e64697a8..ff94c3f17d 100755
--- a/t/t9801-git-p4-branch.sh
+++ b/t/t9801-git-p4-branch.sh
@@ -203,19 +203,19 @@ test_expect_success 'git p4 clone simple branches' '
git p4 clone --dest=. --detect-branches //depot@all &&
git log --all --graph --decorate --stat &&
git reset --hard p4/depot/branch1 &&
- test -f file1 &&
- test -f file2 &&
- test -f file3 &&
+ test_path_is_file file1 &&
+ test_path_is_file file2 &&
+ test_path_is_file file3 &&
grep update file2 &&
git reset --hard p4/depot/branch2 &&
- test -f file1 &&
- test -f file2 &&
+ test_path_is_file file1 &&
+ test_path_is_file file2 &&
test ! -f file3 &&
! grep update file2 &&
git reset --hard p4/depot/branch3 &&
- test -f file1 &&
- test -f file2 &&
- test -f file3 &&
+ test_path_is_file file1 &&
+ test_path_is_file file2 &&
+ test_path_is_file file3 &&
grep update file2 &&
cd "$cli" &&
cd branch1 &&
@@ -606,22 +606,22 @@ test_expect_success 'git p4 clone simple branches with base folder on server sid
git p4 clone --dest=. --use-client-spec --detect-branches //depot@all &&
git log --all --graph --decorate --stat &&
git reset --hard p4/depot/branch1 &&
- test -f file1 &&
- test -f file2 &&
- test -f file3 &&
- test -f sub_file1 &&
+ test_path_is_file file1 &&
+ test_path_is_file file2 &&
+ test_path_is_file file3 &&
+ test_path_is_file sub_file1 &&
grep update file2 &&
git reset --hard p4/depot/branch2 &&
- test -f file1 &&
- test -f file2 &&
+ test_path_is_file file1 &&
+ test_path_is_file file2 &&
test ! -f file3 &&
- test -f sub_file1 &&
+ test_path_is_file sub_file1 &&
! grep update file2 &&
git reset --hard p4/depot/branch3 &&
- test -f file1 &&
- test -f file2 &&
- test -f file3 &&
- test -f sub_file1 &&
+ test_path_is_file file1 &&
+ test_path_is_file file2 &&
+ test_path_is_file file3 &&
+ test_path_is_file sub_file1 &&
grep update file2 &&
cd "$cli" &&
cd branch1 &&