summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
Diffstat (limited to 't')
-rw-r--r--t/annotate-tests.sh4
-rw-r--r--t/lib-httpd/apache.conf4
-rw-r--r--t/lib-proto-disable.sh96
-rwxr-xr-xt/perf/aggregate.perl1
-rwxr-xr-xt/t0002-gitfile.sh42
-rwxr-xr-xt/t0060-path-utils.sh6
-rwxr-xr-xt/t0090-cache-tree.sh34
-rwxr-xr-xt/t1090-sparse-checkout-scope.sh52
-rwxr-xr-xt/t1300-repo-config.sh22
-rwxr-xr-xt/t1400-update-ref.sh62
-rwxr-xr-xt/t1402-check-ref-format.sh8
-rwxr-xr-xt/t1410-reflog.sh24
-rwxr-xr-xt/t1411-reflog-show.sh7
-rwxr-xr-xt/t1430-bad-ref-name.sh31
-rwxr-xr-xt/t1450-fsck.sh22
-rwxr-xr-xt/t1503-rev-parse-verify.sh9
-rwxr-xr-xt/t1509-root-worktree.sh8
-rwxr-xr-xt/t2019-checkout-ambiguous-ref.sh2
-rwxr-xr-xt/t2025-worktree-add.sh39
-rwxr-xr-xt/t3001-ls-files-others-exclude.sh25
-rwxr-xr-xt/t3020-ls-files-error-unmatch.sh2
-rwxr-xr-xt/t3200-branch.sh12
-rwxr-xr-xt/t3203-branch-output.sh20
-rwxr-xr-xt/t3210-pack-refs.sh9
-rwxr-xr-xt/t3301-notes.sh6
-rwxr-xr-xt/t3309-notes-merge-auto-resolve.sh79
-rwxr-xr-xt/t3310-notes-merge-manual-resolve.sh12
-rwxr-xr-xt/t3320-notes-merge-worktrees.sh72
-rwxr-xr-xt/t3404-rebase-interactive.sh10
-rwxr-xr-xt/t3420-rebase-autostash.sh10
-rwxr-xr-xt/t3903-stash.sh2
-rwxr-xr-xt/t4018-diff-funcname.sh1
-rw-r--r--t/t4018/fountain-scene4
-rwxr-xr-xt/t4150-am.sh84
-rwxr-xr-xt/t4151-am-abort.sh24
-rwxr-xr-xt/t4153-am-resume-override-opts.sh102
-rwxr-xr-xt/t4202-log.sh14
-rwxr-xr-xt/t5004-archive-corner-cases.sh40
-rwxr-xr-xt/t5312-prune-corruption.sh2
-rwxr-xr-xt/t5505-remote.sh37
-rwxr-xr-xt/t5507-remote-environment.sh34
-rwxr-xr-xt/t5511-refspec.sh11
-rwxr-xr-xt/t5512-ls-remote.sh23
-rwxr-xr-xt/t5520-pull.sh11
-rwxr-xr-xt/t5560-http-backend-noserver.sh4
-rwxr-xr-xt/t5561-http-backend.sh8
-rwxr-xr-xt/t556x_common12
-rwxr-xr-xt/t5603-clone-dirname.sh106
-rwxr-xr-xt/t5700-clone-reference.sh196
-rwxr-xr-xt/t5801-remote-helpers.sh12
-rwxr-xr-xt/t5810-proto-disable-local.sh14
-rwxr-xr-xt/t5811-proto-disable-git.sh20
-rwxr-xr-xt/t5812-proto-disable-http.sh33
-rwxr-xr-xt/t5813-proto-disable-ssh.sh20
-rwxr-xr-xt/t5814-proto-disable-ext.sh18
-rwxr-xr-xt/t5815-submodule-protos.sh43
-rwxr-xr-xt/t6030-bisect-porcelain.sh137
-rwxr-xr-xt/t6120-describe.sh8
-rwxr-xr-xt/t6300-for-each-ref.sh162
-rwxr-xr-xt/t6302-for-each-ref-filter.sh258
-rwxr-xr-xt/t6501-freshen-objects.sh2
-rwxr-xr-xt/t7004-tag.sh61
-rwxr-xr-xt/t7006-pager.sh9
-rwxr-xr-xt/t7060-wtstatus.sh2
-rwxr-xr-xt/t7063-status-untracked-cache.sh215
-rwxr-xr-xt/t7300-clean.sh18
-rwxr-xr-xt/t7410-submodule-checkout-to.sh10
-rwxr-xr-xt/t7411-submodule-config.sh153
-rwxr-xr-xt/t7509-commit.sh13
-rwxr-xr-xt/t7513-interpret-trailers.sh29
-rwxr-xr-xt/t7610-mergetool.sh2
-rwxr-xr-xt/t7800-difftool.sh8
-rwxr-xr-xt/t9811-git-p4-label-import.sh45
-rwxr-xr-xt/t9821-git-p4-path-variations.sh200
-rwxr-xr-xt/t9822-git-p4-path-encoding.sh58
-rwxr-xr-xt/t9825-git-p4-handle-utf16-without-bom.sh50
-rw-r--r--t/test-lib-functions.sh25
-rw-r--r--t/test-lib.sh13
-rwxr-xr-xt/test-terminal.perl32
79 files changed, 2797 insertions, 318 deletions
diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh
index f5c01758ca..b1673b3e8f 100644
--- a/t/annotate-tests.sh
+++ b/t/annotate-tests.sh
@@ -111,6 +111,10 @@ test_expect_success 'blame 2 authors + 2 merged-in authors' '
check_count A 2 B 1 B1 2 B2 1
'
+test_expect_success 'blame --first-parent blames merge for branch1' '
+ check_count --first-parent A 2 B 1 "A U Thor" 2 B2 1
+'
+
test_expect_success 'blame ancestor' '
check_count -h master A 2 B 2
'
diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
index 0b81a0047b..7d15e6d44c 100644
--- a/t/lib-httpd/apache.conf
+++ b/t/lib-httpd/apache.conf
@@ -119,6 +119,10 @@ RewriteRule ^/smart-redir-perm/(.*)$ /smart/$1 [R=301]
RewriteRule ^/smart-redir-temp/(.*)$ /smart/$1 [R=302]
RewriteRule ^/smart-redir-auth/(.*)$ /auth/smart/$1 [R=301]
RewriteRule ^/smart-redir-limited/(.*)/info/refs$ /smart/$1/info/refs [R=301]
+RewriteRule ^/ftp-redir/(.*)$ ftp://localhost:1000/$1 [R=302]
+
+RewriteRule ^/loop-redir/x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-(.*) /$1 [R=302]
+RewriteRule ^/loop-redir/(.*)$ /loop-redir/x-$1 [R=302]
<IfDefine SSL>
LoadModule ssl_module modules/mod_ssl.so
diff --git a/t/lib-proto-disable.sh b/t/lib-proto-disable.sh
new file mode 100644
index 0000000000..b0917d93e6
--- /dev/null
+++ b/t/lib-proto-disable.sh
@@ -0,0 +1,96 @@
+# Test routines for checking protocol disabling.
+
+# test cloning a particular protocol
+# $1 - description of the protocol
+# $2 - machine-readable name of the protocol
+# $3 - the URL to try cloning
+test_proto () {
+ desc=$1
+ proto=$2
+ url=$3
+
+ test_expect_success "clone $1 (enabled)" '
+ rm -rf tmp.git &&
+ (
+ GIT_ALLOW_PROTOCOL=$proto &&
+ export GIT_ALLOW_PROTOCOL &&
+ git clone --bare "$url" tmp.git
+ )
+ '
+
+ test_expect_success "fetch $1 (enabled)" '
+ (
+ cd tmp.git &&
+ GIT_ALLOW_PROTOCOL=$proto &&
+ export GIT_ALLOW_PROTOCOL &&
+ git fetch
+ )
+ '
+
+ test_expect_success "push $1 (enabled)" '
+ (
+ cd tmp.git &&
+ GIT_ALLOW_PROTOCOL=$proto &&
+ export GIT_ALLOW_PROTOCOL &&
+ git push origin HEAD:pushed
+ )
+ '
+
+ test_expect_success "push $1 (disabled)" '
+ (
+ cd tmp.git &&
+ GIT_ALLOW_PROTOCOL=none &&
+ export GIT_ALLOW_PROTOCOL &&
+ test_must_fail git push origin HEAD:pushed
+ )
+ '
+
+ test_expect_success "fetch $1 (disabled)" '
+ (
+ cd tmp.git &&
+ GIT_ALLOW_PROTOCOL=none &&
+ export GIT_ALLOW_PROTOCOL &&
+ test_must_fail git fetch
+ )
+ '
+
+ test_expect_success "clone $1 (disabled)" '
+ rm -rf tmp.git &&
+ (
+ GIT_ALLOW_PROTOCOL=none &&
+ export GIT_ALLOW_PROTOCOL &&
+ test_must_fail git clone --bare "$url" tmp.git
+ )
+ '
+}
+
+# set up an ssh wrapper that will access $host/$repo in the
+# trash directory, and enable it for subsequent tests.
+setup_ssh_wrapper () {
+ test_expect_success 'setup ssh wrapper' '
+ write_script ssh-wrapper <<-\EOF &&
+ echo >&2 "ssh: $*"
+ host=$1; shift
+ cd "$TRASH_DIRECTORY/$host" &&
+ eval "$*"
+ EOF
+ GIT_SSH="$PWD/ssh-wrapper" &&
+ export GIT_SSH &&
+ export TRASH_DIRECTORY
+ '
+}
+
+# set up a wrapper that can be used with remote-ext to
+# access repositories in the "remote" directory of trash-dir,
+# like "ext::fake-remote %S repo.git"
+setup_ext_wrapper () {
+ test_expect_success 'setup ext wrapper' '
+ write_script fake-remote <<-\EOF &&
+ echo >&2 "fake-remote: $*"
+ cd "$TRASH_DIRECTORY/remote" &&
+ eval "$*"
+ EOF
+ PATH=$TRASH_DIRECTORY:$PATH &&
+ export TRASH_DIRECTORY
+ '
+}
diff --git a/t/perf/aggregate.perl b/t/perf/aggregate.perl
index 15f7fc1b80..924b19dab4 100755
--- a/t/perf/aggregate.perl
+++ b/t/perf/aggregate.perl
@@ -1,5 +1,6 @@
#!/usr/bin/perl
+use lib '../../perl/blib/lib';
use strict;
use warnings;
use Git;
diff --git a/t/t0002-gitfile.sh b/t/t0002-gitfile.sh
index 9393322c3e..9670e8cbe6 100755
--- a/t/t0002-gitfile.sh
+++ b/t/t0002-gitfile.sh
@@ -116,4 +116,46 @@ test_expect_success 'setup_git_dir twice in subdir' '
)
'
+test_expect_success 'enter_repo non-strict mode' '
+ test_create_repo enter_repo &&
+ (
+ cd enter_repo &&
+ test_tick &&
+ test_commit foo &&
+ mv .git .realgit &&
+ echo "gitdir: .realgit" >.git
+ ) &&
+ git ls-remote enter_repo >actual &&
+ cat >expected <<-\EOF &&
+ 946e985ab20de757ca5b872b16d64e92ff3803a9 HEAD
+ 946e985ab20de757ca5b872b16d64e92ff3803a9 refs/heads/master
+ 946e985ab20de757ca5b872b16d64e92ff3803a9 refs/tags/foo
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'enter_repo linked checkout' '
+ (
+ cd enter_repo &&
+ git worktree add ../foo refs/tags/foo
+ ) &&
+ git ls-remote foo >actual &&
+ cat >expected <<-\EOF &&
+ 946e985ab20de757ca5b872b16d64e92ff3803a9 HEAD
+ 946e985ab20de757ca5b872b16d64e92ff3803a9 refs/heads/master
+ 946e985ab20de757ca5b872b16d64e92ff3803a9 refs/tags/foo
+ EOF
+ test_cmp expected actual
+'
+
+test_expect_success 'enter_repo strict mode' '
+ git ls-remote --upload-pack="git upload-pack --strict" foo/.git >actual &&
+ cat >expected <<-\EOF &&
+ 946e985ab20de757ca5b872b16d64e92ff3803a9 HEAD
+ 946e985ab20de757ca5b872b16d64e92ff3803a9 refs/heads/master
+ 946e985ab20de757ca5b872b16d64e92ff3803a9 refs/tags/foo
+ EOF
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 93605f42f2..627ef854d5 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -266,15 +266,21 @@ test_expect_success 'setup common repository' 'git --git-dir=bar init'
test_git_path GIT_COMMON_DIR=bar index .git/index
test_git_path GIT_COMMON_DIR=bar HEAD .git/HEAD
test_git_path GIT_COMMON_DIR=bar logs/HEAD .git/logs/HEAD
+test_git_path GIT_COMMON_DIR=bar logs/refs/bisect/foo .git/logs/refs/bisect/foo
+test_git_path GIT_COMMON_DIR=bar logs/refs/bisec/foo bar/logs/refs/bisec/foo
+test_git_path GIT_COMMON_DIR=bar logs/refs/bisec bar/logs/refs/bisec
+test_git_path GIT_COMMON_DIR=bar logs/refs/bisectfoo bar/logs/refs/bisectfoo
test_git_path GIT_COMMON_DIR=bar objects bar/objects
test_git_path GIT_COMMON_DIR=bar objects/bar bar/objects/bar
test_git_path GIT_COMMON_DIR=bar info/exclude bar/info/exclude
test_git_path GIT_COMMON_DIR=bar info/grafts bar/info/grafts
test_git_path GIT_COMMON_DIR=bar info/sparse-checkout .git/info/sparse-checkout
+test_git_path GIT_COMMON_DIR=bar info//sparse-checkout .git/info//sparse-checkout
test_git_path GIT_COMMON_DIR=bar remotes/bar bar/remotes/bar
test_git_path GIT_COMMON_DIR=bar branches/bar bar/branches/bar
test_git_path GIT_COMMON_DIR=bar logs/refs/heads/master bar/logs/refs/heads/master
test_git_path GIT_COMMON_DIR=bar refs/heads/master bar/refs/heads/master
+test_git_path GIT_COMMON_DIR=bar refs/bisect/foo .git/refs/bisect/foo
test_git_path GIT_COMMON_DIR=bar hooks/me bar/hooks/me
test_git_path GIT_COMMON_DIR=bar config bar/config
test_git_path GIT_COMMON_DIR=bar packed-refs bar/packed-refs
diff --git a/t/t0090-cache-tree.sh b/t/t0090-cache-tree.sh
index 601d02d71f..adfd4f0b5e 100755
--- a/t/t0090-cache-tree.sh
+++ b/t/t0090-cache-tree.sh
@@ -199,6 +199,30 @@ test_expect_success 'checkout -B gives cache-tree' '
test_cache_tree
'
+test_expect_success 'merge --ff-only maintains cache-tree' '
+ git checkout current &&
+ git checkout -b changes &&
+ test_commit llamas &&
+ test_commit pachyderm &&
+ test_cache_tree &&
+ git checkout current &&
+ test_cache_tree &&
+ git merge --ff-only changes &&
+ test_cache_tree
+'
+
+test_expect_success 'merge maintains cache-tree' '
+ git checkout current &&
+ git checkout -b changes2 &&
+ test_commit alpacas &&
+ test_cache_tree &&
+ git checkout current &&
+ test_commit struthio &&
+ test_cache_tree &&
+ git merge changes2 &&
+ test_cache_tree
+'
+
test_expect_success 'partial commit gives cache-tree' '
git checkout -b partial no-children &&
test_commit one &&
@@ -218,4 +242,14 @@ test_expect_success 'no phantom error when switching trees' '
! test -s errors
'
+test_expect_success 'switching trees does not invalidate shared index' '
+ git update-index --split-index &&
+ >split &&
+ git add split &&
+ test-dump-split-index .git/index | grep -v ^own >before &&
+ git commit -m "as-is" &&
+ test-dump-split-index .git/index | grep -v ^own >after &&
+ test_cmp before after
+'
+
test_done
diff --git a/t/t1090-sparse-checkout-scope.sh b/t/t1090-sparse-checkout-scope.sh
new file mode 100755
index 0000000000..1f61eb3e88
--- /dev/null
+++ b/t/t1090-sparse-checkout-scope.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+test_description='sparse checkout scope tests'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ echo "initial" >a &&
+ echo "initial" >b &&
+ echo "initial" >c &&
+ git add a b c &&
+ git commit -m "initial commit"
+'
+
+test_expect_success 'create feature branch' '
+ git checkout -b feature &&
+ echo "modified" >b &&
+ echo "modified" >c &&
+ git add b c &&
+ git commit -m "modification"
+'
+
+test_expect_success 'perform sparse checkout of master' '
+ git config --local --bool core.sparsecheckout true &&
+ echo "!/*" >.git/info/sparse-checkout &&
+ echo "/a" >>.git/info/sparse-checkout &&
+ echo "/c" >>.git/info/sparse-checkout &&
+ git checkout master &&
+ test_path_is_file a &&
+ test_path_is_missing b &&
+ test_path_is_file c
+'
+
+test_expect_success 'merge feature branch into sparse checkout of master' '
+ git merge feature &&
+ test_path_is_file a &&
+ test_path_is_missing b &&
+ test_path_is_file c &&
+ test "$(cat c)" = "modified"
+'
+
+test_expect_success 'return to full checkout of master' '
+ git checkout feature &&
+ echo "/*" >.git/info/sparse-checkout &&
+ git checkout master &&
+ test_path_is_file a &&
+ test_path_is_file b &&
+ test_path_is_file c &&
+ test "$(cat b)" = "modified"
+'
+
+test_done
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index 66dd28644f..52678e7d0a 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -353,6 +353,18 @@ test_expect_success '--list without repo produces empty output' '
'
cat > expect << EOF
+beta.noindent
+nextsection.nonewline
+123456.a123
+version.1.2.3eX.alpha
+EOF
+
+test_expect_success '--name-only --list' '
+ git config --name-only --list >output &&
+ test_cmp expect output
+'
+
+cat > expect << EOF
beta.noindent sillyValue
nextsection.nonewline wow2 for me
EOF
@@ -363,6 +375,16 @@ test_expect_success '--get-regexp' '
'
cat > expect << EOF
+beta.noindent
+nextsection.nonewline
+EOF
+
+test_expect_success '--name-only --get-regexp' '
+ git config --name-only --get-regexp in >output &&
+ test_cmp expect output
+'
+
+cat > expect << EOF
wow2 for me
wow4 for you
EOF
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index d787bf50f8..af1b20dd5c 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -23,6 +23,7 @@ test_expect_success setup '
m=refs/heads/master
n_dir=refs/heads/gu
n=$n_dir/fixes
+outside=foo
test_expect_success \
"create $m" \
@@ -74,6 +75,24 @@ test_expect_success "delete $m (by HEAD)" '
'
rm -f .git/$m
+test_expect_success 'update-ref does not create reflogs by default' '
+ test_when_finished "git update-ref -d $outside" &&
+ git update-ref $outside $A &&
+ git rev-parse $A >expect &&
+ git rev-parse $outside >actual &&
+ test_cmp expect actual &&
+ test_must_fail git reflog exists $outside
+'
+
+test_expect_success 'update-ref creates reflogs with --create-reflog' '
+ test_when_finished "git update-ref -d $outside" &&
+ git update-ref --create-reflog $outside $A &&
+ git rev-parse $A >expect &&
+ git rev-parse $outside >actual &&
+ test_cmp expect actual &&
+ git reflog exists $outside
+'
+
test_expect_success \
"create $m (by HEAD)" \
"git update-ref HEAD $A &&
@@ -155,12 +174,11 @@ test_expect_success "(not) changed .git/$m" "
'
rm -f .git/$m
-: a repository with working tree always has reflog these days...
-: >.git/logs/refs/heads/master
+rm -f .git/logs/refs/heads/master
test_expect_success \
"create $m (logged by touch)" \
'GIT_COMMITTER_DATE="2005-05-26 23:30" \
- git update-ref HEAD '"$A"' -m "Initial Creation" &&
+ git update-ref --create-reflog HEAD '"$A"' -m "Initial Creation" &&
test '"$A"' = $(cat .git/'"$m"')'
test_expect_success \
"update $m (logged by touch)" \
@@ -472,6 +490,25 @@ test_expect_success 'stdin create ref works' '
test_cmp expect actual
'
+test_expect_success 'stdin does not create reflogs by default' '
+ test_when_finished "git update-ref -d $outside" &&
+ echo "create $outside $m" >stdin &&
+ git update-ref --stdin <stdin &&
+ git rev-parse $m >expect &&
+ git rev-parse $outside >actual &&
+ test_cmp expect actual &&
+ test_must_fail git reflog exists $outside
+'
+
+test_expect_success 'stdin creates reflogs with --create-reflog' '
+ echo "create $outside $m" >stdin &&
+ git update-ref --create-reflog --stdin <stdin &&
+ git rev-parse $m >expect &&
+ git rev-parse $outside >actual &&
+ test_cmp expect actual &&
+ git reflog exists $outside
+'
+
test_expect_success 'stdin succeeds with quoted argument' '
git update-ref -d $a &&
echo "create $a \"$m\"" >stdin &&
@@ -1093,4 +1130,23 @@ test_expect_success ULIMIT_FILE_DESCRIPTORS 'large transaction deleting branches
)
'
+test_expect_success 'handle per-worktree refs in refs/bisect' '
+ git commit --allow-empty -m "initial commit" &&
+ git worktree add -b branch worktree &&
+ (
+ cd worktree &&
+ git commit --allow-empty -m "test commit" &&
+ git for-each-ref >for-each-ref.out &&
+ ! grep refs/bisect for-each-ref.out &&
+ git update-ref refs/bisect/something HEAD &&
+ git rev-parse refs/bisect/something >../worktree-head &&
+ git for-each-ref | grep refs/bisect/something
+ ) &&
+ test_path_is_missing .git/refs/bisect &&
+ test_must_fail git rev-parse refs/bisect/something &&
+ git update-ref refs/bisect/something HEAD &&
+ git rev-parse refs/bisect/something >main-head &&
+ ! test_cmp main-head worktree-head
+'
+
test_done
diff --git a/t/t1402-check-ref-format.sh b/t/t1402-check-ref-format.sh
index e5dc62e9ef..0790edf60d 100755
--- a/t/t1402-check-ref-format.sh
+++ b/t/t1402-check-ref-format.sh
@@ -62,9 +62,11 @@ invalid_ref 'heads/foo\bar'
invalid_ref "$(printf 'heads/foo\t')"
invalid_ref "$(printf 'heads/foo\177')"
valid_ref "$(printf 'heads/fu\303\237')"
-invalid_ref 'heads/*foo/bar' --refspec-pattern
-invalid_ref 'heads/foo*/bar' --refspec-pattern
-invalid_ref 'heads/f*o/bar' --refspec-pattern
+valid_ref 'heads/*foo/bar' --refspec-pattern
+valid_ref 'heads/foo*/bar' --refspec-pattern
+valid_ref 'heads/f*o/bar' --refspec-pattern
+invalid_ref 'heads/f*o*/bar' --refspec-pattern
+invalid_ref 'heads/foo*/bar*' --refspec-pattern
ref='foo'
invalid_ref "$ref"
diff --git a/t/t1410-reflog.sh b/t/t1410-reflog.sh
index 779d4e3829..b79049f6f6 100755
--- a/t/t1410-reflog.sh
+++ b/t/t1410-reflog.sh
@@ -100,7 +100,8 @@ test_expect_success setup '
check_fsck &&
- test_line_count = 4 .git/logs/refs/heads/master
+ git reflog refs/heads/master >output &&
+ test_line_count = 4 output
'
test_expect_success rewind '
@@ -116,7 +117,8 @@ test_expect_success rewind '
check_have A B C D E F G H I J K L &&
- test_line_count = 5 .git/logs/refs/heads/master
+ git reflog refs/heads/master >output &&
+ test_line_count = 5 output
'
test_expect_success 'corrupt and check' '
@@ -134,7 +136,8 @@ test_expect_success 'reflog expire --dry-run should not touch reflog' '
--stale-fix \
--all &&
- test_line_count = 5 .git/logs/refs/heads/master &&
+ git reflog refs/heads/master >output &&
+ test_line_count = 5 output &&
check_fsck "missing blob $F"
'
@@ -147,7 +150,8 @@ test_expect_success 'reflog expire' '
--stale-fix \
--all &&
- test_line_count = 2 .git/logs/refs/heads/master &&
+ git reflog refs/heads/master >output &&
+ test_line_count = 2 output &&
check_fsck "dangling commit $K"
'
@@ -213,7 +217,8 @@ test_expect_success 'delete' '
test_expect_success 'rewind2' '
test_tick && git reset --hard HEAD~2 &&
- test_line_count = 4 .git/logs/refs/heads/master
+ git reflog refs/heads/master >output &&
+ test_line_count = 4 output
'
test_expect_success '--expire=never' '
@@ -222,7 +227,8 @@ test_expect_success '--expire=never' '
--expire=never \
--expire-unreachable=never \
--all &&
- test_line_count = 4 .git/logs/refs/heads/master
+ git reflog refs/heads/master >output &&
+ test_line_count = 4 output
'
test_expect_success 'gc.reflogexpire=never' '
@@ -230,7 +236,8 @@ test_expect_success 'gc.reflogexpire=never' '
git config gc.reflogexpire never &&
git config gc.reflogexpireunreachable never &&
git reflog expire --verbose --all &&
- test_line_count = 4 .git/logs/refs/heads/master
+ git reflog refs/heads/master >output &&
+ test_line_count = 4 output
'
test_expect_success 'gc.reflogexpire=false' '
@@ -238,7 +245,8 @@ test_expect_success 'gc.reflogexpire=false' '
git config gc.reflogexpire false &&
git config gc.reflogexpireunreachable false &&
git reflog expire --verbose --all &&
- test_line_count = 4 .git/logs/refs/heads/master &&
+ git reflog refs/heads/master >output &&
+ test_line_count = 4 output &&
git config --unset gc.reflogexpire &&
git config --unset gc.reflogexpireunreachable
diff --git a/t/t1411-reflog-show.sh b/t/t1411-reflog-show.sh
index 6f47c0dd0e..6ac7734d79 100755
--- a/t/t1411-reflog-show.sh
+++ b/t/t1411-reflog-show.sh
@@ -138,7 +138,7 @@ test_expect_success '--date magic does not override explicit @{0} syntax' '
: >expect
test_expect_success 'empty reflog file' '
git branch empty &&
- : >.git/logs/refs/heads/empty &&
+ git reflog expire --expire=all refs/heads/empty &&
git log -g empty >actual &&
test_cmp expect actual
@@ -166,4 +166,9 @@ test_expect_success 'git log -g -p shows diffs vs. parents' '
test_cmp expect actual
'
+test_expect_success 'reflog exists works' '
+ git reflog exists refs/heads/master &&
+ ! git reflog exists refs/heads/nonexistent
+'
+
test_done
diff --git a/t/t1430-bad-ref-name.sh b/t/t1430-bad-ref-name.sh
index 16d0b8bd1a..c465abe8e3 100755
--- a/t/t1430-bad-ref-name.sh
+++ b/t/t1430-bad-ref-name.sh
@@ -38,18 +38,20 @@ test_expect_success 'fast-import: fail on invalid branch name "bad[branch]name"'
test_must_fail git fast-import <input
'
-test_expect_success 'git branch shows badly named ref' '
+test_expect_success 'git branch shows badly named ref as warning' '
cp .git/refs/heads/master .git/refs/heads/broken...ref &&
test_when_finished "rm -f .git/refs/heads/broken...ref" &&
- git branch >output &&
- grep -e "broken\.\.\.ref" output
+ git branch >output 2>error &&
+ grep -e "broken\.\.\.ref" error &&
+ ! grep -e "broken\.\.\.ref" output
'
test_expect_success 'branch -d can delete badly named ref' '
cp .git/refs/heads/master .git/refs/heads/broken...ref &&
test_when_finished "rm -f .git/refs/heads/broken...ref" &&
git branch -d broken...ref &&
- git branch >output &&
+ git branch >output 2>error &&
+ ! grep -e "broken\.\.\.ref" error &&
! grep -e "broken\.\.\.ref" output
'
@@ -57,7 +59,8 @@ test_expect_success 'branch -D can delete badly named ref' '
cp .git/refs/heads/master .git/refs/heads/broken...ref &&
test_when_finished "rm -f .git/refs/heads/broken...ref" &&
git branch -D broken...ref &&
- git branch >output &&
+ git branch >output 2>error &&
+ ! grep -e "broken\.\.\.ref" error &&
! grep -e "broken\.\.\.ref" output
'
@@ -85,7 +88,8 @@ test_expect_success 'branch -D cannot delete absolute path' '
test_expect_success 'git branch cannot create a badly named ref' '
test_when_finished "rm -f .git/refs/heads/broken...ref" &&
test_must_fail git branch broken...ref &&
- git branch >output &&
+ git branch >output 2>error &&
+ ! grep -e "broken\.\.\.ref" error &&
! grep -e "broken\.\.\.ref" output
'
@@ -95,7 +99,8 @@ test_expect_success 'branch -m cannot rename to a bad ref name' '
git branch goodref &&
test_must_fail git branch -m goodref broken...ref &&
test_cmp_rev master goodref &&
- git branch >output &&
+ git branch >output 2>error &&
+ ! grep -e "broken\.\.\.ref" error &&
! grep -e "broken\.\.\.ref" output
'
@@ -104,14 +109,16 @@ test_expect_failure 'branch -m can rename from a bad ref name' '
test_when_finished "rm -f .git/refs/heads/broken...ref" &&
git branch -m broken...ref renamed &&
test_cmp_rev master renamed &&
- git branch >output &&
+ git branch >output 2>error &&
+ ! grep -e "broken\.\.\.ref" error &&
! grep -e "broken\.\.\.ref" output
'
test_expect_success 'push cannot create a badly named ref' '
test_when_finished "rm -f .git/refs/heads/broken...ref" &&
test_must_fail git push "file://$(pwd)" HEAD:refs/heads/broken...ref &&
- git branch >output &&
+ git branch >output 2>error &&
+ ! grep -e "broken\.\.\.ref" error &&
! grep -e "broken\.\.\.ref" output
'
@@ -131,7 +138,8 @@ test_expect_failure 'push --mirror can delete badly named ref' '
cp .git/refs/heads/master .git/refs/heads/broken...ref
) &&
git -C src push --mirror "file://$top/dest" &&
- git -C dest branch >output &&
+ git -C dest branch >output 2>error &&
+ ! grep -e "broken\.\.\.ref" error &&
! grep -e "broken\.\.\.ref" output
'
@@ -159,7 +167,8 @@ test_expect_success 'update-ref -d can delete broken name' '
cp .git/refs/heads/master .git/refs/heads/broken...ref &&
test_when_finished "rm -f .git/refs/heads/broken...ref" &&
git update-ref -d refs/heads/broken...ref &&
- git branch >output &&
+ git branch >output 2>error &&
+ ! grep -e "broken\.\.\.ref" error &&
! grep -e "broken\.\.\.ref" output
'
diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh
index 956673b8a1..dc09797021 100755
--- a/t/t1450-fsck.sh
+++ b/t/t1450-fsck.sh
@@ -77,11 +77,31 @@ test_expect_success 'object with bad sha1' '
test_expect_success 'branch pointing to non-commit' '
git rev-parse HEAD^{tree} >.git/refs/heads/invalid &&
test_when_finished "git update-ref -d refs/heads/invalid" &&
- git fsck 2>out &&
+ test_must_fail git fsck 2>out &&
cat out &&
grep "not a commit" out
'
+test_expect_success 'HEAD link pointing at a funny object' '
+ test_when_finished "mv .git/SAVED_HEAD .git/HEAD" &&
+ mv .git/HEAD .git/SAVED_HEAD &&
+ echo 0000000000000000000000000000000000000000 >.git/HEAD &&
+ # avoid corrupt/broken HEAD from interfering with repo discovery
+ test_must_fail env GIT_DIR=.git git fsck 2>out &&
+ cat out &&
+ grep "detached HEAD points" out
+'
+
+test_expect_success 'HEAD link pointing at a funny place' '
+ test_when_finished "mv .git/SAVED_HEAD .git/HEAD" &&
+ mv .git/HEAD .git/SAVED_HEAD &&
+ echo "ref: refs/funny/place" >.git/HEAD &&
+ # avoid corrupt/broken HEAD from interfering with repo discovery
+ test_must_fail env GIT_DIR=.git git fsck 2>out &&
+ cat out &&
+ grep "HEAD points to something strange" out
+'
+
test_expect_success 'email without @ is okay' '
git cat-file commit HEAD >basis &&
sed "s/@/AT/" basis >okay &&
diff --git a/t/t1503-rev-parse-verify.sh b/t/t1503-rev-parse-verify.sh
index 823fe1d799..ab27d0db5c 100755
--- a/t/t1503-rev-parse-verify.sh
+++ b/t/t1503-rev-parse-verify.sh
@@ -85,8 +85,7 @@ test_expect_success 'fails silently when using -q' '
test_expect_success 'fails silently when using -q with deleted reflogs' '
ref=$(git rev-parse HEAD) &&
- : >.git/logs/refs/test &&
- git update-ref -m "message for refs/test" refs/test "$ref" &&
+ git update-ref --create-reflog -m "message for refs/test" refs/test "$ref" &&
git reflog delete --updateref --rewrite refs/test@{0} &&
test_must_fail git rev-parse -q --verify refs/test@{0} >error 2>&1 &&
test_must_be_empty error
@@ -94,16 +93,14 @@ test_expect_success 'fails silently when using -q with deleted reflogs' '
test_expect_success 'fails silently when using -q with not enough reflogs' '
ref=$(git rev-parse HEAD) &&
- : >.git/logs/refs/test2 &&
- git update-ref -m "message for refs/test2" refs/test2 "$ref" &&
+ git update-ref --create-reflog -m "message for refs/test2" refs/test2 "$ref" &&
test_must_fail git rev-parse -q --verify refs/test2@{999} >error 2>&1 &&
test_must_be_empty error
'
test_expect_success 'succeeds silently with -q and reflogs that do not go far back enough in time' '
ref=$(git rev-parse HEAD) &&
- : >.git/logs/refs/test3 &&
- git update-ref -m "message for refs/test3" refs/test3 "$ref" &&
+ git update-ref --create-reflog -m "message for refs/test3" refs/test3 "$ref" &&
git rev-parse -q --verify refs/test3@{1.year.ago} >actual 2>error &&
test_must_be_empty error &&
echo "$ref" >expect &&
diff --git a/t/t1509-root-worktree.sh b/t/t1509-root-worktree.sh
index b6977d4b39..553a3f601b 100755
--- a/t/t1509-root-worktree.sh
+++ b/t/t1509-root-worktree.sh
@@ -125,7 +125,7 @@ fi
ONE_SHA1=d00491fd7e5bb6fa28c517a0bb32b8b506539d4d
test_expect_success 'setup' '
- rm -rf /foo
+ rm -rf /foo &&
mkdir /foo &&
mkdir /foo/bar &&
echo 1 > /foo/foome &&
@@ -218,7 +218,7 @@ unset GIT_WORK_TREE
test_expect_success 'go to /' 'cd /'
test_expect_success 'setup' '
- rm -rf /.git
+ rm -rf /.git &&
echo "Initialized empty Git repository in /.git/" > expected &&
git init > result &&
test_cmp expected result
@@ -241,8 +241,8 @@ say "auto bare gitdir"
# DESTROYYYYY!!!!!
test_expect_success 'setup' '
- rm -rf /refs /objects /info /hooks
- rm /*
+ rm -rf /refs /objects /info /hooks &&
+ rm -f /expected /ls.expected /me /result &&
cd / &&
echo "Initialized empty Git repository in /" > expected &&
git init --bare > result &&
diff --git a/t/t2019-checkout-ambiguous-ref.sh b/t/t2019-checkout-ambiguous-ref.sh
index 8396320d52..199b22d85e 100755
--- a/t/t2019-checkout-ambiguous-ref.sh
+++ b/t/t2019-checkout-ambiguous-ref.sh
@@ -69,7 +69,7 @@ test_expect_success 'wildcard ambiguation, paths win' '
)
'
-test_expect_success 'wildcard ambiguation, refs lose' '
+test_expect_success !MINGW 'wildcard ambiguation, refs lose' '
git init ambi2 &&
(
cd ambi2 &&
diff --git a/t/t2025-worktree-add.sh b/t/t2025-worktree-add.sh
index ead8aa2a9d..3694174989 100755
--- a/t/t2025-worktree-add.sh
+++ b/t/t2025-worktree-add.sh
@@ -83,6 +83,14 @@ test_expect_success 'die the same branch is already checked out' '
)
'
+test_expect_success SYMLINKS 'die the same branch is already checked out (symlink)' '
+ head=$(git -C there rev-parse --git-path HEAD) &&
+ ref=$(git -C there symbolic-ref HEAD) &&
+ rm "$head" &&
+ ln -s "$ref" "$head" &&
+ test_must_fail git -C here checkout newmaster
+'
+
test_expect_success 'not die the same branch is already checked out' '
(
cd here &&
@@ -145,6 +153,14 @@ test_expect_success '"add -b" with <branch> omitted' '
test_cmp_rev HEAD burble
'
+test_expect_success '"add --detach" with <branch> omitted' '
+ git worktree add --detach fishhook &&
+ git rev-parse HEAD >expected &&
+ git -C fishhook rev-parse HEAD >actual &&
+ test_cmp expected actual &&
+ test_must_fail git -C fishhook symbolic-ref HEAD
+'
+
test_expect_success '"add" with <branch> omitted' '
git worktree add wiffle/bat &&
test_cmp_rev HEAD bat
@@ -159,4 +175,27 @@ test_expect_success '"add" auto-vivify does not clobber existing branch' '
test_path_is_missing precious
'
+test_expect_success '"add" no auto-vivify with --detach and <branch> omitted' '
+ git worktree add --detach mish/mash &&
+ test_must_fail git rev-parse mash -- &&
+ test_must_fail git -C mish/mash symbolic-ref HEAD
+'
+
+test_expect_success '"add" -b/-B mutually exclusive' '
+ test_must_fail git worktree add -b poodle -B poodle bamboo master
+'
+
+test_expect_success '"add" -b/--detach mutually exclusive' '
+ test_must_fail git worktree add -b poodle --detach bamboo master
+'
+
+test_expect_success '"add" -B/--detach mutually exclusive' '
+ test_must_fail git worktree add -B poodle --detach bamboo master
+'
+
+test_expect_success 'local clone from linked checkout' '
+ git clone --local here here-clone &&
+ ( cd here-clone && git fsck )
+'
+
test_done
diff --git a/t/t3001-ls-files-others-exclude.sh b/t/t3001-ls-files-others-exclude.sh
index 3fc484e8c3..da257c020f 100755
--- a/t/t3001-ls-files-others-exclude.sh
+++ b/t/t3001-ls-files-others-exclude.sh
@@ -305,4 +305,29 @@ test_expect_success 'ls-files with "**" patterns and no slashes' '
test_cmp expect actual
'
+test_expect_success 'negative patterns' '
+ git init reinclude &&
+ (
+ cd reinclude &&
+ cat >.gitignore <<-\EOF &&
+ /fooo
+ /foo
+ !foo/bar/bar
+ EOF
+ mkdir fooo &&
+ cat >fooo/.gitignore <<-\EOF &&
+ !/*
+ EOF
+ mkdir -p foo/bar &&
+ touch abc foo/def foo/bar/ghi foo/bar/bar &&
+ git ls-files -o --exclude-standard >../actual &&
+ cat >../expected <<-\EOF &&
+ .gitignore
+ abc
+ foo/bar/bar
+ EOF
+ test_cmp ../expected ../actual
+ )
+'
+
test_done
diff --git a/t/t3020-ls-files-error-unmatch.sh b/t/t3020-ls-files-error-unmatch.sh
index ca01053bcc..124e73b8e6 100755
--- a/t/t3020-ls-files-error-unmatch.sh
+++ b/t/t3020-ls-files-error-unmatch.sh
@@ -22,7 +22,7 @@ test_expect_success \
'test_must_fail git ls-files --error-unmatch foo bar-does-not-match'
test_expect_success \
- 'git ls-files --error-unmatch should succeed eith matched paths.' \
+ 'git ls-files --error-unmatch should succeed with matched paths.' \
'git ls-files --error-unmatch foo bar'
test_done
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index ddea49808d..cdaf6f64ec 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -59,7 +59,7 @@ test_expect_success 'git branch -l d/e/f should create a branch and a log' '
test_expect_success 'git branch -d d/e/f should delete a branch and a log' '
git branch -d d/e/f &&
test_path_is_missing .git/refs/heads/d/e/f &&
- test_path_is_missing .git/logs/refs/heads/d/e/f
+ test_must_fail git reflog exists refs/heads/d/e/f
'
test_expect_success 'git branch j/k should work after branch j has been deleted' '
@@ -82,13 +82,13 @@ test_expect_success 'git branch -m dumps usage' '
test_expect_success 'git branch -m m m/m should work' '
git branch -l m &&
git branch -m m m/m &&
- test_path_is_file .git/logs/refs/heads/m/m
+ git reflog exists refs/heads/m/m
'
test_expect_success 'git branch -m n/n n should work' '
git branch -l n/n &&
git branch -m n/n n &&
- test_path_is_file .git/logs/refs/heads/n
+ git reflog exists refs/heads/n
'
test_expect_success 'git branch -m o/o o should fail when o/p exists' '
@@ -267,12 +267,12 @@ git config branch.s/s.dummy Hello
test_expect_success 'git branch -m s/s s should work when s/t is deleted' '
git branch -l s/s &&
- test_path_is_file .git/logs/refs/heads/s/s &&
+ git reflog exists refs/heads/s/s &&
git branch -l s/t &&
- test_path_is_file .git/logs/refs/heads/s/t &&
+ git reflog exists refs/heads/s/t &&
git branch -d s/t &&
git branch -m s/s s &&
- test_path_is_file .git/logs/refs/heads/s
+ git reflog exists refs/heads/s
'
test_expect_success 'config information was renamed, too' '
diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh
index f51d0f3cad..f1ae5ff662 100755
--- a/t/t3203-branch-output.sh
+++ b/t/t3203-branch-output.sh
@@ -143,4 +143,24 @@ EOF
test_i18ncmp expect actual
'
+test_expect_success 'git branch `--sort` option' '
+ cat >expect <<-\EOF &&
+ branch-two
+ * (HEAD detached from fromtag)
+ branch-one
+ master
+ EOF
+ git branch --sort=objectsize >actual &&
+ test_i18ncmp expect actual
+'
+
+test_expect_success 'git branch --points-at option' '
+ cat >expect <<-\EOF &&
+ branch-one
+ master
+ EOF
+ git branch --points-at=branch-one >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh
index 8aae98d482..db244d2f88 100755
--- a/t/t3210-pack-refs.sh
+++ b/t/t3210-pack-refs.sh
@@ -160,6 +160,13 @@ test_expect_success 'pack ref directly below refs/' '
test_path_is_missing .git/refs/top
'
+test_expect_success 'do not pack ref in refs/bisect' '
+ git update-ref refs/bisect/local HEAD &&
+ git pack-refs --all --prune &&
+ ! grep refs/bisect/local .git/packed-refs >/dev/null &&
+ test_path_is_file .git/refs/bisect/local
+'
+
test_expect_success 'disable reflogs' '
git config core.logallrefupdates false &&
rm -rf .git/logs
@@ -169,7 +176,7 @@ test_expect_success 'create packed foo/bar/baz branch' '
git branch foo/bar/baz &&
git pack-refs --all --prune &&
test_path_is_missing .git/refs/heads/foo/bar/baz &&
- test_path_is_missing .git/logs/refs/heads/foo/bar/baz
+ test_must_fail git reflog exists refs/heads/foo/bar/baz
'
test_expect_success 'notice d/f conflict with existing directory' '
diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh
index 8cffd35fb0..cd70274ea5 100755
--- a/t/t3301-notes.sh
+++ b/t/t3301-notes.sh
@@ -1122,6 +1122,12 @@ test_expect_success 'git notes copy diagnoses too many or too few parameters' '
test_must_fail git notes copy one two three
'
+test_expect_success 'git notes get-ref expands refs/heads/master to refs/notes/refs/heads/master' '
+ test_unconfig core.notesRef &&
+ sane_unset GIT_NOTES_REF &&
+ test "$(git notes --ref=refs/heads/master get-ref)" = "refs/notes/refs/heads/master"
+'
+
test_expect_success 'git notes get-ref (no overrides)' '
test_unconfig core.notesRef &&
sane_unset GIT_NOTES_REF &&
diff --git a/t/t3309-notes-merge-auto-resolve.sh b/t/t3309-notes-merge-auto-resolve.sh
index 461fd84755..14c2adf970 100755
--- a/t/t3309-notes-merge-auto-resolve.sh
+++ b/t/t3309-notes-merge-auto-resolve.sh
@@ -298,6 +298,13 @@ test_expect_success 'merge z into y with invalid strategy => Fail/No changes' '
verify_notes y y
'
+test_expect_success 'merge z into y with invalid configuration option => Fail/No changes' '
+ git config core.notesRef refs/notes/y &&
+ test_must_fail git -c notes.mergeStrategy="foo" notes merge z &&
+ # Verify no changes (y)
+ verify_notes y y
+'
+
cat <<EOF | sort >expect_notes_ours
68b8630d25516028bed862719855b3d6768d7833 $commit_sha15
5de7ea7ad4f47e7ff91989fb82234634730f75df $commit_sha14
@@ -365,6 +372,28 @@ test_expect_success 'reset to pre-merge state (y)' '
verify_notes y y
'
+test_expect_success 'merge z into y with "ours" configuration option => Non-conflicting 3-way merge' '
+ git -c notes.mergeStrategy="ours" notes merge z &&
+ verify_notes y ours
+'
+
+test_expect_success 'reset to pre-merge state (y)' '
+ git update-ref refs/notes/y refs/notes/y^1 &&
+ # Verify pre-merge state
+ verify_notes y y
+'
+
+test_expect_success 'merge z into y with "ours" per-ref configuration option => Non-conflicting 3-way merge' '
+ git -c notes.y.mergeStrategy="ours" notes merge z &&
+ verify_notes y ours
+'
+
+test_expect_success 'reset to pre-merge state (y)' '
+ git update-ref refs/notes/y refs/notes/y^1 &&
+ # Verify pre-merge state
+ verify_notes y y
+'
+
cat <<EOF | sort >expect_notes_theirs
9b4b2c61f0615412da3c10f98ff85b57c04ec765 $commit_sha15
5de7ea7ad4f47e7ff91989fb82234634730f75df $commit_sha14
@@ -432,6 +461,17 @@ test_expect_success 'reset to pre-merge state (y)' '
verify_notes y y
'
+test_expect_success 'merge z into y with "theirs" strategy overriding configuration option "ours" => Non-conflicting 3-way merge' '
+ git -c notes.mergeStrategy="ours" notes merge --strategy=theirs z &&
+ verify_notes y theirs
+'
+
+test_expect_success 'reset to pre-merge state (y)' '
+ git update-ref refs/notes/y refs/notes/y^1 &&
+ # Verify pre-merge state
+ verify_notes y y
+'
+
cat <<EOF | sort >expect_notes_union
7c4e546efd0fe939f876beb262ece02797880b54 $commit_sha15
5de7ea7ad4f47e7ff91989fb82234634730f75df $commit_sha14
@@ -505,6 +545,34 @@ test_expect_success 'reset to pre-merge state (y)' '
verify_notes y y
'
+test_expect_success 'merge z into y with "union" strategy overriding per-ref configuration => Non-conflicting 3-way merge' '
+ git -c notes.y.mergeStrategy="theirs" notes merge --strategy=union z &&
+ verify_notes y union
+'
+
+test_expect_success 'reset to pre-merge state (y)' '
+ git update-ref refs/notes/y refs/notes/y^1 &&
+ # Verify pre-merge state
+ verify_notes y y
+'
+
+test_expect_success 'merge z into y with "union" per-ref overriding general configuration => Non-conflicting 3-way merge' '
+ git -c notes.y.mergeStrategy="union" -c notes.mergeStrategy="theirs" notes merge z &&
+ verify_notes y union
+'
+
+test_expect_success 'reset to pre-merge state (y)' '
+ git update-ref refs/notes/y refs/notes/y^1 &&
+ # Verify pre-merge state
+ verify_notes y y
+'
+
+test_expect_success 'merge z into y with "manual" per-ref only checks specific ref configuration => Conflicting 3-way merge' '
+ test_must_fail git -c notes.z.mergeStrategy="union" notes merge z &&
+ git notes merge --abort &&
+ verify_notes y y
+'
+
cat <<EOF | sort >expect_notes_union2
d682107b8bf7a7aea1e537a8d5cb6a12b60135f1 $commit_sha15
5de7ea7ad4f47e7ff91989fb82234634730f75df $commit_sha14
@@ -644,4 +712,15 @@ test_expect_success 'merge y into z with "cat_sort_uniq" strategy => Non-conflic
verify_notes z cat_sort_uniq
'
+test_expect_success 'reset to pre-merge state (z)' '
+ git update-ref refs/notes/z refs/notes/z^1 &&
+ # Verify pre-merge state
+ verify_notes z z
+'
+
+test_expect_success 'merge y into z with "cat_sort_uniq" strategy configuration option => Non-conflicting 3-way merge' '
+ git -c notes.mergeStrategy="cat_sort_uniq" notes merge y &&
+ verify_notes z cat_sort_uniq
+'
+
test_done
diff --git a/t/t3310-notes-merge-manual-resolve.sh b/t/t3310-notes-merge-manual-resolve.sh
index 195bb97f85..d5572121da 100755
--- a/t/t3310-notes-merge-manual-resolve.sh
+++ b/t/t3310-notes-merge-manual-resolve.sh
@@ -314,6 +314,18 @@ y and z notes on 1st commit
EOF
+test_expect_success 'do not allow mixing --commit and --abort' '
+ test_must_fail git notes merge --commit --abort
+'
+
+test_expect_success 'do not allow mixing --commit and --strategy' '
+ test_must_fail git notes merge --commit --strategy theirs
+'
+
+test_expect_success 'do not allow mixing --abort and --strategy' '
+ test_must_fail git notes merge --abort --strategy theirs
+'
+
test_expect_success 'finalize conflicting merge (z => m)' '
# Resolve conflicts and finalize merge
cat >.git/NOTES_MERGE_WORKTREE/$commit_sha1 <<EOF &&
diff --git a/t/t3320-notes-merge-worktrees.sh b/t/t3320-notes-merge-worktrees.sh
new file mode 100755
index 0000000000..1f71d589f5
--- /dev/null
+++ b/t/t3320-notes-merge-worktrees.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+#
+# Copyright (c) 2015 Twitter, Inc
+#
+
+test_description='Test merging of notes trees in multiple worktrees'
+
+. ./test-lib.sh
+
+test_expect_success 'setup commit' '
+ test_commit tantrum
+'
+
+commit_tantrum=$(git rev-parse tantrum^{commit})
+
+test_expect_success 'setup notes ref (x)' '
+ git config core.notesRef refs/notes/x &&
+ git notes add -m "x notes on tantrum" tantrum
+'
+
+test_expect_success 'setup local branch (y)' '
+ git update-ref refs/notes/y refs/notes/x &&
+ git config core.notesRef refs/notes/y &&
+ git notes remove tantrum
+'
+
+test_expect_success 'setup remote branch (z)' '
+ git update-ref refs/notes/z refs/notes/x &&
+ git config core.notesRef refs/notes/z &&
+ git notes add -f -m "conflicting notes on tantrum" tantrum
+'
+
+test_expect_success 'modify notes ref ourselves (x)' '
+ git config core.notesRef refs/notes/x &&
+ git notes add -f -m "more conflicting notes on tantrum" tantrum
+'
+
+test_expect_success 'create some new worktrees' '
+ git worktree add -b newbranch worktree master &&
+ git worktree add -b newbranch2 worktree2 master
+'
+
+test_expect_success 'merge z into y fails and sets NOTES_MERGE_REF' '
+ git config core.notesRef refs/notes/y &&
+ test_must_fail git notes merge z &&
+ echo "ref: refs/notes/y" >expect &&
+ test_cmp .git/NOTES_MERGE_REF expect
+'
+
+test_expect_success 'merge z into y while mid-merge in another workdir fails' '
+ (
+ cd worktree &&
+ git config core.notesRef refs/notes/y &&
+ test_must_fail git notes merge z 2>err &&
+ grep "A notes merge into refs/notes/y is already in-progress at" err
+ ) &&
+ test_path_is_missing .git/worktrees/worktree/NOTES_MERGE_REF
+'
+
+test_expect_success 'merge z into x while mid-merge on y succeeds' '
+ (
+ cd worktree2 &&
+ git config core.notesRef refs/notes/x &&
+ test_must_fail git notes merge z 2>&1 >out &&
+ grep "Automatic notes merge failed" out &&
+ grep -v "A notes merge into refs/notes/x is already in-progress in" out
+ ) &&
+ echo "ref: refs/notes/x" >expect &&
+ test_cmp .git/worktrees/worktree2/NOTES_MERGE_REF expect
+'
+
+test_done
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 9d26064aba..d26e3f57dc 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -961,13 +961,13 @@ test_expect_success 'rebase -i produces readable reflog' '
set_fake_editor &&
git rebase -i --onto I F branch-reflog-test &&
cat >expect <<-\EOF &&
- rebase -i (start): checkout I
- rebase -i (pick): G
- rebase -i (pick): H
rebase -i (finish): returning to refs/heads/branch-reflog-test
+ rebase -i (pick): H
+ rebase -i (pick): G
+ rebase -i (start): checkout I
EOF
- tail -n 4 .git/logs/HEAD |
- sed -e "s/.* //" >actual &&
+ git reflog -n4 HEAD |
+ sed "s/[^:]*: //" >actual &&
test_cmp expect actual
'
diff --git a/t/t3420-rebase-autostash.sh b/t/t3420-rebase-autostash.sh
index d783f03d3f..944154b2e0 100755
--- a/t/t3420-rebase-autostash.sh
+++ b/t/t3420-rebase-autostash.sh
@@ -37,6 +37,16 @@ testrebase() {
type=$1
dotest=$2
+ test_expect_success "rebase$type: dirty worktree, --no-autostash" '
+ test_config rebase.autostash true &&
+ git reset --hard &&
+ git checkout -b rebased-feature-branch feature-branch &&
+ test_when_finished git branch -D rebased-feature-branch &&
+ test_when_finished git checkout feature-branch &&
+ echo dirty >>file3 &&
+ test_must_fail git rebase$type --no-autostash unrelated-onto-branch
+ '
+
test_expect_success "rebase$type: dirty worktree, non-conflicting rebase" '
test_config rebase.autostash true &&
git reset --hard &&
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index f5f18b7d21..2142c1fa92 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -672,7 +672,7 @@ test_expect_success 'store updates stash ref and reflog' '
! grep quux bazzy &&
git stash store -m quuxery $STASH_ID &&
test $(cat .git/refs/stash) = $STASH_ID &&
- grep $STASH_ID .git/logs/refs/stash &&
+ git reflog --format=%H stash| grep $STASH_ID &&
git stash pop &&
grep quux bazzy
'
diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh
index 1dbaa3864a..67373dc44e 100755
--- a/t/t4018-diff-funcname.sh
+++ b/t/t4018-diff-funcname.sh
@@ -31,6 +31,7 @@ diffpatterns="
cpp
csharp
fortran
+ fountain
html
java
matlab
diff --git a/t/t4018/fountain-scene b/t/t4018/fountain-scene
new file mode 100644
index 0000000000..6b3257d680
--- /dev/null
+++ b/t/t4018/fountain-scene
@@ -0,0 +1,4 @@
+EXT. STREET RIGHT OUTSIDE - DAY
+
+CHARACTER
+You didn't say the magic phrase, "ChangeMe".
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index dd627c42d3..b41bd17264 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -873,4 +873,88 @@ test_expect_success 'am --message-id -s signs off after the message id' '
test_cmp expected actual
'
+test_expect_success 'am -3 works with rerere' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
+
+ # make patches one->two and two->three...
+ test_commit one file &&
+ test_commit two file &&
+ test_commit three file &&
+ git format-patch -2 --stdout >seq.patch &&
+
+ # and create a situation that conflicts...
+ git reset --hard one &&
+ test_commit other file &&
+
+ # enable rerere...
+ test_config rerere.enabled true &&
+ test_when_finished "rm -rf .git/rr-cache" &&
+
+ # ...and apply. Our resolution is to skip the first
+ # patch, and the rerere the second one.
+ test_must_fail git am -3 seq.patch &&
+ test_must_fail git am --skip &&
+ echo resolved >file &&
+ git add file &&
+ git am --resolved &&
+
+ # now apply again, and confirm that rerere engaged (we still
+ # expect failure from am because rerere does not auto-commit
+ # for us).
+ git reset --hard other &&
+ test_must_fail git am -3 seq.patch &&
+ test_must_fail git am --skip &&
+ echo resolved >expect &&
+ test_cmp expect file
+'
+
+test_expect_success 'am -s unexpected trailer block' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
+ echo signed >file &&
+ git add file &&
+ cat >msg <<-EOF &&
+ subject here
+
+ Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
+ [jc: tweaked log message]
+ Signed-off-by: J C H <j@c.h>
+ EOF
+ git commit -F msg &&
+ git cat-file commit HEAD | sed -e '1,/^$/d' >original &&
+ git format-patch --stdout -1 >patch &&
+
+ git reset --hard HEAD^ &&
+ git am -s patch &&
+ (
+ cat original &&
+ echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
+ ) >expect &&
+ git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
+ test_cmp expect actual &&
+
+ cat >msg <<-\EOF &&
+ subject here
+
+ We make sure that there is a blank line between the log
+ message proper and Signed-off-by: line added.
+ EOF
+ git reset HEAD^ &&
+ git commit -F msg file &&
+ git cat-file commit HEAD | sed -e '1,/^$/d' >original &&
+ git format-patch --stdout -1 >patch &&
+
+ git reset --hard HEAD^ &&
+ git am -s patch &&
+
+ (
+ cat original &&
+ echo &&
+ echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
+ ) >expect &&
+ git cat-file commit HEAD | sed -e '1,/^$/d' >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t4151-am-abort.sh b/t/t4151-am-abort.sh
index 05bdc3ee49..ea5ace99a1 100755
--- a/t/t4151-am-abort.sh
+++ b/t/t4151-am-abort.sh
@@ -168,4 +168,28 @@ test_expect_success 'am --abort on unborn branch will keep local commits intact'
test_cmp expect actual
'
+test_expect_success 'am --skip leaves index stat info alone' '
+ git checkout -f --orphan skip-stat-info &&
+ git reset &&
+ test_commit skip-should-be-untouched &&
+ test-chmtime =0 skip-should-be-untouched.t &&
+ git update-index --refresh &&
+ git diff-files --exit-code --quiet &&
+ test_must_fail git am 0001-*.patch &&
+ git am --skip &&
+ git diff-files --exit-code --quiet
+'
+
+test_expect_success 'am --abort leaves index stat info alone' '
+ git checkout -f --orphan abort-stat-info &&
+ git reset &&
+ test_commit abort-should-be-untouched &&
+ test-chmtime =0 abort-should-be-untouched.t &&
+ git update-index --refresh &&
+ git diff-files --exit-code --quiet &&
+ test_must_fail git am 0001-*.patch &&
+ git am --abort &&
+ git diff-files --exit-code --quiet
+'
+
test_done
diff --git a/t/t4153-am-resume-override-opts.sh b/t/t4153-am-resume-override-opts.sh
new file mode 100755
index 0000000000..7c013d84d5
--- /dev/null
+++ b/t/t4153-am-resume-override-opts.sh
@@ -0,0 +1,102 @@
+#!/bin/sh
+
+test_description='git-am command-line options override saved options'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-terminal.sh
+
+format_patch () {
+ git format-patch --stdout -1 "$1" >"$1".eml
+}
+
+test_expect_success 'setup' '
+ test_commit initial file &&
+ test_commit first file &&
+
+ git checkout initial &&
+ git mv file file2 &&
+ test_tick &&
+ git commit -m renamed-file &&
+ git tag renamed-file &&
+
+ git checkout -b side initial &&
+ test_commit side1 file &&
+ test_commit side2 file &&
+
+ format_patch side1 &&
+ format_patch side2
+'
+
+test_expect_success TTY '--3way overrides --no-3way' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
+ git checkout renamed-file &&
+
+ # Applying side1 will fail as the file has been renamed.
+ test_must_fail git am --no-3way side[12].eml &&
+ test_path_is_dir .git/rebase-apply &&
+ test_cmp_rev renamed-file HEAD &&
+ test -z "$(git ls-files -u)" &&
+
+ # Applying side1 with am --3way will succeed due to the threeway-merge.
+ # Applying side2 will fail as --3way does not apply to it.
+ test_must_fail test_terminal git am --3way </dev/zero &&
+ test_path_is_dir .git/rebase-apply &&
+ test side1 = "$(cat file2)"
+'
+
+test_expect_success '--no-quiet overrides --quiet' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
+ git checkout first &&
+
+ # Applying side1 will be quiet.
+ test_must_fail git am --quiet side[123].eml >out &&
+ test_path_is_dir .git/rebase-apply &&
+ ! test_i18ngrep "^Applying: " out &&
+ echo side1 >file &&
+ git add file &&
+
+ # Applying side1 will not be quiet.
+ # Applying side2 will be quiet.
+ git am --no-quiet --continue >out &&
+ echo "Applying: side1" >expected &&
+ test_i18ncmp expected out
+'
+
+test_expect_success '--signoff overrides --no-signoff' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
+ git checkout first &&
+
+ test_must_fail git am --no-signoff side[12].eml &&
+ test_path_is_dir .git/rebase-apply &&
+ echo side1 >file &&
+ git add file &&
+ git am --signoff --continue &&
+
+ # Applied side1 will be signed off
+ echo "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" >expected &&
+ git cat-file commit HEAD^ | grep "Signed-off-by:" >actual &&
+ test_cmp expected actual &&
+
+ # Applied side2 will not be signed off
+ test $(git cat-file commit HEAD | grep -c "Signed-off-by:") -eq 0
+'
+
+test_expect_success TTY '--reject overrides --no-reject' '
+ rm -fr .git/rebase-apply &&
+ git reset --hard &&
+ git checkout first &&
+ rm -f file.rej &&
+
+ test_must_fail git am --no-reject side1.eml &&
+ test_path_is_dir .git/rebase-apply &&
+ test_path_is_missing file.rej &&
+
+ test_must_fail test_terminal git am --reject </dev/zero &&
+ test_path_is_dir .git/rebase-apply &&
+ test_path_is_file file.rej
+'
+
+test_done
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 35d2d7c221..6ede0692f6 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -894,4 +894,18 @@ test_expect_success 'log --graph --no-walk is forbidden' '
test_must_fail git log --graph --no-walk
'
+test_expect_success 'log diagnoses bogus HEAD' '
+ git init empty &&
+ test_must_fail git -C empty log 2>stderr &&
+ test_i18ngrep does.not.have.any.commits stderr &&
+ echo 1234abcd >empty/.git/refs/heads/master &&
+ test_must_fail git -C empty log 2>stderr &&
+ test_i18ngrep broken stderr &&
+ echo "ref: refs/heads/invalid.lock" >empty/.git/HEAD &&
+ test_must_fail git -C empty log 2>stderr &&
+ test_i18ngrep broken stderr &&
+ test_must_fail git -C empty log --default totally-bogus 2>stderr &&
+ test_i18ngrep broken stderr
+'
+
test_done
diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh
index 654addaae3..cca23383c5 100755
--- a/t/t5004-archive-corner-cases.sh
+++ b/t/t5004-archive-corner-cases.sh
@@ -115,4 +115,44 @@ test_expect_success 'archive empty subtree by direct pathspec' '
check_dir extract sub
'
+ZIPINFO=zipinfo
+
+test_lazy_prereq ZIPINFO '
+ n=$("$ZIPINFO" "$TEST_DIRECTORY"/t5004/empty.zip | sed -n "2s/.* //p")
+ test "x$n" = "x0"
+'
+
+test_expect_success ZIPINFO 'zip archive with many entries' '
+ # add a directory with 256 files
+ mkdir 00 &&
+ for a in 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ do
+ for b in 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ do
+ : >00/$a$b
+ done
+ done &&
+ git add 00 &&
+ git commit -m "256 files in 1 directory" &&
+
+ # duplicate it to get 65536 files in 256 directories
+ subtree=$(git write-tree --prefix=00/) &&
+ for c in 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ do
+ for d in 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ do
+ echo "040000 tree $subtree $c$d"
+ done
+ done >tree &&
+ tree=$(git mktree <tree) &&
+
+ # zip them
+ git archive -o many.zip $tree &&
+
+ # check the number of entries in the ZIP file directory
+ expr 65536 + 256 >expect &&
+ "$ZIPINFO" many.zip | head -2 | sed -n "2s/.* //p" >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t5312-prune-corruption.sh b/t/t5312-prune-corruption.sh
index 8e98b44083..da9d59940d 100755
--- a/t/t5312-prune-corruption.sh
+++ b/t/t5312-prune-corruption.sh
@@ -12,7 +12,7 @@ delete objects that cannot be recovered.
test_expect_success 'disable reflogs' '
git config core.logallrefupdates false &&
- rm -rf .git/logs
+ git reflog expire --expire=all --all
'
test_expect_success 'create history reachable only from a bogus-named ref' '
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 7a8499ce66..dfaf9d9f68 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -919,6 +919,19 @@ test_expect_success 'new remote' '
cmp expect actual
'
+get_url_test () {
+ cat >expect &&
+ git remote get-url "$@" >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success 'get-url on new remote' '
+ echo foo | get_url_test someremote &&
+ echo foo | get_url_test --all someremote &&
+ echo foo | get_url_test --push someremote &&
+ echo foo | get_url_test --push --all someremote
+'
+
test_expect_success 'remote set-url bar' '
git remote set-url someremote bar &&
echo bar >expect &&
@@ -961,6 +974,13 @@ test_expect_success 'remote set-url --push zot' '
cmp expect actual
'
+test_expect_success 'get-url with different urls' '
+ echo baz | get_url_test someremote &&
+ echo baz | get_url_test --all someremote &&
+ echo zot | get_url_test --push someremote &&
+ echo zot | get_url_test --push --all someremote
+'
+
test_expect_success 'remote set-url --push qux zot' '
git remote set-url --push someremote qux zot &&
echo qux >expect &&
@@ -995,6 +1015,14 @@ test_expect_success 'remote set-url --push --add aaa' '
cmp expect actual
'
+test_expect_success 'get-url on multi push remote' '
+ echo foo | get_url_test --push someremote &&
+ get_url_test --push --all someremote <<-\EOF
+ foo
+ aaa
+ EOF
+'
+
test_expect_success 'remote set-url --push bar aaa' '
git remote set-url --push someremote bar aaa &&
echo foo >expect &&
@@ -1039,6 +1067,14 @@ test_expect_success 'remote set-url --add bbb' '
cmp expect actual
'
+test_expect_success 'get-url on multi fetch remote' '
+ echo baz | get_url_test someremote &&
+ get_url_test --all someremote <<-\EOF
+ baz
+ bbb
+ EOF
+'
+
test_expect_success 'remote set-url --delete .*' '
test_must_fail git remote set-url --delete someremote .\* &&
echo "YYY" >expect &&
@@ -1108,6 +1144,7 @@ test_extra_arg rename origin newname
test_extra_arg remove origin
test_extra_arg set-head origin master
# set-branches takes any number of args
+test_extra_arg get-url origin newurl
test_extra_arg set-url origin newurl oldurl
# show takes any number of args
# prune takes any number of args
diff --git a/t/t5507-remote-environment.sh b/t/t5507-remote-environment.sh
new file mode 100755
index 0000000000..e6149295b1
--- /dev/null
+++ b/t/t5507-remote-environment.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+test_description='check environment showed to remote side of transports'
+. ./test-lib.sh
+
+test_expect_success 'set up "remote" push situation' '
+ test_commit one &&
+ git config push.default current &&
+ git init remote
+'
+
+test_expect_success 'set up fake ssh' '
+ GIT_SSH_COMMAND="f() {
+ cd \"\$TRASH_DIRECTORY\" &&
+ eval \"\$2\"
+ }; f" &&
+ export GIT_SSH_COMMAND &&
+ export TRASH_DIRECTORY
+'
+
+# due to receive.denyCurrentBranch=true
+test_expect_success 'confirm default push fails' '
+ test_must_fail git push remote
+'
+
+test_expect_success 'config does not travel over same-machine push' '
+ test_must_fail git -c receive.denyCurrentBranch=false push remote
+'
+
+test_expect_success 'config does not travel over ssh push' '
+ test_must_fail git -c receive.denyCurrentBranch=false push host:remote
+'
+
+test_done
diff --git a/t/t5511-refspec.sh b/t/t5511-refspec.sh
index de6db86ccf..f541f30bc2 100755
--- a/t/t5511-refspec.sh
+++ b/t/t5511-refspec.sh
@@ -71,15 +71,18 @@ test_refspec fetch ':refs/remotes/frotz/HEAD-to-me'
test_refspec push ':refs/remotes/frotz/delete me' invalid
test_refspec fetch ':refs/remotes/frotz/HEAD to me' invalid
-test_refspec fetch 'refs/heads/*/for-linus:refs/remotes/mine/*-blah' invalid
-test_refspec push 'refs/heads/*/for-linus:refs/remotes/mine/*-blah' invalid
+test_refspec fetch 'refs/heads/*/for-linus:refs/remotes/mine/*-blah'
+test_refspec push 'refs/heads/*/for-linus:refs/remotes/mine/*-blah'
-test_refspec fetch 'refs/heads*/for-linus:refs/remotes/mine/*' invalid
-test_refspec push 'refs/heads*/for-linus:refs/remotes/mine/*' invalid
+test_refspec fetch 'refs/heads*/for-linus:refs/remotes/mine/*'
+test_refspec push 'refs/heads*/for-linus:refs/remotes/mine/*'
test_refspec fetch 'refs/heads/*/*/for-linus:refs/remotes/mine/*' invalid
test_refspec push 'refs/heads/*/*/for-linus:refs/remotes/mine/*' invalid
+test_refspec fetch 'refs/heads/*g*/for-linus:refs/remotes/mine/*' invalid
+test_refspec push 'refs/heads/*g*/for-linus:refs/remotes/mine/*' invalid
+
test_refspec fetch 'refs/heads/*/for-linus:refs/remotes/mine/*'
test_refspec push 'refs/heads/*/for-linus:refs/remotes/mine/*'
diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh
index 3bd9759e0f..aadaac515e 100755
--- a/t/t5512-ls-remote.sh
+++ b/t/t5512-ls-remote.sh
@@ -128,6 +128,11 @@ test_expect_success 'Report match with --exit-code' '
test_cmp expect actual
'
+test_expect_success 'set up some extra tags for ref hiding' '
+ git tag magic/one &&
+ git tag magic/two
+'
+
for configsection in transfer uploadpack
do
test_expect_success "Hide some refs with $configsection.hiderefs" '
@@ -138,6 +143,24 @@ do
sed -e "/ refs\/tags\//d" >expect &&
test_cmp expect actual
'
+
+ test_expect_success "Override hiding of $configsection.hiderefs" '
+ test_when_finished "test_unconfig $configsection.hiderefs" &&
+ git config --add $configsection.hiderefs refs/tags &&
+ git config --add $configsection.hiderefs "!refs/tags/magic" &&
+ git config --add $configsection.hiderefs refs/tags/magic/one &&
+ git ls-remote . >actual &&
+ grep refs/tags/magic/two actual &&
+ ! grep refs/tags/magic/one actual
+ '
+
done
+test_expect_success 'overrides work between mixed transfer/upload-pack hideRefs' '
+ test_config uploadpack.hiderefs refs/tags &&
+ test_config transfer.hiderefs "!refs/tags/magic" &&
+ git ls-remote . >actual &&
+ grep refs/tags/magic actual
+'
+
test_done
diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
index f4a7193677..a0013ee32f 100755
--- a/t/t5520-pull.sh
+++ b/t/t5520-pull.sh
@@ -245,6 +245,17 @@ test_expect_success '--rebase fails with multiple branches' '
test modified = "$(git show HEAD:file)"
'
+test_expect_success 'pull --rebase succeeds with dirty working directory and rebase.autostash set' '
+ test_config rebase.autostash true &&
+ git reset --hard before-rebase &&
+ echo dirty >new_file &&
+ git add new_file &&
+ git pull --rebase . copy &&
+ test_cmp_rev HEAD^ copy &&
+ test "$(cat new_file)" = dirty &&
+ test "$(cat file)" = "modified again"
+'
+
test_expect_success 'pull.rebase' '
git reset --hard before-rebase &&
test_config pull.rebase true &&
diff --git a/t/t5560-http-backend-noserver.sh b/t/t5560-http-backend-noserver.sh
index aa73eeaef8..9fafcf1945 100755
--- a/t/t5560-http-backend-noserver.sh
+++ b/t/t5560-http-backend-noserver.sh
@@ -44,10 +44,6 @@ POST() {
test_cmp exp act
}
-log_div() {
- return 0
-}
-
. "$TEST_DIRECTORY"/t556x_common
expect_aliased() {
diff --git a/t/t5561-http-backend.sh b/t/t5561-http-backend.sh
index 19afe96698..90e0d6f0fe 100755
--- a/t/t5561-http-backend.sh
+++ b/t/t5561-http-backend.sh
@@ -29,15 +29,9 @@ POST() {
test_cmp exp act
}
-log_div() {
- echo >>"$HTTPD_ROOT_PATH"/access.log
- echo "### $1" >>"$HTTPD_ROOT_PATH"/access.log
- echo "###" >>"$HTTPD_ROOT_PATH"/access.log
-}
-
. "$TEST_DIRECTORY"/t556x_common
-cat >exp <<EOF
+grep '^[^#]' >exp <<EOF
### refs/heads/master
###
diff --git a/t/t556x_common b/t/t556x_common
index 82926cfdb7..359fcfe32b 100755
--- a/t/t556x_common
+++ b/t/t556x_common
@@ -52,21 +52,17 @@ get_static_files() {
SMART=smart
GIT_HTTP_EXPORT_ALL=1 && export GIT_HTTP_EXPORT_ALL
test_expect_success 'direct refs/heads/master not found' '
- log_div "refs/heads/master" &&
GET refs/heads/master "404 Not Found"
'
test_expect_success 'static file is ok' '
- log_div "getanyfile default" &&
get_static_files "200 OK"
'
SMART=smart_noexport
unset GIT_HTTP_EXPORT_ALL
test_expect_success 'no export by default' '
- log_div "no git-daemon-export-ok" &&
get_static_files "404 Not Found"
'
test_expect_success 'export if git-daemon-export-ok' '
- log_div "git-daemon-export-ok" &&
(cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
touch git-daemon-export-ok
) &&
@@ -75,47 +71,39 @@ test_expect_success 'export if git-daemon-export-ok' '
SMART=smart
GIT_HTTP_EXPORT_ALL=1 && export GIT_HTTP_EXPORT_ALL
test_expect_success 'static file if http.getanyfile true is ok' '
- log_div "getanyfile true" &&
config http.getanyfile true &&
get_static_files "200 OK"
'
test_expect_success 'static file if http.getanyfile false fails' '
- log_div "getanyfile false" &&
config http.getanyfile false &&
get_static_files "403 Forbidden"
'
test_expect_success 'http.uploadpack default enabled' '
- log_div "uploadpack default" &&
GET info/refs?service=git-upload-pack "200 OK" &&
POST git-upload-pack 0000 "200 OK"
'
test_expect_success 'http.uploadpack true' '
- log_div "uploadpack true" &&
config http.uploadpack true &&
GET info/refs?service=git-upload-pack "200 OK" &&
POST git-upload-pack 0000 "200 OK"
'
test_expect_success 'http.uploadpack false' '
- log_div "uploadpack false" &&
config http.uploadpack false &&
GET info/refs?service=git-upload-pack "403 Forbidden" &&
POST git-upload-pack 0000 "403 Forbidden"
'
test_expect_success 'http.receivepack default disabled' '
- log_div "receivepack default" &&
GET info/refs?service=git-receive-pack "403 Forbidden" &&
POST git-receive-pack 0000 "403 Forbidden"
'
test_expect_success 'http.receivepack true' '
- log_div "receivepack true" &&
config http.receivepack true &&
GET info/refs?service=git-receive-pack "200 OK" &&
POST git-receive-pack 0000 "200 OK"
'
test_expect_success 'http.receivepack false' '
- log_div "receivepack false" &&
config http.receivepack false &&
GET info/refs?service=git-receive-pack "403 Forbidden" &&
POST git-receive-pack 0000 "403 Forbidden"
diff --git a/t/t5603-clone-dirname.sh b/t/t5603-clone-dirname.sh
new file mode 100755
index 0000000000..d5af758129
--- /dev/null
+++ b/t/t5603-clone-dirname.sh
@@ -0,0 +1,106 @@
+#!/bin/sh
+
+test_description='check output directory names used by git-clone'
+. ./test-lib.sh
+
+# we use a fake ssh wrapper that ignores the arguments
+# entirely; we really only care that we get _some_ repo,
+# as the real test is what clone does on the local side
+test_expect_success 'setup ssh wrapper' '
+ write_script "$TRASH_DIRECTORY/ssh-wrapper" <<-\EOF &&
+ git upload-pack "$TRASH_DIRECTORY"
+ EOF
+ GIT_SSH="$TRASH_DIRECTORY/ssh-wrapper" &&
+ export GIT_SSH &&
+ export TRASH_DIRECTORY
+'
+
+# make sure that cloning $1 results in local directory $2
+test_clone_dir () {
+ url=$1; shift
+ dir=$1; shift
+ expect=success
+ bare=non-bare
+ clone_opts=
+ for i in "$@"
+ do
+ case "$i" in
+ fail)
+ expect=failure
+ ;;
+ bare)
+ bare=bare
+ clone_opts=--bare
+ ;;
+ esac
+ done
+ test_expect_$expect "clone of $url goes to $dir ($bare)" "
+ rm -rf $dir &&
+ git clone $clone_opts $url &&
+ test_path_is_dir $dir
+ "
+}
+
+# basic syntax with bare and non-bare variants
+test_clone_dir host:foo foo
+test_clone_dir host:foo foo.git bare
+test_clone_dir host:foo.git foo
+test_clone_dir host:foo.git foo.git bare
+test_clone_dir host:foo/.git foo
+test_clone_dir host:foo/.git foo.git bare
+
+# similar, but using ssh URL rather than host:path syntax
+test_clone_dir ssh://host/foo foo
+test_clone_dir ssh://host/foo foo.git bare
+test_clone_dir ssh://host/foo.git foo
+test_clone_dir ssh://host/foo.git foo.git bare
+test_clone_dir ssh://host/foo/.git foo
+test_clone_dir ssh://host/foo/.git foo.git bare
+
+# we should remove trailing slashes and .git suffixes
+test_clone_dir ssh://host/foo/ foo
+test_clone_dir ssh://host/foo/// foo
+test_clone_dir ssh://host/foo/.git/ foo
+test_clone_dir ssh://host/foo.git/ foo
+test_clone_dir ssh://host/foo.git/// foo
+test_clone_dir ssh://host/foo///.git/ foo
+test_clone_dir ssh://host/foo/.git/// foo
+
+test_clone_dir host:foo/ foo
+test_clone_dir host:foo/// foo
+test_clone_dir host:foo.git/ foo
+test_clone_dir host:foo/.git/ foo
+test_clone_dir host:foo.git/// foo
+test_clone_dir host:foo///.git/ foo
+test_clone_dir host:foo/.git/// foo
+
+# omitting the path should default to the hostname
+test_clone_dir ssh://host/ host
+test_clone_dir ssh://host:1234/ host
+test_clone_dir ssh://user@host/ host
+test_clone_dir host:/ host
+
+# auth materials should be redacted
+test_clone_dir ssh://user:password@host/ host
+test_clone_dir ssh://user:password@host:1234/ host
+test_clone_dir ssh://user:passw@rd@host:1234/ host
+test_clone_dir user@host:/ host
+test_clone_dir user:password@host:/ host
+test_clone_dir user:passw@rd@host:/ host
+
+# auth-like material should not be dropped
+test_clone_dir ssh://host/foo@bar foo@bar
+test_clone_dir ssh://host/foo@bar.git foo@bar
+test_clone_dir ssh://user:password@host/foo@bar foo@bar
+test_clone_dir ssh://user:passw@rd@host/foo@bar.git foo@bar
+
+test_clone_dir host:/foo@bar foo@bar
+test_clone_dir host:/foo@bar.git foo@bar
+test_clone_dir user:password@host:/foo@bar foo@bar
+test_clone_dir user:passw@rd@host:/foo@bar.git foo@bar
+
+# trailing port-like numbers should not be stripped for paths
+test_clone_dir ssh://user:password@host/test:1234 1234
+test_clone_dir ssh://user:password@host/test:1234.git 1234
+
+test_done
diff --git a/t/t5700-clone-reference.sh b/t/t5700-clone-reference.sh
index 3e783fc450..ef1779f5ca 100755
--- a/t/t5700-clone-reference.sh
+++ b/t/t5700-clone-reference.sh
@@ -10,49 +10,51 @@ base_dir=`pwd`
U=$base_dir/UPLOAD_LOG
-test_expect_success 'preparing first repository' \
-'test_create_repo A && cd A &&
-echo first > file1 &&
-git add file1 &&
-git commit -m initial'
-
-cd "$base_dir"
-
-test_expect_success 'preparing second repository' \
-'git clone A B && cd B &&
-echo second > file2 &&
-git add file2 &&
-git commit -m addition &&
-git repack -a -d &&
-git prune'
-
-cd "$base_dir"
-
-test_expect_success 'cloning with reference (-l -s)' \
-'git clone -l -s --reference B A C'
-
-cd "$base_dir"
-
-test_expect_success 'existence of info/alternates' \
-'test_line_count = 2 C/.git/objects/info/alternates'
-
-cd "$base_dir"
+# create a commit in repo $1 with name $2
+commit_in () {
+ (
+ cd "$1" &&
+ echo "$2" >"$2" &&
+ git add "$2" &&
+ git commit -m "$2"
+ )
+}
+
+# check that there are $2 loose objects in repo $1
+test_objcount () {
+ echo "$2" >expect &&
+ git -C "$1" count-objects >actual.raw &&
+ cut -d' ' -f1 <actual.raw >actual &&
+ test_cmp expect actual
+}
+
+test_expect_success 'preparing first repository' '
+ test_create_repo A &&
+ commit_in A file1
+'
-test_expect_success 'pulling from reference' \
-'cd C &&
-git pull ../B master'
+test_expect_success 'preparing second repository' '
+ git clone A B &&
+ commit_in B file2 &&
+ git -C B repack -ad &&
+ git -C B prune
+'
-cd "$base_dir"
+test_expect_success 'cloning with reference (-l -s)' '
+ git clone -l -s --reference B A C
+'
-test_expect_success 'that reference gets used' \
-'cd C &&
-echo "0 objects, 0 kilobytes" > expected &&
-git count-objects > current &&
-test_cmp expected current'
+test_expect_success 'existence of info/alternates' '
+ test_line_count = 2 C/.git/objects/info/alternates
+'
-cd "$base_dir"
+test_expect_success 'pulling from reference' '
+ git -C C pull ../B master
+'
-rm -f "$U.D"
+test_expect_success 'that reference gets used' '
+ test_objcount C 0
+'
test_expect_success 'cloning with reference (no -l -s)' '
GIT_TRACE_PACKET=$U.D git clone --reference B "file://$(pwd)/A" D
@@ -63,95 +65,69 @@ test_expect_success 'fetched no objects' '
! grep " want" "$U.D"
'
-cd "$base_dir"
-
-test_expect_success 'existence of info/alternates' \
-'test_line_count = 1 D/.git/objects/info/alternates'
-
-cd "$base_dir"
-
-test_expect_success 'pulling from reference' \
-'cd D && git pull ../B master'
-
-cd "$base_dir"
-
-test_expect_success 'that reference gets used' \
-'cd D && echo "0 objects, 0 kilobytes" > expected &&
-git count-objects > current &&
-test_cmp expected current'
-
-cd "$base_dir"
+test_expect_success 'existence of info/alternates' '
+ test_line_count = 1 D/.git/objects/info/alternates
+'
-test_expect_success 'updating origin' \
-'cd A &&
-echo third > file3 &&
-git add file3 &&
-git commit -m update &&
-git repack -a -d &&
-git prune'
+test_expect_success 'pulling from reference' '
+ git -C D pull ../B master
+'
-cd "$base_dir"
+test_expect_success 'that reference gets used' '
+ test_objcount D 0
+'
-test_expect_success 'pulling changes from origin' \
-'cd C &&
-git pull origin'
+test_expect_success 'updating origin' '
+ commit_in A file3 &&
+ git -C A repack -ad &&
+ git -C A prune
+'
-cd "$base_dir"
+test_expect_success 'pulling changes from origin' '
+ git -C C pull origin
+'
# the 2 local objects are commit and tree from the merge
-test_expect_success 'that alternate to origin gets used' \
-'cd C &&
-echo "2 objects" > expected &&
-git count-objects | cut -d, -f1 > current &&
-test_cmp expected current'
-
-cd "$base_dir"
-
-test_expect_success 'pulling changes from origin' \
-'cd D &&
-git pull origin'
+test_expect_success 'that alternate to origin gets used' '
+ test_objcount C 2
+'
-cd "$base_dir"
+test_expect_success 'pulling changes from origin' '
+ git -C D pull origin
+'
# the 5 local objects are expected; file3 blob, commit in A to add it
# and its tree, and 2 are our tree and the merge commit.
-test_expect_success 'check objects expected to exist locally' \
-'cd D &&
-echo "5 objects" > expected &&
-git count-objects | cut -d, -f1 > current &&
-test_cmp expected current'
-
-cd "$base_dir"
-
-test_expect_success 'preparing alternate repository #1' \
-'test_create_repo F && cd F &&
-echo first > file1 &&
-git add file1 &&
-git commit -m initial'
-
-cd "$base_dir"
-
-test_expect_success 'cloning alternate repo #2 and adding changes to repo #1' \
-'git clone F G && cd F &&
-echo second > file2 &&
-git add file2 &&
-git commit -m addition'
+test_expect_success 'check objects expected to exist locally' '
+ test_objcount D 5
+'
-cd "$base_dir"
+test_expect_success 'preparing alternate repository #1' '
+ test_create_repo F &&
+ commit_in F file1
+'
-test_expect_success 'cloning alternate repo #1, using #2 as reference' \
-'git clone --reference G F H'
+test_expect_success 'cloning alternate repo #2 and adding changes to repo #1' '
+ git clone F G &&
+ commit_in F file2
+'
-cd "$base_dir"
+test_expect_success 'cloning alternate repo #1, using #2 as reference' '
+ git clone --reference G F H
+'
-test_expect_success 'cloning with reference being subset of source (-l -s)' \
-'git clone -l -s --reference A B E'
+test_expect_success 'cloning with reference being subset of source (-l -s)' '
+ git clone -l -s --reference A B E
+'
-cd "$base_dir"
+test_expect_success 'cloning with multiple references drops duplicates' '
+ git clone -s --reference B --reference A --reference B A dups &&
+ test_line_count = 2 dups/.git/objects/info/alternates
+'
test_expect_success 'clone with reference from a tagged repository' '
(
- cd A && git tag -a -m 'tagged' HEAD
+ cd A && git tag -a -m tagged HEAD
) &&
git clone --reference=A A I
'
@@ -168,8 +144,6 @@ test_expect_success 'prepare branched repository' '
)
'
-rm -f "$U.K"
-
test_expect_success 'fetch with incomplete alternates' '
git init K &&
echo "$base_dir/A/.git/objects" >K/.git/objects/info/alternates &&
diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
index c9d3ed14c3..362b1581e0 100755
--- a/t/t5801-remote-helpers.sh
+++ b/t/t5801-remote-helpers.sh
@@ -242,13 +242,6 @@ clean_mark () {
sort >$(basename "$1")
}
-cmp_marks () {
- test_when_finished "rm -rf git.marks testgit.marks" &&
- clean_mark ".git/testgit/$1/git.marks" &&
- clean_mark ".git/testgit/$1/testgit.marks" &&
- test_cmp git.marks testgit.marks
-}
-
test_expect_success 'proper failure checks for fetching' '
(cd local &&
test_must_fail env GIT_REMOTE_TESTGIT_FAILURE=1 git fetch 2>error &&
@@ -258,12 +251,15 @@ test_expect_success 'proper failure checks for fetching' '
'
test_expect_success 'proper failure checks for pushing' '
+ test_when_finished "rm -rf local/git.marks local/testgit.marks" &&
(cd local &&
git checkout -b crash master &&
echo crash >>file &&
git commit -a -m crash &&
test_must_fail env GIT_REMOTE_TESTGIT_FAILURE=1 git push --all &&
- cmp_marks origin
+ clean_mark ".git/testgit/origin/git.marks" &&
+ clean_mark ".git/testgit/origin/testgit.marks" &&
+ test_cmp git.marks testgit.marks
)
'
diff --git a/t/t5810-proto-disable-local.sh b/t/t5810-proto-disable-local.sh
new file mode 100755
index 0000000000..563592d8a8
--- /dev/null
+++ b/t/t5810-proto-disable-local.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+test_description='test disabling of local paths in clone/fetch'
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-proto-disable.sh"
+
+test_expect_success 'setup repository to clone' '
+ test_commit one
+'
+
+test_proto "file://" file "file://$PWD"
+test_proto "path" file .
+
+test_done
diff --git a/t/t5811-proto-disable-git.sh b/t/t5811-proto-disable-git.sh
new file mode 100755
index 0000000000..8ac6b2a1d0
--- /dev/null
+++ b/t/t5811-proto-disable-git.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+test_description='test disabling of git-over-tcp in clone/fetch'
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-proto-disable.sh"
+. "$TEST_DIRECTORY/lib-git-daemon.sh"
+start_git_daemon
+
+test_expect_success 'create git-accessible repo' '
+ bare="$GIT_DAEMON_DOCUMENT_ROOT_PATH/repo.git" &&
+ test_commit one &&
+ git --bare init "$bare" &&
+ git push "$bare" HEAD &&
+ >"$bare/git-daemon-export-ok" &&
+ git -C "$bare" config daemon.receivepack true
+'
+
+test_proto "git://" git "$GIT_DAEMON_URL/repo.git"
+
+test_done
diff --git a/t/t5812-proto-disable-http.sh b/t/t5812-proto-disable-http.sh
new file mode 100755
index 0000000000..0d105d5417
--- /dev/null
+++ b/t/t5812-proto-disable-http.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+test_description='test disabling of git-over-http in clone/fetch'
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-proto-disable.sh"
+. "$TEST_DIRECTORY/lib-httpd.sh"
+start_httpd
+
+test_expect_success 'create git-accessible repo' '
+ bare="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+ test_commit one &&
+ git --bare init "$bare" &&
+ git push "$bare" HEAD &&
+ git -C "$bare" config http.receivepack true
+'
+
+test_proto "smart http" http "$HTTPD_URL/smart/repo.git"
+
+test_expect_success 'curl redirects respect whitelist' '
+ test_must_fail env GIT_ALLOW_PROTOCOL=http:https \
+ git clone "$HTTPD_URL/ftp-redir/repo.git" 2>stderr &&
+ {
+ test_i18ngrep "ftp.*disabled" stderr ||
+ test_i18ngrep "your curl version is too old"
+ }
+'
+
+test_expect_success 'curl limits redirects' '
+ test_must_fail git clone "$HTTPD_URL/loop-redir/smart/repo.git"
+'
+
+stop_httpd
+test_done
diff --git a/t/t5813-proto-disable-ssh.sh b/t/t5813-proto-disable-ssh.sh
new file mode 100755
index 0000000000..ad877d774a
--- /dev/null
+++ b/t/t5813-proto-disable-ssh.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+test_description='test disabling of git-over-ssh in clone/fetch'
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-proto-disable.sh"
+
+setup_ssh_wrapper
+
+test_expect_success 'setup repository to clone' '
+ test_commit one &&
+ mkdir remote &&
+ git init --bare remote/repo.git &&
+ git push remote/repo.git HEAD
+'
+
+test_proto "host:path" ssh "remote:repo.git"
+test_proto "ssh://" ssh "ssh://remote/$PWD/remote/repo.git"
+test_proto "git+ssh://" ssh "git+ssh://remote/$PWD/remote/repo.git"
+
+test_done
diff --git a/t/t5814-proto-disable-ext.sh b/t/t5814-proto-disable-ext.sh
new file mode 100755
index 0000000000..9d6f7dfa2c
--- /dev/null
+++ b/t/t5814-proto-disable-ext.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+test_description='test disabling of remote-helper paths in clone/fetch'
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-proto-disable.sh"
+
+setup_ext_wrapper
+
+test_expect_success 'setup repository to clone' '
+ test_commit one &&
+ mkdir remote &&
+ git init --bare remote/repo.git &&
+ git push remote/repo.git HEAD
+'
+
+test_proto "remote-helper" ext "ext::fake-remote %S repo.git"
+
+test_done
diff --git a/t/t5815-submodule-protos.sh b/t/t5815-submodule-protos.sh
new file mode 100755
index 0000000000..06f55a1b8a
--- /dev/null
+++ b/t/t5815-submodule-protos.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+test_description='test protocol whitelisting with submodules'
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-proto-disable.sh
+
+setup_ext_wrapper
+setup_ssh_wrapper
+
+test_expect_success 'setup repository with submodules' '
+ mkdir remote &&
+ git init remote/repo.git &&
+ (cd remote/repo.git && test_commit one) &&
+ # submodule-add should probably trust what we feed it on the cmdline,
+ # but its implementation is overly conservative.
+ GIT_ALLOW_PROTOCOL=ssh git submodule add remote:repo.git ssh-module &&
+ GIT_ALLOW_PROTOCOL=ext git submodule add "ext::fake-remote %S repo.git" ext-module &&
+ git commit -m "add submodules"
+'
+
+test_expect_success 'clone with recurse-submodules fails' '
+ test_must_fail git clone --recurse-submodules . dst
+'
+
+test_expect_success 'setup individual updates' '
+ rm -rf dst &&
+ git clone . dst &&
+ git -C dst submodule init
+'
+
+test_expect_success 'update of ssh allowed' '
+ git -C dst submodule update ssh-module
+'
+
+test_expect_success 'update of ext not allowed' '
+ test_must_fail git -C dst submodule update ext-module
+'
+
+test_expect_success 'user can override whitelist' '
+ GIT_ALLOW_PROTOCOL=ext git -C dst submodule update ext-module
+'
+
+test_done
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 06b4868109..e74662ba5c 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -362,7 +362,7 @@ test_expect_success 'bisect starting with a detached HEAD' '
test_expect_success 'bisect errors out if bad and good are mistaken' '
git bisect reset &&
test_must_fail git bisect start $HASH2 $HASH4 2> rev_list_error &&
- grep "mistake good and bad" rev_list_error &&
+ grep "mistook good and bad" rev_list_error &&
git bisect reset
'
@@ -759,4 +759,139 @@ test_expect_success '"git bisect bad HEAD" behaves as "git bisect bad"' '
git bisect reset
'
+test_expect_success 'bisect starts with only one new' '
+ git bisect reset &&
+ git bisect start &&
+ git bisect new $HASH4 &&
+ git bisect next
+'
+
+test_expect_success 'bisect does not start with only one old' '
+ git bisect reset &&
+ git bisect start &&
+ git bisect old $HASH1 &&
+ test_must_fail git bisect next
+'
+
+test_expect_success 'bisect start with one new and old' '
+ git bisect reset &&
+ git bisect start &&
+ git bisect old $HASH1 &&
+ git bisect new $HASH4 &&
+ git bisect new &&
+ git bisect new >bisect_result &&
+ grep "$HASH2 is the first new commit" bisect_result &&
+ git bisect log >log_to_replay.txt &&
+ git bisect reset
+'
+
+test_expect_success 'bisect replay with old and new' '
+ git bisect replay log_to_replay.txt >bisect_result &&
+ grep "$HASH2 is the first new commit" bisect_result &&
+ git bisect reset
+'
+
+test_expect_success 'bisect cannot mix old/new and good/bad' '
+ git bisect start &&
+ git bisect bad $HASH4 &&
+ test_must_fail git bisect old $HASH1
+'
+
+test_expect_success 'bisect terms needs 0 or 1 argument' '
+ git bisect reset &&
+ test_must_fail git bisect terms only-one &&
+ test_must_fail git bisect terms 1 2 &&
+ test_must_fail git bisect terms 2>actual &&
+ echo "no terms defined" >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'bisect terms shows good/bad after start' '
+ git bisect reset &&
+ git bisect start HEAD $HASH1 &&
+ git bisect terms --term-good >actual &&
+ echo good >expected &&
+ test_cmp expected actual &&
+ git bisect terms --term-bad >actual &&
+ echo bad >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'bisect start with one term1 and term2' '
+ git bisect reset &&
+ git bisect start --term-old term2 --term-new term1 &&
+ git bisect term2 $HASH1 &&
+ git bisect term1 $HASH4 &&
+ git bisect term1 &&
+ git bisect term1 >bisect_result &&
+ grep "$HASH2 is the first term1 commit" bisect_result &&
+ git bisect log >log_to_replay.txt &&
+ git bisect reset
+'
+
+test_expect_success 'bisect replay with term1 and term2' '
+ git bisect replay log_to_replay.txt >bisect_result &&
+ grep "$HASH2 is the first term1 commit" bisect_result &&
+ git bisect reset
+'
+
+test_expect_success 'bisect start term1 term2' '
+ git bisect reset &&
+ git bisect start --term-new term1 --term-old term2 $HASH4 $HASH1 &&
+ git bisect term1 &&
+ git bisect term1 >bisect_result &&
+ grep "$HASH2 is the first term1 commit" bisect_result &&
+ git bisect log >log_to_replay.txt &&
+ git bisect reset
+'
+
+test_expect_success 'bisect cannot mix terms' '
+ git bisect reset &&
+ git bisect start --term-good term1 --term-bad term2 $HASH4 $HASH1 &&
+ test_must_fail git bisect a &&
+ test_must_fail git bisect b &&
+ test_must_fail git bisect bad &&
+ test_must_fail git bisect good &&
+ test_must_fail git bisect new &&
+ test_must_fail git bisect old
+'
+
+test_expect_success 'bisect terms rejects invalid terms' '
+ git bisect reset &&
+ test_must_fail git bisect start --term-good invalid..term &&
+ test_must_fail git bisect terms --term-bad invalid..term &&
+ test_must_fail git bisect terms --term-good bad &&
+ test_must_fail git bisect terms --term-good old &&
+ test_must_fail git bisect terms --term-good skip &&
+ test_must_fail git bisect terms --term-good reset &&
+ test_path_is_missing .git/BISECT_TERMS
+'
+
+test_expect_success 'bisect start --term-* does store terms' '
+ git bisect reset &&
+ git bisect start --term-bad=one --term-good=two &&
+ git bisect terms >actual &&
+ cat <<-EOF >expected &&
+ Your current terms are two for the old state
+ and one for the new state.
+ EOF
+ test_cmp expected actual &&
+ git bisect terms --term-bad >actual &&
+ echo one >expected &&
+ test_cmp expected actual &&
+ git bisect terms --term-good >actual &&
+ echo two >expected &&
+ test_cmp expected actual
+'
+
+test_expect_success 'bisect start takes options and revs in any order' '
+ git bisect reset &&
+ git bisect start --term-good one $HASH4 \
+ --term-good two --term-bad bad-term \
+ $HASH1 --term-good three -- &&
+ (git bisect terms --term-bad && git bisect terms --term-good) >actual &&
+ printf "%s\n%s\n" bad-term three >expected &&
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index c0e5b2a627..85f269411c 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -113,6 +113,14 @@ check_describe A-3-* --long HEAD^^2
check_describe c-7-* --tags
check_describe e-3-* --first-parent --tags
+test_expect_success 'describe --contains defaults to HEAD without commit-ish' '
+ echo "A^0" >expect &&
+ git checkout A &&
+ test_when_finished "git checkout -" &&
+ git describe --contains >actual &&
+ test_cmp expect actual
+'
+
: >err.expect
check_describe A --all A^0
test_expect_success 'no warning was displayed for A' '
diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh
index 7c9bec7630..03873b09d1 100755
--- a/t/t6300-for-each-ref.sh
+++ b/t/t6300-for-each-ref.sh
@@ -8,8 +8,8 @@ test_description='for-each-ref test'
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-gpg.sh
-# Mon Jul 3 15:18:43 2006 +0000
-datestamp=1151939923
+# Mon Jul 3 23:18:43 2006 +0000
+datestamp=1151968723
setdate_and_increment () {
GIT_COMMITTER_DATE="$datestamp +0200"
datestamp=$(expr "$datestamp" + 1)
@@ -61,21 +61,21 @@ test_atom head object ''
test_atom head type ''
test_atom head '*objectname' ''
test_atom head '*objecttype' ''
-test_atom head author 'A U Thor <author@example.com> 1151939924 +0200'
+test_atom head author 'A U Thor <author@example.com> 1151968724 +0200'
test_atom head authorname 'A U Thor'
test_atom head authoremail '<author@example.com>'
-test_atom head authordate 'Mon Jul 3 17:18:44 2006 +0200'
-test_atom head committer 'C O Mitter <committer@example.com> 1151939923 +0200'
+test_atom head authordate 'Tue Jul 4 01:18:44 2006 +0200'
+test_atom head committer 'C O Mitter <committer@example.com> 1151968723 +0200'
test_atom head committername 'C O Mitter'
test_atom head committeremail '<committer@example.com>'
-test_atom head committerdate 'Mon Jul 3 17:18:43 2006 +0200'
+test_atom head committerdate 'Tue Jul 4 01:18:43 2006 +0200'
test_atom head tag ''
test_atom head tagger ''
test_atom head taggername ''
test_atom head taggeremail ''
test_atom head taggerdate ''
-test_atom head creator 'C O Mitter <committer@example.com> 1151939923 +0200'
-test_atom head creatordate 'Mon Jul 3 17:18:43 2006 +0200'
+test_atom head creator 'C O Mitter <committer@example.com> 1151968723 +0200'
+test_atom head creatordate 'Tue Jul 4 01:18:43 2006 +0200'
test_atom head subject 'Initial'
test_atom head contents:subject 'Initial'
test_atom head body ''
@@ -96,7 +96,7 @@ test_atom tag parent ''
test_atom tag numparent ''
test_atom tag object $(git rev-parse refs/tags/testtag^0)
test_atom tag type 'commit'
-test_atom tag '*objectname' '67a36f10722846e891fbada1ba48ed035de75581'
+test_atom tag '*objectname' 'ea122842f48be4afb2d1fc6a4b96c05885ab7463'
test_atom tag '*objecttype' 'commit'
test_atom tag author ''
test_atom tag authorname ''
@@ -107,18 +107,18 @@ test_atom tag committername ''
test_atom tag committeremail ''
test_atom tag committerdate ''
test_atom tag tag 'testtag'
-test_atom tag tagger 'C O Mitter <committer@example.com> 1151939925 +0200'
+test_atom tag tagger 'C O Mitter <committer@example.com> 1151968725 +0200'
test_atom tag taggername 'C O Mitter'
test_atom tag taggeremail '<committer@example.com>'
-test_atom tag taggerdate 'Mon Jul 3 17:18:45 2006 +0200'
-test_atom tag creator 'C O Mitter <committer@example.com> 1151939925 +0200'
-test_atom tag creatordate 'Mon Jul 3 17:18:45 2006 +0200'
-test_atom tag subject 'Tagging at 1151939927'
-test_atom tag contents:subject 'Tagging at 1151939927'
+test_atom tag taggerdate 'Tue Jul 4 01:18:45 2006 +0200'
+test_atom tag creator 'C O Mitter <committer@example.com> 1151968725 +0200'
+test_atom tag creatordate 'Tue Jul 4 01:18:45 2006 +0200'
+test_atom tag subject 'Tagging at 1151968727'
+test_atom tag contents:subject 'Tagging at 1151968727'
test_atom tag body ''
test_atom tag contents:body ''
test_atom tag contents:signature ''
-test_atom tag contents 'Tagging at 1151939927
+test_atom tag contents 'Tagging at 1151968727
'
test_atom tag HEAD ' '
@@ -146,95 +146,123 @@ test_expect_success 'Check invalid format specifiers are errors' '
test_must_fail git for-each-ref --format="%(authordate:INVALID)" refs/heads
'
-cat >expected <<\EOF
-'refs/heads/master' 'Mon Jul 3 17:18:43 2006 +0200' 'Mon Jul 3 17:18:44 2006 +0200'
-'refs/tags/testtag' 'Mon Jul 3 17:18:45 2006 +0200'
-EOF
+test_date () {
+ f=$1 &&
+ committer_date=$2 &&
+ author_date=$3 &&
+ tagger_date=$4 &&
+ cat >expected <<-EOF &&
+ 'refs/heads/master' '$committer_date' '$author_date'
+ 'refs/tags/testtag' '$tagger_date'
+ EOF
+ (
+ git for-each-ref --shell \
+ --format="%(refname) %(committerdate${f:+:$f}) %(authordate${f:+:$f})" \
+ refs/heads &&
+ git for-each-ref --shell \
+ --format="%(refname) %(taggerdate${f:+:$f})" \
+ refs/tags
+ ) >actual &&
+ test_cmp expected actual
+}
test_expect_success 'Check unformatted date fields output' '
- (git for-each-ref --shell --format="%(refname) %(committerdate) %(authordate)" refs/heads &&
- git for-each-ref --shell --format="%(refname) %(taggerdate)" refs/tags) >actual &&
- test_cmp expected actual
+ test_date "" \
+ "Tue Jul 4 01:18:43 2006 +0200" \
+ "Tue Jul 4 01:18:44 2006 +0200" \
+ "Tue Jul 4 01:18:45 2006 +0200"
'
test_expect_success 'Check format "default" formatted date fields output' '
- f=default &&
- (git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads &&
- git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual &&
- test_cmp expected actual
+ test_date default \
+ "Tue Jul 4 01:18:43 2006 +0200" \
+ "Tue Jul 4 01:18:44 2006 +0200" \
+ "Tue Jul 4 01:18:45 2006 +0200"
+'
+
+test_expect_success 'Check format "default-local" date fields output' '
+ test_date default-local "Mon Jul 3 23:18:43 2006" "Mon Jul 3 23:18:44 2006" "Mon Jul 3 23:18:45 2006"
'
# Don't know how to do relative check because I can't know when this script
# is going to be run and can't fake the current time to git, and hence can't
# provide expected output. Instead, I'll just make sure that "relative"
# doesn't exit in error
-#
-#cat >expected <<\EOF
-#
-#EOF
-#
test_expect_success 'Check format "relative" date fields output' '
f=relative &&
(git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads &&
git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual
'
-cat >expected <<\EOF
-'refs/heads/master' '2006-07-03' '2006-07-03'
-'refs/tags/testtag' '2006-07-03'
-EOF
+# We just check that this is the same as "relative" for now.
+test_expect_success 'Check format "relative-local" date fields output' '
+ test_date relative-local \
+ "$(git for-each-ref --format="%(committerdate:relative)" refs/heads)" \
+ "$(git for-each-ref --format="%(authordate:relative)" refs/heads)" \
+ "$(git for-each-ref --format="%(taggerdate:relative)" refs/tags)"
+'
test_expect_success 'Check format "short" date fields output' '
- f=short &&
- (git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads &&
- git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual &&
- test_cmp expected actual
+ test_date short 2006-07-04 2006-07-04 2006-07-04
'
-cat >expected <<\EOF
-'refs/heads/master' 'Mon Jul 3 15:18:43 2006' 'Mon Jul 3 15:18:44 2006'
-'refs/tags/testtag' 'Mon Jul 3 15:18:45 2006'
-EOF
+test_expect_success 'Check format "short-local" date fields output' '
+ test_date short-local 2006-07-03 2006-07-03 2006-07-03
+'
test_expect_success 'Check format "local" date fields output' '
- f=local &&
- (git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads &&
- git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual &&
- test_cmp expected actual
+ test_date local \
+ "Mon Jul 3 23:18:43 2006" \
+ "Mon Jul 3 23:18:44 2006" \
+ "Mon Jul 3 23:18:45 2006"
'
-cat >expected <<\EOF
-'refs/heads/master' '2006-07-03 17:18:43 +0200' '2006-07-03 17:18:44 +0200'
-'refs/tags/testtag' '2006-07-03 17:18:45 +0200'
-EOF
-
test_expect_success 'Check format "iso8601" date fields output' '
- f=iso8601 &&
- (git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads &&
- git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual &&
- test_cmp expected actual
+ test_date iso8601 \
+ "2006-07-04 01:18:43 +0200" \
+ "2006-07-04 01:18:44 +0200" \
+ "2006-07-04 01:18:45 +0200"
'
-cat >expected <<\EOF
-'refs/heads/master' 'Mon, 3 Jul 2006 17:18:43 +0200' 'Mon, 3 Jul 2006 17:18:44 +0200'
-'refs/tags/testtag' 'Mon, 3 Jul 2006 17:18:45 +0200'
-EOF
+test_expect_success 'Check format "iso8601-local" date fields output' '
+ test_date iso8601-local "2006-07-03 23:18:43 +0000" "2006-07-03 23:18:44 +0000" "2006-07-03 23:18:45 +0000"
+'
test_expect_success 'Check format "rfc2822" date fields output' '
- f=rfc2822 &&
- (git for-each-ref --shell --format="%(refname) %(committerdate:$f) %(authordate:$f)" refs/heads &&
- git for-each-ref --shell --format="%(refname) %(taggerdate:$f)" refs/tags) >actual &&
- test_cmp expected actual
+ test_date rfc2822 \
+ "Tue, 4 Jul 2006 01:18:43 +0200" \
+ "Tue, 4 Jul 2006 01:18:44 +0200" \
+ "Tue, 4 Jul 2006 01:18:45 +0200"
+'
+
+test_expect_success 'Check format "rfc2822-local" date fields output' '
+ test_date rfc2822-local "Mon, 3 Jul 2006 23:18:43 +0000" "Mon, 3 Jul 2006 23:18:44 +0000" "Mon, 3 Jul 2006 23:18:45 +0000"
+'
+
+test_expect_success 'Check format "raw" date fields output' '
+ test_date raw "1151968723 +0200" "1151968724 +0200" "1151968725 +0200"
+'
+
+test_expect_success 'Check format "raw-local" date fields output' '
+ test_date raw-local "1151968723 +0000" "1151968724 +0000" "1151968725 +0000"
'
test_expect_success 'Check format of strftime date fields' '
- echo "my date is 2006-07-03" >expected &&
+ echo "my date is 2006-07-04" >expected &&
git for-each-ref \
--format="%(authordate:format:my date is %Y-%m-%d)" \
refs/heads >actual &&
test_cmp expected actual
'
+test_expect_success 'Check format of strftime-local date fields' '
+ echo "my date is 2006-07-03" >expected &&
+ git for-each-ref \
+ --format="%(authordate:format-local:my date is %Y-%m-%d)" \
+ refs/heads >actual &&
+ test_cmp expected actual
+'
+
test_expect_success 'exercise strftime with odd fields' '
echo >expected &&
git for-each-ref --format="%(authordate:format:)" refs/heads >actual &&
@@ -546,8 +574,8 @@ body contents
$sig"
cat >expected <<EOF
-$(git rev-parse refs/tags/master) <committer@example.com> refs/tags/master
$(git rev-parse refs/tags/bogo) <committer@example.com> refs/tags/bogo
+$(git rev-parse refs/tags/master) <committer@example.com> refs/tags/master
EOF
test_expect_success 'Verify sort with multiple keys' '
diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
new file mode 100755
index 0000000000..fe4796cc9c
--- /dev/null
+++ b/t/t6302-for-each-ref-filter.sh
@@ -0,0 +1,258 @@
+#!/bin/sh
+
+test_description='test for-each-refs usage of ref-filter APIs'
+
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-gpg.sh
+
+if ! test_have_prereq GPG
+then
+ skip_all="skipping for-each-ref tests, GPG not available"
+ test_done
+fi
+
+test_expect_success 'setup some history and refs' '
+ test_commit one &&
+ test_commit two &&
+ test_commit three &&
+ git checkout -b side &&
+ test_commit four &&
+ git tag -s -m "A signed tag message" signed-tag &&
+ git tag -s -m "Annonated doubly" double-tag signed-tag &&
+ git checkout master &&
+ git update-ref refs/odd/spot master
+'
+
+test_expect_success 'filtering with --points-at' '
+ cat >expect <<-\EOF &&
+ refs/heads/master
+ refs/odd/spot
+ refs/tags/three
+ EOF
+ git for-each-ref --format="%(refname)" --points-at=master >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'check signed tags with --points-at' '
+ sed -e "s/Z$//" >expect <<-\EOF &&
+ refs/heads/side Z
+ refs/tags/four Z
+ refs/tags/signed-tag four
+ EOF
+ git for-each-ref --format="%(refname) %(*subject)" --points-at=side >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'filtering with --merged' '
+ cat >expect <<-\EOF &&
+ refs/heads/master
+ refs/odd/spot
+ refs/tags/one
+ refs/tags/three
+ refs/tags/two
+ EOF
+ git for-each-ref --format="%(refname)" --merged=master >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'filtering with --no-merged' '
+ cat >expect <<-\EOF &&
+ refs/heads/side
+ refs/tags/double-tag
+ refs/tags/four
+ refs/tags/signed-tag
+ EOF
+ git for-each-ref --format="%(refname)" --no-merged=master >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'filtering with --contains' '
+ cat >expect <<-\EOF &&
+ refs/heads/master
+ refs/heads/side
+ refs/odd/spot
+ refs/tags/double-tag
+ refs/tags/four
+ refs/tags/signed-tag
+ refs/tags/three
+ refs/tags/two
+ EOF
+ git for-each-ref --format="%(refname)" --contains=two >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '%(color) must fail' '
+ test_must_fail git for-each-ref --format="%(color)%(refname)"
+'
+
+test_expect_success 'left alignment is default' '
+ cat >expect <<-\EOF &&
+ refname is refs/heads/master |refs/heads/master
+ refname is refs/heads/side |refs/heads/side
+ refname is refs/odd/spot |refs/odd/spot
+ refname is refs/tags/double-tag|refs/tags/double-tag
+ refname is refs/tags/four |refs/tags/four
+ refname is refs/tags/one |refs/tags/one
+ refname is refs/tags/signed-tag|refs/tags/signed-tag
+ refname is refs/tags/three |refs/tags/three
+ refname is refs/tags/two |refs/tags/two
+ EOF
+ git for-each-ref --format="%(align:30)refname is %(refname)%(end)|%(refname)" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'middle alignment' '
+ cat >expect <<-\EOF &&
+ | refname is refs/heads/master |refs/heads/master
+ | refname is refs/heads/side |refs/heads/side
+ | refname is refs/odd/spot |refs/odd/spot
+ |refname is refs/tags/double-tag|refs/tags/double-tag
+ | refname is refs/tags/four |refs/tags/four
+ | refname is refs/tags/one |refs/tags/one
+ |refname is refs/tags/signed-tag|refs/tags/signed-tag
+ | refname is refs/tags/three |refs/tags/three
+ | refname is refs/tags/two |refs/tags/two
+ EOF
+ git for-each-ref --format="|%(align:middle,30)refname is %(refname)%(end)|%(refname)" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'right alignment' '
+ cat >expect <<-\EOF &&
+ | refname is refs/heads/master|refs/heads/master
+ | refname is refs/heads/side|refs/heads/side
+ | refname is refs/odd/spot|refs/odd/spot
+ |refname is refs/tags/double-tag|refs/tags/double-tag
+ | refname is refs/tags/four|refs/tags/four
+ | refname is refs/tags/one|refs/tags/one
+ |refname is refs/tags/signed-tag|refs/tags/signed-tag
+ | refname is refs/tags/three|refs/tags/three
+ | refname is refs/tags/two|refs/tags/two
+ EOF
+ git for-each-ref --format="|%(align:30,right)refname is %(refname)%(end)|%(refname)" >actual &&
+ test_cmp expect actual
+'
+
+# Individual atoms inside %(align:...) and %(end) must not be quoted.
+
+test_expect_success 'alignment with format quote' "
+ cat >expect <<-\EOF &&
+ |' '\''master| A U Thor'\'' '|
+ |' '\''side| A U Thor'\'' '|
+ |' '\''odd/spot| A U Thor'\'' '|
+ |' '\''double-tag| '\'' '|
+ |' '\''four| A U Thor'\'' '|
+ |' '\''one| A U Thor'\'' '|
+ |' '\''signed-tag| '\'' '|
+ |' '\''three| A U Thor'\'' '|
+ |' '\''two| A U Thor'\'' '|
+ EOF
+ git for-each-ref --shell --format=\"|%(align:30,middle)'%(refname:short)| %(authorname)'%(end)|\" >actual &&
+ test_cmp expect actual
+"
+
+test_expect_success 'nested alignment with quote formatting' "
+ cat >expect <<-\EOF &&
+ |' master '|
+ |' side '|
+ |' odd/spot '|
+ |' double-tag '|
+ |' four '|
+ |' one '|
+ |' signed-tag '|
+ |' three '|
+ |' two '|
+ EOF
+ git for-each-ref --shell --format='|%(align:30,left)%(align:15,right)%(refname:short)%(end)%(end)|' >actual &&
+ test_cmp expect actual
+"
+
+test_expect_success 'check `%(contents:lines=1)`' '
+ cat >expect <<-\EOF &&
+ master |three
+ side |four
+ odd/spot |three
+ double-tag |Annonated doubly
+ four |four
+ one |one
+ signed-tag |A signed tag message
+ three |three
+ two |two
+ EOF
+ git for-each-ref --format="%(refname:short) |%(contents:lines=1)" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'check `%(contents:lines=0)`' '
+ cat >expect <<-\EOF &&
+ master |
+ side |
+ odd/spot |
+ double-tag |
+ four |
+ one |
+ signed-tag |
+ three |
+ two |
+ EOF
+ git for-each-ref --format="%(refname:short) |%(contents:lines=0)" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'check `%(contents:lines=99999)`' '
+ cat >expect <<-\EOF &&
+ master |three
+ side |four
+ odd/spot |three
+ double-tag |Annonated doubly
+ four |four
+ one |one
+ signed-tag |A signed tag message
+ three |three
+ two |two
+ EOF
+ git for-each-ref --format="%(refname:short) |%(contents:lines=99999)" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '`%(contents:lines=-1)` should fail' '
+ test_must_fail git for-each-ref --format="%(refname:short) |%(contents:lines=-1)"
+'
+
+test_expect_success 'setup for version sort' '
+ test_commit foo1.3 &&
+ test_commit foo1.6 &&
+ test_commit foo1.10
+'
+
+test_expect_success 'version sort' '
+ git for-each-ref --sort=version:refname --format="%(refname:short)" refs/tags/ | grep "foo" >actual &&
+ cat >expect <<-\EOF &&
+ foo1.3
+ foo1.6
+ foo1.10
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'version sort (shortened)' '
+ git for-each-ref --sort=v:refname --format="%(refname:short)" refs/tags/ | grep "foo" >actual &&
+ cat >expect <<-\EOF &&
+ foo1.3
+ foo1.6
+ foo1.10
+ EOF
+ test_cmp expect actual
+'
+
+test_expect_success 'reverse version sort' '
+ git for-each-ref --sort=-version:refname --format="%(refname:short)" refs/tags/ | grep "foo" >actual &&
+ cat >expect <<-\EOF &&
+ foo1.10
+ foo1.6
+ foo1.3
+ EOF
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t6501-freshen-objects.sh b/t/t6501-freshen-objects.sh
index 2adf825076..cf076dcd94 100755
--- a/t/t6501-freshen-objects.sh
+++ b/t/t6501-freshen-objects.sh
@@ -56,7 +56,7 @@ for repack in '' true; do
test_expect_success "disable reflogs ($title)" '
git config core.logallrefupdates false &&
- rm -rf .git/logs
+ git reflog expire --expire=all --all
'
test_expect_success "setup basic history ($title)" '
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index d1ff5c94f2..3dd2f51e49 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -51,7 +51,19 @@ test_expect_success 'creating a tag using default HEAD should succeed' '
echo foo >foo &&
git add foo &&
git commit -m Foo &&
- git tag mytag
+ git tag mytag &&
+ test_must_fail git reflog exists refs/tags/mytag
+'
+
+test_expect_success 'creating a tag with --create-reflog should create reflog' '
+ test_when_finished "git tag -d tag_with_reflog" &&
+ git tag --create-reflog tag_with_reflog &&
+ git reflog exists refs/tags/tag_with_reflog
+'
+
+test_expect_success '--create-reflog does not create reflog on failure' '
+ test_must_fail git tag --create-reflog mytag &&
+ test_must_fail git reflog exists refs/tags/mytag
'
test_expect_success 'listing all tags if one exists should succeed' '
@@ -1450,13 +1462,7 @@ test_expect_success 'invalid sort parameter on command line' '
test_expect_success 'invalid sort parameter in configuratoin' '
git config tag.sort "v:notvalid" &&
- git tag -l "foo*" >actual &&
- cat >expect <<-\EOF &&
- foo1.10
- foo1.3
- foo1.6
- EOF
- test_cmp expect actual
+ test_must_fail git tag -l "foo*"
'
test_expect_success 'version sort with prerelease reordering' '
@@ -1513,4 +1519,43 @@ EOF"
test_cmp expect actual
'
+test_expect_success '--format should list tags as per format given' '
+ cat >expect <<-\EOF &&
+ refname : refs/tags/foo1.10
+ refname : refs/tags/foo1.3
+ refname : refs/tags/foo1.6
+ refname : refs/tags/foo1.6-rc1
+ refname : refs/tags/foo1.6-rc2
+ EOF
+ git tag -l --format="refname : %(refname)" "foo*" >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'setup --merged test tags' '
+ git tag mergetest-1 HEAD~2 &&
+ git tag mergetest-2 HEAD~1 &&
+ git tag mergetest-3 HEAD
+'
+
+test_expect_success '--merged cannot be used in non-list mode' '
+ test_must_fail git tag --merged=mergetest-2 foo
+'
+
+test_expect_success '--merged shows merged tags' '
+ cat >expect <<-\EOF &&
+ mergetest-1
+ mergetest-2
+ EOF
+ git tag -l --merged=mergetest-2 mergetest-* >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success '--no-merged show unmerged tags' '
+ cat >expect <<-\EOF &&
+ mergetest-3
+ EOF
+ git tag -l --no-merged=mergetest-2 mergetest-* >actual &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh
index 947b690fd7..6ea7ac4c41 100755
--- a/t/t7006-pager.sh
+++ b/t/t7006-pager.sh
@@ -447,4 +447,13 @@ test_expect_success TTY 'external command pagers override sub-commands' '
test_cmp expect actual
'
+test_expect_success 'command with underscores does not complain' '
+ write_script git-under_score <<-\EOF &&
+ echo ok
+ EOF
+ git --exec-path=. under_score >actual 2>&1 &&
+ echo ok >expect &&
+ test_cmp expect actual
+'
+
test_done
diff --git a/t/t7060-wtstatus.sh b/t/t7060-wtstatus.sh
index 741ec08576..32d81765cb 100755
--- a/t/t7060-wtstatus.sh
+++ b/t/t7060-wtstatus.sh
@@ -106,7 +106,7 @@ test_expect_success 'git diff-index --cached -M shows 2 added + 1 unmerged' '
A THREE
A TWO
EOF
- git diff-index --cached --name-status HEAD >actual &&
+ git diff-index --cached -M --name-status HEAD >actual &&
test_cmp expected actual
'
diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh
index bd4806c12a..37a24c1312 100755
--- a/t/t7063-status-untracked-cache.sh
+++ b/t/t7063-status-untracked-cache.sh
@@ -354,4 +354,219 @@ EOF
test_cmp ../expect ../actual
'
+test_expect_success 'set up for sparse checkout testing' '
+ echo two >done/.gitignore &&
+ echo three >>done/.gitignore &&
+ echo two >done/two &&
+ git add -f done/two done/.gitignore &&
+ git commit -m "first commit"
+'
+
+test_expect_success 'status after commit' '
+ : >../trace &&
+ GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
+ git status --porcelain >../actual &&
+ cat >../status.expect <<EOF &&
+?? .gitignore
+?? dtwo/
+EOF
+ test_cmp ../status.expect ../actual &&
+ cat >../trace.expect <<EOF &&
+node creation: 0
+gitignore invalidation: 0
+directory invalidation: 0
+opendir: 2
+EOF
+ test_cmp ../trace.expect ../trace
+'
+
+test_expect_success 'untracked cache correct after commit' '
+ test-dump-untracked-cache >../actual &&
+ cat >../expect <<EOF &&
+info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
+core.excludesfile 0000000000000000000000000000000000000000
+exclude_per_dir .gitignore
+flags 00000006
+/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
+.gitignore
+dtwo/
+/done/ 0000000000000000000000000000000000000000 recurse valid
+/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
+/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
+two
+EOF
+ test_cmp ../expect ../actual
+'
+
+test_expect_success 'set up sparse checkout' '
+ echo "done/[a-z]*" >.git/info/sparse-checkout &&
+ test_config core.sparsecheckout true &&
+ git checkout master &&
+ git update-index --force-untracked-cache &&
+ git status --porcelain >/dev/null && # prime the cache
+ test_path_is_missing done/.gitignore &&
+ test_path_is_file done/one
+'
+
+test_expect_success 'create/modify files, some of which are gitignored' '
+ echo two bis >done/two &&
+ echo three >done/three && # three is gitignored
+ echo four >done/four && # four is gitignored at a higher level
+ echo five >done/five # five is not gitignored
+'
+
+test_expect_success 'test sparse status with untracked cache' '
+ : >../trace &&
+ avoid_racy &&
+ GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
+ git status --porcelain >../status.actual &&
+ cat >../status.expect <<EOF &&
+ M done/two
+?? .gitignore
+?? done/five
+?? dtwo/
+EOF
+ test_cmp ../status.expect ../status.actual &&
+ cat >../trace.expect <<EOF &&
+node creation: 0
+gitignore invalidation: 1
+directory invalidation: 2
+opendir: 2
+EOF
+ test_cmp ../trace.expect ../trace
+'
+
+test_expect_success 'untracked cache correct after status' '
+ test-dump-untracked-cache >../actual &&
+ cat >../expect <<EOF &&
+info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
+core.excludesfile 0000000000000000000000000000000000000000
+exclude_per_dir .gitignore
+flags 00000006
+/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
+.gitignore
+dtwo/
+/done/ 1946f0437f90c5005533cbe1736a6451ca301714 recurse valid
+five
+/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
+/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
+two
+EOF
+ test_cmp ../expect ../actual
+'
+
+test_expect_success 'test sparse status again with untracked cache' '
+ avoid_racy &&
+ : >../trace &&
+ GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
+ git status --porcelain >../status.actual &&
+ cat >../status.expect <<EOF &&
+ M done/two
+?? .gitignore
+?? done/five
+?? dtwo/
+EOF
+ test_cmp ../status.expect ../status.actual &&
+ cat >../trace.expect <<EOF &&
+node creation: 0
+gitignore invalidation: 0
+directory invalidation: 0
+opendir: 0
+EOF
+ test_cmp ../trace.expect ../trace
+'
+
+test_expect_success 'set up for test of subdir and sparse checkouts' '
+ mkdir done/sub &&
+ mkdir done/sub/sub &&
+ echo "sub" > done/sub/sub/file
+'
+
+test_expect_success 'test sparse status with untracked cache and subdir' '
+ avoid_racy &&
+ : >../trace &&
+ GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
+ git status --porcelain >../status.actual &&
+ cat >../status.expect <<EOF &&
+ M done/two
+?? .gitignore
+?? done/five
+?? done/sub/
+?? dtwo/
+EOF
+ test_cmp ../status.expect ../status.actual &&
+ cat >../trace.expect <<EOF &&
+node creation: 2
+gitignore invalidation: 0
+directory invalidation: 1
+opendir: 3
+EOF
+ test_cmp ../trace.expect ../trace
+'
+
+test_expect_success 'verify untracked cache dump (sparse/subdirs)' '
+ test-dump-untracked-cache >../actual &&
+ cat >../expect <<EOF &&
+info/exclude 13263c0978fb9fad16b2d580fb800b6d811c3ff0
+core.excludesfile 0000000000000000000000000000000000000000
+exclude_per_dir .gitignore
+flags 00000006
+/ e6fcc8f2ee31bae321d66afd183fcb7237afae6e recurse valid
+.gitignore
+dtwo/
+/done/ 1946f0437f90c5005533cbe1736a6451ca301714 recurse valid
+five
+sub/
+/done/sub/ 0000000000000000000000000000000000000000 recurse check_only valid
+sub/
+/done/sub/sub/ 0000000000000000000000000000000000000000 recurse check_only valid
+file
+/dthree/ 0000000000000000000000000000000000000000 recurse check_only valid
+/dtwo/ 0000000000000000000000000000000000000000 recurse check_only valid
+two
+EOF
+ test_cmp ../expect ../actual
+'
+
+test_expect_success 'test sparse status again with untracked cache and subdir' '
+ avoid_racy &&
+ : >../trace &&
+ GIT_TRACE_UNTRACKED_STATS="$TRASH_DIRECTORY/trace" \
+ git status --porcelain >../status.actual &&
+ test_cmp ../status.expect ../status.actual &&
+ cat >../trace.expect <<EOF &&
+node creation: 0
+gitignore invalidation: 0
+directory invalidation: 0
+opendir: 0
+EOF
+ test_cmp ../trace.expect ../trace
+'
+
+test_expect_success 'move entry in subdir from untracked to cached' '
+ git add dtwo/two &&
+ git status --porcelain >../status.actual &&
+ cat >../status.expect <<EOF &&
+ M done/two
+A dtwo/two
+?? .gitignore
+?? done/five
+?? done/sub/
+EOF
+ test_cmp ../status.expect ../status.actual
+'
+
+test_expect_success 'move entry in subdir from cached to untracked' '
+ git rm --cached dtwo/two &&
+ git status --porcelain >../status.actual &&
+ cat >../status.expect <<EOF &&
+ M done/two
+?? .gitignore
+?? done/five
+?? done/sub/
+?? dtwo/
+EOF
+ test_cmp ../status.expect ../status.actual
+'
+
test_done
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index 32e96da7e3..86ceb38b01 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -432,9 +432,7 @@ test_expect_success 'nested git work tree' '
(
cd foo &&
git init &&
- >hello.world
- git add . &&
- git commit -a -m nested
+ test_commit nested hello.world
) &&
(
cd bar &&
@@ -443,9 +441,7 @@ test_expect_success 'nested git work tree' '
(
cd baz/boo &&
git init &&
- >deeper.world
- git add . &&
- git commit -a -m deeply.nested
+ test_commit deeply.nested deeper.world
) &&
git clean -f -d &&
test -f foo/.git/index &&
@@ -499,7 +495,7 @@ test_expect_success 'should not clean submodules' '
test_path_is_missing to_clean
'
-test_expect_success 'should avoid cleaning possible submodules' '
+test_expect_success POSIXPERM 'should avoid cleaning possible submodules' '
rm -fr to_clean possible_sub1 &&
mkdir to_clean possible_sub1 &&
test_when_finished "rm -rf possible_sub*" &&
@@ -601,9 +597,7 @@ test_expect_success 'force removal of nested git work tree' '
(
cd foo &&
git init &&
- >hello.world
- git add . &&
- git commit -a -m nested
+ test_commit nested hello.world
) &&
(
cd bar &&
@@ -612,9 +606,7 @@ test_expect_success 'force removal of nested git work tree' '
(
cd baz/boo &&
git init &&
- >deeper.world
- git add . &&
- git commit -a -m deeply.nested
+ test_commit deeply.nested deeper.world
) &&
git clean -f -f -d &&
! test -d foo &&
diff --git a/t/t7410-submodule-checkout-to.sh b/t/t7410-submodule-checkout-to.sh
index 3f609e8909..1acef32647 100755
--- a/t/t7410-submodule-checkout-to.sh
+++ b/t/t7410-submodule-checkout-to.sh
@@ -47,4 +47,14 @@ test_expect_success 'checkout main and initialize independed clones' \
test_expect_success 'can see submodule diffs after independed cloning' \
'(cd fully_cloned_submodule/main && git diff --submodule master"^!" | grep "file1 updated")'
+test_expect_success 'checkout sub manually' \
+ 'mkdir linked_submodule &&
+ (cd clone/main &&
+ git worktree add "$base_path/linked_submodule/main" "$rev1_hash_main") &&
+ (cd clone/main/sub &&
+ git worktree add "$base_path/linked_submodule/main/sub" "$rev1_hash_sub")'
+
+test_expect_success 'can see submodule diffs after manual checkout of linked submodule' \
+ '(cd linked_submodule/main && git diff --submodule master"^!" | grep "file1 updated")'
+
test_done
diff --git a/t/t7411-submodule-config.sh b/t/t7411-submodule-config.sh
new file mode 100755
index 0000000000..fc97c3314e
--- /dev/null
+++ b/t/t7411-submodule-config.sh
@@ -0,0 +1,153 @@
+#!/bin/sh
+#
+# Copyright (c) 2014 Heiko Voigt
+#
+
+test_description='Test submodules config cache infrastructure
+
+This test verifies that parsing .gitmodules configurations directly
+from the database and from the worktree works.
+'
+
+TEST_NO_CREATE_REPO=1
+. ./test-lib.sh
+
+test_expect_success 'submodule config cache setup' '
+ mkdir submodule &&
+ (cd submodule &&
+ git init &&
+ echo a >a &&
+ git add . &&
+ git commit -ma
+ ) &&
+ mkdir super &&
+ (cd super &&
+ git init &&
+ git submodule add ../submodule &&
+ git submodule add ../submodule a &&
+ git commit -m "add as submodule and as a" &&
+ git mv a b &&
+ git commit -m "move a to b"
+ )
+'
+
+cat >super/expect <<EOF
+Submodule name: 'a' for path 'a'
+Submodule name: 'a' for path 'b'
+Submodule name: 'submodule' for path 'submodule'
+Submodule name: 'submodule' for path 'submodule'
+EOF
+
+test_expect_success 'test parsing and lookup of submodule config by path' '
+ (cd super &&
+ test-submodule-config \
+ HEAD^ a \
+ HEAD b \
+ HEAD^ submodule \
+ HEAD submodule \
+ >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'test parsing and lookup of submodule config by name' '
+ (cd super &&
+ test-submodule-config --name \
+ HEAD^ a \
+ HEAD a \
+ HEAD^ submodule \
+ HEAD submodule \
+ >actual &&
+ test_cmp expect actual
+ )
+'
+
+cat >super/expect_error <<EOF
+Submodule name: 'a' for path 'b'
+Submodule name: 'submodule' for path 'submodule'
+EOF
+
+test_expect_success 'error in one submodule config lets continue' '
+ (cd super &&
+ cp .gitmodules .gitmodules.bak &&
+ echo " value = \"" >>.gitmodules &&
+ git add .gitmodules &&
+ mv .gitmodules.bak .gitmodules &&
+ git commit -m "add error" &&
+ test-submodule-config \
+ HEAD b \
+ HEAD submodule \
+ >actual &&
+ test_cmp expect_error actual
+ )
+'
+
+cat >super/expect_url <<EOF
+Submodule url: 'git@somewhere.else.net:a.git' for path 'b'
+Submodule url: 'git@somewhere.else.net:submodule.git' for path 'submodule'
+EOF
+
+cat >super/expect_local_path <<EOF
+Submodule name: 'a' for path 'c'
+Submodule name: 'submodule' for path 'submodule'
+EOF
+
+test_expect_success 'reading of local configuration' '
+ (cd super &&
+ old_a=$(git config submodule.a.url) &&
+ old_submodule=$(git config submodule.submodule.url) &&
+ git config submodule.a.url git@somewhere.else.net:a.git &&
+ git config submodule.submodule.url git@somewhere.else.net:submodule.git &&
+ test-submodule-config --url \
+ "" b \
+ "" submodule \
+ >actual &&
+ test_cmp expect_url actual &&
+ git config submodule.a.path c &&
+ test-submodule-config \
+ "" c \
+ "" submodule \
+ >actual &&
+ test_cmp expect_local_path actual &&
+ git config submodule.a.url $old_a &&
+ git config submodule.submodule.url $old_submodule &&
+ git config --unset submodule.a.path c
+ )
+'
+
+cat >super/expect_fetchrecurse_die.err <<EOF
+fatal: bad submodule.submodule.fetchrecursesubmodules argument: blabla
+EOF
+
+test_expect_success 'local error in fetchrecursesubmodule dies early' '
+ (cd super &&
+ git config submodule.submodule.fetchrecursesubmodules blabla &&
+ test_must_fail test-submodule-config \
+ "" b \
+ "" submodule \
+ >actual.out 2>actual.err &&
+ touch expect_fetchrecurse_die.out &&
+ test_cmp expect_fetchrecurse_die.out actual.out &&
+ test_cmp expect_fetchrecurse_die.err actual.err &&
+ git config --unset submodule.submodule.fetchrecursesubmodules
+ )
+'
+
+test_expect_success 'error in history in fetchrecursesubmodule lets continue' '
+ (cd super &&
+ git config -f .gitmodules \
+ submodule.submodule.fetchrecursesubmodules blabla &&
+ git add .gitmodules &&
+ git config --unset -f .gitmodules \
+ submodule.submodule.fetchrecursesubmodules &&
+ git commit -m "add error in fetchrecursesubmodules" &&
+ test-submodule-config \
+ HEAD b \
+ HEAD submodule \
+ >actual &&
+ test_cmp expect_error actual &&
+ git reset --hard HEAD^
+ )
+'
+
+test_done
diff --git a/t/t7509-commit.sh b/t/t7509-commit.sh
index 9ac794052d..db9774e345 100755
--- a/t/t7509-commit.sh
+++ b/t/t7509-commit.sh
@@ -90,22 +90,10 @@ sha1_file() {
remove_object() {
rm -f $(sha1_file "$*")
}
-no_reflog() {
- cp .git/config .git/config.saved &&
- echo "[core] logallrefupdates = false" >>.git/config &&
- test_when_finished "mv -f .git/config.saved .git/config" &&
-
- if test -e .git/logs
- then
- mv .git/logs . &&
- test_when_finished "mv logs .git/"
- fi
-}
test_expect_success '--amend option with empty author' '
git cat-file commit Initial >tmp &&
sed "s/author [^<]* </author </" tmp >empty-author &&
- no_reflog &&
sha=$(git hash-object -t commit -w empty-author) &&
test_when_finished "remove_object $sha" &&
git checkout $sha &&
@@ -119,7 +107,6 @@ test_expect_success '--amend option with empty author' '
test_expect_success '--amend option with missing author' '
git cat-file commit Initial >tmp &&
sed "s/author [^<]* </author </" tmp >malformed &&
- no_reflog &&
sha=$(git hash-object -t commit -w malformed) &&
test_when_finished "remove_object $sha" &&
git checkout $sha &&
diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh
index bd0ab46750..322c436a49 100755
--- a/t/t7513-interpret-trailers.sh
+++ b/t/t7513-interpret-trailers.sh
@@ -93,12 +93,39 @@ test_expect_success 'with config option on the command line' '
Acked-by: Johan
Reviewed-by: Peff
EOF
- echo "Acked-by: Johan" |
+ { echo; echo "Acked-by: Johan"; } |
git -c "trailer.Acked-by.ifexists=addifdifferent" interpret-trailers \
--trailer "Reviewed-by: Peff" --trailer "Acked-by: Johan" >actual &&
test_cmp expected actual
'
+test_expect_success 'with only a title in the message' '
+ cat >expected <<-\EOF &&
+ area: change
+
+ Reviewed-by: Peff
+ Acked-by: Johan
+ EOF
+ echo "area: change" |
+ git interpret-trailers --trailer "Reviewed-by: Peff" \
+ --trailer "Acked-by: Johan" >actual &&
+ test_cmp expected actual
+'
+
+test_expect_success 'with multiline title in the message' '
+ cat >expected <<-\EOF &&
+ place of
+ code: change
+
+ Reviewed-by: Peff
+ Acked-by: Johan
+ EOF
+ printf "%s\n" "place of" "code: change" |
+ git interpret-trailers --trailer "Reviewed-by: Peff" \
+ --trailer "Acked-by: Johan" >actual &&
+ test_cmp expected actual
+'
+
test_expect_success 'with config setup' '
git config trailer.ack.key "Acked-by: " &&
cat >expected <<-\EOF &&
diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh
index 7eeb207b32..6f12b235b3 100755
--- a/t/t7610-mergetool.sh
+++ b/t/t7610-mergetool.sh
@@ -174,9 +174,9 @@ test_expect_success 'mergetool skips autoresolved' '
'
test_expect_success 'mergetool merges all from subdir' '
+ test_config rerere.enabled false &&
(
cd subdir &&
- test_config rerere.enabled false &&
test_must_fail git merge master &&
( yes "r" | git mergetool ../submod ) &&
( yes "d" "d" | git mergetool --no-prompt ) &&
diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index ea35a0241c..48c6e2bc83 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -492,12 +492,12 @@ test_expect_success PERL 'difftool --no-symlinks detects conflict ' '
test_expect_success PERL 'difftool properly honors gitlink and core.worktree' '
git submodule add ./. submod/ule &&
+ test_config -C submod/ule diff.tool checktrees &&
+ test_config -C submod/ule difftool.checktrees.cmd '\''
+ test -d "$LOCAL" && test -d "$REMOTE" && echo good
+ '\'' &&
(
cd submod/ule &&
- test_config diff.tool checktrees &&
- test_config difftool.checktrees.cmd '\''
- test -d "$LOCAL" && test -d "$REMOTE" && echo good
- '\'' &&
echo good >expect &&
git difftool --tool=checktrees --dir-diff HEAD~ >actual &&
test_cmp expect actual
diff --git a/t/t9811-git-p4-label-import.sh b/t/t9811-git-p4-label-import.sh
index 095238fffe..decb66ba30 100755
--- a/t/t9811-git-p4-label-import.sh
+++ b/t/t9811-git-p4-label-import.sh
@@ -214,6 +214,51 @@ test_expect_success 'use git config to enable import/export of tags' '
)
'
+p4_head_revision() {
+ p4 changes -m 1 "$@" | awk '{print $2}'
+}
+
+# Importing a label that references a P4 commit that
+# has not been seen. The presence of a label on a commit
+# we haven't seen should not cause git-p4 to fail. It should
+# merely skip that label, and still import other labels.
+test_expect_success 'importing labels with missing revisions' '
+ test_when_finished cleanup_git &&
+ (
+ rm -fr "$cli" "$git" &&
+ mkdir "$cli" &&
+ P4CLIENT=missing-revision &&
+ client_view "//depot/missing-revision/... //missing-revision/..." &&
+ cd "$cli" &&
+ >f1 && p4 add f1 && p4 submit -d "start" &&
+
+ p4 tag -l TAG_S0 ... &&
+
+ >f2 && p4 add f2 && p4 submit -d "second" &&
+
+ startrev=$(p4_head_revision //depot/missing-revision/...) &&
+
+ >f3 && p4 add f3 && p4 submit -d "third" &&
+
+ p4 edit f2 && date >f2 && p4 submit -d "change" f2 &&
+
+ endrev=$(p4_head_revision //depot/missing-revision/...) &&
+
+ p4 tag -l TAG_S1 ... &&
+
+ # we should skip TAG_S0 since it is before our startpoint,
+ # but pick up TAG_S1.
+
+ git p4 clone --dest="$git" --import-labels -v \
+ //depot/missing-revision/...@$startrev,$endrev &&
+ (
+ cd "$git" &&
+ git rev-parse TAG_S1 &&
+ ! git rev-parse TAG_S0
+ )
+ )
+'
+
test_expect_success 'kill p4d' '
kill_p4d
diff --git a/t/t9821-git-p4-path-variations.sh b/t/t9821-git-p4-path-variations.sh
new file mode 100755
index 0000000000..81e46acfa8
--- /dev/null
+++ b/t/t9821-git-p4-path-variations.sh
@@ -0,0 +1,200 @@
+#!/bin/sh
+
+test_description='Clone repositories with path case variations'
+
+. ./lib-git-p4.sh
+
+test_expect_success 'start p4d with case folding enabled' '
+ start_p4d -C1
+'
+
+test_expect_success 'Create a repo with path case variations' '
+ client_view "//depot/... //client/..." &&
+ (
+ cd "$cli" &&
+
+ mkdir -p Path/to &&
+ >Path/to/File2.txt &&
+ p4 add Path/to/File2.txt &&
+ p4 submit -d "Add file2" &&
+ rm -rf Path &&
+
+ mkdir -p path/TO &&
+ >path/TO/file1.txt &&
+ p4 add path/TO/file1.txt &&
+ p4 submit -d "Add file1" &&
+ rm -rf path &&
+
+ mkdir -p path/to &&
+ >path/to/file3.txt &&
+ p4 add path/to/file3.txt &&
+ p4 submit -d "Add file3" &&
+ rm -rf path &&
+
+ mkdir -p x-outside-spec &&
+ >x-outside-spec/file4.txt &&
+ p4 add x-outside-spec/file4.txt &&
+ p4 submit -d "Add file4" &&
+ rm -rf x-outside-spec
+ )
+'
+
+test_expect_success 'Clone root' '
+ client_view "//depot/... //client/..." &&
+ test_when_finished cleanup_git &&
+ (
+ cd "$git" &&
+ git init . &&
+ git config core.ignorecase false &&
+ git p4 clone --use-client-spec --destination="$git" //depot &&
+ # This method is used instead of "test -f" to ensure the case is
+ # checked even if the test is executed on case-insensitive file systems.
+ # All files are there as expected although the path cases look random.
+ cat >expect <<-\EOF &&
+ Path/to/File2.txt
+ path/TO/file1.txt
+ path/to/file3.txt
+ x-outside-spec/file4.txt
+ EOF
+ git ls-files >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'Clone root (ignorecase)' '
+ client_view "//depot/... //client/..." &&
+ test_when_finished cleanup_git &&
+ (
+ cd "$git" &&
+ git init . &&
+ git config core.ignorecase true &&
+ git p4 clone --use-client-spec --destination="$git" //depot &&
+ # This method is used instead of "test -f" to ensure the case is
+ # checked even if the test is executed on case-insensitive file systems.
+ # All files are there as expected although the path cases look random.
+ cat >expect <<-\EOF &&
+ path/TO/File2.txt
+ path/TO/file1.txt
+ path/TO/file3.txt
+ x-outside-spec/file4.txt
+ EOF
+ git ls-files >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'Clone root and ignore one file' '
+ client_view \
+ "//depot/... //client/..." \
+ "-//depot/path/TO/file1.txt //client/path/TO/file1.txt" &&
+ test_when_finished cleanup_git &&
+ (
+ cd "$git" &&
+ git init . &&
+ git config core.ignorecase false &&
+ git p4 clone --use-client-spec --destination="$git" //depot &&
+ # We ignore one file in the client spec and all path cases change from
+ # "TO" to "to"!
+ cat >expect <<-\EOF &&
+ Path/to/File2.txt
+ path/to/file3.txt
+ x-outside-spec/file4.txt
+ EOF
+ git ls-files >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'Clone root and ignore one file (ignorecase)' '
+ client_view \
+ "//depot/... //client/..." \
+ "-//depot/path/TO/file1.txt //client/path/TO/file1.txt" &&
+ test_when_finished cleanup_git &&
+ (
+ cd "$git" &&
+ git init . &&
+ git config core.ignorecase true &&
+ git p4 clone --use-client-spec --destination="$git" //depot &&
+ # We ignore one file in the client spec and all path cases change from
+ # "TO" to "to"!
+ cat >expect <<-\EOF &&
+ Path/to/File2.txt
+ Path/to/file3.txt
+ x-outside-spec/file4.txt
+ EOF
+ git ls-files >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'Clone path' '
+ client_view "//depot/Path/... //client/..." &&
+ test_when_finished cleanup_git &&
+ (
+ cd "$git" &&
+ git init . &&
+ git config core.ignorecase false &&
+ git p4 clone --use-client-spec --destination="$git" //depot &&
+ cat >expect <<-\EOF &&
+ to/File2.txt
+ EOF
+ git ls-files >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'Clone path (ignorecase)' '
+ client_view "//depot/Path/... //client/..." &&
+ test_when_finished cleanup_git &&
+ (
+ cd "$git" &&
+ git init . &&
+ git config core.ignorecase true &&
+ git p4 clone --use-client-spec --destination="$git" //depot &&
+ cat >expect <<-\EOF &&
+ TO/File2.txt
+ TO/file1.txt
+ TO/file3.txt
+ EOF
+ git ls-files >actual &&
+ test_cmp expect actual
+ )
+'
+
+# It looks like P4 determines the path case based on the first file in
+# lexicographical order. Please note the lower case "to" directory for all
+# files triggered through the addition of "File0.txt".
+test_expect_success 'Add a new file and clone path with new file (ignorecase)' '
+ client_view "//depot/... //client/..." &&
+ (
+ cd "$cli" &&
+ mkdir -p Path/to &&
+ >Path/to/File0.txt &&
+ p4 add Path/to/File0.txt &&
+ p4 submit -d "Add file" &&
+ rm -rf Path
+ ) &&
+
+ client_view "//depot/Path/... //client/..." &&
+ test_when_finished cleanup_git &&
+ (
+ cd "$git" &&
+ git init . &&
+ git config core.ignorecase true &&
+ git p4 clone --use-client-spec --destination="$git" //depot &&
+ cat >expect <<-\EOF &&
+ to/File0.txt
+ to/File2.txt
+ to/file1.txt
+ to/file3.txt
+ EOF
+ git ls-files >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'kill p4d' '
+ kill_p4d
+'
+
+test_done
diff --git a/t/t9822-git-p4-path-encoding.sh b/t/t9822-git-p4-path-encoding.sh
new file mode 100755
index 0000000000..7b83e696a9
--- /dev/null
+++ b/t/t9822-git-p4-path-encoding.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+test_description='Clone repositories with non ASCII paths'
+
+. ./lib-git-p4.sh
+
+UTF8_ESCAPED="a-\303\244_o-\303\266_u-\303\274.txt"
+ISO8859_ESCAPED="a-\344_o-\366_u-\374.txt"
+
+test_expect_success 'start p4d' '
+ start_p4d
+'
+
+test_expect_success 'Create a repo containing iso8859-1 encoded paths' '
+ (
+ cd "$cli" &&
+ ISO8859="$(printf "$ISO8859_ESCAPED")" &&
+ echo content123 >"$ISO8859" &&
+ p4 add "$ISO8859" &&
+ p4 submit -d "test commit"
+ )
+'
+
+test_expect_failure 'Clone auto-detects depot with iso8859-1 paths' '
+ git p4 clone --destination="$git" //depot &&
+ test_when_finished cleanup_git &&
+ (
+ cd "$git" &&
+ UTF8="$(printf "$UTF8_ESCAPED")" &&
+ echo "$UTF8" >expect &&
+ git -c core.quotepath=false ls-files >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'Clone repo containing iso8859-1 encoded paths with git-p4.pathEncoding' '
+ test_when_finished cleanup_git &&
+ (
+ cd "$git" &&
+ git init . &&
+ git config git-p4.pathEncoding iso8859-1 &&
+ git p4 clone --use-client-spec --destination="$git" //depot &&
+ UTF8="$(printf "$UTF8_ESCAPED")" &&
+ echo "$UTF8" >expect &&
+ git -c core.quotepath=false ls-files >actual &&
+ test_cmp expect actual &&
+
+ echo content123 >expect &&
+ cat "$UTF8" >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'kill p4d' '
+ kill_p4d
+'
+
+test_done
diff --git a/t/t9825-git-p4-handle-utf16-without-bom.sh b/t/t9825-git-p4-handle-utf16-without-bom.sh
new file mode 100755
index 0000000000..1551845dc1
--- /dev/null
+++ b/t/t9825-git-p4-handle-utf16-without-bom.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+test_description='git p4 handling of UTF-16 files without BOM'
+
+. ./lib-git-p4.sh
+
+UTF16="\227\000\227\000"
+
+test_expect_success 'start p4d' '
+ start_p4d
+'
+
+test_expect_success 'init depot with UTF-16 encoded file and artificially remove BOM' '
+ (
+ cd "$cli" &&
+ printf "$UTF16" >file1 &&
+ p4 add -t utf16 file1 &&
+ p4 submit -d "file1"
+ ) &&
+
+ (
+ cd db &&
+ p4d -jc &&
+ # P4D automatically adds a BOM. Remove it here to make the file invalid.
+ sed -e "\$d" depot/file1,v >depot/file1,v.new &&
+ mv depot/file1,v.new depot/file1,v &&
+ printf "@$UTF16@" >>depot/file1,v &&
+ p4d -jrF checkpoint.1
+ )
+'
+
+test_expect_success 'clone depot with invalid UTF-16 file in verbose mode' '
+ git p4 clone --dest="$git" --verbose //depot &&
+ test_when_finished cleanup_git &&
+ (
+ cd "$git" &&
+ printf "$UTF16" >expect &&
+ test_cmp_bin expect file1
+ )
+'
+
+test_expect_failure 'clone depot with invalid UTF-16 file in non-verbose mode' '
+ git p4 clone --dest="$git" //depot
+'
+
+test_expect_success 'kill p4d' '
+ kill_p4d
+'
+
+test_done
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index e8d3c0fdbc..6dffb8bcde 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -201,7 +201,14 @@ test_chmod () {
# Unset a configuration variable, but don't fail if it doesn't exist.
test_unconfig () {
- git config --unset-all "$@"
+ config_dir=
+ if test "$1" = -C
+ then
+ shift
+ config_dir=$1
+ shift
+ fi
+ git ${config_dir:+-C "$config_dir"} config --unset-all "$@"
config_status=$?
case "$config_status" in
5) # ok, nothing to unset
@@ -213,8 +220,15 @@ test_unconfig () {
# Set git config, automatically unsetting it after the test is over.
test_config () {
- test_when_finished "test_unconfig '$1'" &&
- git config "$@"
+ config_dir=
+ if test "$1" = -C
+ then
+ shift
+ config_dir=$1
+ shift
+ fi
+ test_when_finished "test_unconfig ${config_dir:+-C '$config_dir'} '$1'" &&
+ git ${config_dir:+-C "$config_dir"} config "$@"
}
test_config_global () {
@@ -722,6 +736,11 @@ test_seq () {
# what went wrong.
test_when_finished () {
+ # We cannot detect when we are in a subshell in general, but by
+ # doing so on Bash is better than nothing (the test will
+ # silently pass on other shells).
+ test "${BASH_SUBSHELL-0}" = 0 ||
+ error "bug in test script: test_when_finished does nothing in a subshell"
test_cleanup="{ $*
} && (exit \"\$eval_ret\"); eval_ret=\$?; $test_cleanup"
}
diff --git a/t/test-lib.sh b/t/test-lib.sh
index cea6cda604..16c4d7b516 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -531,6 +531,10 @@ maybe_setup_valgrind () {
fi
}
+want_trace () {
+ test "$trace" = t && test "$verbose" = t
+}
+
# This is a separate function because some tests use
# "return" to end a test_expect_success block early
# (and we want to make sure we run any cleanup like
@@ -538,7 +542,7 @@ maybe_setup_valgrind () {
test_eval_inner_ () {
# Do not add anything extra (including LF) after '$*'
eval "
- test \"$trace\" = t && set -x
+ want_trace && set -x
$*"
}
@@ -554,7 +558,7 @@ test_eval_ () {
{
test_eval_inner_ "$@" </dev/null >&3 2>&4
test_eval_ret_=$?
- if test "$trace" = t
+ if want_trace
then
set +x
if test "$test_eval_ret_" != 0
@@ -571,12 +575,17 @@ test_run_ () {
expecting_failure=$2
if test "${GIT_TEST_CHAIN_LINT:-1}" != 0; then
+ # turn off tracing for this test-eval, as it simply creates
+ # confusing noise in the "-x" output
+ trace_tmp=$trace
+ trace=
# 117 is magic because it is unlikely to match the exit
# code of other programs
test_eval_ "(exit 117) && $1"
if test "$?" != 117; then
error "bug in the test script: broken &&-chain: $1"
fi
+ trace=$trace_tmp
fi
setup_malloc_check
diff --git a/t/test-terminal.perl b/t/test-terminal.perl
index 1fb373f25b..96b6a03e1c 100755
--- a/t/test-terminal.perl
+++ b/t/test-terminal.perl
@@ -5,15 +5,17 @@ use warnings;
use IO::Pty;
use File::Copy;
-# Run @$argv in the background with stdio redirected to $out and $err.
+# Run @$argv in the background with stdio redirected to $in, $out and $err.
sub start_child {
- my ($argv, $out, $err) = @_;
+ my ($argv, $in, $out, $err) = @_;
my $pid = fork;
if (not defined $pid) {
die "fork failed: $!"
} elsif ($pid == 0) {
+ open STDIN, "<&", $in;
open STDOUT, ">&", $out;
open STDERR, ">&", $err;
+ close $in;
close $out;
exec(@$argv) or die "cannot exec '$argv->[0]': $!"
}
@@ -49,6 +51,17 @@ sub xsendfile {
copy($in, $out, 4096) or $!{EIO} or die "cannot copy from child: $!";
}
+sub copy_stdin {
+ my ($in) = @_;
+ my $pid = fork;
+ if (!$pid) {
+ xsendfile($in, \*STDIN);
+ exit 0;
+ }
+ close($in);
+ return $pid;
+}
+
sub copy_stdio {
my ($out, $err) = @_;
my $pid = fork;
@@ -67,14 +80,25 @@ sub copy_stdio {
if ($#ARGV < 1) {
die "usage: test-terminal program args";
}
+my $master_in = new IO::Pty;
my $master_out = new IO::Pty;
my $master_err = new IO::Pty;
+$master_in->set_raw();
$master_out->set_raw();
$master_err->set_raw();
+$master_in->slave->set_raw();
$master_out->slave->set_raw();
$master_err->slave->set_raw();
-my $pid = start_child(\@ARGV, $master_out->slave, $master_err->slave);
+my $pid = start_child(\@ARGV, $master_in->slave, $master_out->slave, $master_err->slave);
+close $master_in->slave;
close $master_out->slave;
close $master_err->slave;
+my $in_pid = copy_stdin($master_in);
copy_stdio($master_out, $master_err);
-exit(finish_child($pid));
+my $ret = finish_child($pid);
+# If the child process terminates before our copy_stdin() process is able to
+# write all of its data to $master_in, the copy_stdin() process could stall.
+# Send SIGTERM to it to ensure it terminates.
+kill 'TERM', $in_pid;
+finish_child($in_pid);
+exit($ret);