aboutsummaryrefslogtreecommitdiffstats
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/Makefile14
-rw-r--r--t/helper/test-pack-deltas.c10
-rw-r--r--t/meson.build1
-rwxr-xr-xt/t0014-alias.sh57
-rwxr-xr-xt/t0300-credentials.sh19
-rwxr-xr-xt/t1400-update-ref.sh53
-rwxr-xr-xt/t1421-reflog-write.sh126
-rwxr-xr-xt/t1460-refs-migrate.sh22
-rwxr-xr-xt/t3404-rebase-interactive.sh1
-rwxr-xr-xt/t3415-rebase-autosquash.sh28
-rwxr-xr-xt/t3701-add-interactive.sh53
-rwxr-xr-xt/t3904-stash-patch.sh19
-rwxr-xr-xt/t4013-diff-various.sh13
-rwxr-xr-xt/t4015-diff-whitespace.sh8
-rwxr-xr-xt/t4035-diff-quiet.sh4
-rwxr-xr-xt/t4053-diff-no-index.sh33
-rwxr-xr-xt/t4211-line-log.sh2
-rw-r--r--t/t4211/sha1/expect.multiple6
-rw-r--r--t/t4211/sha1/expect.no-assertion-error90
-rw-r--r--t/t4211/sha1/expect.two-ranges6
-rw-r--r--t/t4211/sha256/expect.multiple6
-rw-r--r--t/t4211/sha256/expect.no-assertion-error90
-rw-r--r--t/t4211/sha256/expect.two-ranges6
-rwxr-xr-xt/t5319-multi-pack-index.sh22
-rwxr-xr-xt/t5510-fetch.sh114
-rwxr-xr-xt/t5516-fetch-push.sh54
-rwxr-xr-xt/t5530-upload-pack-error.sh68
-rwxr-xr-xt/t5564-http-proxy.sh4
-rwxr-xr-xt/t6137-pathspec-wildcards-literal.sh12
-rwxr-xr-xt/t6423-merge-rename-directories.sh519
-rwxr-xr-xt/t7508-status.sh11
-rwxr-xr-xt/t7528-signed-commit-ssh.sh2
-rwxr-xr-xt/t7700-repack.sh63
33 files changed, 1396 insertions, 140 deletions
diff --git a/t/Makefile b/t/Makefile
index 757674e727..ab8a5b54aa 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -189,15 +189,9 @@ perf:
.PHONY: libgit-sys-test libgit-rs-test
libgit-sys-test:
- $(QUIET)(\
- cd ../contrib/libgit-sys && \
- cargo test \
- )
-libgit-rs-test:
- $(QUIET)(\
- cd ../contrib/libgit-rs && \
- cargo test \
- )
+ $(QUIET)cargo test --manifest-path ../contrib/libgit-sys/Cargo.toml
+libgit-rs-test: libgit-sys-test
+ $(QUIET)cargo test --manifest-path ../contrib/libgit-rs/Cargo.toml
ifdef INCLUDE_LIBGIT_RS
-all:: libgit-sys-test libgit-rs-test
+all:: libgit-rs-test
endif
diff --git a/t/helper/test-pack-deltas.c b/t/helper/test-pack-deltas.c
index 4caa024b1e..4981401eaa 100644
--- a/t/helper/test-pack-deltas.c
+++ b/t/helper/test-pack-deltas.c
@@ -51,16 +51,14 @@ static void write_ref_delta(struct hashfile *f,
unsigned long size, base_size, delta_size, compressed_size, hdrlen;
enum object_type type;
void *base_buf, *delta_buf;
- void *buf = repo_read_object_file(the_repository,
- oid, &type,
- &size);
+ void *buf = odb_read_object(the_repository->objects,
+ oid, &type, &size);
if (!buf)
die("unable to read %s", oid_to_hex(oid));
- base_buf = repo_read_object_file(the_repository,
- base, &type,
- &base_size);
+ base_buf = odb_read_object(the_repository->objects,
+ base, &type, &base_size);
if (!base_buf)
die("unable to read %s", oid_to_hex(base));
diff --git a/t/meson.build b/t/meson.build
index bbeba1a8d5..983245501c 100644
--- a/t/meson.build
+++ b/t/meson.build
@@ -204,6 +204,7 @@ integration_tests = [
't1418-reflog-exists.sh',
't1419-exclude-refs.sh',
't1420-lost-found.sh',
+ 't1421-reflog-write.sh',
't1430-bad-ref-name.sh',
't1450-fsck.sh',
't1451-fsck-buffer.sh',
diff --git a/t/t0014-alias.sh b/t/t0014-alias.sh
index 854d59ec58..07a53e7366 100755
--- a/t/t0014-alias.sh
+++ b/t/t0014-alias.sh
@@ -27,6 +27,20 @@ test_expect_success 'looping aliases - internal execution' '
test_grep "^fatal: alias loop detected: expansion of" output
'
+test_expect_success 'looping aliases - deprecated builtins' '
+ test_config alias.whatchanged pack-redundant &&
+ test_config alias.pack-redundant whatchanged &&
+ cat >expect <<-EOF &&
+ ${SQ}whatchanged${SQ} is aliased to ${SQ}pack-redundant${SQ}
+ ${SQ}pack-redundant${SQ} is aliased to ${SQ}whatchanged${SQ}
+ fatal: alias loop detected: expansion of ${SQ}whatchanged${SQ} does not terminate:
+ whatchanged <==
+ pack-redundant ==>
+ EOF
+ test_must_fail git whatchanged -h 2>actual &&
+ test_cmp expect actual
+'
+
# This test is disabled until external loops are fixed, because would block
# the test suite for a full minute.
#
@@ -55,4 +69,47 @@ test_expect_success 'tracing a shell alias with arguments shows trace of prepare
test_cmp expect actual
'
+can_alias_deprecated_builtin () {
+ cmd="$1" &&
+ # some git(1) commands will fail for `-h` (the case for
+ # git-status as of 2025-09-07)
+ test_might_fail git status -h >expect &&
+ test_file_not_empty expect &&
+ test_might_fail git -c alias."$cmd"=status "$cmd" -h >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success 'can alias-shadow deprecated builtins' '
+ for cmd in $(git --list-cmds=deprecated)
+ do
+ can_alias_deprecated_builtin "$cmd" || return 1
+ done
+'
+
+test_expect_success 'can alias-shadow via two deprecated builtins' '
+ # some git(1) commands will fail... (see above)
+ test_might_fail git status -h >expect &&
+ test_file_not_empty expect &&
+ test_might_fail git -c alias.whatchanged=pack-redundant \
+ -c alias.pack-redundant=status whatchanged -h >actual &&
+ test_cmp expect actual
+'
+
+cannot_alias_regular_builtin () {
+ cmd="$1" &&
+ # some git(1) commands will fail... (see above)
+ test_might_fail git "$cmd" -h >expect &&
+ test_file_not_empty expect &&
+ test_might_fail git -c alias."$cmd"=status "$cmd" -h >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success 'cannot alias-shadow a sample of regular builtins' '
+ for cmd in grep check-ref-format interpret-trailers \
+ checkout-index fast-import diagnose rev-list prune
+ do
+ cannot_alias_regular_builtin "$cmd" || return 1
+ done
+'
+
test_done
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
index cb3a85c7ff..07aa834d33 100755
--- a/t/t0300-credentials.sh
+++ b/t/t0300-credentials.sh
@@ -991,18 +991,24 @@ test_expect_success 'url parser not confused by encoded markers' '
test_expect_success 'credential config with partial URLs' '
echo "echo password=yep" | write_script git-credential-yep &&
- test_write_lines url=https://user@example.com/repo.git >stdin &&
+ test_write_lines url=https://user@example.com/org/repo.git >stdin &&
for partial in \
example.com \
+ example.com/org/repo.git \
user@example.com \
+ user@example.com/org/repo.git \
https:// \
https://example.com \
https://example.com/ \
+ https://example.com/org \
+ https://example.com/org/ \
+ https://example.com/org/repo.git \
https://user@example.com \
https://user@example.com/ \
- https://example.com/repo.git \
- https://user@example.com/repo.git \
- /repo.git
+ https://user@example.com/org \
+ https://user@example.com/org/ \
+ https://user@example.com/org/repo.git \
+ /org/repo.git
do
git -c credential.$partial.helper=yep \
credential fill <stdin >stdout &&
@@ -1012,7 +1018,12 @@ test_expect_success 'credential config with partial URLs' '
for partial in \
dont.use.this \
+ example.com/o \
+ user@example.com/o \
http:// \
+ https://example.com/o \
+ https://user@example.com/o \
+ /o \
/repo
do
git -c credential.$partial.helper=yep \
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 96648a6e5d..08d5df2af7 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -2294,6 +2294,59 @@ do
)
'
+ test_expect_success CASE_INSENSITIVE_FS,REFFILES "stdin $type batch-updates existing reference" '
+ git init repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+ test_commit one &&
+ old_head=$(git rev-parse HEAD) &&
+ test_commit two &&
+ head=$(git rev-parse HEAD) &&
+
+ {
+ format_command $type "create refs/heads/foo" "$head" &&
+ format_command $type "create refs/heads/ref" "$old_head" &&
+ format_command $type "create refs/heads/Foo" "$old_head"
+ } >stdin &&
+ git update-ref $type --stdin --batch-updates <stdin >stdout &&
+
+ echo $head >expect &&
+ git rev-parse refs/heads/foo >actual &&
+ echo $old_head >expect &&
+ git rev-parse refs/heads/ref >actual &&
+ test_cmp expect actual &&
+ test_grep -q "reference conflict due to case-insensitive filesystem" stdout
+ )
+ '
+
+ test_expect_success CASE_INSENSITIVE_FS "stdin $type batch-updates existing reference" '
+ git init --ref-format=reftable repo &&
+ test_when_finished "rm -fr repo" &&
+ (
+ cd repo &&
+ test_commit one &&
+ old_head=$(git rev-parse HEAD) &&
+ test_commit two &&
+ head=$(git rev-parse HEAD) &&
+
+ {
+ format_command $type "create refs/heads/foo" "$head" &&
+ format_command $type "create refs/heads/ref" "$old_head" &&
+ format_command $type "create refs/heads/Foo" "$old_head"
+ } >stdin &&
+ git update-ref $type --stdin --batch-updates <stdin >stdout &&
+
+ echo $head >expect &&
+ git rev-parse refs/heads/foo >actual &&
+ echo $old_head >expect &&
+ git rev-parse refs/heads/ref >actual &&
+ test_cmp expect actual &&
+ git rev-parse refs/heads/Foo >actual &&
+ test_cmp expect actual
+ )
+ '
+
test_expect_success "stdin $type batch-updates delete incorrect symbolic ref" '
git init repo &&
test_when_finished "rm -fr repo" &&
diff --git a/t/t1421-reflog-write.sh b/t/t1421-reflog-write.sh
new file mode 100755
index 0000000000..46df64c176
--- /dev/null
+++ b/t/t1421-reflog-write.sh
@@ -0,0 +1,126 @@
+#!/bin/sh
+
+test_description='Manually write reflog entries'
+
+. ./test-lib.sh
+
+SIGNATURE="C O Mitter <committer@example.com> 1112911993 -0700"
+
+test_reflog_matches () {
+ repo="$1" &&
+ refname="$2" &&
+ cat >actual &&
+ test-tool -C "$repo" ref-store main for-each-reflog-ent "$refname" >expected &&
+ test_cmp expected actual
+}
+
+test_expect_success 'invalid number of arguments' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ for args in "" "1" "1 2" "1 2 3" "1 2 3 4 5"
+ do
+ test_must_fail git reflog write $args 2>err &&
+ test_grep "usage: git reflog write" err || return 1
+ done
+ )
+'
+
+test_expect_success 'invalid refname' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_must_fail git reflog write "refs/heads/ invalid" $ZERO_OID $ZERO_OID first 2>err &&
+ test_grep "invalid reference name: " err
+ )
+'
+
+test_expect_success 'unqualified refname is rejected' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_must_fail git reflog write unqualified $ZERO_OID $ZERO_OID first 2>err &&
+ test_grep "invalid reference name: " err
+ )
+'
+
+test_expect_success 'nonexistent object IDs' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_must_fail git reflog write refs/heads/something $(test_oid deadbeef) $ZERO_OID old-object-id 2>err &&
+ test_grep "old object .* does not exist" err &&
+ test_must_fail git reflog write refs/heads/something $ZERO_OID $(test_oid deadbeef) new-object-id 2>err &&
+ test_grep "new object .* does not exist" err
+ )
+'
+
+test_expect_success 'abbreviated object IDs' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ abbreviated_oid=$(git rev-parse HEAD | test_copy_bytes 8) &&
+ test_must_fail git reflog write refs/heads/something $abbreviated_oid $ZERO_OID old-object-id 2>err &&
+ test_grep "invalid old object ID" err &&
+ test_must_fail git reflog write refs/heads/something $ZERO_OID $abbreviated_oid new-object-id 2>err &&
+ test_grep "invalid new object ID" err
+ )
+'
+
+test_expect_success 'reflog message gets normalized' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ COMMIT_OID=$(git rev-parse HEAD) &&
+ git reflog write HEAD $COMMIT_OID $COMMIT_OID "$(printf "message\nwith\nnewlines")" &&
+ git reflog show -1 --format=%gs HEAD >actual &&
+ echo "message with newlines" >expected &&
+ test_cmp expected actual
+ )
+'
+
+test_expect_success 'simple writes' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ COMMIT_OID=$(git rev-parse HEAD) &&
+
+ git reflog write refs/heads/something $ZERO_OID $COMMIT_OID first &&
+ test_reflog_matches . refs/heads/something <<-EOF &&
+ $ZERO_OID $COMMIT_OID $SIGNATURE first
+ EOF
+
+ git reflog write refs/heads/something $COMMIT_OID $COMMIT_OID second &&
+ test_reflog_matches . refs/heads/something <<-EOF
+ $ZERO_OID $COMMIT_OID $SIGNATURE first
+ $COMMIT_OID $COMMIT_OID $SIGNATURE second
+ EOF
+ )
+'
+
+test_expect_success 'can write to root ref' '
+ test_when_finished "rm -rf repo" &&
+ git init repo &&
+ (
+ cd repo &&
+ test_commit initial &&
+ COMMIT_OID=$(git rev-parse HEAD) &&
+
+ git reflog write ROOT_REF_HEAD $ZERO_OID $COMMIT_OID first &&
+ test_reflog_matches . ROOT_REF_HEAD <<-EOF
+ $ZERO_OID $COMMIT_OID $SIGNATURE first
+ EOF
+ )
+'
+
+test_done
diff --git a/t/t1460-refs-migrate.sh b/t/t1460-refs-migrate.sh
index 2ab97e1b7d..0e1116a319 100755
--- a/t/t1460-refs-migrate.sh
+++ b/t/t1460-refs-migrate.sh
@@ -7,6 +7,17 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
. ./test-lib.sh
+print_all_reflog_entries () {
+ repo=$1 &&
+ test-tool -C "$repo" ref-store main for-each-reflog >reflogs &&
+ while read reflog
+ do
+ echo "REFLOG: $reflog" &&
+ test-tool -C "$repo" ref-store main for-each-reflog-ent "$reflog" ||
+ return 1
+ done <reflogs
+}
+
# Migrate the provided repository from one format to the other and
# verify that the references and logs are migrated over correctly.
# Usage: test_migration <repo> <format> [<skip_reflog_verify> [<options...>]]
@@ -28,8 +39,7 @@ test_migration () {
--format='%(refname) %(objectname) %(symref)' >expect &&
if ! $skip_reflog_verify
then
- git -C "$repo" reflog --all >expect_logs &&
- git -C "$repo" reflog list >expect_log_list
+ print_all_reflog_entries "$repo" >expect_logs
fi &&
git -C "$repo" refs migrate --ref-format="$format" "$@" &&
@@ -39,10 +49,8 @@ test_migration () {
test_cmp expect actual &&
if ! $skip_reflog_verify
then
- git -C "$repo" reflog --all >actual_logs &&
- git -C "$repo" reflog list >actual_log_list &&
- test_cmp expect_logs actual_logs &&
- test_cmp expect_log_list actual_log_list
+ print_all_reflog_entries "$repo" >actual_logs &&
+ test_cmp expect_logs actual_logs
fi &&
git -C "$repo" rev-parse --show-ref-format >actual &&
@@ -273,7 +281,7 @@ test_expect_success 'multiple reftable blocks with multiple entries' '
test_commit -C repo second &&
printf "update refs/heads/ref-%d HEAD\n" $(test_seq 3000) >stdin &&
git -C repo update-ref --stdin <stdin &&
- test_migration repo reftable
+ test_migration repo reftable true
'
test_expect_success 'migrating from files format deletes backend files' '
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 6bac217ed3..34d6ad0770 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -2263,6 +2263,7 @@ test_expect_success 'non-merge commands reject merge commits' '
edit $oid
fixup $oid
squash $oid
+ drop $oid # acceptable, no advice
EOF
(
set_replace_editor todo &&
diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh
index 5d093e3a7a..5033411a43 100755
--- a/t/t3415-rebase-autosquash.sh
+++ b/t/t3415-rebase-autosquash.sh
@@ -486,12 +486,28 @@ test_expect_success 'fixup a fixup' '
test XZWY = $(git show | tr -cd W-Z)
'
-test_expect_success 'fixup does not clean up commit message' '
- oneline="#818" &&
- git commit --allow-empty -m "$oneline" &&
- git commit --fixup HEAD --allow-empty &&
- git -c commit.cleanup=strip rebase -ki --autosquash HEAD~2 &&
- test "$oneline" = "$(git show -s --format=%s)"
+test_expect_success 'pick and fixup respect commit.cleanup' '
+ git reset --hard base &&
+ test_commit --no-tag "fixup! second commit" file1 fixup &&
+ test_commit something &&
+ write_script .git/hooks/prepare-commit-msg <<-\EOF &&
+ printf "\n# Prepared\n" >> "$1"
+ EOF
+ git rebase -i --autosquash HEAD~3 &&
+ test_commit_message HEAD~1 <<-\EOF &&
+ second commit
+
+ # Prepared
+ EOF
+ test_commit_message HEAD <<-\EOF &&
+ something
+
+ # Prepared
+ EOF
+ git reset --hard something &&
+ git -c commit.cleanup=strip rebase -i --autosquash HEAD~3 &&
+ test_commit_message HEAD~1 -m "second commit" &&
+ test_commit_message HEAD -m "something"
'
test_done
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index 04d2a19835..d9fe289a7a 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -866,6 +866,44 @@ test_expect_success 'colorized diffs respect diff.wsErrorHighlight' '
test_grep "old<" output
'
+test_expect_success 'diff color respects color.diff' '
+ git reset --hard &&
+
+ echo old >test &&
+ git add test &&
+ echo new >test &&
+
+ printf n >n &&
+ force_color git \
+ -c color.interactive=auto \
+ -c color.interactive.prompt=blue \
+ -c color.diff=false \
+ -c color.diff.old=red \
+ add -p >output.raw 2>&1 <n &&
+ test_decode_color <output.raw >output &&
+ test_grep "BLUE.*Stage this hunk" output &&
+ test_grep ! "RED" output
+'
+
+test_expect_success 're-coloring diff without color.interactive' '
+ git reset --hard &&
+
+ test_write_lines 1 2 3 >test &&
+ git add test &&
+ test_write_lines one 2 three >test &&
+
+ test_write_lines s n n |
+ force_color git \
+ -c color.interactive=false \
+ -c color.interactive.prompt=blue \
+ -c color.diff=true \
+ -c color.diff.frag="bold magenta" \
+ add -p >output.raw 2>&1 &&
+ test_decode_color <output.raw >output &&
+ test_grep "<BOLD;MAGENTA>@@" output &&
+ test_grep ! "BLUE" output
+'
+
test_expect_success 'diffFilter filters diff' '
git reset --hard &&
@@ -1283,6 +1321,12 @@ test_expect_success 'stash accepts -U and --inter-hunk-context' '
test_grep "@@ -2,20 +2,20 @@" actual
'
+test_expect_success 'set up base for -p color tests' '
+ echo commit >file &&
+ git commit -am "commit state" &&
+ git tag patch-base
+'
+
for cmd in add checkout commit reset restore "stash save" "stash push"
do
test_expect_success "$cmd rejects invalid context options" '
@@ -1299,6 +1343,15 @@ do
test_must_fail git $cmd --inter-hunk-context 2 2>actual &&
test_grep -E ".--inter-hunk-context. requires .(--interactive/)?--patch." actual
'
+
+ test_expect_success "$cmd falls back to color.ui" '
+ git reset --hard patch-base &&
+ echo working-tree >file &&
+ test_write_lines y |
+ force_color git -c color.ui=false $cmd -p >output.raw 2>&1 &&
+ test_decode_color <output.raw >output &&
+ test_cmp output.raw output
+ '
done
test_done
diff --git a/t/t3904-stash-patch.sh b/t/t3904-stash-patch.sh
index ae313e3c70..90a4ff2c10 100755
--- a/t/t3904-stash-patch.sh
+++ b/t/t3904-stash-patch.sh
@@ -107,4 +107,23 @@ test_expect_success 'stash -p with split hunk' '
! grep "added line 2" test
'
+test_expect_success 'stash -p not confused by GIT_PAGER_IN_USE' '
+ echo to-stash >test &&
+ # Set both GIT_PAGER_IN_USE and TERM. Our goal is to entice any
+ # diff subprocesses into thinking that they could output
+ # color, even though their stdout is not going into a tty.
+ echo y |
+ GIT_PAGER_IN_USE=1 TERM=vt100 git stash -p &&
+ git diff --exit-code
+'
+
+test_expect_success 'index push not confused by GIT_PAGER_IN_USE' '
+ echo index >test &&
+ git add test &&
+ echo working-tree >test &&
+ # As above, we try to entice the child diff into using color.
+ GIT_PAGER_IN_USE=1 TERM=vt100 git stash push test &&
+ git diff --exit-code
+'
+
test_done
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 8ebd170451..cfeec239e0 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -648,6 +648,19 @@ test_expect_success 'diff -I<regex>: detect malformed regex' '
test_grep "invalid regex given to -I: " error
'
+test_expect_success 'diff -I<regex>: ignore matching file' '
+ test_when_finished "git rm -f file1" &&
+ test_seq 50 >file1 &&
+ git add file1 &&
+ test_seq 50 | sed -e "s/13/ten and three/" -e "s/^[124-9].*/& /" >file1 &&
+
+ : >actual &&
+ git diff --raw --ignore-blank-lines -I"ten.*e" -I"^[124-9]" >>actual &&
+ git diff --name-only --ignore-blank-lines -I"ten.*e" -I"^[124-9]" >>actual &&
+ git diff --name-status --ignore-blank-lines -I"ten.*e" -I"^[124-9]" >>actual &&
+ test_grep ! "file1" actual
+'
+
# check_prefix <patch> <src> <dst>
# check only lines with paths to avoid dependency on exact oid/contents
check_prefix () {
diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index 52e3e476ff..9de7f73f42 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -11,12 +11,8 @@ test_description='Test special whitespace in diff engine.
. "$TEST_DIRECTORY"/lib-diff.sh
for opt_res in --patch --quiet -s --stat --shortstat --dirstat=lines \
- --raw! --name-only! --name-status!
+ --raw --name-only --name-status
do
- opts=${opt_res%!} expect_failure=
- test "$opts" = "$opt_res" ||
- expect_failure="test_expect_code 1"
-
test_expect_success "status with $opts (different)" '
echo foo >x &&
git add x &&
@@ -43,7 +39,7 @@ do
echo foo >x &&
git add x &&
echo " foo" >x &&
- $expect_failure git diff -w $opts --exit-code x
+ git diff -w $opts --exit-code x
'
done
diff --git a/t/t4035-diff-quiet.sh b/t/t4035-diff-quiet.sh
index 0352bf81a9..35eaf0855f 100755
--- a/t/t4035-diff-quiet.sh
+++ b/t/t4035-diff-quiet.sh
@@ -50,6 +50,10 @@ test_expect_success 'git diff-tree HEAD HEAD' '
test_expect_code 0 git diff-tree --quiet HEAD HEAD >cnt &&
test_line_count = 0 cnt
'
+test_expect_success 'git diff-tree -w HEAD^ HEAD' '
+ test_expect_code 1 git diff-tree --quiet -w HEAD^ HEAD >cnt &&
+ test_line_count = 0 cnt
+'
test_expect_success 'git diff-files' '
test_expect_code 0 git diff-files --quiet >cnt &&
test_line_count = 0 cnt
diff --git a/t/t4053-diff-no-index.sh b/t/t4053-diff-no-index.sh
index 01db9243ab..69599279e9 100755
--- a/t/t4053-diff-no-index.sh
+++ b/t/t4053-diff-no-index.sh
@@ -26,6 +26,23 @@ test_expect_success 'git diff --no-index directories' '
test_line_count = 14 cnt
'
+test_expect_success 'git diff --no-index with -' '
+ cat >expect <<-\EOF &&
+ diff --git a/- b/-
+ new file mode 100644
+ --- /dev/null
+ +++ b/-
+ @@ -0,0 +1 @@
+ +frotz
+ EOF
+ (
+ cd a &&
+ echo frotz |
+ test_expect_code 1 git diff --no-index /dev/null - >../actual
+ ) &&
+ test_cmp expect actual
+'
+
test_expect_success 'git diff --no-index relative path outside repo' '
(
cd repo &&
@@ -322,6 +339,22 @@ test_expect_success 'diff --no-index with pathspec' '
test_cmp expect actual
'
+test_expect_success 'diff --no-index first path ending in slash with pathspec' '
+ test_expect_code 1 git diff --name-status --no-index a/ b 1 >actual &&
+ cat >expect <<-EOF &&
+ D a/1
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'diff --no-index second path ending in slash with pathspec' '
+ test_expect_code 1 git diff --name-status --no-index a b/ 1 >actual &&
+ cat >expect <<-EOF &&
+ D a/1
+ EOF
+ test_cmp expect actual
+'
+
test_expect_success 'diff --no-index with pathspec no matches' '
test_expect_code 0 git diff --name-status --no-index a b missing
'
diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh
index 950451cf6a..0a7c3ca42f 100755
--- a/t/t4211-line-log.sh
+++ b/t/t4211-line-log.sh
@@ -78,6 +78,8 @@ canned_test "-L :main:a.c -L 4,18:a.c simple" multiple-overlapping
canned_test "-L 4:a.c -L 8,12:a.c simple" multiple-superset
canned_test "-L 8,12:a.c -L 4:a.c simple" multiple-superset
+canned_test "-L 10,16:b.c -L 18,26:b.c main" no-assertion-error
+
test_bad_opts "-L" "switch.*requires a value"
test_bad_opts "-L b.c" "argument not .start,end:file"
test_bad_opts "-L 1:" "argument not .start,end:file"
diff --git a/t/t4211/sha1/expect.multiple b/t/t4211/sha1/expect.multiple
index 76ad5b598c..1eee8a7801 100644
--- a/t/t4211/sha1/expect.multiple
+++ b/t/t4211/sha1/expect.multiple
@@ -102,3 +102,9 @@ diff --git a/a.c b/a.c
+ s++;
+ }
+}
+@@ -0,0 +16,5 @@
++int main ()
++{
++ printf("%d\n", f(15));
++ return 0;
++}
diff --git a/t/t4211/sha1/expect.no-assertion-error b/t/t4211/sha1/expect.no-assertion-error
new file mode 100644
index 0000000000..994c37db1e
--- /dev/null
+++ b/t/t4211/sha1/expect.no-assertion-error
@@ -0,0 +1,90 @@
+commit 0d8dcfc6b968e06a27d5215bad1fdde3de9d6235
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:50:24 2013 +0100
+
+ move within the file
+
+diff --git a/b.c b/b.c
+--- a/b.c
++++ b/b.c
+@@ -25,0 +18,9 @@
++long f(long x)
++{
++ int s = 0;
++ while (x) {
++ x /= 2;
++ s++;
++ }
++ return s;
++}
+
+commit 4659538844daa2849b1a9e7d6fadb96fcd26fc83
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:48:43 2013 +0100
+
+ change back to complete line
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -18,5 +18,7 @@
+ int main ()
+ {
+ printf("%ld\n", f(15));
+ return 0;
+-}
+\ No newline at end of file
++}
++
++/* incomplete lines are bad! */
+
+commit 100b61a6f2f720f812620a9d10afb3a960ccb73c
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:48:10 2013 +0100
+
+ change to an incomplete line at end
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -18,5 +18,5 @@
+ int main ()
+ {
+ printf("%ld\n", f(15));
+ return 0;
+-}
++}
+\ No newline at end of file
+
+commit a6eb82647d5d67f893da442f8f9375fd89a3b1e2
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:45:16 2013 +0100
+
+ touch both functions
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -17,5 +17,5 @@
+ int main ()
+ {
+- printf("%d\n", f(15));
++ printf("%ld\n", f(15));
+ return 0;
+ }
+
+commit de4c48ae814792c02a49c4c3c0c757ae69c55f6a
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:44:48 2013 +0100
+
+ initial
+
+diff --git a/a.c b/a.c
+--- /dev/null
++++ b/a.c
+@@ -0,0 +16,5 @@
++int main ()
++{
++ printf("%d\n", f(15));
++ return 0;
++}
diff --git a/t/t4211/sha1/expect.two-ranges b/t/t4211/sha1/expect.two-ranges
index 6109aa0dce..c5164f3be3 100644
--- a/t/t4211/sha1/expect.two-ranges
+++ b/t/t4211/sha1/expect.two-ranges
@@ -100,3 +100,9 @@ diff --git a/a.c b/a.c
+ s++;
+ }
+}
+@@ -0,0 +16,5 @@
++int main ()
++{
++ printf("%d\n", f(15));
++ return 0;
++}
diff --git a/t/t4211/sha256/expect.multiple b/t/t4211/sha256/expect.multiple
index ca00409b9a..dbd987b74a 100644
--- a/t/t4211/sha256/expect.multiple
+++ b/t/t4211/sha256/expect.multiple
@@ -102,3 +102,9 @@ diff --git a/a.c b/a.c
+ s++;
+ }
+}
+@@ -0,0 +16,5 @@
++int main ()
++{
++ printf("%d\n", f(15));
++ return 0;
++}
diff --git a/t/t4211/sha256/expect.no-assertion-error b/t/t4211/sha256/expect.no-assertion-error
new file mode 100644
index 0000000000..36ed12aa9c
--- /dev/null
+++ b/t/t4211/sha256/expect.no-assertion-error
@@ -0,0 +1,90 @@
+commit eb871b8aa9aff323e484723039c9a92ab0266e060bc0ef2afb08fadda25c5ace
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:50:24 2013 +0100
+
+ move within the file
+
+diff --git a/b.c b/b.c
+--- a/b.c
++++ b/b.c
+@@ -25,0 +18,9 @@
++long f(long x)
++{
++ int s = 0;
++ while (x) {
++ x /= 2;
++ s++;
++ }
++ return s;
++}
+
+commit 5526ed05c2476b56af8b7be499e8f78bd50f490740733a9ca7e1f55878fa90a9
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:48:43 2013 +0100
+
+ change back to complete line
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -18,5 +18,7 @@
+ int main ()
+ {
+ printf("%ld\n", f(15));
+ return 0;
+-}
+\ No newline at end of file
++}
++
++/* incomplete lines are bad! */
+
+commit 29f32ac3141c48b22803e5c4127b719917b67d0f8ca8c5248bebfa2a19f7da10
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:48:10 2013 +0100
+
+ change to an incomplete line at end
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -18,5 +18,5 @@
+ int main ()
+ {
+ printf("%ld\n", f(15));
+ return 0;
+-}
++}
+\ No newline at end of file
+
+commit ccf97b9878189c40a981da50b15713bb80a35755326320ec80900caf22ced46f
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:45:16 2013 +0100
+
+ touch both functions
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -17,5 +17,5 @@
+ int main ()
+ {
+- printf("%d\n", f(15));
++ printf("%ld\n", f(15));
+ return 0;
+ }
+
+commit 1dd7e9b2b1699324b53b341e728653b913bc192a14dfea168c5b51f2b3d03592
+Author: Thomas Rast <trast@student.ethz.ch>
+Date: Thu Feb 28 10:44:48 2013 +0100
+
+ initial
+
+diff --git a/a.c b/a.c
+--- /dev/null
++++ b/a.c
+@@ -0,0 +16,5 @@
++int main ()
++{
++ printf("%d\n", f(15));
++ return 0;
++}
diff --git a/t/t4211/sha256/expect.two-ranges b/t/t4211/sha256/expect.two-ranges
index af57c8b997..6a94d3b9cb 100644
--- a/t/t4211/sha256/expect.two-ranges
+++ b/t/t4211/sha256/expect.two-ranges
@@ -100,3 +100,9 @@ diff --git a/a.c b/a.c
+ s++;
+ }
+}
+@@ -0,0 +16,5 @@
++int main ()
++{
++ printf("%d\n", f(15));
++ return 0;
++}
diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh
index bd75dea950..2c22fdb931 100755
--- a/t/t5319-multi-pack-index.sh
+++ b/t/t5319-multi-pack-index.sh
@@ -989,6 +989,23 @@ test_expect_success 'repack --batch-size=0 repacks everything' '
)
'
+test_expect_success EXPENSIVE 'repack/expire with many packs' '
+ cp -r dup many &&
+ (
+ cd many &&
+
+ for i in $(test_seq 1 100)
+ do
+ test_commit extra$i &&
+ git maintenance run --task=loose-objects || return 1
+ done &&
+
+ git multi-pack-index write &&
+ git multi-pack-index repack &&
+ git multi-pack-index expire
+ )
+'
+
test_expect_success 'repack --batch-size=<large> repacks everything' '
(
cd dup2 &&
@@ -1083,7 +1100,10 @@ test_expect_success 'load reverse index when missing .idx, .pack' '
mv $idx.bak $idx &&
mv $pack $pack.bak &&
- git cat-file --batch-check="%(objectsize:disk)" <tip
+ git cat-file --batch-check="%(objectsize:disk)" <tip &&
+
+ test_must_fail git multi-pack-index write 2>err &&
+ test_grep "could not load pack" err
)
'
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index ebc696546b..6b2739db26 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -47,7 +47,25 @@ test_expect_success "clone and setup child repos" '
git config set branch.main.merge refs/heads/one
) &&
git clone . bundle &&
- git clone . seven
+ git clone . seven &&
+ git clone --ref-format=reftable . case_sensitive &&
+ (
+ cd case_sensitive &&
+ git branch branch1 &&
+ git branch bRanch1
+ ) &&
+ git clone --ref-format=reftable . case_sensitive_fd &&
+ (
+ cd case_sensitive_fd &&
+ git branch foo/bar &&
+ git branch Foo
+ ) &&
+ git clone --ref-format=reftable . case_sensitive_df &&
+ (
+ cd case_sensitive_df &&
+ git branch Foo/bar &&
+ git branch foo
+ )
'
test_expect_success "fetch test" '
@@ -1526,6 +1544,100 @@ test_expect_success SYMLINKS 'clone does not get confused by a D/F conflict' '
test_path_is_missing whoops
'
+test_expect_success CASE_INSENSITIVE_FS,REFFILES 'existing references in a case insensitive filesystem' '
+ test_when_finished rm -rf case_insensitive &&
+ (
+ git init --bare case_insensitive &&
+ cd case_insensitive &&
+ git remote add origin -- ../case_sensitive &&
+ test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err &&
+ test_grep "You${SQ}re on a case-insensitive filesystem" err &&
+ git rev-parse refs/heads/main >expect &&
+ git rev-parse refs/heads/branch1 >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success REFFILES 'existing reference lock in repo' '
+ test_when_finished rm -rf base repo &&
+ (
+ git init --ref-format=reftable base &&
+ cd base &&
+ echo >file update &&
+ git add . &&
+ git commit -m "updated" &&
+ git branch -M main &&
+
+ git update-ref refs/heads/foo @ &&
+ git update-ref refs/heads/branch @ &&
+ cd .. &&
+
+ git init --ref-format=files --bare repo &&
+ cd repo &&
+ git remote add origin ../base &&
+ touch refs/heads/foo.lock &&
+ test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err &&
+ test_grep "error: fetching ref refs/heads/foo failed: reference already exists" err &&
+ git rev-parse refs/heads/main >expect &&
+ git rev-parse refs/heads/branch >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success CASE_INSENSITIVE_FS,REFFILES 'F/D conflict on case insensitive filesystem' '
+ test_when_finished rm -rf case_insensitive &&
+ (
+ git init --bare case_insensitive &&
+ cd case_insensitive &&
+ git remote add origin -- ../case_sensitive_fd &&
+ test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err &&
+ test_grep "failed: refname conflict" err &&
+ git rev-parse refs/heads/main >expect &&
+ git rev-parse refs/heads/foo/bar >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success CASE_INSENSITIVE_FS,REFFILES 'D/F conflict on case insensitive filesystem' '
+ test_when_finished rm -rf case_insensitive &&
+ (
+ git init --bare case_insensitive &&
+ cd case_insensitive &&
+ git remote add origin -- ../case_sensitive_df &&
+ test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err &&
+ test_grep "failed: refname conflict" err &&
+ git rev-parse refs/heads/main >expect &&
+ git rev-parse refs/heads/Foo/bar >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success REFFILES 'D/F conflict on case sensitive filesystem with lock' '
+ (
+ git init --ref-format=reftable base &&
+ cd base &&
+ echo >file update &&
+ git add . &&
+ git commit -m "updated" &&
+ git branch -M main &&
+
+ git update-ref refs/heads/foo @ &&
+ git update-ref refs/heads/branch @ &&
+ cd .. &&
+
+ git init --ref-format=files --bare repo &&
+ cd repo &&
+ git remote add origin ../base &&
+ mkdir refs/heads/foo &&
+ touch refs/heads/foo/random.lock &&
+ test_must_fail git fetch origin "refs/heads/*:refs/heads/*" 2>err &&
+ test_grep "some local refs could not be updated; try running" err &&
+ git rev-parse refs/heads/main >expect &&
+ git rev-parse refs/heads/branch >actual &&
+ test_cmp expect actual
+ )
+'
+
. "$TEST_DIRECTORY"/lib-httpd.sh
start_httpd
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 4e9c27b0f2..46926e7bbd 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -105,7 +105,6 @@ check_push_result () {
}
test_expect_success setup '
-
>path1 &&
git add path1 &&
test_tick &&
@@ -117,7 +116,6 @@ test_expect_success setup '
test_tick &&
git commit -a -m second &&
the_commit=$(git show-ref -s --verify refs/heads/main)
-
'
for cmd in push fetch
@@ -322,104 +320,82 @@ test_expect_success 'push with pushInsteadOf and explicit pushurl (pushInsteadOf
'
test_expect_success 'push with matching heads' '
-
mk_test testrepo heads/main &&
git push testrepo : &&
check_push_result testrepo $the_commit heads/main
-
'
test_expect_success 'push with matching heads on the command line' '
-
mk_test testrepo heads/main &&
git push testrepo : &&
check_push_result testrepo $the_commit heads/main
-
'
test_expect_success 'failed (non-fast-forward) push with matching heads' '
-
mk_test testrepo heads/main &&
git push testrepo : &&
git commit --amend -massaged &&
test_must_fail git push testrepo &&
check_push_result testrepo $the_commit heads/main &&
git reset --hard $the_commit
-
'
test_expect_success 'push --force with matching heads' '
-
mk_test testrepo heads/main &&
git push testrepo : &&
git commit --amend -massaged &&
git push --force testrepo : &&
! check_push_result testrepo $the_commit heads/main &&
git reset --hard $the_commit
-
'
test_expect_success 'push with matching heads and forced update' '
-
mk_test testrepo heads/main &&
git push testrepo : &&
git commit --amend -massaged &&
git push testrepo +: &&
! check_push_result testrepo $the_commit heads/main &&
git reset --hard $the_commit
-
'
test_expect_success 'push with no ambiguity (1)' '
-
mk_test testrepo heads/main &&
git push testrepo main:main &&
check_push_result testrepo $the_commit heads/main
-
'
test_expect_success 'push with no ambiguity (2)' '
-
mk_test testrepo remotes/origin/main &&
git push testrepo main:origin/main &&
check_push_result testrepo $the_commit remotes/origin/main
-
'
test_expect_success 'push with colon-less refspec, no ambiguity' '
-
mk_test testrepo heads/main heads/t/main &&
git branch -f t/main main &&
git push testrepo main &&
check_push_result testrepo $the_commit heads/main &&
check_push_result testrepo $the_first_commit heads/t/main
-
'
test_expect_success 'push with weak ambiguity (1)' '
-
mk_test testrepo heads/main remotes/origin/main &&
git push testrepo main:main &&
check_push_result testrepo $the_commit heads/main &&
check_push_result testrepo $the_first_commit remotes/origin/main
-
'
test_expect_success 'push with weak ambiguity (2)' '
-
mk_test testrepo heads/main remotes/origin/main remotes/another/main &&
git push testrepo main:main &&
check_push_result testrepo $the_commit heads/main &&
check_push_result testrepo $the_first_commit remotes/origin/main remotes/another/main
-
'
test_expect_success 'push with ambiguity' '
-
mk_test testrepo heads/frotz tags/frotz &&
test_must_fail git push testrepo main:frotz &&
check_push_result testrepo $the_first_commit heads/frotz tags/frotz
-
'
test_expect_success 'push with onelevel ref' '
@@ -428,17 +404,14 @@ test_expect_success 'push with onelevel ref' '
'
test_expect_success 'push with colon-less refspec (1)' '
-
mk_test testrepo heads/frotz tags/frotz &&
git branch -f frotz main &&
git push testrepo frotz &&
check_push_result testrepo $the_commit heads/frotz &&
check_push_result testrepo $the_first_commit tags/frotz
-
'
test_expect_success 'push with colon-less refspec (2)' '
-
mk_test testrepo heads/frotz tags/frotz &&
if git show-ref --verify -q refs/heads/frotz
then
@@ -448,7 +421,6 @@ test_expect_success 'push with colon-less refspec (2)' '
git push -f testrepo frotz &&
check_push_result testrepo $the_commit tags/frotz &&
check_push_result testrepo $the_first_commit heads/frotz
-
'
test_expect_success 'push with colon-less refspec (3)' '
@@ -465,7 +437,6 @@ test_expect_success 'push with colon-less refspec (3)' '
'
test_expect_success 'push with colon-less refspec (4)' '
-
mk_test testrepo &&
if git show-ref --verify -q refs/heads/frotz
then
@@ -475,38 +446,34 @@ test_expect_success 'push with colon-less refspec (4)' '
git push testrepo frotz &&
check_push_result testrepo $the_commit tags/frotz &&
test 1 = $( cd testrepo && git show-ref | wc -l )
-
'
test_expect_success 'push head with non-existent, incomplete dest' '
-
mk_test testrepo &&
git push testrepo main:branch &&
check_push_result testrepo $the_commit heads/branch
-
'
test_expect_success 'push tag with non-existent, incomplete dest' '
-
mk_test testrepo &&
git tag -f v1.0 &&
git push testrepo v1.0:tag &&
check_push_result testrepo $the_commit tags/tag
-
'
test_expect_success 'push oid with non-existent, incomplete dest' '
-
mk_test testrepo &&
test_must_fail git push testrepo $(git rev-parse main):foo
-
'
test_expect_success 'push ref expression with non-existent, incomplete dest' '
-
mk_test testrepo &&
test_must_fail git push testrepo main^:branch
+'
+test_expect_success 'push ref expression with non-existent oid src' '
+ mk_test testrepo &&
+ test_must_fail git push testrepo $(test_oid 001):branch
'
for head in HEAD @
@@ -550,7 +517,6 @@ do
git checkout main &&
git push testrepo $head:branch &&
check_push_result testrepo $the_commit heads/branch
-
'
test_expect_success "push with config remote.*.push = $head" '
@@ -596,7 +562,6 @@ test_expect_success 'push with remote.pushdefault' '
'
test_expect_success 'push with config remote.*.pushurl' '
-
mk_test testrepo heads/main &&
git checkout main &&
test_config remote.there.url test2repo &&
@@ -655,7 +620,6 @@ test_expect_success 'push ignores "branch." config without subsection' '
'
test_expect_success 'push with dry-run' '
-
mk_test testrepo heads/main &&
old_commit=$(git -C testrepo show-ref -s --verify refs/heads/main) &&
git push --dry-run testrepo : &&
@@ -663,7 +627,6 @@ test_expect_success 'push with dry-run' '
'
test_expect_success 'push updates local refs' '
-
mk_test testrepo heads/main &&
mk_child testrepo child &&
(
@@ -673,11 +636,9 @@ test_expect_success 'push updates local refs' '
test $(git rev-parse main) = \
$(git rev-parse remotes/origin/main)
)
-
'
test_expect_success 'push updates up-to-date local refs' '
-
mk_test testrepo heads/main &&
mk_child testrepo child1 &&
mk_child testrepo child2 &&
@@ -689,11 +650,9 @@ test_expect_success 'push updates up-to-date local refs' '
test $(git rev-parse main) = \
$(git rev-parse remotes/origin/main)
)
-
'
test_expect_success 'push preserves up-to-date packed refs' '
-
mk_test testrepo heads/main &&
mk_child testrepo child &&
(
@@ -701,11 +660,9 @@ test_expect_success 'push preserves up-to-date packed refs' '
git push &&
! test -f .git/refs/remotes/origin/main
)
-
'
test_expect_success 'push does not update local refs on failure' '
-
mk_test testrepo heads/main &&
mk_child testrepo child &&
echo "#!/no/frobnication/today" >testrepo/.git/hooks/pre-receive &&
@@ -717,16 +674,13 @@ test_expect_success 'push does not update local refs on failure' '
test $(git rev-parse main) != \
$(git rev-parse remotes/origin/main)
)
-
'
test_expect_success 'allow deleting an invalid remote ref' '
-
mk_test testrepo heads/branch &&
rm -f testrepo/.git/objects/??/* &&
git push testrepo :refs/heads/branch &&
(cd testrepo && test_must_fail git rev-parse --verify refs/heads/branch)
-
'
test_expect_success 'pushing valid refs triggers post-receive and post-update hooks' '
diff --git a/t/t5530-upload-pack-error.sh b/t/t5530-upload-pack-error.sh
index 558eedf25a..d40292cfb7 100755
--- a/t/t5530-upload-pack-error.sh
+++ b/t/t5530-upload-pack-error.sh
@@ -4,8 +4,6 @@ test_description='errors in upload-pack'
. ./test-lib.sh
-D=$(pwd)
-
corrupt_repo () {
object_sha1=$(git rev-parse "$1") &&
ob=$(expr "$object_sha1" : "\(..\)") &&
@@ -21,11 +19,7 @@ test_expect_success 'setup and corrupt repository' '
test_tick &&
echo changed >file &&
git commit -a -m changed &&
- corrupt_repo HEAD:file
-
-'
-
-test_expect_success 'fsck fails' '
+ corrupt_repo HEAD:file &&
test_must_fail git fsck
'
@@ -40,17 +34,12 @@ test_expect_success 'upload-pack fails due to error in pack-objects packing' '
'
test_expect_success 'corrupt repo differently' '
-
git hash-object -w file &&
- corrupt_repo HEAD^^{tree}
-
-'
-
-test_expect_success 'fsck fails' '
+ corrupt_repo HEAD^^{tree} &&
test_must_fail git fsck
'
-test_expect_success 'upload-pack fails due to error in rev-list' '
+test_expect_success 'upload-pack fails due to error in rev-list' '
printf "%04xwant %s\n%04xshallow %s00000009done\n0000" \
$(($hexsz + 10)) $(git rev-parse HEAD) \
$(($hexsz + 12)) $(git rev-parse HEAD^) >input &&
@@ -59,7 +48,6 @@ test_expect_success 'upload-pack fails due to error in rev-list' '
'
test_expect_success 'upload-pack fails due to bad want (no object)' '
-
printf "%04xwant %s multi_ack_detailed\n00000009done\n0000" \
$(($hexsz + 29)) $(test_oid deadbeef) >input &&
test_must_fail git upload-pack . <input >output 2>output.err &&
@@ -69,7 +57,6 @@ test_expect_success 'upload-pack fails due to bad want (no object)' '
'
test_expect_success 'upload-pack fails due to bad want (not tip)' '
-
oid=$(echo an object we have | git hash-object -w --stdin) &&
printf "%04xwant %s multi_ack_detailed\n00000009done\n0000" \
$(($hexsz + 29)) "$oid" >input &&
@@ -80,7 +67,6 @@ test_expect_success 'upload-pack fails due to bad want (not tip)' '
'
test_expect_success 'upload-pack fails due to error in pack-objects enumeration' '
-
printf "%04xwant %s\n00000009done\n0000" \
$((hexsz + 10)) $(git rev-parse HEAD) >input &&
test_must_fail git upload-pack . <input >/dev/null 2>output.err &&
@@ -105,18 +91,48 @@ test_expect_success 'upload-pack tolerates EOF just after stateless client wants
test_cmp expect actual
'
-test_expect_success 'create empty repository' '
-
- mkdir foo &&
- cd foo &&
- git init
-
-'
-
test_expect_success 'fetch fails' '
+ git init foo &&
+ test_must_fail git -C foo fetch .. main
+'
- test_must_fail git fetch .. main
+test_expect_success 'upload-pack ACKs repeated non-commit objects repeatedly (protocol v0)' '
+ commit_id=$(git rev-parse HEAD) &&
+ tree_id=$(git rev-parse HEAD^{tree}) &&
+ test-tool pkt-line pack >request <<-EOF &&
+ want $commit_id
+ 0000
+ have $tree_id
+ have $tree_id
+ 0000
+ EOF
+ git upload-pack --stateless-rpc . <request >actual &&
+ depacketize <actual >actual.raw &&
+ grep ^ACK actual.raw >actual.acks &&
+ cat >expect <<-EOF &&
+ ACK $tree_id
+ ACK $tree_id
+ EOF
+ test_cmp expect actual.acks
+'
+test_expect_success 'upload-pack ACKs repeated non-commit objects once only (protocol v2)' '
+ commit_id=$(git rev-parse HEAD) &&
+ tree_id=$(git rev-parse HEAD^{tree}) &&
+ test-tool pkt-line pack >request <<-EOF &&
+ command=fetch
+ object-format=$(test_oid algo)
+ 0001
+ want $commit_id
+ have $tree_id
+ have $tree_id
+ 0000
+ EOF
+ GIT_PROTOCOL=version=2 git upload-pack . <request >actual &&
+ depacketize <actual >actual.raw &&
+ grep ^ACK actual.raw >actual.acks &&
+ echo "ACK $tree_id" >expect &&
+ test_cmp expect actual.acks
'
test_done
diff --git a/t/t5564-http-proxy.sh b/t/t5564-http-proxy.sh
index b27e481f95..c3903faf2d 100755
--- a/t/t5564-http-proxy.sh
+++ b/t/t5564-http-proxy.sh
@@ -72,7 +72,9 @@ test_expect_success SOCKS_PROXY 'clone via Unix socket' '
test_when_finished "rm -rf clone" &&
test_config_global http.proxy "socks4://localhost$PWD/%2530.sock" && {
{
- GIT_TRACE_CURL=$PWD/trace git clone "$HTTPD_URL/smart/repo.git" clone 2>err &&
+ GIT_TRACE_CURL=$PWD/trace \
+ GIT_TRACE_CURL_COMPONENTS=socks \
+ git clone "$HTTPD_URL/smart/repo.git" clone 2>err &&
grep -i "SOCKS4 request granted" trace
} ||
old_libcurl_error err
diff --git a/t/t6137-pathspec-wildcards-literal.sh b/t/t6137-pathspec-wildcards-literal.sh
index 20abad5667..17a03085ef 100755
--- a/t/t6137-pathspec-wildcards-literal.sh
+++ b/t/t6137-pathspec-wildcards-literal.sh
@@ -3,8 +3,8 @@ test_description='test wildcards and literals with git add/commit (subshell styl
. ./test-lib.sh
-test_have_prereq FUNNYNAMES || {
- skip_all='skipping: needs FUNNYNAMES (non-Windows only)'
+test_have_prereq BSLASHPSPEC || {
+ skip_all='skipping: needs BSLASHPSPEC (backslashes in pathspecs)'
test_done
}
@@ -184,7 +184,7 @@ test_expect_success 'add wildcard f?z' '
)
'
-test_expect_success 'add literal \? literal' '
+test_expect_success 'add literal \?' '
git init test-q-lit &&
(
cd test-q-lit &&
@@ -241,7 +241,7 @@ test_expect_success 'add literal hello\?world' '
)
'
-test_expect_success 'add literal [abc]' '
+test_expect_success 'add literal \[abc\]' '
git init test-brackets-lit &&
(
cd test-brackets-lit &&
@@ -280,7 +280,7 @@ test_expect_success 'commit: wildcard *' '
)
'
-test_expect_success 'commit: literal *' '
+test_expect_success 'commit: literal \*' '
git init test-c-asterisk-lit &&
(
cd test-c-asterisk-lit &&
@@ -328,7 +328,7 @@ test_expect_success 'commit: literal f\*' '
)
'
-test_expect_success 'commit: wildcard pathspec limits commit' '
+test_expect_success 'commit: wildcard f**' '
git init test-c-pathlimit &&
(
cd test-c-pathlimit &&
diff --git a/t/t6423-merge-rename-directories.sh b/t/t6423-merge-rename-directories.sh
index f48ed6d035..533ac85dc8 100755
--- a/t/t6423-merge-rename-directories.sh
+++ b/t/t6423-merge-rename-directories.sh
@@ -4731,7 +4731,7 @@ test_setup_12i () {
mkdir -p source/subdir &&
echo foo >source/subdir/foo &&
- echo bar >source/bar &&
+ printf "%d\n" 1 2 3 4 5 6 7 >source/bar &&
echo baz >source/baz &&
git add source &&
git commit -m orig &&
@@ -4747,6 +4747,7 @@ test_setup_12i () {
git switch B &&
git mv source/bar source/subdir/bar &&
echo more baz >>source/baz &&
+ git add source/baz &&
git commit -m B
)
}
@@ -4758,6 +4759,88 @@ test_expect_success '12i: Directory rename causes rename-to-self' '
git checkout A^0 &&
+ # NOTE: A potentially better resolution would be for
+ # source/bar -> source/subdir/bar
+ # to use the directory rename to become
+ # source/bar -> source/bar
+ # (a rename to self), and thus we end up with bar with
+ # a path conflict (given merge.directoryRenames=conflict).
+ # However, since the relevant renames optimization
+ # prevents us from noticing
+ # source/bar -> source/subdir/bar
+ # as a rename and looking at it just as
+ # delete source/bar
+ # add source/subdir/bar
+ # the directory rename of source/subdir/bar -> source/bar does
+ # not look like a rename-to-self situation but a
+ # rename-on-top-of-other-file situation. We do not want
+ # stage 1 entries from an unrelated file, so we expect an
+ # error about there being a file in the way.
+
+ test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 >out &&
+
+ grep "CONFLICT (implicit dir rename).*source/bar in the way" out &&
+ test_path_is_missing source/bar &&
+ test_path_is_file source/subdir/bar &&
+ test_path_is_file source/baz &&
+
+ git ls-files >actual &&
+ uniq <actual >tracked &&
+ test_line_count = 3 tracked &&
+
+ git status --porcelain -uno >actual &&
+ cat >expect <<-\EOF &&
+ M source/baz
+ R source/bar -> source/subdir/bar
+ EOF
+ test_cmp expect actual
+ )
+'
+
+# Testcase 12i2, Identical to 12i except that source/subdir/bar modified on unrenamed side
+# Commit O: source/{subdir/foo, bar, baz_1}
+# Commit A: source/{foo, bar_2, baz_1}
+# Commit B: source/{subdir/{foo, bar}, baz_2}
+# Expected: source/{foo, bar, baz_2}, with conflicts on
+# source/bar vs. source/subdir/bar
+
+test_setup_12i2 () {
+ git init 12i2 &&
+ (
+ cd 12i2 &&
+
+ mkdir -p source/subdir &&
+ echo foo >source/subdir/foo &&
+ printf "%d\n" 1 2 3 4 5 6 7 >source/bar &&
+ echo baz >source/baz &&
+ git add source &&
+ git commit -m orig &&
+
+ git branch O &&
+ git branch A &&
+ git branch B &&
+
+ git switch A &&
+ git mv source/subdir/foo source/foo &&
+ echo 8 >> source/bar &&
+ git add source/bar &&
+ git commit -m A &&
+
+ git switch B &&
+ git mv source/bar source/subdir/bar &&
+ echo more baz >>source/baz &&
+ git add source/baz &&
+ git commit -m B
+ )
+}
+
+test_expect_success '12i2: Directory rename causes rename-to-self' '
+ test_setup_12i2 &&
+ (
+ cd 12i2 &&
+
+ git checkout A^0 &&
+
test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 &&
test_path_is_missing source/subdir &&
@@ -4771,7 +4854,7 @@ test_expect_success '12i: Directory rename causes rename-to-self' '
git status --porcelain -uno >actual &&
cat >expect <<-\EOF &&
UU source/bar
- M source/baz
+ M source/baz
EOF
test_cmp expect actual
)
@@ -4806,6 +4889,7 @@ test_setup_12j () {
git switch B &&
git mv bar subdir/bar &&
echo more baz >>baz &&
+ git add baz &&
git commit -m B
)
}
@@ -4817,10 +4901,29 @@ test_expect_success '12j: Directory rename to root causes rename-to-self' '
git checkout A^0 &&
- test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 &&
-
- test_path_is_missing subdir &&
- test_path_is_file bar &&
+ # NOTE: A potentially better resolution would be for
+ # bar -> subdir/bar
+ # to use the directory rename to become
+ # bar -> bar
+ # (a rename to self), and thus we end up with bar with
+ # a path conflict (given merge.directoryRenames=conflict).
+ # However, since the relevant renames optimization
+ # prevents us from noticing
+ # bar -> subdir/bar
+ # as a rename and looking at it just as
+ # delete bar
+ # add subdir/bar
+ # the directory rename of subdir/bar -> bar does not look
+ # like a rename-to-self situation but a
+ # rename-on-top-of-other-file situation. We do not want
+ # stage 1 entries from an unrelated file, so we expect an
+ # error about there being a file in the way.
+
+ test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 >out &&
+ grep "CONFLICT (implicit dir rename).*bar in the way" out &&
+
+ test_path_is_missing bar &&
+ test_path_is_file subdir/bar &&
test_path_is_file baz &&
git ls-files >actual &&
@@ -4829,8 +4932,8 @@ test_expect_success '12j: Directory rename to root causes rename-to-self' '
git status --porcelain -uno >actual &&
cat >expect <<-\EOF &&
- UU bar
- M baz
+ M baz
+ R bar -> subdir/bar
EOF
test_cmp expect actual
)
@@ -4865,6 +4968,7 @@ test_setup_12k () {
git switch B &&
git mv dirA/bar dirB/bar &&
echo more baz >>dirA/baz &&
+ git add dirA/baz &&
git commit -m B
)
}
@@ -4876,10 +4980,29 @@ test_expect_success '12k: Directory rename with sibling causes rename-to-self' '
git checkout A^0 &&
- test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 &&
-
- test_path_is_missing dirB &&
- test_path_is_file dirA/bar &&
+ # NOTE: A potentially better resolution would be for
+ # dirA/bar -> dirB/bar
+ # to use the directory rename (dirB/ -> dirA/) to become
+ # dirA/bar -> dirA/bar
+ # (a rename to self), and thus we end up with bar with
+ # a path conflict (given merge.directoryRenames=conflict).
+ # However, since the relevant renames optimization
+ # prevents us from noticing
+ # dirA/bar -> dirB/bar
+ # as a rename and looking at it just as
+ # delete dirA/bar
+ # add dirB/bar
+ # the directory rename of dirA/bar -> dirB/bar does
+ # not look like a rename-to-self situation but a
+ # rename-on-top-of-other-file situation. We do not want
+ # stage 1 entries from an unrelated file, so we expect an
+ # error about there being a file in the way.
+
+ test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 >out &&
+ grep "CONFLICT (implicit dir rename).*dirA/bar in the way" out &&
+
+ test_path_is_missing dirA/bar &&
+ test_path_is_file dirB/bar &&
test_path_is_file dirA/baz &&
git ls-files >actual &&
@@ -4888,8 +5011,8 @@ test_expect_success '12k: Directory rename with sibling causes rename-to-self' '
git status --porcelain -uno >actual &&
cat >expect <<-\EOF &&
- UU dirA/bar
- M dirA/baz
+ M dirA/baz
+ R dirA/bar -> dirB/bar
EOF
test_cmp expect actual
)
@@ -5056,6 +5179,25 @@ test_expect_success '12m: Change parent of renamed-dir to symlink on other side'
)
'
+# Testcase 12n, Directory rename transitively makes rename back to self
+#
+# (Since this is a cherry-pick instead of merge, the labels are a bit weird.
+# O, the original commit, is A~1 rather than what branch O points to.)
+#
+# Commit O: tools/hello
+# world
+# Commit A: tools/hello
+# tools/world
+# Commit B: hello
+# In words:
+# A: world -> tools/world
+# B: tools/ -> /, i.e. rename all of tools to toplevel directory
+# delete world
+#
+# Expected:
+# CONFLICT (file location): tools/world vs. world
+#
+
test_setup_12n () {
git init 12n &&
(
@@ -5092,10 +5234,357 @@ test_expect_success '12n: Directory rename transitively makes rename back to sel
git checkout -q B^0 &&
test_must_fail git cherry-pick A^0 >out &&
- grep "CONFLICT (file location).*should perhaps be moved" out
+ test_grep "CONFLICT (file location).*should perhaps be moved" out &&
+
+ # Should have 1 entry for hello, and 2 for world
+ test_stdout_line_count = 3 git ls-files -s &&
+ test_stdout_line_count = 1 git ls-files -s hello &&
+ test_stdout_line_count = 2 git ls-files -s world
+ )
+'
+
+# Testcase 12n2, Directory rename transitively makes rename back to self
+#
+# Commit O: tools/hello
+# world
+# Commit A: tools/hello
+# tools/world
+# Commit B: hello
+# In words:
+# A: world -> tools/world
+# B: tools/ -> /, i.e. rename all of tools to toplevel directory
+# delete world
+#
+# Expected:
+# CONFLICT (file location): tools/world vs. world
+#
+
+test_setup_12n2 () {
+ git init 12n2 &&
+ (
+ cd 12n2 &&
+
+ mkdir tools &&
+ echo hello >tools/hello &&
+ git add tools/hello &&
+ echo world >world &&
+ git add world &&
+ git commit -m "O" &&
+
+ git branch O &&
+ git branch A &&
+ git branch B &&
+
+ git switch A &&
+ git mv world tools/world &&
+ git commit -m "Move world into tools/" &&
+
+ git switch B &&
+ git mv tools/hello hello &&
+ git rm world &&
+ git commit -m "Move hello from tools/ to toplevel"
+ )
+}
+
+test_expect_success '12n2: Directory rename transitively makes rename back to self' '
+ test_setup_12n2 &&
+ (
+ cd 12n2 &&
+
+ git checkout -q B^0 &&
+
+ test_might_fail git -c merge.directoryRenames=true merge A^0 >out &&
+
+ # Should have 1 entry for hello, and either 0 or 2 for world
+ #
+ # NOTE: Since merge.directoryRenames=true, there is no path
+ # conflict for world vs. tools/world; it should end up at
+ # world. The fact that world was unmodified on side A, means
+ # there was no content conflict; we should just take the
+ # content from side B -- i.e. delete the file. So merging
+ # could just delete world.
+ #
+ # However, rename-to-self-via-directory-rename is a bit more
+ # challenging. Relax this test to allow world to be treated
+ # as a modify/delete conflict as well, meaning it will have
+ # two higher order stages, that just so happen to match.
+ #
+ test_stdout_line_count = 1 git ls-files -s hello &&
+ test_stdout_line_count = 2 git ls-files -s world &&
+ test_grep "CONFLICT (modify/delete).*world deleted in HEAD" out
)
'
+# Testcase 12o, Directory rename hits other rename source; file still in way on same side
+# Commit O: A/file1_1
+# A/stuff
+# B/file1_2
+# B/stuff
+# C/other
+# Commit A: A/file1_1
+# A/stuff
+# B/stuff
+# C/file1_2
+# C/other
+# Commit B: D/file2_1
+# A/stuff
+# B/file1_2
+# B/stuff
+# A/other
+# In words:
+# A: rename B/file1_2 -> C/file1_2
+# B: rename C/ -> A/
+# rename A/file1_1 -> D/file2_1
+# Rationale:
+# A/stuff is unmodified, it shows up in final output
+# B/stuff is unmodified, it shows up in final output
+# C/other touched on one side (rename to A), so A/other shows up in output
+# A/file1 is renamed to D/file2
+# B/file1 -> C/file1 and even though C/ -> A/, A/file1 is
+# "in the way" so we don't do the directory rename
+# Expected: A/stuff
+# B/stuff
+# A/other
+# D/file2
+# C/file1
+# + CONFLICT (implicit dir rename): A/file1 in way of C/file1
+#
+
+test_setup_12o () {
+ git init 12o &&
+ (
+ cd 12o &&
+
+ mkdir -p A B C &&
+ echo 1 >A/file1 &&
+ echo 2 >B/file1 &&
+ echo other >C/other &&
+ echo Astuff >A/stuff &&
+ echo Bstuff >B/stuff &&
+ git add . &&
+ git commit -m "O" &&
+
+ git branch O &&
+ git branch A &&
+ git branch B &&
+
+ git switch A &&
+ git mv B/file1 C/ &&
+ git add . &&
+ git commit -m "A" &&
+
+ git switch B &&
+ mkdir -p D &&
+ git mv A/file1 D/file2 &&
+ git mv C/other A/other &&
+ git add . &&
+ git commit -m "B"
+ )
+}
+
+test_expect_success '12o: Directory rename hits other rename source; file still in way on same side' '
+ test_setup_12o &&
+ (
+ cd 12o &&
+
+ git checkout -q A^0 &&
+
+ test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 >out &&
+
+ test_stdout_line_count = 5 git ls-files -s &&
+ test_stdout_line_count = 1 git ls-files -s A/other &&
+ test_stdout_line_count = 1 git ls-files -s A/stuff &&
+ test_stdout_line_count = 1 git ls-files -s B/stuff &&
+ test_stdout_line_count = 1 git ls-files -s D/file2 &&
+
+ grep "CONFLICT (implicit dir rename).*Existing file/dir at A/file1 in the way" out &&
+ test_stdout_line_count = 1 git ls-files -s C/file1
+ )
+'
+
+# Testcase 12p, Directory rename hits other rename source; file still in way on other side
+# Commit O: A/file1_1
+# A/stuff
+# B/file1_2
+# B/stuff
+# C/other
+# Commit A: D/file2_1
+# A/stuff
+# B/stuff
+# C/file1_2
+# C/other
+# Commit B: A/file1_1
+# A/stuff
+# B/file1_2
+# B/stuff
+# A/other
+# Short version:
+# A: rename A/file1_1 -> D/file2_1
+# rename B/file1_2 -> C/file1_2
+# B: Rename C/ -> A/
+# Rationale:
+# A/stuff is unmodified, it shows up in final output
+# B/stuff is unmodified, it shows up in final output
+# C/other touched on one side (rename to A), so A/other shows up in output
+# A/file1 is renamed to D/file2
+# B/file1 -> C/file1 and even though C/ -> A/, A/file1 is
+# "in the way" so we don't do the directory rename
+# Expected: A/stuff
+# B/stuff
+# A/other
+# D/file2
+# C/file1
+# + CONFLICT (implicit dir rename): A/file1 in way of C/file1
+#
+
+test_setup_12p () {
+ git init 12p &&
+ (
+ cd 12p &&
+
+ mkdir -p A B C &&
+ echo 1 >A/file1 &&
+ echo 2 >B/file1 &&
+ echo other >C/other &&
+ echo Astuff >A/stuff &&
+ echo Bstuff >B/stuff &&
+ git add . &&
+ git commit -m "O" &&
+
+ git branch O &&
+ git branch A &&
+ git branch B &&
+
+ git switch A &&
+ mkdir -p D &&
+ git mv A/file1 D/file2 &&
+ git mv B/file1 C/ &&
+ git add . &&
+ git commit -m "A" &&
+
+ git switch B &&
+ git mv C/other A/other &&
+ git add . &&
+ git commit -m "B"
+ )
+}
+
+test_expect_success '12p: Directory rename hits other rename source; file still in way on other side' '
+ test_setup_12p &&
+ (
+ cd 12p &&
+
+ git checkout -q A^0 &&
+
+ test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 >out &&
+
+ test_stdout_line_count = 5 git ls-files -s &&
+ test_stdout_line_count = 1 git ls-files -s A/other &&
+ test_stdout_line_count = 1 git ls-files -s A/stuff &&
+ test_stdout_line_count = 1 git ls-files -s B/stuff &&
+ test_stdout_line_count = 1 git ls-files -s D/file2 &&
+
+ grep "CONFLICT (implicit dir rename).*Existing file/dir at A/file1 in the way" out &&
+ test_stdout_line_count = 1 git ls-files -s C/file1
+ )
+'
+
+# Testcase 12q, Directory rename hits other rename source; file removed though
+# Commit O: A/file1_1
+# A/stuff
+# B/file1_2
+# B/stuff
+# C/other
+# Commit A: A/stuff
+# B/stuff
+# C/file1_2
+# C/other
+# Commit B: D/file2_1
+# A/stuff
+# B/file1_2
+# B/stuff
+# A/other
+# In words:
+# A: delete A/file1_1, rename B/file1_2 -> C/file1_2
+# B: Rename C/ -> A/, rename A/file1_1 -> D/file2_1
+# Rationale:
+# A/stuff is unmodified, it shows up in final output
+# B/stuff is unmodified, it shows up in final output
+# C/other touched on one side (rename to A), so A/other shows up in output
+# A/file1 is rename/delete to D/file2, so two stages for D/file2
+# B/file1 -> C/file1 and even though C/ -> A/, A/file1 as a source was
+# "in the way" (ish) so we don't do the directory rename
+# Expected: A/stuff
+# B/stuff
+# A/other
+# D/file2 (two stages)
+# C/file1
+# + CONFLICT (implicit dir rename): A/file1 in way of C/file1
+# + CONFLICT (rename/delete): D/file2
+#
+
+test_setup_12q () {
+ git init 12q &&
+ (
+ cd 12q &&
+
+ mkdir -p A B C &&
+ echo 1 >A/file1 &&
+ echo 2 >B/file1 &&
+ echo other >C/other &&
+ echo Astuff >A/stuff &&
+ echo Bstuff >B/stuff &&
+ git add . &&
+ git commit -m "O" &&
+
+ git branch O &&
+ git branch A &&
+ git branch B &&
+
+ git switch A &&
+ git rm A/file1 &&
+ git mv B/file1 C/ &&
+ git add . &&
+ git commit -m "A" &&
+
+ git switch B &&
+ mkdir -p D &&
+ git mv A/file1 D/file2 &&
+ git mv C/other A/other &&
+ git add . &&
+ git commit -m "B"
+ )
+}
+
+test_expect_success '12q: Directory rename hits other rename source; file removed though' '
+ test_setup_12q &&
+ (
+ cd 12q &&
+
+ git checkout -q A^0 &&
+
+ test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 >out &&
+
+ grep "CONFLICT (rename/delete).*A/file1.*D/file2" out &&
+ grep "CONFLICT (implicit dir rename).*Existing file/dir at A/file1 in the way" out &&
+
+ test_stdout_line_count = 6 git ls-files -s &&
+ test_stdout_line_count = 1 git ls-files -s A/other &&
+ test_stdout_line_count = 1 git ls-files -s A/stuff &&
+ test_stdout_line_count = 1 git ls-files -s B/stuff &&
+ test_stdout_line_count = 2 git ls-files -s D/file2 &&
+
+ # This is a slightly suboptimal resolution; allowing the
+ # rename of C/ -> A/ to affect C/file1 and further rename
+ # it to A/file1 would probably be preferable, but since
+ # A/file1 existed as the source of another rename, allowing
+ # the dir rename of C/file1 -> A/file1 would mean modifying
+ # the code so that renames do not adjust both their source
+ # and target paths in all cases.
+ ! grep "CONFLICT (file location)" out &&
+ test_stdout_line_count = 1 git ls-files -s C/file1
+ )
+'
###########################################################################
# SECTION 13: Checking informational and conflict messages
diff --git a/t/t7508-status.sh b/t/t7508-status.sh
index cdc1d6fcc7..abad229e9d 100755
--- a/t/t7508-status.sh
+++ b/t/t7508-status.sh
@@ -717,6 +717,17 @@ test_expect_success TTY 'status -s with color.status' '
'
+test_expect_success TTY 'status -s keeps colors with -z' '
+ test_when_finished "rm -f output.*" &&
+ test_terminal git status -s -z >output.raw &&
+ # convert back to newlines to avoid portability issues with
+ # test_decode_color and test_cmp, and to let us use the same expected
+ # output as earlier tests
+ tr "\0" "\n" <output.raw >output.nl &&
+ test_decode_color <output.nl >output &&
+ test_cmp expect output
+'
+
cat >expect <<\EOF
## <YELLOW>main<RESET>...<CYAN>upstream<RESET> [ahead <YELLOW>1<RESET>, behind <CYAN>2<RESET>]
<RED>M<RESET> dir1/modified
diff --git a/t/t7528-signed-commit-ssh.sh b/t/t7528-signed-commit-ssh.sh
index 0f887a3ebe..b50306b9b3 100755
--- a/t/t7528-signed-commit-ssh.sh
+++ b/t/t7528-signed-commit-ssh.sh
@@ -82,7 +82,7 @@ test_expect_success GPGSSH 'create signed commits' '
test_expect_success GPGSSH 'sign commits using literal public keys with ssh-agent' '
test_when_finished "test_unconfig commit.gpgsign" &&
test_config gpg.format ssh &&
- eval $(ssh-agent) &&
+ eval $(ssh-agent -T || ssh-agent) &&
test_when_finished "kill ${SSH_AGENT_PID}" &&
test_when_finished "test_unconfig user.signingkey" &&
mkdir tmpdir &&
diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh
index 611755cc13..73b78bdd88 100755
--- a/t/t7700-repack.sh
+++ b/t/t7700-repack.sh
@@ -838,4 +838,67 @@ test_expect_success '-n overrides repack.updateServerInfo=true' '
test_server_info_missing
'
+test_expect_success 'pending objects are repacked appropriately' '
+ test_when_finished rm -rf pending &&
+ git init pending &&
+
+ (
+ cd pending &&
+
+ # Commit file, a/b/c and never change them.
+ mkdir -p a/b &&
+ echo singleton >file &&
+ echo stuff >a/b/c &&
+ echo more >a/d &&
+ git add file a &&
+ git commit -m "single blobs" &&
+
+ # Files a/d and a/e will not be singletons.
+ echo d >a/d &&
+ echo e >a/e &&
+ git add a &&
+ git commit -m "more blobs" &&
+
+ # This use of a sparse index helps to force
+ # test that the cache-tree is walked, too.
+ git sparse-checkout set --sparse-index a x &&
+
+ # Create staged changes:
+ # * a/e now has multiple versions.
+ # * a/i now has only one version.
+ echo f >a/d &&
+ echo h >a/e &&
+ echo i >a/i &&
+ git add a &&
+
+ # Stage and unstage a change to make use of
+ # resolve-undo cache and how that impacts fsck.
+ mkdir x &&
+ echo y >x/y &&
+ git add x &&
+ xy=$(git rev-parse :x/y) &&
+ git rm --cached x/y &&
+
+ # The blob for x/y must persist through repacks,
+ # but fsck currently ignores the REUC extension
+ # for finding links to the blob.
+ cat >expect <<-EOF &&
+ dangling blob $xy
+ EOF
+
+ # Bring the loose objects into a packfile to avoid
+ # leftovers in next test. Without this, the loose
+ # objects persist and the test succeeds for other
+ # reasons.
+ git repack -adf &&
+ git fsck >out &&
+ test_cmp expect out &&
+
+ # Test path walk version with pack.useSparse.
+ git -c pack.useSparse=true repack -adf --path-walk &&
+ git fsck >out &&
+ test_cmp expect out
+ )
+'
+
test_done