git-sh-setup: Fix scripts whose PWD is a symlink into a git work-dir
I want directories of my working tree to be linked to from various
paths on my filesystem where third-party components expect them, both
in development and production environments. A build system's install
step could solve this, but I develop scripts and web pages that don't
need to be built. Git's submodule system could solve this, but we
tend to develop, branch, and test those directories all in unison, so
one big repository feels more natural. We prefer to edit and commit
on the symlinked paths, not the canonical ones, and in that setting,
"git pull" fails to find the top-level directory of the repository
while other commands work fine.
"git pull" fails because POSIX shells have a notion of current working
directory that is different from getcwd(). The shell stores this path
in PWD. As a result, "cd ../" can be interpreted differently in a
shell script than chdir("../") in a C program. The shell interprets
"../" by essentially stripping the last textual path component from
PWD, whereas C chdir() follows the ".." link in the current directory
on the filesystem. When PWD is a symlink, these are different
destinations. As a result, Git's C commands find the correct
top-level working tree, and shell scripts do not.
Changes:
* When interpreting a relative upward (../) path in cd_to_toplevel,
prepend the cwd without symlinks, given by /bin/pwd
* Add tests for cd_to_toplevel and "git pull" in a symlinked
directory that failed before this fix, plus contrasting scenarios
that already worked
Signed-off-by: Marcel M. Cary <marcel@oak.homeunix.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
16 years ago
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
test_description='pulling from symlinked subdir'
|
|
|
|
|
|
|
|
. ./test-lib.sh
|
|
|
|
|
|
|
|
if ! test_have_prereq SYMLINKS
|
|
|
|
then
|
|
|
|
skip_all='Symbolic links not supported, skipping tests.'
|
|
|
|
test_done
|
|
|
|
fi
|
|
|
|
|
git-sh-setup: Fix scripts whose PWD is a symlink into a git work-dir
I want directories of my working tree to be linked to from various
paths on my filesystem where third-party components expect them, both
in development and production environments. A build system's install
step could solve this, but I develop scripts and web pages that don't
need to be built. Git's submodule system could solve this, but we
tend to develop, branch, and test those directories all in unison, so
one big repository feels more natural. We prefer to edit and commit
on the symlinked paths, not the canonical ones, and in that setting,
"git pull" fails to find the top-level directory of the repository
while other commands work fine.
"git pull" fails because POSIX shells have a notion of current working
directory that is different from getcwd(). The shell stores this path
in PWD. As a result, "cd ../" can be interpreted differently in a
shell script than chdir("../") in a C program. The shell interprets
"../" by essentially stripping the last textual path component from
PWD, whereas C chdir() follows the ".." link in the current directory
on the filesystem. When PWD is a symlink, these are different
destinations. As a result, Git's C commands find the correct
top-level working tree, and shell scripts do not.
Changes:
* When interpreting a relative upward (../) path in cd_to_toplevel,
prepend the cwd without symlinks, given by /bin/pwd
* Add tests for cd_to_toplevel and "git pull" in a symlinked
directory that failed before this fix, plus contrasting scenarios
that already worked
Signed-off-by: Marcel M. Cary <marcel@oak.homeunix.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
16 years ago
|
|
|
# The scenario we are building:
|
|
|
|
#
|
|
|
|
# trash\ directory/
|
|
|
|
# clone-repo/
|
|
|
|
# subdir/
|
|
|
|
# bar
|
|
|
|
# subdir-link -> clone-repo/subdir/
|
|
|
|
#
|
|
|
|
# The working directory is subdir-link.
|
|
|
|
|
|
|
|
test_expect_success setup '
|
|
|
|
mkdir subdir &&
|
|
|
|
echo file >subdir/file &&
|
|
|
|
git add subdir/file &&
|
|
|
|
git commit -q -m file &&
|
|
|
|
git clone -q . clone-repo &&
|
|
|
|
ln -s clone-repo/subdir/ subdir-link &&
|
|
|
|
(
|
|
|
|
cd clone-repo &&
|
|
|
|
git config receive.denyCurrentBranch warn
|
|
|
|
) &&
|
|
|
|
git config receive.denyCurrentBranch warn
|
|
|
|
'
|
git-sh-setup: Fix scripts whose PWD is a symlink into a git work-dir
I want directories of my working tree to be linked to from various
paths on my filesystem where third-party components expect them, both
in development and production environments. A build system's install
step could solve this, but I develop scripts and web pages that don't
need to be built. Git's submodule system could solve this, but we
tend to develop, branch, and test those directories all in unison, so
one big repository feels more natural. We prefer to edit and commit
on the symlinked paths, not the canonical ones, and in that setting,
"git pull" fails to find the top-level directory of the repository
while other commands work fine.
"git pull" fails because POSIX shells have a notion of current working
directory that is different from getcwd(). The shell stores this path
in PWD. As a result, "cd ../" can be interpreted differently in a
shell script than chdir("../") in a C program. The shell interprets
"../" by essentially stripping the last textual path component from
PWD, whereas C chdir() follows the ".." link in the current directory
on the filesystem. When PWD is a symlink, these are different
destinations. As a result, Git's C commands find the correct
top-level working tree, and shell scripts do not.
Changes:
* When interpreting a relative upward (../) path in cd_to_toplevel,
prepend the cwd without symlinks, given by /bin/pwd
* Add tests for cd_to_toplevel and "git pull" in a symlinked
directory that failed before this fix, plus contrasting scenarios
that already worked
Signed-off-by: Marcel M. Cary <marcel@oak.homeunix.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
16 years ago
|
|
|
|
|
|
|
# Demonstrate that things work if we just avoid the symlink
|
|
|
|
#
|
|
|
|
test_expect_success 'pulling from real subdir' '
|
|
|
|
(
|
|
|
|
echo real >subdir/file &&
|
|
|
|
git commit -m real subdir/file &&
|
|
|
|
cd clone-repo/subdir/ &&
|
|
|
|
git pull &&
|
|
|
|
test real = $(cat file)
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
|
|
|
# From subdir-link, pulling should work as it does from
|
|
|
|
# clone-repo/subdir/.
|
|
|
|
#
|
|
|
|
# Instead, the error pull gave was:
|
|
|
|
#
|
|
|
|
# fatal: 'origin': unable to chdir or not a git archive
|
|
|
|
# fatal: The remote end hung up unexpectedly
|
|
|
|
#
|
|
|
|
# because git would find the .git/config for the "trash directory"
|
|
|
|
# repo, not for the clone-repo repo. The "trash directory" repo
|
|
|
|
# had no entry for origin. Git found the wrong .git because
|
|
|
|
# git rev-parse --show-cdup printed a path relative to
|
|
|
|
# clone-repo/subdir/, not subdir-link/. Git rev-parse --show-cdup
|
|
|
|
# used the correct .git, but when the git pull shell script did
|
|
|
|
# "cd `git rev-parse --show-cdup`", it ended up in the wrong
|
|
|
|
# directory. A POSIX shell's "cd" works a little differently
|
|
|
|
# than chdir() in C; "cd -P" is much closer to chdir().
|
|
|
|
#
|
|
|
|
test_expect_success 'pulling from symlinked subdir' '
|
|
|
|
(
|
|
|
|
echo link >subdir/file &&
|
|
|
|
git commit -m link subdir/file &&
|
|
|
|
cd subdir-link/ &&
|
|
|
|
git pull &&
|
|
|
|
test link = $(cat file)
|
|
|
|
)
|
|
|
|
'
|
|
|
|
|
|
|
|
# Prove that the remote end really is a repo, and other commands
|
|
|
|
# work fine in this context. It's just that "git pull" breaks.
|
|
|
|
#
|
|
|
|
test_expect_success 'pushing from symlinked subdir' '
|
|
|
|
(
|
|
|
|
cd subdir-link/ &&
|
|
|
|
echo push >file &&
|
|
|
|
git commit -m push ./file &&
|
|
|
|
git push
|
|
|
|
) &&
|
|
|
|
test push = $(git show HEAD:subdir/file)
|
|
|
|
'
|
|
|
|
|
|
|
|
test_done
|