* [RFC PATCH 0/2] fixing git pull from symlinked directory @ 2008-11-15 15:11 Marcel M. Cary 2008-11-15 15:11 ` [RFC PATCH 1/2] Add failing test for "git pull" in " Marcel M. Cary 2008-11-22 21:33 ` [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir Marcel M. Cary 0 siblings, 2 replies; 27+ messages in thread From: Marcel M. Cary @ 2008-11-15 15:11 UTC (permalink / raw) To: git; +Cc: Marcel M. Cary In a past message I described a problem when pulling in a directory that I arrived at by "cd"-ing to a symlink. http://article.gmane.org/gmane.comp.version-control.git/98223 I've created a unit test to illustrate the problem and compare it to "git pull" without the symlink and "git push" with the symlink, which both work. That's the first patch in this series. I think the root cause here is that a shell's "cd" and C's chdir() behave slightly different with symlinks. See the unit test comments for more details. I can make the unit test pass if I make bash's "cd" behave like chdir() by adding "-P", as in the second patch of this series, but I think that has portability issues. Any tips for addressing that? Maybe instead call realpath() on the result of "git rev-parse --show-cdup" in C before printing it? That's a substantial change as it would print /full/path/to/work-dir/ instead of just "../". Marcel M. Cary (2): Add failing test for "git pull" in symlinked directory Support shell scripts that run from symlinks into a git working dir git-sh-setup.sh | 2 +- t/t5521-pull-symlink.sh | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletions(-) create mode 100644 t/t5521-pull-symlink.sh ^ permalink raw reply [flat|nested] 27+ messages in thread
* [RFC PATCH 1/2] Add failing test for "git pull" in symlinked directory 2008-11-15 15:11 [RFC PATCH 0/2] fixing git pull from symlinked directory Marcel M. Cary @ 2008-11-15 15:11 ` Marcel M. Cary 2008-11-15 15:11 ` [RFC PATCH 2/2] Support shell scripts that run from symlinks into a git working dir Marcel M. Cary 2008-11-22 21:33 ` [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir Marcel M. Cary 1 sibling, 1 reply; 27+ messages in thread From: Marcel M. Cary @ 2008-11-15 15:11 UTC (permalink / raw) To: git; +Cc: Marcel M. Cary * Illustrate the scenario of interest and show how it breaks * Show a contrasting working "git pull" without the symlink * Show a contrasting working "git push" with the symlink Signed-off-by: Marcel M. Cary <marcel@oak.homeunix.org> --- t/t5521-pull-symlink.sh | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 67 insertions(+), 0 deletions(-) diff --git a/t/t5521-pull-symlink.sh b/t/t5521-pull-symlink.sh new file mode 100644 index 0000000..683784d --- /dev/null +++ b/t/t5521-pull-symlink.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +test_description='pulling from symlinked subdir' + +. ./test-lib.sh + +D=`pwd` + +# 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 && + touch subdir/bar && + git add subdir/bar && + git commit -m empty && + git clone . clone-repo && + # demonstrate that things work without the symlink + test_debug "cd clone-repo/subdir/ && git pull; cd ../.." && + ln -s clone-repo/subdir/ subdir-link && + cd subdir-link/ && + test_debug "set +x" +' + +# 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 +# +# bacause 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. Shell "cd" works a little different from chdir() in C. +# Bash's "cd -P" works like chdir() in C. +# +test_expect_failure 'pulling from symlinked subdir' ' + + git pull +' + +# Prove that the remote end really is a repo, and other commands +# work fine in this context. +# +test_debug " + test_expect_success 'pushing from symlinked subdir' ' + + git push + ' +" +cd "$D" + +test_done -- 1.6.0.3 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* [RFC PATCH 2/2] Support shell scripts that run from symlinks into a git working dir 2008-11-15 15:11 ` [RFC PATCH 1/2] Add failing test for "git pull" in " Marcel M. Cary @ 2008-11-15 15:11 ` Marcel M. Cary 0 siblings, 0 replies; 27+ messages in thread From: Marcel M. Cary @ 2008-11-15 15:11 UTC (permalink / raw) To: git; +Cc: Marcel M. Cary Use "cd -P" instead of just "cd" when switching to the top level of the git working directory. When working from a symlink into GIT_WORK_TREE, the shell function cd_to_toplevel will now change to GIT_WORK_TREE rather than the parent of the symlink, which may not even be the root of a git working directory. Unfortunately this solution looks non-portable. Signed-off-by: Marcel M. Cary <marcel@oak.homeunix.org> --- git-sh-setup.sh | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/git-sh-setup.sh b/git-sh-setup.sh index dbdf209..4006150 100755 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -85,7 +85,7 @@ cd_to_toplevel () { cdup=$(git rev-parse --show-cdup) if test ! -z "$cdup" then - cd "$cdup" || { + cd -P "$cdup" || { echo >&2 "Cannot chdir to $cdup, the toplevel of the working tree" exit 1 } -- 1.6.0.3 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir 2008-11-15 15:11 [RFC PATCH 0/2] fixing git pull from symlinked directory Marcel M. Cary 2008-11-15 15:11 ` [RFC PATCH 1/2] Add failing test for "git pull" in " Marcel M. Cary @ 2008-11-22 21:33 ` Marcel M. Cary 2008-11-22 21:54 ` Jakub Narebski 2008-11-25 7:30 ` Johannes Sixt 1 sibling, 2 replies; 27+ messages in thread From: Marcel M. Cary @ 2008-11-22 21:33 UTC (permalink / raw) To: gitster, git; +Cc: Marcel M. Cary * Change "git rev-parse --show-cdup" to print a full path instead of a series of "../" when it prints anything * Added a special case to support some existing scripts that rely on --show-cdup's prior behavior of printing a blank line when in the work-tree root * Add some tests for "git rev-parse --show-cdup" in existing scenarios and add a symlinked scenario that failed before this fix * Add a test for "git pull" in a symlinked directory that failed before this fix, plus constrasting already working scenarios Signed-off-by: Marcel M. Cary <marcel@oak.homeunix.org> --- I suggested use of realpath() but then realized that git seems to chdir to the work-dir before processing the "--show-cdup" option, so getcwd() is a simpler option. By changing rev-parse instead of cd_to_toplevel, the fix will help shell scripts that call rev-parse directly as well. Hopefully the change from "../" to /full/path/to/work-dir will not be too disruptive -- no tests fail at least. builtin-rev-parse.c | 25 ++++++++++++----- t/t1501-worktree.sh | 53 ++++++++++++++++++++++++++----------- t/t5521-pull-symlink.sh | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 23 deletions(-) create mode 100755 t/t5521-pull-symlink.sh diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c index 81d5a6f..9cf5f82 100644 --- a/builtin-rev-parse.c +++ b/builtin-rev-parse.c @@ -536,14 +536,25 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) printf("%s\n", work_tree); continue; } - while (pfx) { - pfx = strchr(pfx, '/'); - if (pfx) { - pfx++; - printf("../"); - } + /* + * An empty line tells some scripts they are at + * the work dir's root. For example, + * rebase --interactive. + */ + if (!prefix) { + putchar('\n'); + continue; } - putchar('\n'); + /* + * A full path is less ambiguous than ../ when + * the shell arrived at it's cwd via a symlink. + * Otherwise the shell's "cd" may choose the + * symbolic parent. + */ + static char cwd[PATH_MAX]; + if (!getcwd(cwd, PATH_MAX)) + die("unable to get current working directory"); + printf("%s\n", cwd); continue; } if (!strcmp(arg, "--git-dir")) { diff --git a/t/t1501-worktree.sh b/t/t1501-worktree.sh index f6a6f83..7e83c81 100755 --- a/t/t1501-worktree.sh +++ b/t/t1501-worktree.sh @@ -22,15 +22,35 @@ test_rev_parse() { shift [ $# -eq 0 ] && return + test_expect_success "$name: cdup" \ + "test '$1' = \"\$(git rev-parse --show-cdup)\"" + shift + [ $# -eq 0 ] && return + test_expect_success "$name: prefix" \ "test '$1' = \"\$(git rev-parse --show-prefix)\"" shift [ $# -eq 0 ] && return } +D="$(pwd)" + EMPTY_TREE=$(git write-tree) -mkdir -p work/sub/dir || exit 1 -mv .git repo.git || exit 1 +mkdir -p repo/sub/dir || exit 1 +ln -s repo/sub/dir lnk || exit 1 +mv .git repo/ || exit 1 +work="$(pwd)/repo" +cd lnk + +say "worktree is parent of symlink" +test_rev_parse 'symlink' false false true "$work" sub/dir/ +cd "$D" + + +mv repo/.git repo.git || exit 1 +mv repo work || exit 1 +rm lnk || exit 1 +work="$(pwd)/work" say "core.worktree = relative path" GIT_DIR=repo.git @@ -38,26 +58,26 @@ GIT_CONFIG="$(pwd)"/$GIT_DIR/config export GIT_DIR GIT_CONFIG unset GIT_WORK_TREE git config core.worktree ../work -test_rev_parse 'outside' false false false +test_rev_parse 'outside' false false false "$work" cd work || exit 1 GIT_DIR=../repo.git GIT_CONFIG="$(pwd)"/$GIT_DIR/config -test_rev_parse 'inside' false false true '' +test_rev_parse 'inside' false false true '' '' cd sub/dir || exit 1 GIT_DIR=../../../repo.git GIT_CONFIG="$(pwd)"/$GIT_DIR/config -test_rev_parse 'subdirectory' false false true sub/dir/ +test_rev_parse 'subdirectory' false false true "$work" sub/dir/ cd ../../.. || exit 1 say "core.worktree = absolute path" GIT_DIR=$(pwd)/repo.git GIT_CONFIG=$GIT_DIR/config git config core.worktree "$(pwd)/work" -test_rev_parse 'outside' false false false +test_rev_parse 'outside' false false false "$work" cd work || exit 1 -test_rev_parse 'inside' false false true '' +test_rev_parse 'inside' false false true '' '' cd sub/dir || exit 1 -test_rev_parse 'subdirectory' false false true sub/dir/ +test_rev_parse 'subdirectory' false false true "$work" sub/dir/ cd ../../.. || exit 1 say "GIT_WORK_TREE=relative path (override core.worktree)" @@ -66,30 +86,31 @@ GIT_CONFIG=$GIT_DIR/config git config core.worktree non-existent GIT_WORK_TREE=work export GIT_WORK_TREE -test_rev_parse 'outside' false false false +test_rev_parse 'outside' false false false "$work" cd work || exit 1 GIT_WORK_TREE=. -test_rev_parse 'inside' false false true '' +test_rev_parse 'inside' false false true '' '' cd sub/dir || exit 1 GIT_WORK_TREE=../.. -test_rev_parse 'subdirectory' false false true sub/dir/ +test_rev_parse 'subdirectory' false false true "$work" sub/dir/ cd ../../.. || exit 1 mv work repo.git/work +work="$(pwd)/repo.git/work" say "GIT_WORK_TREE=absolute path, work tree below git dir" GIT_DIR=$(pwd)/repo.git GIT_CONFIG=$GIT_DIR/config GIT_WORK_TREE=$(pwd)/repo.git/work -test_rev_parse 'outside' false false false +test_rev_parse 'outside' false false false "$work" cd repo.git || exit 1 -test_rev_parse 'in repo.git' false true false +test_rev_parse 'in repo.git' false true false "$work" cd objects || exit 1 -test_rev_parse 'in repo.git/objects' false true false +test_rev_parse 'in repo.git/objects' false true false "$work" cd ../work || exit 1 -test_rev_parse 'in repo.git/work' false true true '' +test_rev_parse 'in repo.git/work' false true true '' '' cd sub/dir || exit 1 -test_rev_parse 'in repo.git/sub/dir' false true true sub/dir/ +test_rev_parse 'in repo.git/sub/dir' false true true "$work" sub/dir/ cd ../../../.. || exit 1 test_expect_success 'repo finds its work tree' ' diff --git a/t/t5521-pull-symlink.sh b/t/t5521-pull-symlink.sh new file mode 100755 index 0000000..f18fec7 --- /dev/null +++ b/t/t5521-pull-symlink.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +test_description='pulling from symlinked subdir' + +. ./test-lib.sh + +D=`pwd` + +# 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 && + touch subdir/bar && + git add subdir/bar && + git commit -m empty && + git clone . clone-repo && + # demonstrate that things work without the symlink + test_debug "cd clone-repo/subdir/ && git pull; cd ../.." && + ln -s clone-repo/subdir/ subdir-link && + cd subdir-link/ && + test_debug "set +x" +' + +# 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. Shell "cd" works a little different from chdir() in C. +# Bash's "cd -P" works like chdir() in C. +# +test_expect_success 'pulling from symlinked subdir' ' + + git pull +' + +# Prove that the remote end really is a repo, and other commands +# work fine in this context. +# +test_debug " + test_expect_success 'pushing from symlinked subdir' ' + + git push + ' +" +cd "$D" + +test_done -- 1.6.0.3 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir 2008-11-22 21:33 ` [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir Marcel M. Cary @ 2008-11-22 21:54 ` Jakub Narebski 2008-11-23 7:10 ` Andreas Ericsson 2008-11-25 5:17 ` Marcel M. Cary 2008-11-25 7:30 ` Johannes Sixt 1 sibling, 2 replies; 27+ messages in thread From: Jakub Narebski @ 2008-11-22 21:54 UTC (permalink / raw) To: Marcel M. Cary; +Cc: gitster, git "Marcel M. Cary" <marcel@oak.homeunix.org> writes: > * Change "git rev-parse --show-cdup" to print a full path instead of > a series of "../" when it prints anything But that is contrary to the _name_ of option. It is --show-cdup, as in "show cd up". And I think your change will break a few scripts. I think you should use "git rev-parse --work-tree" for full path to working directory: --show-cdup When the command is invoked from a subdirectory, show the path of the top-level directory relative to the current directory (typically a sequence of "../", or an empty string). -- Jakub Narebski Poland ShadeHawk on #git ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir 2008-11-22 21:54 ` Jakub Narebski @ 2008-11-23 7:10 ` Andreas Ericsson 2008-11-25 5:54 ` Marcel M. Cary 2008-11-25 5:17 ` Marcel M. Cary 1 sibling, 1 reply; 27+ messages in thread From: Andreas Ericsson @ 2008-11-23 7:10 UTC (permalink / raw) To: Jakub Narebski; +Cc: Marcel M. Cary, gitster, git Jakub Narebski wrote: > "Marcel M. Cary" <marcel@oak.homeunix.org> writes: > >> * Change "git rev-parse --show-cdup" to print a full path instead of >> a series of "../" when it prints anything > > But that is contrary to the _name_ of option. It is --show-cdup, as > in "show cd up". And I think your change will break a few scripts. > > I think you should use "git rev-parse --work-tree" for full path > to working directory: > > --show-cdup > When the command is invoked from a subdirectory, show the path > of the top-level directory relative to the current directory > (typically a sequence of "../", or an empty string). > AFAIR, it was introduced to make test-builds of really large projects in really deep directories with a ton of symlinks leading to the path work a lot faster. The thing to remember about git and its UI is that it was evolved from users' actual needs. Very, very little of what is in the UI can be reworked without breaking something for someone, so it's (almost) always better to add a new option. For this, I'd suggest "--show-absolute-worktree-path" if that's what it does. Since it's an option primarily targeting scripts, I'm not too worried that it's half a mile long. -- Andreas Ericsson andreas.ericsson@op5.se OP5 AB www.op5.se Tel: +46 8-230225 Fax: +46 8-230231 ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir 2008-11-23 7:10 ` Andreas Ericsson @ 2008-11-25 5:54 ` Marcel M. Cary 2008-11-25 6:50 ` Andreas Ericsson 0 siblings, 1 reply; 27+ messages in thread From: Marcel M. Cary @ 2008-11-25 5:54 UTC (permalink / raw) To: Andreas Ericsson; +Cc: Jakub Narebski, gitster, git > AFAIR, it was introduced to make test-builds of really large projects in > really deep directories with a ton of symlinks leading to the path work a > lot faster. Andreas, I see value in keeping Git very fast. That is, after all, why I chose Git over Mercurial. Do you know where that discussion was, if was in the archives? I found these reasons to avoid absolute paths in the git archives: * paths with more components are slower to work with (in the context of add and diff, which deal with many many paths) * absolute paths may exceed PATH_MAX while relative ones didn't * getcwd() will fail if parent directories are not executable, or on some platforms, if parent directories are not readable My impression is that the performance issue is probably not significant for cd_to_toplevel since it's not in a tight inner loop, and dito for other potential callers of --show-cdup. The PATH_MAX seems to be a restriction elsewhere in the code already. Even if there were a scenario that put --show-cdup in a tight loop, I wonder whether current implementation provides much performance benefit, at least when bash is the calling language: bash seems to make the relative path absolute anyway inside the "cd" builtin. The commit (5f94c730) that introduces that code doesn't mention performance. It compares to: git rev-parse --show-prefix | sed -e 's|[^/][^/]*|..|g' I also noticed that this failure case with "--show-cdup" in a symlinked directory has come up more than once before. http://marc.info/?l=git&m=122452534912000&w=2 http://marc.info/?l=git&m=121613416212958&w=2 https://kerneltrap.org/mailarchive/git/2007/4/25/244653/thread Marcel ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir 2008-11-25 5:54 ` Marcel M. Cary @ 2008-11-25 6:50 ` Andreas Ericsson 0 siblings, 0 replies; 27+ messages in thread From: Andreas Ericsson @ 2008-11-25 6:50 UTC (permalink / raw) To: Marcel M. Cary; +Cc: Jakub Narebski, gitster, git Marcel M. Cary wrote: >> AFAIR, it was introduced to make test-builds of really large projects in >> really deep directories with a ton of symlinks leading to the path work a >> lot faster. > > Andreas, > > I see value in keeping Git very fast. That is, after all, why I chose > Git over Mercurial. Do you know where that discussion was, if was in > the archives? I found these reasons to avoid absolute paths in the git > archives: > > * paths with more components are slower to work with (in the context of > add and diff, which deal with many many paths) > * absolute paths may exceed PATH_MAX while relative ones didn't > * getcwd() will fail if parent directories are not executable, or on > some platforms, if parent directories are not readable > > My impression is that the performance issue is probably not significant > for cd_to_toplevel since it's not in a tight inner loop, and dito for > other potential callers of --show-cdup. The PATH_MAX seems to be a > restriction elsewhere in the code already. > The performance issue does not come from cd_to_toplevel itself, but from its callers. That is, if scripts start to use absolute paths from *other* tight loops, that's when we hit a problem. > Even if there were a scenario that put --show-cdup in a tight loop, I > wonder whether current implementation provides much performance benefit, > at least when bash is the calling language: bash seems to make the > relative path absolute anyway inside the "cd" builtin. > > The commit (5f94c730) that introduces that code doesn't mention > performance. It compares to: > > git rev-parse --show-prefix | sed -e 's|[^/][^/]*|..|g' > > > I also noticed that this failure case with "--show-cdup" in a symlinked > directory has come up more than once before. > http://marc.info/?l=git&m=122452534912000&w=2 > http://marc.info/?l=git&m=121613416212958&w=2 > https://kerneltrap.org/mailarchive/git/2007/4/25/244653/thread > I can imagine. However, --show-cdup has a different use too. It's nifty for printing relative paths from commands running inside a subdirectory of the repository. If you need the absolute path to the root of the repo, I'd suggest you add "--show-absolute-path" instead. -- Andreas Ericsson andreas.ericsson@op5.se OP5 AB www.op5.se Tel: +46 8-230225 Fax: +46 8-230231 ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir 2008-11-22 21:54 ` Jakub Narebski 2008-11-23 7:10 ` Andreas Ericsson @ 2008-11-25 5:17 ` Marcel M. Cary 1 sibling, 0 replies; 27+ messages in thread From: Marcel M. Cary @ 2008-11-25 5:17 UTC (permalink / raw) To: Jakub Narebski; +Cc: gitster, git > But that is contrary to the _name_ of option. It is --show-cdup, as > in "show cd up". And I think your change will break a few scripts. > > I think you should use "git rev-parse --work-tree" for full path > to working directory: > > --show-cdup > When the command is invoked from a subdirectory, show the path > of the top-level directory relative to the current directory > (typically a sequence of "../", or an empty string). Jakub, Yes, I agree, there is a risk in breaking scripts that rely on the "../" format. That's the "substantial change" I was alluding. Here's how I arrived at that choice. I considered these fixes: (a) add some shell code to cd_to_toplevel to find the canonical pwd and interpret --show-cdup output from there (b) make a new option (--work-tree would be a good name) to print the canonical work tree path, and leave --show-cdup as it is. Then change cd_to_toplevel and/or git pull to use the new option (c) change --show-cdup to print the canonical work tree path, even though it's not entirely consistent with the name of the option The main reason I avoided (a), even though that "cd" is what violated my expecations, is because I didn't want to have to re-implement code to check whether each path component is a symlink. (Now I see that "cd `/bin/pwd` might be a more concise fix.) The reason I avoided (b) is because, to make all of git work for me, I expected to have to change several calling scripts. (Now that I look, I see only three calls to --show-cdup in the git codebase to change.) Even so, third-party scripts that I might want to use in the future would not immediately be changed. Option (c) keeps the change small and isolated and makes it effective everywhere. The documentation, while perhaps in need of update given my patch, doesn't promise to always return zero or more "../". Also, there's a branch branch of the --show-cdup code (that I can't seem to exercise) that the result of get_git_work_tree(), which might not be zero or more "../". Would you suggest pursuing option (a)? I wonder whether there are languages other than shell that might suffer from the same problem of keeping an internal PWD variable of some sort, or perhaps there are shell scripts out there that call --show-cdup directly instead of calling cd_to_toplevel. Do you think it would be less likely to break existing scripts if I restrict the (c) behavior to when getenv("PWD") doesn't match the starting getcwd()? (I'm not sure yet whether that's a reliable way to detect the symlink scenario, but it seems to work with bash.) Marcel ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir 2008-11-22 21:33 ` [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir Marcel M. Cary 2008-11-22 21:54 ` Jakub Narebski @ 2008-11-25 7:30 ` Johannes Sixt 2008-11-25 16:16 ` Marcel M. Cary 1 sibling, 1 reply; 27+ messages in thread From: Johannes Sixt @ 2008-11-25 7:30 UTC (permalink / raw) To: Marcel M. Cary; +Cc: gitster, git Marcel M. Cary schrieb: > * Change "git rev-parse --show-cdup" to print a full path instead of > a series of "../" when it prints anything http://thread.gmane.org/gmane.comp.version-control.git/88557/focus=88562 I don't see that you bring in any new arguments. -- Hannes ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir 2008-11-25 7:30 ` Johannes Sixt @ 2008-11-25 16:16 ` Marcel M. Cary 2008-11-25 16:30 ` Johannes Sixt 2008-11-25 18:17 ` Junio C Hamano 0 siblings, 2 replies; 27+ messages in thread From: Marcel M. Cary @ 2008-11-25 16:16 UTC (permalink / raw) To: Johannes Sixt; +Cc: gitster, git Johannes Sixt wrote: > Marcel M. Cary schrieb: >> * Change "git rev-parse --show-cdup" to print a full path instead of >> a series of "../" when it prints anything > > http://thread.gmane.org/gmane.comp.version-control.git/88557/focus=88562 > > I don't see that you bring in any new arguments. To be clear, as mentioned here: http://thread.gmane.org/gmane.comp.version-control.git/88557/focus=88573 I'm not talking about a situation where the symlink is in the working tree pointing outwards. I'm talking about a symlink outside pointing in. And as mentioned later in that thread, the --work-tree workaround doesn't actually work. One new thing I have to add is that the reason --show-cdup prints a correct path but pull fails is because it's the *shell* who misinterprets the path. So telling git rev-parse where the work-tree is helps nothing. It already knows. http://thread.gmane.org/gmane.comp.version-control.git/88557/focus=88581 So far I've seen no response to the idea, which Yves mentions, about trying to restrict the absolute path behavior to times when bash would interpret the "../" incorrectly. Nor have I seen a response to the idea of correcting the shell's behavior in cd_to_toplevel, for example by adding a "cd `pwd`", and I don't really understand the scenario where this would be a performance concern; I think I haven't found a particular discussion that several people have referenced. Perhaps I should prepare a patch for that so I can verify that it works as I expect and so we have something more concrete to discuss? Any tips on how to follow the reference 7vk5sly3h9.fsf@assigned-by-dhcp.cox.net in the first url above? It looks to be about performance. Message-Id seems to not be indexed for searching. Marcel ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir 2008-11-25 16:16 ` Marcel M. Cary @ 2008-11-25 16:30 ` Johannes Sixt 2008-11-25 18:17 ` Junio C Hamano 1 sibling, 0 replies; 27+ messages in thread From: Johannes Sixt @ 2008-11-25 16:30 UTC (permalink / raw) To: Marcel M. Cary; +Cc: gitster, git Marcel M. Cary schrieb: > Any tips on how to follow the reference > 7vk5sly3h9.fsf@assigned-by-dhcp.cox.net in the first url above? It > looks to be about performance. Message-Id seems to not be indexed for > searching. http://mid.gmane.org/7vk5sly3h9.fsf@assigned-by-dhcp.cox.net -- Hannes ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir 2008-11-25 16:16 ` Marcel M. Cary 2008-11-25 16:30 ` Johannes Sixt @ 2008-11-25 18:17 ` Junio C Hamano 2008-12-03 5:27 ` [PATCH] git-sh-setup: Fix scripts whose PWD " Marcel M. Cary 1 sibling, 1 reply; 27+ messages in thread From: Junio C Hamano @ 2008-11-25 18:17 UTC (permalink / raw) To: Marcel M. Cary; +Cc: Johannes Sixt, git "Marcel M. Cary" <marcel@oak.homeunix.org> writes: > Nor have I seen a response to the idea of correcting the shell's > behavior in cd_to_toplevel, for example by adding a "cd `pwd`",... I think you probably could fool the shell by unsetting PWD or something silly like that (or "cd -P" which may not be supported by non POSIX shells but I suspect the ones we care about do support it). Doing a 'cd "$(pwd)"' inside cd_to_toplevel would be a less objectionable and arguably more portable workaround for the case where you have a symlink pointing into somewhere in your work tree. ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH] git-sh-setup: Fix scripts whose PWD is a symlink into a git work-dir 2008-11-25 18:17 ` Junio C Hamano @ 2008-12-03 5:27 ` Marcel M. Cary 2008-12-03 7:20 ` Junio C Hamano 0 siblings, 1 reply; 27+ messages in thread From: Marcel M. Cary @ 2008-12-03 5:27 UTC (permalink / raw) To: gitster, git; +Cc: jnareb, ae, j.sixt, Marcel M. Cary * Before interpretting an upward path (../) in cd_to_toplevel, cd to a path 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 constrasting scenarios that already worked Signed-off-by: Marcel M. Cary <marcel@oak.homeunix.org> --- I hope this patch will address concerns both about changes to existing APIs and speed of the new behavior. A few notes on implementation choices: I used /bin/pwd because of this precedent for choosing it over "cd -P" for compatibility. http://article.gmane.org/gmane.comp.version-control.git/46918 If cd_to_toplevel had concatenated $(/bin/pwd) with $cdup to avoid the separate "cd", it would require checking for $cdup being an absolute path. I wasn't sure how to check that in a way that is both portable and clearly faster than "cd", so cd_to_toplevel runs "cd" twice. I'm assuming that running an external command like expr or grep is slower than just doing the "cd". cd_to_toplevel doesn't check $PWD to see whether to do the first cd, because some shells allegedly don't update it reliably. Since cd_to_toplevel doesn't know whether it's at a symlinked PWD or not, I wrote it to treat the "cd $(/bin/pwd)" as mandatory, even when it might not actually be. So on systems without /bin/pwd, it will fail even when there are no symlinks. I thought that was better than inconsistent behavior depending on whether /bin/pwd is available. The extra "cd" will be skipped when the script is already at the top of the working tree. git-sh-setup.sh | 11 +++++++ t/t2300-cd-to-toplevel.sh | 37 +++++++++++++++++++++++++ t/t5521-pull-symlink.sh | 67 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+), 0 deletions(-) create mode 100755 t/t2300-cd-to-toplevel.sh create mode 100755 t/t5521-pull-symlink.sh diff --git a/git-sh-setup.sh b/git-sh-setup.sh index dbdf209..377700b 100755 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -85,6 +85,17 @@ cd_to_toplevel () { cdup=$(git rev-parse --show-cdup) if test ! -z "$cdup" then + # Interpret $cdup relative to the physical, not logical, cwd. + # Probably /bin/pwd is more portable than passing -P to cd or pwd. + phys="$(/bin/pwd)" || { + echo >&2 "Cannot determine the physical path to the current dir" + exit 1 + } + cd "$phys" || { + echo >&2 "Cannot chdir to the physical path to current dir: $phys" + exit 1 + } + cd "$cdup" || { echo >&2 "Cannot chdir to $cdup, the toplevel of the working tree" exit 1 diff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh new file mode 100755 index 0000000..293dc35 --- /dev/null +++ b/t/t2300-cd-to-toplevel.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +test_description='cd_to_toplevel' + +. ./test-lib.sh + +test_cd_to_toplevel () { + test_expect_success "$2" ' + ( + cd '"'$1'"' && + . git-sh-setup && + cd_to_toplevel && + [ "$(pwd -P)" = "$TOPLEVEL" ] + ) + ' +} + +TOPLEVEL="$(pwd -P)/repo" +mkdir -p repo/sub/dir +mv .git repo/ +SUBDIRECTORY_OK=1 + +test_cd_to_toplevel repo 'at physical root' + +test_cd_to_toplevel repo/sub/dir 'at physical subdir' + +ln -s repo symrepo +test_cd_to_toplevel symrepo 'at symbolic root' + +ln -s repo/sub/dir subdir-link +test_cd_to_toplevel subdir-link 'at symbolic subdir' + +cd repo +ln -s sub/dir internal-link +test_cd_to_toplevel internal-link 'at internal symbolic subdir' + +test_done diff --git a/t/t5521-pull-symlink.sh b/t/t5521-pull-symlink.sh new file mode 100755 index 0000000..f18fec7 --- /dev/null +++ b/t/t5521-pull-symlink.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +test_description='pulling from symlinked subdir' + +. ./test-lib.sh + +D=`pwd` + +# 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 && + touch subdir/bar && + git add subdir/bar && + git commit -m empty && + git clone . clone-repo && + # demonstrate that things work without the symlink + test_debug "cd clone-repo/subdir/ && git pull; cd ../.." && + ln -s clone-repo/subdir/ subdir-link && + cd subdir-link/ && + test_debug "set +x" +' + +# 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. Shell "cd" works a little different from chdir() in C. +# Bash's "cd -P" works like chdir() in C. +# +test_expect_success 'pulling from symlinked subdir' ' + + git pull +' + +# Prove that the remote end really is a repo, and other commands +# work fine in this context. +# +test_debug " + test_expect_success 'pushing from symlinked subdir' ' + + git push + ' +" +cd "$D" + +test_done -- 1.6.0.3 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH] git-sh-setup: Fix scripts whose PWD is a symlink into a git work-dir 2008-12-03 5:27 ` [PATCH] git-sh-setup: Fix scripts whose PWD " Marcel M. Cary @ 2008-12-03 7:20 ` Junio C Hamano 2008-12-10 15:04 ` [PATCH v2] " Marcel M. Cary 2009-02-07 3:24 ` [RFC PATCH] git-sh-setup: Use "cd" option, not /bin/pwd, for symlinked work tree Marcel M. Cary 0 siblings, 2 replies; 27+ messages in thread From: Junio C Hamano @ 2008-12-03 7:20 UTC (permalink / raw) To: Marcel M. Cary; +Cc: git, jnareb, ae, j.sixt "Marcel M. Cary" <marcel@oak.homeunix.org> writes: > If cd_to_toplevel had concatenated $(/bin/pwd) with $cdup to > avoid the separate "cd", it would require checking for $cdup > being an absolute path. I wasn't sure how to check that in > a way that is both portable and clearly faster than "cd", case "$v" in /*) : handle absolute path ;; *) : everything else ;; esac In all shells that support "case..esac", it is built-in. Having said that, I think it would probably be better to bite the bullet and start using "cd -P" soon after 1.6.1 goes final, and at the same time existing places that use "cd `pwd`" as a workaround if there are some. ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v2] git-sh-setup: Fix scripts whose PWD is a symlink into a git work-dir 2008-12-03 7:20 ` Junio C Hamano @ 2008-12-10 15:04 ` Marcel M. Cary 2008-12-10 20:18 ` Junio C Hamano 2009-02-07 3:24 ` [RFC PATCH] git-sh-setup: Use "cd" option, not /bin/pwd, for symlinked work tree Marcel M. Cary 1 sibling, 1 reply; 27+ messages in thread From: Marcel M. Cary @ 2008-12-10 15:04 UTC (permalink / raw) To: gitster, git; +Cc: jnareb, ae, j.sixt, Marcel M. Cary * When interpretting 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 constrasting scenarios that already worked Signed-off-by: Marcel M. Cary <marcel@oak.homeunix.org> --- Now /bin/pwd is only used when $cdup both is relative and contains a ".." component, which I think is most of the time that git didn't start out in the top-level directory. I can't seem to exercise the case that show-cdup prints something other than "../" or "", even when setting GIT_WORK_TREE in or out of the work tree. Is it premature to anticipate that show-cdup might print an arbitrary path sometime in the future, given the "if (!is_inside_work_tree())" branch of show-cdup? Or maybe it does now and I just don't see the use case. Also, the additional invocation of "cd" is now removed. git-sh-setup.sh | 23 ++++++++++++++- t/t2300-cd-to-toplevel.sh | 37 +++++++++++++++++++++++++ t/t5521-pull-symlink.sh | 67 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 2 deletions(-) create mode 100755 t/t2300-cd-to-toplevel.sh create mode 100755 t/t5521-pull-symlink.sh diff --git a/git-sh-setup.sh b/git-sh-setup.sh index dbdf209..f07d96b 100755 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -85,8 +85,27 @@ cd_to_toplevel () { cdup=$(git rev-parse --show-cdup) if test ! -z "$cdup" then - cd "$cdup" || { - echo >&2 "Cannot chdir to $cdup, the toplevel of the working tree" + case "$cdup" in + /*) + # Not quite the same as if we did "cd -P '$cdup'" when + # $cdup contains ".." after symlink path components. + # Don't fix that case at least until Git switches to + # "cd -P" across the board. + phys="$cdup" + ;; + ..|../*|*/..|*/../*) + # Interpret $cdup relative to the physical, not logical, cwd. + # Probably /bin/pwd is more portable than passing -P to cd or pwd. + phys="$(/bin/pwd)/$cdup" + ;; + *) + # There's no "..", so no need to make things absolute. + phys="$cdup" + ;; + esac + + cd "$phys" || { + echo >&2 "Cannot chdir to $phys, the toplevel of the working tree" exit 1 } fi diff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh new file mode 100755 index 0000000..293dc35 --- /dev/null +++ b/t/t2300-cd-to-toplevel.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +test_description='cd_to_toplevel' + +. ./test-lib.sh + +test_cd_to_toplevel () { + test_expect_success "$2" ' + ( + cd '"'$1'"' && + . git-sh-setup && + cd_to_toplevel && + [ "$(pwd -P)" = "$TOPLEVEL" ] + ) + ' +} + +TOPLEVEL="$(pwd -P)/repo" +mkdir -p repo/sub/dir +mv .git repo/ +SUBDIRECTORY_OK=1 + +test_cd_to_toplevel repo 'at physical root' + +test_cd_to_toplevel repo/sub/dir 'at physical subdir' + +ln -s repo symrepo +test_cd_to_toplevel symrepo 'at symbolic root' + +ln -s repo/sub/dir subdir-link +test_cd_to_toplevel subdir-link 'at symbolic subdir' + +cd repo +ln -s sub/dir internal-link +test_cd_to_toplevel internal-link 'at internal symbolic subdir' + +test_done diff --git a/t/t5521-pull-symlink.sh b/t/t5521-pull-symlink.sh new file mode 100755 index 0000000..f18fec7 --- /dev/null +++ b/t/t5521-pull-symlink.sh @@ -0,0 +1,67 @@ +#!/bin/sh + +test_description='pulling from symlinked subdir' + +. ./test-lib.sh + +D=`pwd` + +# 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 && + touch subdir/bar && + git add subdir/bar && + git commit -m empty && + git clone . clone-repo && + # demonstrate that things work without the symlink + test_debug "cd clone-repo/subdir/ && git pull; cd ../.." && + ln -s clone-repo/subdir/ subdir-link && + cd subdir-link/ && + test_debug "set +x" +' + +# 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. Shell "cd" works a little different from chdir() in C. +# Bash's "cd -P" works like chdir() in C. +# +test_expect_success 'pulling from symlinked subdir' ' + + git pull +' + +# Prove that the remote end really is a repo, and other commands +# work fine in this context. +# +test_debug " + test_expect_success 'pushing from symlinked subdir' ' + + git push + ' +" +cd "$D" + +test_done -- 1.6.0.3 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH v2] git-sh-setup: Fix scripts whose PWD is a symlink into a git work-dir 2008-12-10 15:04 ` [PATCH v2] " Marcel M. Cary @ 2008-12-10 20:18 ` Junio C Hamano 2008-12-13 20:47 ` [PATCH v3] " Marcel M. Cary 0 siblings, 1 reply; 27+ messages in thread From: Junio C Hamano @ 2008-12-10 20:18 UTC (permalink / raw) To: Marcel M. Cary; +Cc: git, jnareb, ae, j.sixt "Marcel M. Cary" <marcel@oak.homeunix.org> writes: > * When interpretting 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 constrasting > scenarios that already worked These are descriptions of changes (and good ones at that, but "constrasting?"). It however is a good idea to describe the problem the patch tries to solve *before* going into details of what you did. "If A is B, operation C tries to incorrectly access directory D; it should use directory E. This breakage is because F is confused by G..." Yes, the "Subject:" already hints about the "If A is B" part, and the second bullet point uses the word "failed" to hint that there was a breakage, but that will not be sufficient description to recall the analysis you did of the problem, when you have read the commit log message 6 months from now what the breakage was about. In order to justify the change against "Doctor if A is B, it hurts --- don't do it then" rebuttals, it further may make sense to defend why it is sometimes useful to be able to satisify the precondition that triggers the existing problem. That would come before the problem description to prepare readers with the context of the patch. > diff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh > new file mode 100755 > index 0000000..293dc35 > --- /dev/null > +++ b/t/t2300-cd-to-toplevel.sh > @@ -0,0 +1,37 @@ > +#!/bin/sh > + > +test_description='cd_to_toplevel' > + > +. ./test-lib.sh > + > +test_cd_to_toplevel () { > + test_expect_success "$2" ' > + ( > + cd '"'$1'"' && > + . git-sh-setup && > + cd_to_toplevel && > + [ "$(pwd -P)" = "$TOPLEVEL" ] > + ) > + ' > +} > + > +TOPLEVEL="$(pwd -P)/repo" Hmm. Does it make sense to assume everybody's pwd can take -P when the primary change this patch introduces carefully avoids assuming the availability of -P for "cd"? > +ln -s repo symrepo > +test_cd_to_toplevel symrepo 'at symbolic root' > + > +ln -s repo/sub/dir subdir-link > +test_cd_to_toplevel subdir-link 'at symbolic subdir' > + > +cd repo > +ln -s sub/dir internal-link > +test_cd_to_toplevel internal-link 'at internal symbolic subdir' To be very honest, although it is good that you made them work, I am still not getting why the latter two scenarios are worth supporting. The first one I am Ok with, though. > diff --git a/t/t5521-pull-symlink.sh b/t/t5521-pull-symlink.sh > new file mode 100755 > index 0000000..f18fec7 > --- /dev/null > +++ b/t/t5521-pull-symlink.sh > @@ -0,0 +1,67 @@ > +#!/bin/sh > + > +test_description='pulling from symlinked subdir' > + > +. ./test-lib.sh > + > +D=`pwd` > + > +# The scenario we are building: > +# > +# trash\ directory/ > +# clone-repo/ > +# subdir/ > +# bar > +# subdir-link -> clone-repo/subdir/ > +# > +# The working directory is subdir-link. > +# It is great to see the scenario explained like this. It makes it easier to follow what the tests are trying to do. > +test_expect_success setup ' > + > + mkdir subdir && > + touch subdir/bar && > + git add subdir/bar && > + git commit -m empty && > + git clone . clone-repo && > + # demonstrate that things work without the symlink > + test_debug "cd clone-repo/subdir/ && git pull; cd ../.." && > + ln -s clone-repo/subdir/ subdir-link && > + cd subdir-link/ && > + test_debug "set +x" > +' > + > +# 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. Shell "cd" works a little different from chdir() in C. > +# Bash's "cd -P" works like chdir() in C. This is a very good analysis. s/Bash's "cd -P"/"cd -P" in POSIX shells/, though. > +# > +test_expect_success 'pulling from symlinked subdir' ' > + > + git pull > +' I'd prefer to see each test_expect_success be able to fail independently, which would mean (1) when you chdir around, do so in a subshell, and (2) each test_expect_success assumes it begins in the same directory. In the case of these tests, I think it is just the matter of moving the last two lines from the previous test to the beginning of this test and enclosing this test in (), right? > + > +# Prove that the remote end really is a repo, and other commands > +# work fine in this context. > +# > +test_debug " > + test_expect_success 'pushing from symlinked subdir' ' > + > + git push > + ' > +" Why should this be hidden inside test_debug? ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v3] git-sh-setup: Fix scripts whose PWD is a symlink into a git work-dir 2008-12-10 20:18 ` Junio C Hamano @ 2008-12-13 20:47 ` Marcel M. Cary 2008-12-14 3:54 ` Junio C Hamano 0 siblings, 1 reply; 27+ messages in thread From: Marcel M. Cary @ 2008-12-13 20:47 UTC (permalink / raw) To: gitster, git; +Cc: jnareb, ae, j.sixt, Marcel M. Cary 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 we 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 working tree and the .git directory in it. "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 ../" in a shell script can be interpretted differently in a shell 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 interpretting 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> --- Hopefully the new commit message adequately describes the problem and motivation for solving it without getting too long-winded or bogged down in personal details. I also removed the "pwd -P" from the unit test. I originally worried that it was little like testing an algorithm by running it twice and checking the results against eachother. But I guess having the unit tests run on unusual platforms is more important. The pull-symlink test cases should now fail independently. I also moved the setup out of the test_expect_success block for symetry and since I see that other tests don't check for setup failure. There's no "set -e" or anything to catch a setup failure other than the eventual test cases push/pull not working. So is it good form in this situation to not check the setup steps for success? Or would it make sense to put them in their own 'setup' test case? Or would it be better to just "exit 1" if they fail? > > +ln -s repo symrepo > > +test_cd_to_toplevel symrepo 'at symbolic root' > > + > > +ln -s repo/sub/dir subdir-link > > +test_cd_to_toplevel subdir-link 'at symbolic subdir' > > + > > +cd repo > > +ln -s sub/dir internal-link > > +test_cd_to_toplevel internal-link 'at internal symbolic subdir' > > To be very honest, although it is good that you made them work, I am still > not getting why the latter two scenarios are worth supporting. The first > one I am Ok with, though. The middle scenario is the one I want most. I hope the first paragraph of the commit message sheds more light on the reason. The third is really just there for completeness (although there are other cases I didn't include...). Since Git supports operation below the top-level, and it supports symlinks, it seems useful to test the cooperation of those features. I wouldn't miss it much if you thought it was not interesting enough. > > + > > +# Prove that the remote end really is a repo, and other commands > > +# work fine in this context. > > +# > > +test_debug " > > + test_expect_success 'pushing from symlinked subdir' ' > > + > > + git push > > + ' > > +" > > Why should this be hidden inside test_debug? I'm not particularly trying to test "git push" or "git pull" in general here. That's also why the other "git pull" was in a test_debug. I thought it was really only useful to someone trying to understand the contents of the test file. There are other files that cover push and pull. Do you think these test cases should run all the time here? git-sh-setup.sh | 23 +++++++++++++- t/t2300-cd-to-toplevel.sh | 37 +++++++++++++++++++++++ t/t5521-pull-symlink.sh | 73 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 2 deletions(-) create mode 100755 t/t2300-cd-to-toplevel.sh create mode 100755 t/t5521-pull-symlink.sh diff --git a/git-sh-setup.sh b/git-sh-setup.sh index dbdf209..f07d96b 100755 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -85,8 +85,27 @@ cd_to_toplevel () { cdup=$(git rev-parse --show-cdup) if test ! -z "$cdup" then - cd "$cdup" || { - echo >&2 "Cannot chdir to $cdup, the toplevel of the working tree" + case "$cdup" in + /*) + # Not quite the same as if we did "cd -P '$cdup'" when + # $cdup contains ".." after symlink path components. + # Don't fix that case at least until Git switches to + # "cd -P" across the board. + phys="$cdup" + ;; + ..|../*|*/..|*/../*) + # Interpret $cdup relative to the physical, not logical, cwd. + # Probably /bin/pwd is more portable than passing -P to cd or pwd. + phys="$(/bin/pwd)/$cdup" + ;; + *) + # There's no "..", so no need to make things absolute. + phys="$cdup" + ;; + esac + + cd "$phys" || { + echo >&2 "Cannot chdir to $phys, the toplevel of the working tree" exit 1 } fi diff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh new file mode 100755 index 0000000..05854b4 --- /dev/null +++ b/t/t2300-cd-to-toplevel.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +test_description='cd_to_toplevel' + +. ./test-lib.sh + +test_cd_to_toplevel () { + test_expect_success "$2" ' + ( + cd '"'$1'"' && + . git-sh-setup && + cd_to_toplevel && + [ "$(pwd -P)" = "$TOPLEVEL" ] + ) + ' +} + +TOPLEVEL="$(/bin/pwd)/repo" +mkdir -p repo/sub/dir +mv .git repo/ +SUBDIRECTORY_OK=1 + +test_cd_to_toplevel repo 'at physical root' + +test_cd_to_toplevel repo/sub/dir 'at physical subdir' + +ln -s repo symrepo +test_cd_to_toplevel symrepo 'at symbolic root' + +ln -s repo/sub/dir subdir-link +test_cd_to_toplevel subdir-link 'at symbolic subdir' + +cd repo +ln -s sub/dir internal-link +test_cd_to_toplevel internal-link 'at internal symbolic subdir' + +test_done diff --git a/t/t5521-pull-symlink.sh b/t/t5521-pull-symlink.sh new file mode 100755 index 0000000..8869262 --- /dev/null +++ b/t/t5521-pull-symlink.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +test_description='pulling from symlinked subdir' + +. ./test-lib.sh + +# The scenario we are building: +# +# trash\ directory/ +# clone-repo/ +# subdir/ +# bar +# subdir-link -> clone-repo/subdir/ +# +# The working directory is subdir-link. + +mkdir subdir +touch subdir/bar +git add subdir/bar +git commit -m empty +git clone . clone-repo +ln -s clone-repo/subdir/ subdir-link + + +# Demonstrate that things work if we just avoid the symlink +# +test_debug " + test_expect_success 'pulling from real subdir' ' + ( + cd clone-repo/subdir/ && + git pull + ) + ' +" + +# 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' ' + ( + cd subdir-link/ && + git pull + ) +' + +# 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_debug " + test_expect_success 'pushing from symlinked subdir' ' + ( + cd subdir-link/ && + git push + ) + ' +" + +test_done -- 1.6.0.3 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH v3] git-sh-setup: Fix scripts whose PWD is a symlink into a git work-dir 2008-12-13 20:47 ` [PATCH v3] " Marcel M. Cary @ 2008-12-14 3:54 ` Junio C Hamano 2008-12-15 17:34 ` Marcel M. Cary 0 siblings, 1 reply; 27+ messages in thread From: Junio C Hamano @ 2008-12-14 3:54 UTC (permalink / raw) To: Marcel M. Cary; +Cc: git, jnareb, ae, j.sixt "Marcel M. Cary" <marcel@oak.homeunix.org> writes: > I also removed the "pwd -P" from the unit test. Hmm, really...? >> > +# Prove that the remote end really is a repo, and other commands >> > +# work fine in this context. >> > +# >> > +test_debug " >> > + test_expect_success 'pushing from symlinked subdir' ' >> > + >> > + git push >> > + ' >> > +" >> >> Why should this be hidden inside test_debug? > > I'm not particularly trying to test "git push" or "git pull" in general > here. That's also why the other "git pull" was in a test_debug. I > thought it was really only useful to someone trying to understand the > contents of the test file. There are other files that cover push and > pull. Do you think these test cases should run all the time here? I'd say so. Your supporting argument could be "See, push works just fine with this layout, but pull doesn't because it is a shell script that can be fooled, and this change is to fix the inconsistencies between them." Having these test enabled would be a good way to do so. Then it becomes irrelevant if "jump into the middle of a directory hierarchy sideways via symlink" is worth supporting or not ;-) But whether it is inside test_debug or not, the test should check not just the exit status from 'git push' but also check what happened to the receiving repository at least to make sure it is pushing to the location you are expecting it to. > diff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh > new file mode 100755 > index 0000000..05854b4 > --- /dev/null > +++ b/t/t2300-cd-to-toplevel.sh > @@ -0,0 +1,37 @@ > +#!/bin/sh > + > +test_description='cd_to_toplevel' > + > +. ./test-lib.sh > + > +test_cd_to_toplevel () { > + test_expect_success "$2" ' > + ( > + cd '"'$1'"' && > + . git-sh-setup && > + cd_to_toplevel && > + [ "$(pwd -P)" = "$TOPLEVEL" ] > + ) > + ' > +} The quoting of $1 here is a bit tricky, but I think it is good enough for directory names used in tests that use this function. ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v3] git-sh-setup: Fix scripts whose PWD is a symlink into a git work-dir 2008-12-14 3:54 ` Junio C Hamano @ 2008-12-15 17:34 ` Marcel M. Cary 2008-12-15 17:38 ` [PATCH v3] <-- really v4 Marcel M. Cary 0 siblings, 1 reply; 27+ messages in thread From: Marcel M. Cary @ 2008-12-15 17:34 UTC (permalink / raw) To: gitster, git; +Cc: jnareb, ae, j.sixt, Marcel M. Cary 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> --- > > I also removed the "pwd -P" from the unit test. > > Hmm, really...? Ouch. Removing just one occurrence won't help much, will it. > > Do you think these test cases should run all the time here? > > I'd say so. Your supporting argument could be "See, push works just > fine with this layout, but pull doesn't because it is a shell script > that can be fooled, and this change is to fix the inconsistencies > between them." Ok, removed those cases from test_debug and emphasized in the first paragraph of the commit message that other commands support this kind of "sideways jumping." > But whether it is inside test_debug or not, the test should check > not just the exit status from 'git push' but also check what > happened to the receiving repository at least to make sure it is > pushing to the location you are expecting it to. Ok, I did this by adding an additional file each time and checking the same path in the other repository. git-sh-setup.sh | 23 ++++++++++++- t/t2300-cd-to-toplevel.sh | 37 +++++++++++++++++++++ t/t5521-pull-symlink.sh | 78 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+), 2 deletions(-) create mode 100755 t/t2300-cd-to-toplevel.sh create mode 100755 t/t5521-pull-symlink.sh diff --git a/git-sh-setup.sh b/git-sh-setup.sh index dbdf209..f07d96b 100755 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -85,8 +85,27 @@ cd_to_toplevel () { cdup=$(git rev-parse --show-cdup) if test ! -z "$cdup" then - cd "$cdup" || { - echo >&2 "Cannot chdir to $cdup, the toplevel of the working tree" + case "$cdup" in + /*) + # Not quite the same as if we did "cd -P '$cdup'" when + # $cdup contains ".." after symlink path components. + # Don't fix that case at least until Git switches to + # "cd -P" across the board. + phys="$cdup" + ;; + ..|../*|*/..|*/../*) + # Interpret $cdup relative to the physical, not logical, cwd. + # Probably /bin/pwd is more portable than passing -P to cd or pwd. + phys="$(/bin/pwd)/$cdup" + ;; + *) + # There's no "..", so no need to make things absolute. + phys="$cdup" + ;; + esac + + cd "$phys" || { + echo >&2 "Cannot chdir to $phys, the toplevel of the working tree" exit 1 } fi diff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh new file mode 100755 index 0000000..beddb4e --- /dev/null +++ b/t/t2300-cd-to-toplevel.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +test_description='cd_to_toplevel' + +. ./test-lib.sh + +test_cd_to_toplevel () { + test_expect_success "$2" ' + ( + cd '"'$1'"' && + . git-sh-setup && + cd_to_toplevel && + [ "$(/bin/pwd)" = "$TOPLEVEL" ] + ) + ' +} + +TOPLEVEL="$(/bin/pwd)/repo" +mkdir -p repo/sub/dir +mv .git repo/ +SUBDIRECTORY_OK=1 + +test_cd_to_toplevel repo 'at physical root' + +test_cd_to_toplevel repo/sub/dir 'at physical subdir' + +ln -s repo symrepo +test_cd_to_toplevel symrepo 'at symbolic root' + +ln -s repo/sub/dir subdir-link +test_cd_to_toplevel subdir-link 'at symbolic subdir' + +cd repo +ln -s sub/dir internal-link +test_cd_to_toplevel internal-link 'at internal symbolic subdir' + +test_done diff --git a/t/t5521-pull-symlink.sh b/t/t5521-pull-symlink.sh new file mode 100755 index 0000000..5672b51 --- /dev/null +++ b/t/t5521-pull-symlink.sh @@ -0,0 +1,78 @@ +#!/bin/sh + +test_description='pulling from symlinked subdir' + +. ./test-lib.sh + +# The scenario we are building: +# +# trash\ directory/ +# clone-repo/ +# subdir/ +# bar +# subdir-link -> clone-repo/subdir/ +# +# The working directory is subdir-link. + +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 + + +# 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 -- 1.6.0.3 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCH v3] <-- really v4 2008-12-15 17:34 ` Marcel M. Cary @ 2008-12-15 17:38 ` Marcel M. Cary 0 siblings, 0 replies; 27+ messages in thread From: Marcel M. Cary @ 2008-12-15 17:38 UTC (permalink / raw) To: gitster, git; +Cc: jnareb, ae, j.sixt I guess I'm really on v4, sorry. Marcel ^ permalink raw reply [flat|nested] 27+ messages in thread
* [RFC PATCH] git-sh-setup: Use "cd" option, not /bin/pwd, for symlinked work tree 2008-12-03 7:20 ` Junio C Hamano 2008-12-10 15:04 ` [PATCH v2] " Marcel M. Cary @ 2009-02-07 3:24 ` Marcel M. Cary 2009-02-07 12:25 ` Johannes Schindelin 1 sibling, 1 reply; 27+ messages in thread From: Marcel M. Cary @ 2009-02-07 3:24 UTC (permalink / raw) To: git; +Cc: gitster, jnareb, ae, j.sixt, git-dev, win, benji, Marcel M. Cary In cd_to_toplevel, instead of 'cd $(unset PWD; /bin/pwd)/$path' use 'cd -P $path'. The "-P" option yields a desirable similarity to C chdir. While the "-P" option may be slightly less commonly supported than /bin/pwd, it is more concise, better tested, and less error prone. I've already added the 'unset PWD' to fix the /bin/pwd solution on BSD; there may be more edge cases out there. This still passes all the same test cases in t5521-pull-symlink.sh and t2300-cd-to-toplevel.sh, even before updating them to use 'pwd -P'. --- > ... I think it would probably be better to bite the bullet > and start using "cd -P" soon after 1.6.1 goes final, ... Here's a post-1.6.1 way to make Git shell scripts work like C programs when in symlinked directories. > ... and at the same time > existing places that use "cd `pwd`" as a workaround if there are some. I haven't found other places that use the "cd `/bin/pwd`" workaround. I also wasn't able to think of a test case that fails under the previous way and works under this new way either. Any opinions on whether this is worthwhile? It seems more standardized if less supported, odd as that seems to me. Marcel git-sh-setup.sh | 29 ++++++++--------------------- t/t2300-cd-to-toplevel.sh | 4 ++-- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/git-sh-setup.sh b/git-sh-setup.sh index 2142308..8382339 100755 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -85,27 +85,14 @@ cd_to_toplevel () { cdup=$(git rev-parse --show-cdup) if test ! -z "$cdup" then - case "$cdup" in - /*) - # Not quite the same as if we did "cd -P '$cdup'" when - # $cdup contains ".." after symlink path components. - # Don't fix that case at least until Git switches to - # "cd -P" across the board. - phys="$cdup" - ;; - ..|../*|*/..|*/../*) - # Interpret $cdup relative to the physical, not logical, cwd. - # Probably /bin/pwd is more portable than passing -P to cd or pwd. - phys="$(unset PWD; /bin/pwd)/$cdup" - ;; - *) - # There's no "..", so no need to make things absolute. - phys="$cdup" - ;; - esac - - cd "$phys" || { - echo >&2 "Cannot chdir to $phys, the toplevel of the working tree" + # The "-P" option says to follow "physical" directory + # structure instead of following symbolic links. When cdup is + # "../", this means following the ".." entry in the current + # directory instead textually removing a symlink path element + # from the PWD shell variable. The "-P" behavior is more + # consistent with the C-style chdir used by most of Git. + cd -P "$cdup" || { + echo >&2 "Cannot chdir to $cdup, the toplevel of the working tree" exit 1 } fi diff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh index e42cbfe..293dc35 100755 --- a/t/t2300-cd-to-toplevel.sh +++ b/t/t2300-cd-to-toplevel.sh @@ -10,12 +10,12 @@ test_cd_to_toplevel () { cd '"'$1'"' && . git-sh-setup && cd_to_toplevel && - [ "$(unset PWD; /bin/pwd)" = "$TOPLEVEL" ] + [ "$(pwd -P)" = "$TOPLEVEL" ] ) ' } -TOPLEVEL="$(unset PWD; /bin/pwd)/repo" +TOPLEVEL="$(pwd -P)/repo" mkdir -p repo/sub/dir mv .git repo/ SUBDIRECTORY_OK=1 -- 1.6.1 ^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [RFC PATCH] git-sh-setup: Use "cd" option, not /bin/pwd, for symlinked work tree 2009-02-07 3:24 ` [RFC PATCH] git-sh-setup: Use "cd" option, not /bin/pwd, for symlinked work tree Marcel M. Cary @ 2009-02-07 12:25 ` Johannes Schindelin 2009-02-08 18:11 ` Marcel M. Cary 0 siblings, 1 reply; 27+ messages in thread From: Johannes Schindelin @ 2009-02-07 12:25 UTC (permalink / raw) To: Marcel M. Cary; +Cc: git, gitster, jnareb, ae, j.sixt, git-dev, win, benji Hi, On Fri, 6 Feb 2009, Marcel M. Cary wrote: > While the "-P" option may be slightly less commonly supported than > /bin/pwd, Does this not suggest that your patch should at least fall back to using /bin/pwd when it was detected that "cd -P" does not work? Ciao, Dscho ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [RFC PATCH] git-sh-setup: Use "cd" option, not /bin/pwd, for symlinked work tree 2009-02-07 12:25 ` Johannes Schindelin @ 2009-02-08 18:11 ` Marcel M. Cary 2009-02-08 20:56 ` Johannes Schindelin 0 siblings, 1 reply; 27+ messages in thread From: Marcel M. Cary @ 2009-02-08 18:11 UTC (permalink / raw) To: Johannes Schindelin; +Cc: git, gitster, jnareb, ae, j.sixt, git-dev, win, benji Johannes Schindelin wrote: > On Fri, 6 Feb 2009, Marcel M. Cary wrote: >> While the "-P" option may be slightly less commonly supported than >> /bin/pwd, > > Does this not suggest that your patch should at least fall back to > using /bin/pwd when it was detected that "cd -P" does not work? Having the "cd -P" strategy fall back to /bin/pwd negates most of the value I saw in using the simpler strategy. I haven't found cases where "cd -P" is more correct. Are there other reasons to bother with "cd -P" at all? Maybe performance: "cd -P" would save a fork, which seems to make it ~10x faster. Dropping buffer caches doesn't seem to widen or narrow the gap, so I don't think the filesystem access is much different, performance-wise. But I don't expect this "cd" to be a performance bottleneck; most scripts that do something repetitive can just start off in the work tree root to avoid the issue. Falling back to /bin/pwd would help compatibility if it were easy to detect when "cd -P" failed. But since its failure is hypothetical for me at this point -- I don't know of an environment where it fails -- I'm not sure whether to expect it to fail with non-zero exit status or by silently ignoring the "-P". And to handle the cases of silently ignoring the "-P" I'd guess cd_to_toplevel would have to run /bin/pwd just to check that it ended up in the right place, which seems counterproductive to me. Do you think it would be reasonable to just assume "cd -P" will exit non-zero if "cd" doesn't understand "-P", send its stderr to /dev/null, and try again using /bin/pwd? Marcel ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [RFC PATCH] git-sh-setup: Use "cd" option, not /bin/pwd, for symlinked work tree 2009-02-08 18:11 ` Marcel M. Cary @ 2009-02-08 20:56 ` Johannes Schindelin 2009-02-11 14:44 ` Marcel M. Cary 0 siblings, 1 reply; 27+ messages in thread From: Johannes Schindelin @ 2009-02-08 20:56 UTC (permalink / raw) To: Marcel M. Cary; +Cc: git, gitster, jnareb, ae, j.sixt, git-dev, win, benji Hi, On Sun, 8 Feb 2009, Marcel M. Cary wrote: > Johannes Schindelin wrote: > > On Fri, 6 Feb 2009, Marcel M. Cary wrote: > >> While the "-P" option may be slightly less commonly supported than > >> /bin/pwd, > > > > Does this not suggest that your patch should at least fall back to > > using /bin/pwd when it was detected that "cd -P" does not work? > > Having the "cd -P" strategy fall back to /bin/pwd negates most of the > value I saw in using the simpler strategy. > > I haven't found cases where "cd -P" is more correct. Actually, it was not clear for me how much you researched the portability of "cd -P". As long as it is not proven that your patch keeps working setups working, I think you'll have to put in a bit more effort, research it, and then put the discussion into the commit message. Ciao, Dscho ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [RFC PATCH] git-sh-setup: Use "cd" option, not /bin/pwd, for symlinked work tree 2009-02-08 20:56 ` Johannes Schindelin @ 2009-02-11 14:44 ` Marcel M. Cary 2009-02-11 18:16 ` Jeff King 0 siblings, 1 reply; 27+ messages in thread From: Marcel M. Cary @ 2009-02-11 14:44 UTC (permalink / raw) To: Johannes Schindelin; +Cc: git, gitster, jnareb, ae, j.sixt, git-dev, win, benji Johannes Schindelin wrote: > On Sun, 8 Feb 2009, Marcel M. Cary wrote: >> Johannes Schindelin wrote: >>> On Fri, 6 Feb 2009, Marcel M. Cary wrote: >>>> While the "-P" option may be slightly less commonly supported than >>>> /bin/pwd, >>> Does this not suggest that your patch should at least fall back to >>> using /bin/pwd when it was detected that "cd -P" does not work? >> Having the "cd -P" strategy fall back to /bin/pwd negates most of the >> value I saw in using the simpler strategy. >> >> I haven't found cases where "cd -P" is more correct. > > Actually, it was not clear for me how much you researched the portability > of "cd -P". I have not. I've seen only that it's POSIX, is on BSD and Linux, and was suggested by Junio. > As long as it is not proven that your patch keeps working setups working, > I think you'll have to put in a bit more effort, research it, and then put > the discussion into the commit message. Actually, since I haven't heard any continued interest in following up with the suggestion to use "cd -P", I don't see much benefit myself, and there is concern about it not being compatible enough, I'm content to just table this. I agree that keeping working setups working is important, and it seems like a major project to research portability of "cd -P" on a list of platforms that I'm guessing I'd have to collect myself. Marcel ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [RFC PATCH] git-sh-setup: Use "cd" option, not /bin/pwd, for symlinked work tree 2009-02-11 14:44 ` Marcel M. Cary @ 2009-02-11 18:16 ` Jeff King 0 siblings, 0 replies; 27+ messages in thread From: Jeff King @ 2009-02-11 18:16 UTC (permalink / raw) To: Marcel M. Cary Cc: Johannes Schindelin, git, gitster, jnareb, ae, j.sixt, git-dev, win, benji On Wed, Feb 11, 2009 at 06:44:41AM -0800, Marcel M. Cary wrote: > > Actually, it was not clear for me how much you researched the portability > > of "cd -P". > > I have not. I've seen only that it's POSIX, is on BSD and Linux, and > was suggested by Junio. Even Solaris /usr/xpg4/bin/sh has it. Their /bin/sh does not, but that is not a surprise: that shell is useless and already unsupported by git. I don't know about other obscure platforms (wasn't there some guy running git on antique SCO machines or something?). I think it is nice to shoot for "more portable" in general, and I don't particularly care one way or the other about this feature. But I think we are somewhat hampered by having no clue what the supported set of platforms is. I'm pretty sure we support at least: - various recent Linux distributions - FreeBSD 6.x (maybe as far back as 4.x) - OS X - NetBSD and OpenBSD, but no idea which versions - Solaris >= 2.8 - AIX 5.3 and I suspect most of those have somebody building them regularly enough that breakages are caught. I have no idea what people are using beyond that, and how quickly they might catch a portability breakage. -Peff ^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2009-02-11 18:18 UTC | newest] Thread overview: 27+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-11-15 15:11 [RFC PATCH 0/2] fixing git pull from symlinked directory Marcel M. Cary 2008-11-15 15:11 ` [RFC PATCH 1/2] Add failing test for "git pull" in " Marcel M. Cary 2008-11-15 15:11 ` [RFC PATCH 2/2] Support shell scripts that run from symlinks into a git working dir Marcel M. Cary 2008-11-22 21:33 ` [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir Marcel M. Cary 2008-11-22 21:54 ` Jakub Narebski 2008-11-23 7:10 ` Andreas Ericsson 2008-11-25 5:54 ` Marcel M. Cary 2008-11-25 6:50 ` Andreas Ericsson 2008-11-25 5:17 ` Marcel M. Cary 2008-11-25 7:30 ` Johannes Sixt 2008-11-25 16:16 ` Marcel M. Cary 2008-11-25 16:30 ` Johannes Sixt 2008-11-25 18:17 ` Junio C Hamano 2008-12-03 5:27 ` [PATCH] git-sh-setup: Fix scripts whose PWD " Marcel M. Cary 2008-12-03 7:20 ` Junio C Hamano 2008-12-10 15:04 ` [PATCH v2] " Marcel M. Cary 2008-12-10 20:18 ` Junio C Hamano 2008-12-13 20:47 ` [PATCH v3] " Marcel M. Cary 2008-12-14 3:54 ` Junio C Hamano 2008-12-15 17:34 ` Marcel M. Cary 2008-12-15 17:38 ` [PATCH v3] <-- really v4 Marcel M. Cary 2009-02-07 3:24 ` [RFC PATCH] git-sh-setup: Use "cd" option, not /bin/pwd, for symlinked work tree Marcel M. Cary 2009-02-07 12:25 ` Johannes Schindelin 2009-02-08 18:11 ` Marcel M. Cary 2009-02-08 20:56 ` Johannes Schindelin 2009-02-11 14:44 ` Marcel M. Cary 2009-02-11 18:16 ` Jeff King
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).