mirror of
https://github.com/git/git.git
synced 2024-12-18 14:24:11 +08:00
ce83eadd9a
In 4ac9006f83
(real_path: have callers use real_pathdup and
strbuf_realpath, 2016-12-12), we changed the xstrdup(real_path())
pattern to use real_pathdup() directly.
The problem with this change is that real_path() calls
strbuf_realpath() with die_on_error = 1 while real_pathdup() calls
it with die_on_error = 0. Meaning that in cases where real_path()
causes Git to die() with an error message, real_pathdup() is silent
and returns NULL instead.
The callers, however, are ill-prepared for that change, as they expect
the return value to be non-NULL (and otherwise the function died
with an appropriate error message).
Fix this by extending real_pathdup()'s signature to accept the
die_on_error flag and simply pass it through to strbuf_realpath(),
and then adjust all callers after a careful audit whether they would
handle NULLs well.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
435 lines
10 KiB
Bash
Executable File
435 lines
10 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
test_description='test separate work tree'
|
|
. ./test-lib.sh
|
|
|
|
test_expect_success 'setup' '
|
|
EMPTY_TREE=$(git write-tree) &&
|
|
EMPTY_BLOB=$(git hash-object -t blob --stdin </dev/null) &&
|
|
CHANGED_BLOB=$(echo changed | git hash-object -t blob --stdin) &&
|
|
EMPTY_BLOB7=$(echo $EMPTY_BLOB | sed "s/\(.......\).*/\1/") &&
|
|
CHANGED_BLOB7=$(echo $CHANGED_BLOB | sed "s/\(.......\).*/\1/") &&
|
|
|
|
mkdir -p work/sub/dir &&
|
|
mkdir -p work2 &&
|
|
mv .git repo.git
|
|
'
|
|
|
|
test_expect_success 'setup: helper for testing rev-parse' '
|
|
test_rev_parse() {
|
|
echo $1 >expected.bare &&
|
|
echo $2 >expected.inside-git &&
|
|
echo $3 >expected.inside-worktree &&
|
|
if test $# -ge 4
|
|
then
|
|
echo $4 >expected.prefix
|
|
fi &&
|
|
|
|
git rev-parse --is-bare-repository >actual.bare &&
|
|
git rev-parse --is-inside-git-dir >actual.inside-git &&
|
|
git rev-parse --is-inside-work-tree >actual.inside-worktree &&
|
|
if test $# -ge 4
|
|
then
|
|
git rev-parse --show-prefix >actual.prefix
|
|
fi &&
|
|
|
|
test_cmp expected.bare actual.bare &&
|
|
test_cmp expected.inside-git actual.inside-git &&
|
|
test_cmp expected.inside-worktree actual.inside-worktree &&
|
|
if test $# -ge 4
|
|
then
|
|
# rev-parse --show-prefix should output
|
|
# a single newline when at the top of the work tree,
|
|
# but we test for that separately.
|
|
test -z "$4" && ! test -s actual.prefix ||
|
|
test_cmp expected.prefix actual.prefix
|
|
fi
|
|
}
|
|
'
|
|
|
|
test_expect_success 'setup: core.worktree = relative path' '
|
|
sane_unset GIT_WORK_TREE &&
|
|
GIT_DIR=repo.git &&
|
|
GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
|
|
export GIT_DIR GIT_CONFIG &&
|
|
git config core.worktree ../work
|
|
'
|
|
|
|
test_expect_success 'outside' '
|
|
test_rev_parse false false false
|
|
'
|
|
|
|
test_expect_success 'inside work tree' '
|
|
(
|
|
cd work &&
|
|
GIT_DIR=../repo.git &&
|
|
GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
|
|
test_rev_parse false false true ""
|
|
)
|
|
'
|
|
|
|
test_expect_success 'empty prefix is actually written out' '
|
|
echo >expected &&
|
|
(
|
|
cd work &&
|
|
GIT_DIR=../repo.git &&
|
|
GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
|
|
git rev-parse --show-prefix >../actual
|
|
) &&
|
|
test_cmp expected actual
|
|
'
|
|
|
|
test_expect_success 'subdir of work tree' '
|
|
(
|
|
cd work/sub/dir &&
|
|
GIT_DIR=../../../repo.git &&
|
|
GIT_CONFIG="$(pwd)"/$GIT_DIR/config &&
|
|
test_rev_parse false false true sub/dir/
|
|
)
|
|
'
|
|
|
|
test_expect_success 'setup: core.worktree = absolute path' '
|
|
sane_unset GIT_WORK_TREE &&
|
|
GIT_DIR=$(pwd)/repo.git &&
|
|
GIT_CONFIG=$GIT_DIR/config &&
|
|
export GIT_DIR GIT_CONFIG &&
|
|
git config core.worktree "$(pwd)/work"
|
|
'
|
|
|
|
test_expect_success 'outside' '
|
|
test_rev_parse false false false &&
|
|
(
|
|
cd work2 &&
|
|
test_rev_parse false false false
|
|
)
|
|
'
|
|
|
|
test_expect_success 'inside work tree' '
|
|
(
|
|
cd work &&
|
|
test_rev_parse false false true ""
|
|
)
|
|
'
|
|
|
|
test_expect_success 'subdir of work tree' '
|
|
(
|
|
cd work/sub/dir &&
|
|
test_rev_parse false false true sub/dir/
|
|
)
|
|
'
|
|
|
|
test_expect_success 'setup: GIT_WORK_TREE=relative (override core.worktree)' '
|
|
GIT_DIR=$(pwd)/repo.git &&
|
|
GIT_CONFIG=$GIT_DIR/config &&
|
|
git config core.worktree non-existent &&
|
|
GIT_WORK_TREE=work &&
|
|
export GIT_DIR GIT_CONFIG GIT_WORK_TREE
|
|
'
|
|
|
|
test_expect_success 'outside' '
|
|
test_rev_parse false false false &&
|
|
(
|
|
cd work2 &&
|
|
test_rev_parse false false false
|
|
)
|
|
'
|
|
|
|
test_expect_success 'inside work tree' '
|
|
(
|
|
cd work &&
|
|
GIT_WORK_TREE=. &&
|
|
test_rev_parse false false true ""
|
|
)
|
|
'
|
|
|
|
test_expect_success 'subdir of work tree' '
|
|
(
|
|
cd work/sub/dir &&
|
|
GIT_WORK_TREE=../.. &&
|
|
test_rev_parse false false true sub/dir/
|
|
)
|
|
'
|
|
|
|
test_expect_success 'setup: GIT_WORK_TREE=absolute, below git dir' '
|
|
mv work repo.git/work &&
|
|
mv work2 repo.git/work2 &&
|
|
GIT_DIR=$(pwd)/repo.git &&
|
|
GIT_CONFIG=$GIT_DIR/config &&
|
|
GIT_WORK_TREE=$(pwd)/repo.git/work &&
|
|
export GIT_DIR GIT_CONFIG GIT_WORK_TREE
|
|
'
|
|
|
|
test_expect_success 'outside' '
|
|
echo outside &&
|
|
test_rev_parse false false false
|
|
'
|
|
|
|
test_expect_success 'in repo.git' '
|
|
(
|
|
cd repo.git &&
|
|
test_rev_parse false true false
|
|
) &&
|
|
(
|
|
cd repo.git/objects &&
|
|
test_rev_parse false true false
|
|
) &&
|
|
(
|
|
cd repo.git/work2 &&
|
|
test_rev_parse false true false
|
|
)
|
|
'
|
|
|
|
test_expect_success 'inside work tree' '
|
|
(
|
|
cd repo.git/work &&
|
|
test_rev_parse false true true ""
|
|
)
|
|
'
|
|
|
|
test_expect_success 'subdir of work tree' '
|
|
(
|
|
cd repo.git/work/sub/dir &&
|
|
test_rev_parse false true true sub/dir/
|
|
)
|
|
'
|
|
|
|
test_expect_success 'find work tree from repo' '
|
|
echo sub/dir/untracked >expected &&
|
|
cat <<-\EOF >repo.git/work/.gitignore &&
|
|
expected.*
|
|
actual.*
|
|
.gitignore
|
|
EOF
|
|
>repo.git/work/sub/dir/untracked &&
|
|
(
|
|
cd repo.git &&
|
|
git ls-files --others --exclude-standard >../actual
|
|
) &&
|
|
test_cmp expected actual
|
|
'
|
|
|
|
test_expect_success 'find work tree from work tree' '
|
|
echo sub/dir/tracked >expected &&
|
|
>repo.git/work/sub/dir/tracked &&
|
|
(
|
|
cd repo.git/work/sub/dir &&
|
|
git --git-dir=../../.. add tracked
|
|
) &&
|
|
(
|
|
cd repo.git &&
|
|
git ls-files >../actual
|
|
) &&
|
|
test_cmp expected actual
|
|
'
|
|
|
|
test_expect_success '_gently() groks relative GIT_DIR & GIT_WORK_TREE' '
|
|
(
|
|
cd repo.git/work/sub/dir &&
|
|
GIT_DIR=../../.. &&
|
|
GIT_WORK_TREE=../.. &&
|
|
GIT_PAGER= &&
|
|
export GIT_DIR GIT_WORK_TREE GIT_PAGER &&
|
|
|
|
git diff --exit-code tracked &&
|
|
echo changed >tracked &&
|
|
test_must_fail git diff --exit-code tracked
|
|
)
|
|
'
|
|
|
|
test_expect_success 'diff-index respects work tree under .git dir' '
|
|
cat >diff-index-cached.expected <<-EOF &&
|
|
:000000 100644 $_z40 $EMPTY_BLOB A sub/dir/tracked
|
|
EOF
|
|
cat >diff-index.expected <<-EOF &&
|
|
:000000 100644 $_z40 $_z40 A sub/dir/tracked
|
|
EOF
|
|
|
|
(
|
|
GIT_DIR=repo.git &&
|
|
GIT_WORK_TREE=repo.git/work &&
|
|
export GIT_DIR GIT_WORK_TREE &&
|
|
git diff-index $EMPTY_TREE >diff-index.actual &&
|
|
git diff-index --cached $EMPTY_TREE >diff-index-cached.actual
|
|
) &&
|
|
test_cmp diff-index.expected diff-index.actual &&
|
|
test_cmp diff-index-cached.expected diff-index-cached.actual
|
|
'
|
|
|
|
test_expect_success 'diff-files respects work tree under .git dir' '
|
|
cat >diff-files.expected <<-EOF &&
|
|
:100644 100644 $EMPTY_BLOB $_z40 M sub/dir/tracked
|
|
EOF
|
|
|
|
(
|
|
GIT_DIR=repo.git &&
|
|
GIT_WORK_TREE=repo.git/work &&
|
|
export GIT_DIR GIT_WORK_TREE &&
|
|
git diff-files >diff-files.actual
|
|
) &&
|
|
test_cmp diff-files.expected diff-files.actual
|
|
'
|
|
|
|
test_expect_success 'git diff respects work tree under .git dir' '
|
|
cat >diff-TREE.expected <<-EOF &&
|
|
diff --git a/sub/dir/tracked b/sub/dir/tracked
|
|
new file mode 100644
|
|
index 0000000..$CHANGED_BLOB7
|
|
--- /dev/null
|
|
+++ b/sub/dir/tracked
|
|
@@ -0,0 +1 @@
|
|
+changed
|
|
EOF
|
|
cat >diff-TREE-cached.expected <<-EOF &&
|
|
diff --git a/sub/dir/tracked b/sub/dir/tracked
|
|
new file mode 100644
|
|
index 0000000..$EMPTY_BLOB7
|
|
EOF
|
|
cat >diff-FILES.expected <<-EOF &&
|
|
diff --git a/sub/dir/tracked b/sub/dir/tracked
|
|
index $EMPTY_BLOB7..$CHANGED_BLOB7 100644
|
|
--- a/sub/dir/tracked
|
|
+++ b/sub/dir/tracked
|
|
@@ -0,0 +1 @@
|
|
+changed
|
|
EOF
|
|
|
|
(
|
|
GIT_DIR=repo.git &&
|
|
GIT_WORK_TREE=repo.git/work &&
|
|
export GIT_DIR GIT_WORK_TREE &&
|
|
git diff $EMPTY_TREE >diff-TREE.actual &&
|
|
git diff --cached $EMPTY_TREE >diff-TREE-cached.actual &&
|
|
git diff >diff-FILES.actual
|
|
) &&
|
|
test_cmp diff-TREE.expected diff-TREE.actual &&
|
|
test_cmp diff-TREE-cached.expected diff-TREE-cached.actual &&
|
|
test_cmp diff-FILES.expected diff-FILES.actual
|
|
'
|
|
|
|
test_expect_success 'git grep' '
|
|
echo dir/tracked >expected.grep &&
|
|
(
|
|
cd repo.git/work/sub &&
|
|
GIT_DIR=../.. &&
|
|
GIT_WORK_TREE=.. &&
|
|
export GIT_DIR GIT_WORK_TREE &&
|
|
git grep -l changed >../../../actual.grep
|
|
) &&
|
|
test_cmp expected.grep actual.grep
|
|
'
|
|
|
|
test_expect_success 'git commit' '
|
|
(
|
|
cd repo.git &&
|
|
GIT_DIR=. GIT_WORK_TREE=work git commit -a -m done
|
|
)
|
|
'
|
|
|
|
test_expect_success 'absolute pathspec should fail gracefully' '
|
|
(
|
|
cd repo.git &&
|
|
test_might_fail git config --unset core.worktree &&
|
|
test_must_fail git log HEAD -- /home
|
|
)
|
|
'
|
|
|
|
test_expect_success 'make_relative_path handles double slashes in GIT_DIR' '
|
|
>dummy_file &&
|
|
echo git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file &&
|
|
git --git-dir="$(pwd)//repo.git" --work-tree="$(pwd)" add dummy_file
|
|
'
|
|
|
|
test_expect_success 'relative $GIT_WORK_TREE and git subprocesses' '
|
|
GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work \
|
|
test-subprocess --setup-work-tree rev-parse --show-toplevel >actual &&
|
|
echo "$(pwd)/repo.git/work" >expected &&
|
|
test_cmp expected actual
|
|
'
|
|
|
|
test_expect_success 'Multi-worktree setup' '
|
|
mkdir work &&
|
|
mkdir -p repo.git/repos/foo &&
|
|
cp repo.git/HEAD repo.git/index repo.git/repos/foo &&
|
|
test_might_fail cp repo.git/sharedindex.* repo.git/repos/foo &&
|
|
sane_unset GIT_DIR GIT_CONFIG GIT_WORK_TREE
|
|
'
|
|
|
|
test_expect_success 'GIT_DIR set (1)' '
|
|
echo "gitdir: repo.git/repos/foo" >gitfile &&
|
|
echo ../.. >repo.git/repos/foo/commondir &&
|
|
(
|
|
cd work &&
|
|
GIT_DIR=../gitfile git rev-parse --git-common-dir >actual &&
|
|
test-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
|
|
test_cmp expect actual
|
|
)
|
|
'
|
|
|
|
test_expect_success 'GIT_DIR set (2)' '
|
|
echo "gitdir: repo.git/repos/foo" >gitfile &&
|
|
echo "$(pwd)/repo.git" >repo.git/repos/foo/commondir &&
|
|
(
|
|
cd work &&
|
|
GIT_DIR=../gitfile git rev-parse --git-common-dir >actual &&
|
|
test-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
|
|
test_cmp expect actual
|
|
)
|
|
'
|
|
|
|
test_expect_success 'Auto discovery' '
|
|
echo "gitdir: repo.git/repos/foo" >.git &&
|
|
echo ../.. >repo.git/repos/foo/commondir &&
|
|
(
|
|
cd work &&
|
|
git rev-parse --git-common-dir >actual &&
|
|
test-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
|
|
test_cmp expect actual &&
|
|
echo haha >data1 &&
|
|
git add data1 &&
|
|
git ls-files --full-name :/ | grep data1 >actual &&
|
|
echo work/data1 >expect &&
|
|
test_cmp expect actual
|
|
)
|
|
'
|
|
|
|
test_expect_success '$GIT_DIR/common overrides core.worktree' '
|
|
mkdir elsewhere &&
|
|
git --git-dir=repo.git config core.worktree "$TRASH_DIRECTORY/elsewhere" &&
|
|
echo "gitdir: repo.git/repos/foo" >.git &&
|
|
echo ../.. >repo.git/repos/foo/commondir &&
|
|
(
|
|
cd work &&
|
|
git rev-parse --git-common-dir >actual &&
|
|
test-path-utils real_path "$TRASH_DIRECTORY/repo.git" >expect &&
|
|
test_cmp expect actual &&
|
|
echo haha >data2 &&
|
|
git add data2 &&
|
|
git ls-files --full-name :/ | grep data2 >actual &&
|
|
echo work/data2 >expect &&
|
|
test_cmp expect actual
|
|
)
|
|
'
|
|
|
|
test_expect_success '$GIT_WORK_TREE overrides $GIT_DIR/common' '
|
|
echo "gitdir: repo.git/repos/foo" >.git &&
|
|
echo ../.. >repo.git/repos/foo/commondir &&
|
|
(
|
|
cd work &&
|
|
echo haha >data3 &&
|
|
git --git-dir=../.git --work-tree=. add data3 &&
|
|
git ls-files --full-name -- :/ | grep data3 >actual &&
|
|
echo data3 >expect &&
|
|
test_cmp expect actual
|
|
)
|
|
'
|
|
|
|
test_expect_success 'error out gracefully on invalid $GIT_WORK_TREE' '
|
|
(
|
|
GIT_WORK_TREE=/.invalid/work/tree &&
|
|
export GIT_WORK_TREE &&
|
|
test_expect_code 128 git rev-parse
|
|
)
|
|
'
|
|
|
|
test_done
|