summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/helper/test-csprng.c29
-rw-r--r--t/helper/test-tool.c1
-rw-r--r--t/helper/test-tool.h1
-rwxr-xr-xt/t0027-auto-crlf.sh6
-rwxr-xr-xt/t1006-cat-file.sh92
-rwxr-xr-xt/t1091-sparse-checkout-builtin.sh60
-rwxr-xr-xt/t1300-config.sh118
-rwxr-xr-xt/t1800-hook.sh134
-rwxr-xr-xt/t2108-update-index-refresh-racy.sh64
-rwxr-xr-xt/t3400-rebase.sh21
-rwxr-xr-xt/t3412-rebase-root.sh2
-rwxr-xr-xt/t3701-add-interactive.sh48
-rwxr-xr-xt/t4202-log.sh2
-rwxr-xr-xt/t5516-fetch-push.sh12
-rwxr-xr-xt/t5520-pull.sh13
-rwxr-xr-xt/t5700-protocol-v1.sh15
-rwxr-xr-xt/t5702-protocol-v2.sh12
-rwxr-xr-xt/t6007-rev-list-cherry-pick-file.sh26
-rwxr-xr-xt/t6012-rev-list-simplify.sh2
-rwxr-xr-xt/t6111-rev-list-treesame.sh3
-rwxr-xr-xt/t6120-describe.sh9
-rwxr-xr-xt/t6429-merge-sequence-rename-caching.sh67
-rwxr-xr-xt/t7508-status.sh30
-rwxr-xr-xt/t8007-cat-file-textconv.sh42
-rwxr-xr-xt/t9001-send-email.sh4
-rw-r--r--t/test-lib-functions.sh33
-rw-r--r--t/test-lib.sh2
27 files changed, 789 insertions, 59 deletions
diff --git a/t/helper/test-csprng.c b/t/helper/test-csprng.c
new file mode 100644
index 0000000000..65d14973c5
--- /dev/null
+++ b/t/helper/test-csprng.c
@@ -0,0 +1,29 @@
+#include "test-tool.h"
+#include "git-compat-util.h"
+
+
+int cmd__csprng(int argc, const char **argv)
+{
+ unsigned long count;
+ unsigned char buf[1024];
+
+ if (argc > 2) {
+ fprintf(stderr, "usage: %s [<size>]\n", argv[0]);
+ return 2;
+ }
+
+ count = (argc == 2) ? strtoul(argv[1], NULL, 0) : -1L;
+
+ while (count) {
+ unsigned long chunk = count < sizeof(buf) ? count : sizeof(buf);
+ if (csprng_bytes(buf, chunk) < 0) {
+ perror("failed to read");
+ return 5;
+ }
+ if (fwrite(buf, chunk, 1, stdout) != chunk)
+ return 1;
+ count -= chunk;
+ }
+
+ return 0;
+}
diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
index 338a57b104..e6ec69cf32 100644
--- a/t/helper/test-tool.c
+++ b/t/helper/test-tool.c
@@ -20,6 +20,7 @@ static struct test_cmd cmds[] = {
{ "chmtime", cmd__chmtime },
{ "config", cmd__config },
{ "crontab", cmd__crontab },
+ { "csprng", cmd__csprng },
{ "ctype", cmd__ctype },
{ "date", cmd__date },
{ "delta", cmd__delta },
diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
index 48cee1f4a2..20756eefdd 100644
--- a/t/helper/test-tool.h
+++ b/t/helper/test-tool.h
@@ -10,6 +10,7 @@ int cmd__bloom(int argc, const char **argv);
int cmd__chmtime(int argc, const char **argv);
int cmd__config(int argc, const char **argv);
int cmd__crontab(int argc, const char **argv);
+int cmd__csprng(int argc, const char **argv);
int cmd__ctype(int argc, const char **argv);
int cmd__date(int argc, const char **argv);
int cmd__delta(int argc, const char **argv);
diff --git a/t/t0027-auto-crlf.sh b/t/t0027-auto-crlf.sh
index 4a5c5c602c..c5f7ac63b0 100755
--- a/t/t0027-auto-crlf.sh
+++ b/t/t0027-auto-crlf.sh
@@ -597,6 +597,12 @@ do
# auto: core.autocrlf=false and core.eol unset(or native) uses native eol
checkout_files auto "$id" "" false "" $NL CRLF CRLF_mix_LF LF_mix_CR LF_nul
checkout_files auto "$id" "" false native $NL CRLF CRLF_mix_LF LF_mix_CR LF_nul
+ # core.autocrlf false, .gitattributes sets eol
+ checkout_files "" "$id" "lf" false "" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
+ checkout_files "" "$id" "crlf" false "" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
+ # core.autocrlf true, .gitattributes sets eol
+ checkout_files "" "$id" "lf" true "" LF CRLF CRLF_mix_LF LF_mix_CR LF_nul
+ checkout_files "" "$id" "crlf" true "" CRLF CRLF CRLF CRLF_mix_CR CRLF_nul
done
# The rest of the tests are unique; do the usual linting.
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index 39382fa195..145eee11df 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -4,6 +4,98 @@ test_description='git cat-file'
. ./test-lib.sh
+test_cmdmode_usage () {
+ test_expect_code 129 "$@" 2>err &&
+ grep "^error:.*is incompatible with" err
+}
+
+for switches in \
+ '-e -p' \
+ '-p -t' \
+ '-t -s' \
+ '-s --textconv' \
+ '--textconv --filters' \
+ '--batch-all-objects -e'
+do
+ test_expect_success "usage: cmdmode $switches" '
+ test_cmdmode_usage git cat-file $switches
+ '
+done
+
+test_incompatible_usage () {
+ test_expect_code 129 "$@" 2>err &&
+ grep -E "^(fatal|error):.*(requires|incompatible with|needs)" err
+}
+
+for opt in --batch --batch-check
+do
+ test_expect_success "usage: incompatible options: --path with $opt" '
+ test_incompatible_usage git cat-file --path=foo $opt
+ '
+done
+
+test_missing_usage () {
+ test_expect_code 129 "$@" 2>err &&
+ grep -E "^fatal:.*required" err
+}
+
+short_modes="-e -p -t -s"
+cw_modes="--textconv --filters"
+
+for opt in $cw_modes
+do
+ test_expect_success "usage: $opt requires another option" '
+ test_missing_usage git cat-file $opt
+ '
+done
+
+for opt in $short_modes
+do
+ test_expect_success "usage: $opt requires another option" '
+ test_missing_usage git cat-file $opt
+ '
+
+ for opt2 in --batch \
+ --batch-check \
+ --follow-symlinks \
+ "--path=foo HEAD:some-path.txt"
+ do
+ test_expect_success "usage: incompatible options: $opt and $opt2" '
+ test_incompatible_usage git cat-file $opt $opt2
+ '
+ done
+done
+
+test_too_many_arguments () {
+ test_expect_code 129 "$@" 2>err &&
+ grep -E "^fatal: too many arguments$" err
+}
+
+for opt in $short_modes $cw_modes
+do
+ args="one two three"
+ test_expect_success "usage: too many arguments: $opt $args" '
+ test_too_many_arguments git cat-file $opt $args
+ '
+
+ for opt2 in --buffer --follow-symlinks
+ do
+ test_expect_success "usage: incompatible arguments: $opt with batch option $opt2" '
+ test_incompatible_usage git cat-file $opt $opt2
+ '
+ done
+done
+
+for opt in --buffer \
+ --follow-symlinks \
+ --batch-all-objects
+do
+ test_expect_success "usage: bad option combination: $opt without batch mode" '
+ test_incompatible_usage git cat-file $opt &&
+ test_incompatible_usage git cat-file $opt commit HEAD
+ '
+done
+
echo_without_newline () {
printf '%s' "$*"
}
diff --git a/t/t1091-sparse-checkout-builtin.sh b/t/t1091-sparse-checkout-builtin.sh
index 42776984fe..3592d12442 100755
--- a/t/t1091-sparse-checkout-builtin.sh
+++ b/t/t1091-sparse-checkout-builtin.sh
@@ -5,6 +5,9 @@ test_description='sparse checkout builtin tests'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+GIT_TEST_SPLIT_INDEX=false
+export GIT_TEST_SPLIT_INDEX
+
. ./test-lib.sh
list_files() {
@@ -79,6 +82,12 @@ test_expect_success 'git sparse-checkout init' '
check_files repo a
'
+test_expect_success 'git sparse-checkout init in empty repo' '
+ test_when_finished rm -rf empty-repo blank-template &&
+ git init --template= empty-repo &&
+ git -C empty-repo sparse-checkout init
+'
+
test_expect_success 'git sparse-checkout list after init' '
git -C repo sparse-checkout list >actual &&
cat >expect <<-\EOF &&
@@ -228,36 +237,31 @@ test_expect_success 'sparse-checkout disable' '
'
test_expect_success 'sparse-index enabled and disabled' '
- (
- sane_unset GIT_TEST_SPLIT_INDEX &&
- git -C repo update-index --no-split-index &&
-
- git -C repo sparse-checkout init --cone --sparse-index &&
- test_cmp_config -C repo true index.sparse &&
- git -C repo ls-files --sparse >sparse &&
- git -C repo sparse-checkout disable &&
- git -C repo ls-files --sparse >full &&
-
- cat >expect <<-\EOF &&
- @@ -1,4 +1,7 @@
- a
- -deep/
- -folder1/
- -folder2/
- +deep/a
- +deep/deeper1/a
- +deep/deeper1/deepest/a
- +deep/deeper2/a
- +folder1/a
- +folder2/a
- EOF
+ git -C repo sparse-checkout init --cone --sparse-index &&
+ test_cmp_config -C repo true index.sparse &&
+ git -C repo ls-files --sparse >sparse &&
+ git -C repo sparse-checkout disable &&
+ git -C repo ls-files --sparse >full &&
- diff -u sparse full | tail -n +3 >actual &&
- test_cmp expect actual &&
+ cat >expect <<-\EOF &&
+ @@ -1,4 +1,7 @@
+ a
+ -deep/
+ -folder1/
+ -folder2/
+ +deep/a
+ +deep/deeper1/a
+ +deep/deeper1/deepest/a
+ +deep/deeper2/a
+ +folder1/a
+ +folder2/a
+ EOF
+
+ diff -u sparse full | tail -n +3 >actual &&
+ test_cmp expect actual &&
- git -C repo config --list >config &&
- ! grep index.sparse config
- )
+ git -C repo config --list >config &&
+ ! grep index.sparse config
'
test_expect_success 'cone mode: init and set' '
diff --git a/t/t1300-config.sh b/t/t1300-config.sh
index 78359f1f4a..7dd9b325d9 100755
--- a/t/t1300-config.sh
+++ b/t/t1300-config.sh
@@ -2388,4 +2388,122 @@ test_expect_success '--get and --get-all with --fixed-value' '
test_must_fail git config --file=config --get-regexp --fixed-value fixed+ non-existent
'
+test_expect_success 'includeIf.hasconfig:remote.*.url' '
+ git init hasremoteurlTest &&
+ test_when_finished "rm -rf hasremoteurlTest" &&
+
+ cat >include-this <<-\EOF &&
+ [user]
+ this = this-is-included
+ EOF
+ cat >dont-include-that <<-\EOF &&
+ [user]
+ that = that-is-not-included
+ EOF
+ cat >>hasremoteurlTest/.git/config <<-EOF &&
+ [includeIf "hasconfig:remote.*.url:foourl"]
+ path = "$(pwd)/include-this"
+ [includeIf "hasconfig:remote.*.url:barurl"]
+ path = "$(pwd)/dont-include-that"
+ [remote "foo"]
+ url = foourl
+ EOF
+
+ echo this-is-included >expect-this &&
+ git -C hasremoteurlTest config --get user.this >actual-this &&
+ test_cmp expect-this actual-this &&
+
+ test_must_fail git -C hasremoteurlTest config --get user.that
+'
+
+test_expect_success 'includeIf.hasconfig:remote.*.url respects last-config-wins' '
+ git init hasremoteurlTest &&
+ test_when_finished "rm -rf hasremoteurlTest" &&
+
+ cat >include-two-three <<-\EOF &&
+ [user]
+ two = included-config
+ three = included-config
+ EOF
+ cat >>hasremoteurlTest/.git/config <<-EOF &&
+ [remote "foo"]
+ url = foourl
+ [user]
+ one = main-config
+ two = main-config
+ [includeIf "hasconfig:remote.*.url:foourl"]
+ path = "$(pwd)/include-two-three"
+ [user]
+ three = main-config
+ EOF
+
+ echo main-config >expect-main-config &&
+ echo included-config >expect-included-config &&
+
+ git -C hasremoteurlTest config --get user.one >actual &&
+ test_cmp expect-main-config actual &&
+
+ git -C hasremoteurlTest config --get user.two >actual &&
+ test_cmp expect-included-config actual &&
+
+ git -C hasremoteurlTest config --get user.three >actual &&
+ test_cmp expect-main-config actual
+'
+
+test_expect_success 'includeIf.hasconfig:remote.*.url globs' '
+ git init hasremoteurlTest &&
+ test_when_finished "rm -rf hasremoteurlTest" &&
+
+ printf "[user]\ndss = yes\n" >double-star-start &&
+ printf "[user]\ndse = yes\n" >double-star-end &&
+ printf "[user]\ndsm = yes\n" >double-star-middle &&
+ printf "[user]\nssm = yes\n" >single-star-middle &&
+ printf "[user]\nno = no\n" >no &&
+
+ cat >>hasremoteurlTest/.git/config <<-EOF &&
+ [remote "foo"]
+ url = https://foo/bar/baz
+ [includeIf "hasconfig:remote.*.url:**/baz"]
+ path = "$(pwd)/double-star-start"
+ [includeIf "hasconfig:remote.*.url:**/nomatch"]
+ path = "$(pwd)/no"
+ [includeIf "hasconfig:remote.*.url:https:/**"]
+ path = "$(pwd)/double-star-end"
+ [includeIf "hasconfig:remote.*.url:nomatch:/**"]
+ path = "$(pwd)/no"
+ [includeIf "hasconfig:remote.*.url:https:/**/baz"]
+ path = "$(pwd)/double-star-middle"
+ [includeIf "hasconfig:remote.*.url:https:/**/nomatch"]
+ path = "$(pwd)/no"
+ [includeIf "hasconfig:remote.*.url:https://*/bar/baz"]
+ path = "$(pwd)/single-star-middle"
+ [includeIf "hasconfig:remote.*.url:https://*/baz"]
+ path = "$(pwd)/no"
+ EOF
+
+ git -C hasremoteurlTest config --get user.dss &&
+ git -C hasremoteurlTest config --get user.dse &&
+ git -C hasremoteurlTest config --get user.dsm &&
+ git -C hasremoteurlTest config --get user.ssm &&
+ test_must_fail git -C hasremoteurlTest config --get user.no
+'
+
+test_expect_success 'includeIf.hasconfig:remote.*.url forbids remote url in such included files' '
+ git init hasremoteurlTest &&
+ test_when_finished "rm -rf hasremoteurlTest" &&
+
+ cat >include-with-url <<-\EOF &&
+ [remote "bar"]
+ url = barurl
+ EOF
+ cat >>hasremoteurlTest/.git/config <<-EOF &&
+ [includeIf "hasconfig:remote.*.url:foourl"]
+ path = "$(pwd)/include-with-url"
+ EOF
+
+ # test with any Git command
+ test_must_fail git -C hasremoteurlTest status 2>err &&
+ grep "fatal: remote URLs cannot be configured in file directly or indirectly included by includeIf.hasconfig:remote.*.url" err
+'
+
test_done
diff --git a/t/t1800-hook.sh b/t/t1800-hook.sh
new file mode 100755
index 0000000000..29718aa991
--- /dev/null
+++ b/t/t1800-hook.sh
@@ -0,0 +1,134 @@
+#!/bin/sh
+
+test_description='git-hook command'
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+test_expect_success 'git hook usage' '
+ test_expect_code 129 git hook &&
+ test_expect_code 129 git hook run &&
+ test_expect_code 129 git hook run -h &&
+ test_expect_code 129 git hook run --unknown 2>err &&
+ grep "unknown option" err
+'
+
+test_expect_success 'git hook run: nonexistent hook' '
+ cat >stderr.expect <<-\EOF &&
+ error: cannot find a hook named test-hook
+ EOF
+ test_expect_code 1 git hook run test-hook 2>stderr.actual &&
+ test_cmp stderr.expect stderr.actual
+'
+
+test_expect_success 'git hook run: nonexistent hook with --ignore-missing' '
+ git hook run --ignore-missing does-not-exist 2>stderr.actual &&
+ test_must_be_empty stderr.actual
+'
+
+test_expect_success 'git hook run: basic' '
+ write_script .git/hooks/test-hook <<-EOF &&
+ echo Test hook
+ EOF
+
+ cat >expect <<-\EOF &&
+ Test hook
+ EOF
+ git hook run test-hook 2>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git hook run: stdout and stderr both write to our stderr' '
+ write_script .git/hooks/test-hook <<-EOF &&
+ echo >&1 Will end up on stderr
+ echo >&2 Will end up on stderr
+ EOF
+
+ cat >stderr.expect <<-\EOF &&
+ Will end up on stderr
+ Will end up on stderr
+ EOF
+ git hook run test-hook >stdout.actual 2>stderr.actual &&
+ test_cmp stderr.expect stderr.actual &&
+ test_must_be_empty stdout.actual
+'
+
+test_expect_success 'git hook run: exit codes are passed along' '
+ write_script .git/hooks/test-hook <<-EOF &&
+ exit 1
+ EOF
+
+ test_expect_code 1 git hook run test-hook &&
+
+ write_script .git/hooks/test-hook <<-EOF &&
+ exit 2
+ EOF
+
+ test_expect_code 2 git hook run test-hook &&
+
+ write_script .git/hooks/test-hook <<-EOF &&
+ exit 128
+ EOF
+
+ test_expect_code 128 git hook run test-hook &&
+
+ write_script .git/hooks/test-hook <<-EOF &&
+ exit 129
+ EOF
+
+ test_expect_code 129 git hook run test-hook
+'
+
+test_expect_success 'git hook run arg u ments without -- is not allowed' '
+ test_expect_code 129 git hook run test-hook arg u ments
+'
+
+test_expect_success 'git hook run -- pass arguments' '
+ write_script .git/hooks/test-hook <<-\EOF &&
+ echo $1
+ echo $2
+ EOF
+
+ cat >expect <<-EOF &&
+ arg
+ u ments
+ EOF
+
+ git hook run test-hook -- arg "u ments" 2>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'git hook run -- out-of-repo runs excluded' '
+ write_script .git/hooks/test-hook <<-EOF &&
+ echo Test hook
+ EOF
+
+ nongit test_must_fail git hook run test-hook
+'
+
+test_expect_success 'git -c core.hooksPath=<PATH> hook run' '
+ mkdir my-hooks &&
+ write_script my-hooks/test-hook <<-\EOF &&
+ echo Hook ran $1 >>actual
+ EOF
+
+ cat >expect <<-\EOF &&
+ Test hook
+ Hook ran one
+ Hook ran two
+ Hook ran three
+ Hook ran four
+ EOF
+
+ # Test various ways of specifying the path. See also
+ # t1350-config-hooks-path.sh
+ >actual &&
+ git hook run test-hook -- ignored 2>>actual &&
+ git -c core.hooksPath=my-hooks hook run test-hook -- one 2>>actual &&
+ git -c core.hooksPath=my-hooks/ hook run test-hook -- two 2>>actual &&
+ git -c core.hooksPath="$PWD/my-hooks" hook run test-hook -- three 2>>actual &&
+ git -c core.hooksPath="$PWD/my-hooks/" hook run test-hook -- four 2>>actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t2108-update-index-refresh-racy.sh b/t/t2108-update-index-refresh-racy.sh
new file mode 100755
index 0000000000..bc5f2886fa
--- /dev/null
+++ b/t/t2108-update-index-refresh-racy.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+
+test_description='update-index refresh tests related to racy timestamps'
+
+TEST_PASSES_SANITIZE_LEAK=true
+. ./test-lib.sh
+
+reset_files () {
+ echo content >file &&
+ echo content >other &&
+ test_set_magic_mtime file &&
+ test_set_magic_mtime other
+}
+
+update_assert_changed () {
+ test_set_magic_mtime .git/index &&
+ test_might_fail git update-index "$1" &&
+ ! test_is_magic_mtime .git/index
+}
+
+test_expect_success 'setup' '
+ reset_files &&
+ # we are calling reset_files() a couple of times during tests;
+ # test-tool chmtime does not change the ctime; to not weaken
+ # or even break our tests, disable ctime-checks entirely
+ git config core.trustctime false &&
+ git add file other &&
+ git commit -m "initial import"
+'
+
+test_expect_success '--refresh has no racy timestamps to fix' '
+ reset_files &&
+ # set the index time far enough to the future;
+ # it must be at least 3 seconds for VFAT
+ test_set_magic_mtime .git/index +60 &&
+ git update-index --refresh &&
+ test_is_magic_mtime .git/index +60
+'
+
+test_expect_success '--refresh should fix racy timestamp' '
+ reset_files &&
+ update_assert_changed --refresh
+'
+
+test_expect_success '--really-refresh should fix racy timestamp' '
+ reset_files &&
+ update_assert_changed --really-refresh
+'
+
+test_expect_success '--refresh should fix racy timestamp if other file needs update' '
+ reset_files &&
+ echo content2 >other &&
+ test_set_magic_mtime other &&
+ update_assert_changed --refresh
+'
+
+test_expect_success '--refresh should fix racy timestamp if racy file needs update' '
+ reset_files &&
+ echo content2 >file &&
+ test_set_magic_mtime file &&
+ update_assert_changed --refresh
+'
+
+test_done
diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh
index 23dbd3c82e..71b1735e1d 100755
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
@@ -416,4 +416,25 @@ test_expect_success MINGW,SYMLINKS_WINDOWS 'rebase when .git/logs is a symlink'
mv actual_logs .git/logs
'
+test_expect_success 'rebase when inside worktree subdirectory' '
+ git init main-wt &&
+ (
+ cd main-wt &&
+ git commit --allow-empty -m "initial" &&
+ mkdir -p foo/bar &&
+ test_commit foo/bar/baz &&
+ mkdir -p a/b &&
+ test_commit a/b/c &&
+ # create another branch for our other worktree
+ git branch other &&
+ git worktree add ../other-wt other &&
+ cd ../other-wt &&
+ # create and cd into a subdirectory
+ mkdir -p random/dir &&
+ cd random/dir &&
+ # now do the rebase
+ git rebase --onto HEAD^^ HEAD^ # drops the HEAD^ commit
+ )
+'
+
test_done
diff --git a/t/t3412-rebase-root.sh b/t/t3412-rebase-root.sh
index 19c6f4acbf..1e9f7833dd 100755
--- a/t/t3412-rebase-root.sh
+++ b/t/t3412-rebase-root.sh
@@ -11,7 +11,7 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
log_with_names () {
git rev-list --topo-order --parents --pretty="tformat:%s" HEAD |
- git name-rev --stdin --name-only --refs=refs/heads/$1
+ git name-rev --annotate-stdin --name-only --refs=refs/heads/$1
}
diff --git a/t/t3701-add-interactive.sh b/t/t3701-add-interactive.sh
index 207714655f..94537a6b40 100755
--- a/t/t3701-add-interactive.sh
+++ b/t/t3701-add-interactive.sh
@@ -326,7 +326,9 @@ test_expect_success 'correct message when there is nothing to do' '
test_expect_success 'setup again' '
git reset --hard &&
test_chmod +x file &&
- echo content >>file
+ echo content >>file &&
+ test_write_lines A B C D>file2 &&
+ git add file2
'
# Write the patch file with a new line at the top and bottom
@@ -341,13 +343,27 @@ test_expect_success 'setup patch' '
content
+lastline
\ No newline at end of file
+ diff --git a/file2 b/file2
+ index 8422d40..35b930a 100644
+ --- a/file2
+ +++ b/file2
+ @@ -1,4 +1,5 @@
+ -A
+ +Z
+ B
+ +Y
+ C
+ -D
+ +X
EOF
'
# Expected output, diff is similar to the patch but w/ diff at the top
test_expect_success 'setup expected' '
echo diff --git a/file b/file >expected &&
- cat patch |sed "/^index/s/ 100644/ 100755/" >>expected &&
+ sed -e "/^index 180b47c/s/ 100644/ 100755/" \
+ -e /1,5/s//1,4/ \
+ -e /Y/d patch >>expected &&
cat >expected-output <<-\EOF
--- a/file
+++ b/file
@@ -366,6 +382,28 @@ test_expect_success 'setup expected' '
content
+lastline
\ No newline at end of file
+ --- a/file2
+ +++ b/file2
+ @@ -1,4 +1,5 @@
+ -A
+ +Z
+ B
+ +Y
+ C
+ -D
+ +X
+ @@ -1,2 +1,2 @@
+ -A
+ +Z
+ B
+ @@ -2,2 +2,3 @@
+ B
+ +Y
+ C
+ @@ -3,2 +4,2 @@
+ C
+ -D
+ +X
EOF
'
@@ -373,9 +411,9 @@ test_expect_success 'setup expected' '
test_expect_success 'add first line works' '
git commit -am "clear local changes" &&
git apply patch &&
- printf "%s\n" s y y | git add -p file 2>error |
- sed -n -e "s/^([1-2]\/[1-2]) Stage this hunk[^@]*\(@@ .*\)/\1/" \
- -e "/^[-+@ \\\\]"/p >output &&
+ test_write_lines s y y s y n y | git add -p 2>error >raw-output &&
+ sed -n -e "s/^([1-9]\/[1-9]) Stage this hunk[^@]*\(@@ .*\)/\1/" \
+ -e "/^[-+@ \\\\]"/p raw-output >output &&
test_must_be_empty error &&
git diff --cached >diff &&
diff_cmp expected diff &&
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 5049559861..dc884107de 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -659,7 +659,7 @@ EOF
test_expect_success 'log --graph with full output' '
git log --graph --date-order --pretty=short |
- git name-rev --name-only --stdin |
+ git name-rev --name-only --annotate-stdin |
sed "s/Merge:.*/Merge: A B/;s/ *\$//" >actual &&
test_cmp expect actual
'
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 2f04cf9a1c..87881726ed 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -229,6 +229,18 @@ test_expect_success 'push with negotiation proceeds anyway even if negotiation f
test_i18ngrep "push negotiation failed" err
'
+test_expect_success 'push with negotiation does not attempt to fetch submodules' '
+ mk_empty submodule_upstream &&
+ test_commit -C submodule_upstream submodule_commit &&
+ git submodule add ./submodule_upstream submodule &&
+ mk_empty testrepo &&
+ git push testrepo $the_first_commit:refs/remotes/origin/first_commit &&
+ test_commit -C testrepo unrelated_commit &&
+ git -C testrepo config receive.hideRefs refs/remotes/origin/first_commit &&
+ git -c submodule.recurse=true -c protocol.version=2 -c push.negotiate=1 push testrepo refs/heads/main:refs/remotes/origin/main 2>err &&
+ ! grep "Fetching submodule" err
+'
+
test_expect_success 'push without wildcard' '
mk_empty testrepo &&
diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
index 93ecfcdd24..081808009b 100755
--- a/t/t5520-pull.sh
+++ b/t/t5520-pull.sh
@@ -330,6 +330,19 @@ test_expect_success '--rebase --autostash fast forward' '
test_cmp_rev HEAD to-rebase-ff
'
+test_expect_success '--rebase with rebase.autostash succeeds on ff' '
+ test_when_finished "rm -fr src dst actual" &&
+ git init src &&
+ test_commit -C src "initial" file "content" &&
+ git clone src dst &&
+ test_commit -C src --printf "more_content" file "more content\ncontent\n" &&
+ echo "dirty" >>dst/file &&
+ test_config -C dst rebase.autostash true &&
+ git -C dst pull --rebase >actual 2>&1 &&
+ grep -q "Fast-forward" actual &&
+ grep -q "Applied autostash." actual
+'
+
test_expect_success '--rebase with conflicts shows advice' '
test_when_finished "git rebase --abort; git checkout -f to-rebase" &&
git checkout -b seq &&
diff --git a/t/t5700-protocol-v1.sh b/t/t5700-protocol-v1.sh
index 468bd3e13e..6c8d4c6cf1 100755
--- a/t/t5700-protocol-v1.sh
+++ b/t/t5700-protocol-v1.sh
@@ -149,6 +149,21 @@ test_expect_success 'push with file:// using protocol v1' '
grep "push< version 1" log
'
+test_expect_success 'cloning branchless tagless but not refless remote' '
+ rm -rf server client &&
+
+ git -c init.defaultbranch=main init server &&
+ echo foo >server/foo.txt &&
+ git -C server add foo.txt &&
+ git -C server commit -m "message" &&
+ git -C server update-ref refs/notbranch/alsonottag HEAD &&
+ git -C server checkout --detach &&
+ git -C server branch -D main &&
+ git -C server symbolic-ref HEAD refs/heads/nonexistentbranch &&
+
+ git -c protocol.version=1 clone "file://$(pwd)/server" client
+'
+
# Test protocol v1 with 'ssh://' transport
#
test_expect_success 'setup ssh wrapper' '
diff --git a/t/t5702-protocol-v2.sh b/t/t5702-protocol-v2.sh
index 710f33e2aa..900254947f 100755
--- a/t/t5702-protocol-v2.sh
+++ b/t/t5702-protocol-v2.sh
@@ -628,6 +628,18 @@ test_expect_success 'usage: --negotiate-only without --negotiation-tip' '
test_cmp err.expect err.actual
'
+test_expect_success 'usage: --negotiate-only with --recurse-submodules' '
+ cat >err.expect <<-\EOF &&
+ fatal: options '\''--negotiate-only'\'' and '\''--recurse-submodules'\'' cannot be used together
+ EOF
+
+ test_must_fail git -c protocol.version=2 -C client fetch \
+ --negotiate-only \
+ --recurse-submodules \
+ origin 2>err.actual &&
+ test_cmp err.expect err.actual
+'
+
test_expect_success 'file:// --negotiate-only' '
SERVER="server" &&
URI="file://$(pwd)/server" &&
diff --git a/t/t6007-rev-list-cherry-pick-file.sh b/t/t6007-rev-list-cherry-pick-file.sh
index aebe4b69e1..6f3e543977 100755
--- a/t/t6007-rev-list-cherry-pick-file.sh
+++ b/t/t6007-rev-list-cherry-pick-file.sh
@@ -58,7 +58,7 @@ EOF
test_expect_success '--left-right' '
git rev-list --left-right B...C > actual &&
- git name-rev --stdin --name-only --refs="*tags/*" \
+ git name-rev --annotate-stdin --name-only --refs="*tags/*" \
< actual > actual.named &&
test_cmp expect actual.named
'
@@ -78,14 +78,14 @@ EOF
test_expect_success '--cherry-pick bar does not come up empty' '
git rev-list --left-right --cherry-pick B...C -- bar > actual &&
- git name-rev --stdin --name-only --refs="*tags/*" \
+ git name-rev --annotate-stdin --name-only --refs="*tags/*" \
< actual > actual.named &&
test_cmp expect actual.named
'
test_expect_success 'bar does not come up empty' '
git rev-list --left-right B...C -- bar > actual &&
- git name-rev --stdin --name-only --refs="*tags/*" \
+ git name-rev --annotate-stdin --name-only --refs="*tags/*" \
< actual > actual.named &&
test_cmp expect actual.named
'
@@ -97,14 +97,14 @@ EOF
test_expect_success '--cherry-pick bar does not come up empty (II)' '
git rev-list --left-right --cherry-pick F...E -- bar > actual &&
- git name-rev --stdin --name-only --refs="*tags/*" \
+ git name-rev --annotate-stdin --name-only --refs="*tags/*" \
< actual > actual.named &&
test_cmp expect actual.named
'
test_expect_success 'name-rev multiple --refs combine inclusive' '
git rev-list --left-right --cherry-pick F...E -- bar >actual &&
- git name-rev --stdin --name-only --refs="*tags/F" --refs="*tags/E" \
+ git name-rev --annotate-stdin --name-only --refs="*tags/F" --refs="*tags/E" \
<actual >actual.named &&
test_cmp expect actual.named
'
@@ -116,7 +116,7 @@ EOF
test_expect_success 'name-rev --refs excludes non-matched patterns' '
git rev-list --left-right --right-only --cherry-pick F...E -- bar >>expect &&
git rev-list --left-right --cherry-pick F...E -- bar >actual &&
- git name-rev --stdin --name-only --refs="*tags/F" \
+ git name-rev --annotate-stdin --name-only --refs="*tags/F" \
<actual >actual.named &&
test_cmp expect actual.named
'
@@ -128,14 +128,14 @@ EOF
test_expect_success 'name-rev --exclude excludes matched patterns' '
git rev-list --left-right --right-only --cherry-pick F...E -- bar >>expect &&
git rev-list --left-right --cherry-pick F...E -- bar >actual &&
- git name-rev --stdin --name-only --refs="*tags/*" --exclude="*E" \
+ git name-rev --annotate-stdin --name-only --refs="*tags/*" --exclude="*E" \
<actual >actual.named &&
test_cmp expect actual.named
'
test_expect_success 'name-rev --no-refs clears the refs list' '
git rev-list --left-right --cherry-pick F...E -- bar >expect &&
- git name-rev --stdin --name-only --refs="*tags/F" --refs="*tags/E" --no-refs --refs="*tags/G" \
+ git name-rev --annotate-stdin --name-only --refs="*tags/F" --refs="*tags/E" --no-refs --refs="*tags/G" \
<expect >actual &&
test_cmp expect actual
'
@@ -149,7 +149,7 @@ EOF
test_expect_success '--cherry-mark' '
git rev-list --cherry-mark F...E -- bar > actual &&
- git name-rev --stdin --name-only --refs="*tags/*" \
+ git name-rev --annotate-stdin --name-only --refs="*tags/*" \
< actual > actual.named &&
test_cmp expect actual.named
'
@@ -163,7 +163,7 @@ EOF
test_expect_success '--cherry-mark --left-right' '
git rev-list --cherry-mark --left-right F...E -- bar > actual &&
- git name-rev --stdin --name-only --refs="*tags/*" \
+ git name-rev --annotate-stdin --name-only --refs="*tags/*" \
< actual > actual.named &&
test_cmp expect actual.named
'
@@ -174,14 +174,14 @@ EOF
test_expect_success '--cherry-pick --right-only' '
git rev-list --cherry-pick --right-only F...E -- bar > actual &&
- git name-rev --stdin --name-only --refs="*tags/*" \
+ git name-rev --annotate-stdin --name-only --refs="*tags/*" \
< actual > actual.named &&
test_cmp expect actual.named
'
test_expect_success '--cherry-pick --left-only' '
git rev-list --cherry-pick --left-only E...F -- bar > actual &&
- git name-rev --stdin --name-only --refs="*tags/*" \
+ git name-rev --annotate-stdin --name-only --refs="*tags/*" \
< actual > actual.named &&
test_cmp expect actual.named
'
@@ -193,7 +193,7 @@ EOF
test_expect_success '--cherry' '
git rev-list --cherry F...E -- bar > actual &&
- git name-rev --stdin --name-only --refs="*tags/*" \
+ git name-rev --annotate-stdin --name-only --refs="*tags/*" \
< actual > actual.named &&
test_cmp expect actual.named
'
diff --git a/t/t6012-rev-list-simplify.sh b/t/t6012-rev-list-simplify.sh
index 4f7fa8b6c0..4fedc614fa 100755
--- a/t/t6012-rev-list-simplify.sh
+++ b/t/t6012-rev-list-simplify.sh
@@ -12,7 +12,7 @@ note () {
}
unnote () {
- git name-rev --tags --stdin | sed -e "s|$OID_REGEX (tags/\([^)]*\)) |\1 |g"
+ git name-rev --tags --annotate-stdin | sed -e "s|$OID_REGEX (tags/\([^)]*\)) |\1 |g"
}
#
diff --git a/t/t6111-rev-list-treesame.sh b/t/t6111-rev-list-treesame.sh
index e07b6070e0..90ff141640 100755
--- a/t/t6111-rev-list-treesame.sh
+++ b/t/t6111-rev-list-treesame.sh
@@ -23,7 +23,8 @@ note () {
}
unnote () {
- git name-rev --tags --stdin | sed -e "s|$OID_REGEX (tags/\([^)]*\))\([ ]\)|\1\2|g"
+ git name-rev --tags --annotate-stdin | \
+ sed -e "s|$OID_REGEX (tags/\([^)]*\))\([ ]\)|\1\2|g"
}
test_expect_success setup '
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index d8af2bb9d2..9781b92aed 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -270,7 +270,7 @@ test_expect_success 'name-rev --all' '
test_cmp expect actual
'
-test_expect_success 'name-rev --stdin' '
+test_expect_success 'name-rev --annotate-stdin' '
>expect.unsorted &&
for rev in $(git rev-list --all)
do
@@ -278,11 +278,16 @@ test_expect_success 'name-rev --stdin' '
echo "$rev ($name)" >>expect.unsorted || return 1
done &&
sort <expect.unsorted >expect &&
- git rev-list --all | git name-rev --stdin >actual.unsorted &&
+ git rev-list --all | git name-rev --annotate-stdin >actual.unsorted &&
sort <actual.unsorted >actual &&
test_cmp expect actual
'
+test_expect_success 'name-rev --stdin deprecated' "
+ git rev-list --all | git name-rev --stdin 2>actual &&
+ grep -E 'warning: --stdin is deprecated' actual
+"
+
test_expect_success 'describe --contains with the exact tags' '
echo "A^0" >expect &&
tag_object=$(git rev-parse refs/tags/A) &&
diff --git a/t/t6429-merge-sequence-rename-caching.sh b/t/t6429-merge-sequence-rename-caching.sh
index 035edc40b1..f2bc8a7d2a 100755
--- a/t/t6429-merge-sequence-rename-caching.sh
+++ b/t/t6429-merge-sequence-rename-caching.sh
@@ -697,4 +697,71 @@ test_expect_success 'caching renames only on upstream side, part 2' '
)
'
+#
+# The following testcase just creates two simple renames (slightly modified
+# on both sides but without conflicting changes), and a directory full of
+# files that are otherwise uninteresting. The setup is as follows:
+#
+# base: unrelated/<BUNCH OF FILES>
+# numbers
+# values
+# upstream: modify: numbers
+# modify: values
+# topic: add: unrelated/foo
+# modify: numbers
+# modify: values
+# rename: numbers -> sequence
+# rename: values -> progression
+#
+# This is a trivial rename case, but we're curious what happens with a very
+# low renameLimit interacting with the restart optimization trying to notice
+# that unrelated/ looks like a trivial merge candidate.
+#
+test_expect_success 'avoid assuming we detected renames' '
+ git init redo-weirdness &&
+ (
+ cd redo-weirdness &&
+
+ mkdir unrelated &&
+ for i in $(test_seq 1 10)
+ do
+ >unrelated/$i
+ done &&
+ test_seq 2 10 >numbers &&
+ test_seq 12 20 >values &&
+ git add numbers values unrelated/ &&
+ git commit -m orig &&
+
+ git branch upstream &&
+ git branch topic &&
+
+ git switch upstream &&
+ test_seq 1 10 >numbers &&
+ test_seq 11 20 >values &&
+ git add numbers &&
+ git commit -m "Some tweaks" &&
+
+ git switch topic &&
+
+ >unrelated/foo &&
+ test_seq 2 12 >numbers &&
+ test_seq 12 22 >values &&
+ git add numbers values unrelated/ &&
+ git mv numbers sequence &&
+ git mv values progression &&
+ git commit -m A &&
+
+ #
+ # Actual testing
+ #
+
+ git switch --detach topic^0 &&
+
+ test_must_fail git -c merge.renameLimit=1 rebase upstream &&
+
+ git ls-files -u >actual &&
+ ! test_file_is_empty actual
+ )
+'
+
test_done
diff --git a/t/t7508-status.sh b/t/t7508-status.sh
index 05c6c02435..2b7ef6c41a 100755
--- a/t/t7508-status.sh
+++ b/t/t7508-status.sh
@@ -1647,13 +1647,33 @@ test_expect_success '"Initial commit" should not be noted in commit template' '
'
test_expect_success '--no-optional-locks prevents index update' '
- test-tool chmtime =1234567890 .git/index &&
+ test_set_magic_mtime .git/index &&
git --no-optional-locks status &&
- test-tool chmtime --get .git/index >out &&
- grep ^1234567890 out &&
+ test_is_magic_mtime .git/index &&
git status &&
- test-tool chmtime --get .git/index >out &&
- ! grep ^1234567890 out
+ ! test_is_magic_mtime .git/index
+'
+
+test_expect_success 'racy timestamps will be fixed for clean worktree' '
+ echo content >racy-dirty &&
+ echo content >racy-racy &&
+ git add racy* &&
+ git commit -m "racy test files" &&
+ # let status rewrite the index, if necessary; after that we expect
+ # no more index writes unless caused by racy timestamps; note that
+ # timestamps may already be racy now (depending on previous tests)
+ git status &&
+ test_set_magic_mtime .git/index &&
+ git status &&
+ ! test_is_magic_mtime .git/index
+'
+
+test_expect_success 'racy timestamps will be fixed for dirty worktree' '
+ echo content2 >racy-dirty &&
+ git status &&
+ test_set_magic_mtime .git/index &&
+ git status &&
+ ! test_is_magic_mtime .git/index
'
test_done
diff --git a/t/t8007-cat-file-textconv.sh b/t/t8007-cat-file-textconv.sh
index eacd49ade6..b067983ba1 100755
--- a/t/t8007-cat-file-textconv.sh
+++ b/t/t8007-cat-file-textconv.sh
@@ -19,6 +19,48 @@ test_expect_success 'setup ' '
GIT_AUTHOR_NAME=Number2 git commit -a -m Second --date="2010-01-01 20:00:00"
'
+test_expect_success 'usage: <bad rev>' '
+ cat >expect <<-\EOF &&
+ fatal: Not a valid object name HEAD2
+ EOF
+ test_must_fail git cat-file --textconv HEAD2 2>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'usage: <bad rev>:<bad path>' '
+ cat >expect <<-\EOF &&
+ fatal: invalid object name '\''HEAD2'\''.
+ EOF
+ test_must_fail git cat-file --textconv HEAD2:two.bin 2>actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'usage: <rev>:<bad path>' '
+ cat >expect <<-\EOF &&
+ fatal: path '\''two.bin'\'' does not exist in '\''HEAD'\''
+ EOF
+ test_must_fail git cat-file --textconv HEAD:two.bin 2>actual &&
+ test_cmp expect actual
+'
+
+
+test_expect_success 'usage: <rev> with no <path>' '
+ cat >expect <<-\EOF &&
+ fatal: <object>:<path> required, only <object> '\''HEAD'\'' given
+ EOF
+ test_must_fail git cat-file --textconv HEAD 2>actual &&
+ test_cmp expect actual
+'
+
+
+test_expect_success 'usage: <bad rev>:<good (in HEAD) path>' '
+ cat >expect <<-\EOF &&
+ fatal: invalid object name '\''HEAD2'\''.
+ EOF
+ test_must_fail git cat-file --textconv HEAD2:one.bin 2>actual &&
+ test_cmp expect actual
+'
+
cat >expected <<EOF
bin: test version 2
EOF
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index aa0c20499b..84d0f40d76 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -539,7 +539,7 @@ test_expect_success $PREREQ "--validate respects relative core.hooksPath path" '
test_path_is_file my-hooks.ran &&
cat >expect <<-EOF &&
fatal: longline.patch: rejected by sendemail-validate hook
- fatal: command '"'"'my-hooks/sendemail-validate'"'"' died with exit code 1
+ fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch>'"'"' died with exit code 1
warning: no patches were sent
EOF
test_cmp expect actual
@@ -558,7 +558,7 @@ test_expect_success $PREREQ "--validate respects absolute core.hooksPath path" '
test_path_is_file my-hooks.ran &&
cat >expect <<-EOF &&
fatal: longline.patch: rejected by sendemail-validate hook
- fatal: command '"'"'$hooks_path/sendemail-validate'"'"' died with exit code 1
+ fatal: command '"'"'git hook run --ignore-missing sendemail-validate -- <patch>'"'"' died with exit code 1
warning: no patches were sent
EOF
test_cmp expect actual
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index c3d38aaccb..85385d2ede 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -1840,3 +1840,36 @@ test_region () {
test_readlink () {
perl -le 'print readlink($_) for @ARGV' "$@"
}
+
+# Set mtime to a fixed "magic" timestamp in mid February 2009, before we
+# run an operation that may or may not touch the file. If the file was
+# touched, its timestamp will not accidentally have such an old timestamp,
+# as long as your filesystem clock is reasonably correct. To verify the
+# timestamp, follow up with test_is_magic_mtime.
+#
+# An optional increment to the magic timestamp may be specified as second
+# argument.
+test_set_magic_mtime () {
+ local inc=${2:-0} &&
+ local mtime=$((1234567890 + $inc)) &&
+ test-tool chmtime =$mtime "$1" &&
+ test_is_magic_mtime "$1" $inc
+}
+
+# Test whether the given file has the "magic" mtime set. This is meant to
+# be used in combination with test_set_magic_mtime.
+#
+# An optional increment to the magic timestamp may be specified as second
+# argument. Usually, this should be the same increment which was used for
+# the associated test_set_magic_mtime.
+test_is_magic_mtime () {
+ local inc=${2:-0} &&
+ local mtime=$((1234567890 + $inc)) &&
+ echo $mtime >.git/test-mtime-expect &&
+ test-tool chmtime --get "$1" >.git/test-mtime-actual &&
+ test_cmp .git/test-mtime-expect .git/test-mtime-actual
+ local ret=$?
+ rm -f .git/test-mtime-expect
+ rm -f .git/test-mtime-actual
+ return $ret
+}
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 0f7a137c7d..e4716b0b86 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -449,6 +449,8 @@ unset VISUAL EMAIL LANGUAGE $("$PERL_PATH" -e '
unset XDG_CACHE_HOME
unset XDG_CONFIG_HOME
unset GITPERLLIB
+unset GIT_TRACE2_PARENT_NAME
+unset GIT_TRACE2_PARENT_SID
TEST_AUTHOR_LOCALNAME=author
TEST_AUTHOR_DOMAIN=example.com
GIT_AUTHOR_EMAIL=${TEST_AUTHOR_LOCALNAME}@${TEST_AUTHOR_DOMAIN}