{"thread":{"id":"16339","subject":"[RFC PATCH 0/2] fixing git pull from symlinked directory","startedAt":"2008-11-15T15:11:33Z","lastAt":"2009-02-11T18:16:53Z","messageCount":27,"participants":["Marcel M. Cary","Jakub Narebski","Andreas Ericsson","Johannes Sixt","Junio C Hamano","Johannes Schindelin","Jeff King"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"95883","messageId":"cover.1226759762.git.marcel@oak.homeunix.org","threadId":"16339","inReplyTo":null,"subject":"[RFC PATCH 0/2] fixing git pull from symlinked directory","fromName":"Marcel M. Cary","fromEmail":"marcel@oak.homeunix.org","sentAt":"2008-11-15T15:11:33Z","receivedAt":"2008-11-15T15:11:33Z","isPatch":true,"sender":{"key":"marcel@oak.homeunix.org","avatar":"https://gravatar.com/avatar/2bb524e4f383167b7e256bb93256c88353748d9873c34cde0fd461f1165baa0f?d=mp&s=160"},"body":"In a past message I described a problem when pulling in a\ndirectory that I arrived at by \"cd\"-ing to a symlink.\n\nhttp://article.gmane.org/gmane.comp.version-control.git/98223\n\nI've created a unit test to illustrate the problem and\ncompare it to \"git pull\" without the symlink and \"git push\"\nwith the symlink, which both work.  That's the first patch\nin this series.\n\nI think the root cause here is that a shell's \"cd\" and C's\nchdir() behave slightly different with symlinks.  See the unit\ntest comments for more details.\n\nI can make the unit test pass if I make bash's \"cd\" behave\nlike chdir() by adding \"-P\", as in the second patch of this\nseries, but I think that has portability issues.  Any tips\nfor addressing that?  Maybe instead call realpath() on the\nresult of \"git rev-parse --show-cdup\" in C before printing\nit?  That's a substantial change as it would print\n/full/path/to/work-dir/ instead of just \"../\".\n\nMarcel M. Cary (2):\n  Add failing test for \"git pull\" in symlinked directory\n  Support shell scripts that run from symlinks into a git working dir\n\n git-sh-setup.sh         |    2 +-\n t/t5521-pull-symlink.sh |   67 +++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 68 insertions(+), 1 deletions(-)\n create mode 100644 t/t5521-pull-symlink.sh\n"},{"id":"95884","messageId":"096bfa3393a6c5ccaa550ae6363e7fcfc90867d1.1226759762.git.marcel@oak.homeunix.org","threadId":"16339","inReplyTo":"cover.1226759762.git.marcel@oak.homeunix.org","subject":"[RFC PATCH 1/2] Add failing test for \"git pull\" in symlinked directory","fromName":"Marcel M. Cary","fromEmail":"marcel@oak.homeunix.org","sentAt":"2008-11-15T15:11:34Z","receivedAt":"2008-11-15T15:11:34Z","isPatch":true,"sender":{"key":"marcel@oak.homeunix.org","avatar":"https://gravatar.com/avatar/2bb524e4f383167b7e256bb93256c88353748d9873c34cde0fd461f1165baa0f?d=mp&s=160"},"body":"* Illustrate the scenario of interest and show how it breaks\n* Show a contrasting working \"git pull\" without the symlink\n* Show a contrasting working \"git push\" with the symlink\n\nSigned-off-by: Marcel M. Cary <marcel@oak.homeunix.org>\n---\n t/t5521-pull-symlink.sh |   67 +++++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 67 insertions(+), 0 deletions(-)\n\ndiff --git a/t/t5521-pull-symlink.sh b/t/t5521-pull-symlink.sh\nnew file mode 100644\nindex 0000000..683784d\n--- /dev/null\n+++ b/t/t5521-pull-symlink.sh\n@@ -0,0 +1,67 @@\n+#!/bin/sh\n+\n+test_description='pulling from symlinked subdir'\n+\n+. ./test-lib.sh\n+\n+D=`pwd`\n+\n+# The scenario we are building:\n+#\n+#   trash\\ directory/\n+#     clone-repo/\n+#       subdir/\n+#         bar\n+#     subdir-link -> clone-repo/subdir/\n+#\n+# The working directory is subdir-link.\n+#\n+test_expect_success setup '\n+\n+    mkdir subdir &&\n+    touch subdir/bar &&\n+    git add subdir/bar &&\n+    git commit -m empty &&\n+    git clone . clone-repo &&\n+    # demonstrate that things work without the symlink\n+    test_debug \"cd clone-repo/subdir/ && git pull; cd ../..\" &&\n+    ln -s clone-repo/subdir/ subdir-link &&\n+    cd subdir-link/ &&\n+    test_debug \"set +x\"\n+'\n+\n+# From subdir-link, pulling should work as it does from\n+# clone-repo/subdir/.\n+#\n+# Instead, the error pull gave was:\n+#\n+#   fatal: 'origin': unable to chdir or not a git archive\n+#   fatal: The remote end hung up unexpectedly\n+#\n+# bacause git would find the .git/config for the trash\\ directory\n+# repo, not for the clone-repo repo.  The trash\\ directory repo\n+# had no entry for origin.  Git found the wrong .git because\n+# git rev-parse --show-cdup printed a path relative to\n+# clone-repo/subdir/, not subdir-link/.  Git rev-parse --show-cdup\n+# used the correct .git, but when the git pull shell script did\n+# \"cd `git rev-parse --show-cdup`\", it ended up in the wrong\n+# directory.  Shell \"cd\" works a little different from chdir() in C.\n+# Bash's \"cd -P\" works like chdir() in C.\n+#\n+test_expect_failure 'pulling from symlinked subdir' '\n+\n+    git pull\n+'\n+\n+# Prove that the remote end really is a repo, and other commands\n+# work fine in this context.\n+#\n+test_debug \"\n+    test_expect_success 'pushing from symlinked subdir' '\n+\n+        git push\n+    '\n+\"\n+cd \"$D\"\n+\n+test_done\n-- \n1.6.0.3\n"},{"id":"95885","messageId":"fff3a66296d7150a3ce07d39032bce668aa3ebd5.1226759762.git.marcel@oak.homeunix.org","threadId":"16339","inReplyTo":"096bfa3393a6c5ccaa550ae6363e7fcfc90867d1.1226759762.git.marcel@oak.homeunix.org","subject":"[RFC PATCH 2/2] Support shell scripts that run from symlinks into a git working dir","fromName":"Marcel M. Cary","fromEmail":"marcel@oak.homeunix.org","sentAt":"2008-11-15T15:11:35Z","receivedAt":"2008-11-15T15:11:35Z","isPatch":true,"sender":{"key":"marcel@oak.homeunix.org","avatar":"https://gravatar.com/avatar/2bb524e4f383167b7e256bb93256c88353748d9873c34cde0fd461f1165baa0f?d=mp&s=160"},"body":"Use \"cd -P\" instead of just \"cd\" when switching to the top level\nof the git working directory.  When working from a symlink\ninto GIT_WORK_TREE, the shell function cd_to_toplevel will now\nchange to GIT_WORK_TREE rather than the parent of the symlink,\nwhich may not even be the root of a git working directory.\n\nUnfortunately this solution looks non-portable.\n\nSigned-off-by: Marcel M. Cary <marcel@oak.homeunix.org>\n---\n git-sh-setup.sh |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/git-sh-setup.sh b/git-sh-setup.sh\nindex dbdf209..4006150 100755\n--- a/git-sh-setup.sh\n+++ b/git-sh-setup.sh\n@@ -85,7 +85,7 @@ cd_to_toplevel () {\n \tcdup=$(git rev-parse --show-cdup)\n \tif test ! -z \"$cdup\"\n \tthen\n-\t\tcd \"$cdup\" || {\n+\t\tcd -P \"$cdup\" || {\n \t\t\techo >&2 \"Cannot chdir to $cdup, the toplevel of the working tree\"\n \t\t\texit 1\n \t\t}\n-- \n1.6.0.3\n"},{"id":"96368","messageId":"1227389614-10946-1-git-send-email-marcel@oak.homeunix.org","threadId":"16339","inReplyTo":"cover.1226759762.git.marcel@oak.homeunix.org","subject":"[PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir","fromName":"Marcel M. Cary","fromEmail":"marcel@oak.homeunix.org","sentAt":"2008-11-22T21:33:34Z","receivedAt":"2008-11-22T21:33:34Z","isPatch":true,"sender":{"key":"marcel@oak.homeunix.org","avatar":"https://gravatar.com/avatar/2bb524e4f383167b7e256bb93256c88353748d9873c34cde0fd461f1165baa0f?d=mp&s=160"},"body":"* Change \"git rev-parse --show-cdup\" to print a full path instead of\n  a series of \"../\" when it prints anything\n* Added a special case to support some existing scripts that rely\n  on --show-cdup's prior behavior of printing a blank line when in\n  the work-tree root\n* Add some tests for \"git rev-parse --show-cdup\" in existing scenarios\n  and add a symlinked scenario that failed before this fix\n* Add a test for \"git pull\" in a symlinked directory that failed\n  before this fix, plus constrasting already working scenarios\n\nSigned-off-by: Marcel M. Cary <marcel@oak.homeunix.org>\n---\n\nI suggested use of realpath() but then realized that git seems to\nchdir to the work-dir before processing the \"--show-cdup\" option,\nso getcwd() is a simpler option.  \n\nBy changing rev-parse instead of cd_to_toplevel, the fix will\nhelp shell scripts that call rev-parse directly as well.  Hopefully\nthe change from \"../\" to /full/path/to/work-dir will not be too\ndisruptive -- no tests fail at least.\n\n builtin-rev-parse.c     |   25 ++++++++++++-----\n t/t1501-worktree.sh     |   53 ++++++++++++++++++++++++++-----------\n t/t5521-pull-symlink.sh |   67 +++++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 122 insertions(+), 23 deletions(-)\n create mode 100755 t/t5521-pull-symlink.sh\n\ndiff --git a/builtin-rev-parse.c b/builtin-rev-parse.c\nindex 81d5a6f..9cf5f82 100644\n--- a/builtin-rev-parse.c\n+++ b/builtin-rev-parse.c\n@@ -536,14 +536,25 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t\t\t\tprintf(\"%s\\n\", work_tree);\n \t\t\t\t\tcontinue;\n \t\t\t\t}\n-\t\t\t\twhile (pfx) {\n-\t\t\t\t\tpfx = strchr(pfx, '/');\n-\t\t\t\t\tif (pfx) {\n-\t\t\t\t\t\tpfx++;\n-\t\t\t\t\t\tprintf(\"../\");\n-\t\t\t\t\t}\n+\t\t\t\t/*\n+\t\t\t\t * An empty line tells some scripts they are at\n+\t\t\t\t * the work dir's root.  For example,\n+\t\t\t\t * rebase --interactive.\n+\t\t\t\t */\n+\t\t\t\tif (!prefix) {\n+\t\t\t\t\tputchar('\\n');\n+\t\t\t\t\tcontinue;\n \t\t\t\t}\n-\t\t\t\tputchar('\\n');\n+\t\t\t\t/*\n+\t\t\t\t * A full path is less ambiguous than ../ when\n+\t\t\t\t * the shell arrived at it's cwd via a symlink.\n+\t\t\t\t * Otherwise the shell's \"cd\" may choose the\n+\t\t\t\t * symbolic parent.\n+\t\t\t\t */\n+\t\t\t\tstatic char cwd[PATH_MAX];\n+\t\t\t\tif (!getcwd(cwd, PATH_MAX))\n+\t\t\t\t\tdie(\"unable to get current working directory\");\n+\t\t\t\tprintf(\"%s\\n\", cwd);\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"--git-dir\")) {\ndiff --git a/t/t1501-worktree.sh b/t/t1501-worktree.sh\nindex f6a6f83..7e83c81 100755\n--- a/t/t1501-worktree.sh\n+++ b/t/t1501-worktree.sh\n@@ -22,15 +22,35 @@ test_rev_parse() {\n \tshift\n \t[ $# -eq 0 ] && return\n \n+\ttest_expect_success \"$name: cdup\" \\\n+\t\"test '$1' = \\\"\\$(git rev-parse --show-cdup)\\\"\"\n+\tshift\n+\t[ $# -eq 0 ] && return\n+\n \ttest_expect_success \"$name: prefix\" \\\n \t\"test '$1' = \\\"\\$(git rev-parse --show-prefix)\\\"\"\n \tshift\n \t[ $# -eq 0 ] && return\n }\n \n+D=\"$(pwd)\"\n+\n EMPTY_TREE=$(git write-tree)\n-mkdir -p work/sub/dir || exit 1\n-mv .git repo.git || exit 1\n+mkdir -p repo/sub/dir || exit 1\n+ln -s repo/sub/dir lnk || exit 1\n+mv .git repo/ || exit 1\n+work=\"$(pwd)/repo\"\n+cd lnk\n+\n+say \"worktree is parent of symlink\"\n+test_rev_parse 'symlink'      false false true \"$work\" sub/dir/\n+cd \"$D\"\n+\n+\n+mv repo/.git repo.git || exit 1\n+mv repo work || exit 1\n+rm lnk || exit 1\n+work=\"$(pwd)/work\"\n \n say \"core.worktree = relative path\"\n GIT_DIR=repo.git\n@@ -38,26 +58,26 @@ GIT_CONFIG=\"$(pwd)\"/$GIT_DIR/config\n export GIT_DIR GIT_CONFIG\n unset GIT_WORK_TREE\n git config core.worktree ../work\n-test_rev_parse 'outside'      false false false\n+test_rev_parse 'outside'      false false false \"$work\"\n cd work || exit 1\n GIT_DIR=../repo.git\n GIT_CONFIG=\"$(pwd)\"/$GIT_DIR/config\n-test_rev_parse 'inside'       false false true ''\n+test_rev_parse 'inside'       false false true '' ''\n cd sub/dir || exit 1\n GIT_DIR=../../../repo.git\n GIT_CONFIG=\"$(pwd)\"/$GIT_DIR/config\n-test_rev_parse 'subdirectory' false false true sub/dir/\n+test_rev_parse 'subdirectory' false false true \"$work\" sub/dir/\n cd ../../.. || exit 1\n \n say \"core.worktree = absolute path\"\n GIT_DIR=$(pwd)/repo.git\n GIT_CONFIG=$GIT_DIR/config\n git config core.worktree \"$(pwd)/work\"\n-test_rev_parse 'outside'      false false false\n+test_rev_parse 'outside'      false false false \"$work\"\n cd work || exit 1\n-test_rev_parse 'inside'       false false true ''\n+test_rev_parse 'inside'       false false true '' ''\n cd sub/dir || exit 1\n-test_rev_parse 'subdirectory' false false true sub/dir/\n+test_rev_parse 'subdirectory' false false true \"$work\" sub/dir/\n cd ../../.. || exit 1\n \n say \"GIT_WORK_TREE=relative path (override core.worktree)\"\n@@ -66,30 +86,31 @@ GIT_CONFIG=$GIT_DIR/config\n git config core.worktree non-existent\n GIT_WORK_TREE=work\n export GIT_WORK_TREE\n-test_rev_parse 'outside'      false false false\n+test_rev_parse 'outside'      false false false \"$work\"\n cd work || exit 1\n GIT_WORK_TREE=.\n-test_rev_parse 'inside'       false false true ''\n+test_rev_parse 'inside'       false false true '' ''\n cd sub/dir || exit 1\n GIT_WORK_TREE=../..\n-test_rev_parse 'subdirectory' false false true sub/dir/\n+test_rev_parse 'subdirectory' false false true \"$work\" sub/dir/\n cd ../../.. || exit 1\n \n mv work repo.git/work\n+work=\"$(pwd)/repo.git/work\"\n \n say \"GIT_WORK_TREE=absolute path, work tree below git dir\"\n GIT_DIR=$(pwd)/repo.git\n GIT_CONFIG=$GIT_DIR/config\n GIT_WORK_TREE=$(pwd)/repo.git/work\n-test_rev_parse 'outside'              false false false\n+test_rev_parse 'outside'              false false false \"$work\"\n cd repo.git || exit 1\n-test_rev_parse 'in repo.git'              false true  false\n+test_rev_parse 'in repo.git'              false true  false \"$work\"\n cd objects || exit 1\n-test_rev_parse 'in repo.git/objects'      false true  false\n+test_rev_parse 'in repo.git/objects'      false true  false \"$work\"\n cd ../work || exit 1\n-test_rev_parse 'in repo.git/work'         false true true ''\n+test_rev_parse 'in repo.git/work'         false true true '' ''\n cd sub/dir || exit 1\n-test_rev_parse 'in repo.git/sub/dir' false true true sub/dir/\n+test_rev_parse 'in repo.git/sub/dir' false true true \"$work\" sub/dir/\n cd ../../../.. || exit 1\n \n test_expect_success 'repo finds its work tree' '\ndiff --git a/t/t5521-pull-symlink.sh b/t/t5521-pull-symlink.sh\nnew file mode 100755\nindex 0000000..f18fec7\n--- /dev/null\n+++ b/t/t5521-pull-symlink.sh\n@@ -0,0 +1,67 @@\n+#!/bin/sh\n+\n+test_description='pulling from symlinked subdir'\n+\n+. ./test-lib.sh\n+\n+D=`pwd`\n+\n+# The scenario we are building:\n+#\n+#   trash\\ directory/\n+#     clone-repo/\n+#       subdir/\n+#         bar\n+#     subdir-link -> clone-repo/subdir/\n+#\n+# The working directory is subdir-link.\n+#\n+test_expect_success setup '\n+\n+    mkdir subdir &&\n+    touch subdir/bar &&\n+    git add subdir/bar &&\n+    git commit -m empty &&\n+    git clone . clone-repo &&\n+    # demonstrate that things work without the symlink\n+    test_debug \"cd clone-repo/subdir/ && git pull; cd ../..\" &&\n+    ln -s clone-repo/subdir/ subdir-link &&\n+    cd subdir-link/ &&\n+    test_debug \"set +x\"\n+'\n+\n+# From subdir-link, pulling should work as it does from\n+# clone-repo/subdir/.\n+#\n+# Instead, the error pull gave was:\n+#\n+#   fatal: 'origin': unable to chdir or not a git archive\n+#   fatal: The remote end hung up unexpectedly\n+#\n+# because git would find the .git/config for the \"trash directory\"\n+# repo, not for the clone-repo repo.  The \"trash directory\" repo\n+# had no entry for origin.  Git found the wrong .git because\n+# git rev-parse --show-cdup printed a path relative to\n+# clone-repo/subdir/, not subdir-link/.  Git rev-parse --show-cdup\n+# used the correct .git, but when the git pull shell script did\n+# \"cd `git rev-parse --show-cdup`\", it ended up in the wrong\n+# directory.  Shell \"cd\" works a little different from chdir() in C.\n+# Bash's \"cd -P\" works like chdir() in C.\n+#\n+test_expect_success 'pulling from symlinked subdir' '\n+\n+    git pull\n+'\n+\n+# Prove that the remote end really is a repo, and other commands\n+# work fine in this context.\n+#\n+test_debug \"\n+    test_expect_success 'pushing from symlinked subdir' '\n+\n+        git push\n+    '\n+\"\n+cd \"$D\"\n+\n+test_done\n-- \n1.6.0.3\n"},{"id":"96369","messageId":"m31vx3l94x.fsf@localhost.localdomain","threadId":"16339","inReplyTo":"1227389614-10946-1-git-send-email-marcel@oak.homeunix.org","subject":"Re: [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2008-11-22T21:54:09Z","receivedAt":"2008-11-22T21:54:09Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"\"Marcel M. Cary\" <marcel@oak.homeunix.org> writes:\n\n> * Change \"git rev-parse --show-cdup\" to print a full path instead of\n>   a series of \"../\" when it prints anything\n\nBut that is contrary to the _name_ of option. It is --show-cdup, as\nin \"show cd up\". And I think your change will break a few scripts.\n\nI think you should use \"git rev-parse --work-tree\" for full path\nto working directory:\n\n    --show-cdup\n        When the command is invoked from a subdirectory, show the path\n        of the top-level directory relative to the current directory\n        (typically a sequence of \"../\", or an empty string).\n\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"96377","messageId":"49290203.7060808@op5.se","threadId":"16339","inReplyTo":"m31vx3l94x.fsf@localhost.localdomain","subject":"Re: [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir","fromName":"Andreas Ericsson","fromEmail":"ae@op5.se","sentAt":"2008-11-23T07:10:59Z","receivedAt":"2008-11-23T07:10:59Z","isPatch":true,"sender":{"key":"ae@op5.se","avatar":"https://gravatar.com/avatar/426e89595c75a8f5252dd0c989e5fabe5bcac616e68557427ad9aef6b0ca342a?d=mp&s=160"},"body":"Jakub Narebski wrote:\n> \"Marcel M. Cary\" <marcel@oak.homeunix.org> writes:\n> \n>> * Change \"git rev-parse --show-cdup\" to print a full path instead of\n>>   a series of \"../\" when it prints anything\n> \n> But that is contrary to the _name_ of option. It is --show-cdup, as\n> in \"show cd up\". And I think your change will break a few scripts.\n> \n> I think you should use \"git rev-parse --work-tree\" for full path\n> to working directory:\n> \n>     --show-cdup\n>         When the command is invoked from a subdirectory, show the path\n>         of the top-level directory relative to the current directory\n>         (typically a sequence of \"../\", or an empty string).\n> \n\nAFAIR, it was introduced to make test-builds of really large projects in\nreally deep directories with a ton of symlinks leading to the path work a\nlot faster.\n\nThe thing to remember about git and its UI is that it was evolved from\nusers' actual needs. Very, very little of what is in the UI can be reworked\nwithout breaking something for someone, so it's (almost) always better to\nadd a new option. For this, I'd suggest \"--show-absolute-worktree-path\" if\nthat's what it does. Since it's an option primarily targeting scripts, I'm\nnot too worried that it's half a mile long.\n\n-- \nAndreas Ericsson                   andreas.ericsson@op5.se\nOP5 AB                             www.op5.se\nTel: +46 8-230225                  Fax: +46 8-230231\n"},{"id":"96456","messageId":"492B8A64.7070309@oak.homeunix.org","threadId":"16339","inReplyTo":"m31vx3l94x.fsf@localhost.localdomain","subject":"Re: [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir","fromName":"Marcel M. Cary","fromEmail":"marcel@oak.homeunix.org","sentAt":"2008-11-25T05:17:24Z","receivedAt":"2008-11-25T05:17:24Z","isPatch":true,"sender":{"key":"marcel@oak.homeunix.org","avatar":"https://gravatar.com/avatar/2bb524e4f383167b7e256bb93256c88353748d9873c34cde0fd461f1165baa0f?d=mp&s=160"},"body":"> But that is contrary to the _name_ of option. It is --show-cdup, as\n> in \"show cd up\". And I think your change will break a few scripts.\n> \n> I think you should use \"git rev-parse --work-tree\" for full path\n> to working directory:\n> \n>     --show-cdup\n>         When the command is invoked from a subdirectory, show the path\n>         of the top-level directory relative to the current directory\n>         (typically a sequence of \"../\", or an empty string).\n\nJakub,\n\nYes, I agree, there is a risk in breaking scripts that rely on the \"../\"\nformat.  That's the \"substantial change\" I was alluding.  Here's how I\narrived at that choice.  I considered these fixes:\n\n(a) add some shell code to cd_to_toplevel to find the canonical pwd and\n    interpret --show-cdup output from there\n\n(b) make a new option (--work-tree would be a good name) to print the\n    canonical work tree path, and leave --show-cdup as it is.  Then\n    change cd_to_toplevel and/or git pull to use the new option\n\n(c) change --show-cdup to print the canonical work tree path, even\n    though it's not entirely consistent with the name of the option\n\nThe main reason I avoided (a), even though that \"cd\" is what violated my\nexpecations, is because I didn't want to have to re-implement code to\ncheck whether each path component is a symlink.  (Now I see that \"cd\n`/bin/pwd` might be a more concise fix.)\n\nThe reason I avoided (b) is because, to make all of git work for me, I\nexpected to have to change several calling scripts.  (Now that I look, I\nsee only three calls to --show-cdup in the git codebase to change.)\nEven so, third-party scripts that I might want to use in the future\nwould not immediately be changed.\n\nOption (c) keeps the change small and isolated and makes it effective\neverywhere.  The documentation, while perhaps in need of update given my\npatch, doesn't promise to always return zero or more \"../\".  Also,\nthere's a branch branch of the --show-cdup code (that I can't seem to\nexercise) that the result of get_git_work_tree(), which might not be\nzero or more \"../\".\n\n\nWould you suggest pursuing option (a)?  I wonder whether there are\nlanguages other than shell that might suffer from the same problem of\nkeeping an internal PWD variable of some sort, or perhaps there are\nshell scripts out there that call --show-cdup directly instead of\ncalling cd_to_toplevel.\n\nDo you think it would be less likely to break existing scripts if I\nrestrict the (c) behavior to when getenv(\"PWD\") doesn't match the\nstarting getcwd()?  (I'm not sure yet whether that's a reliable way to\ndetect the symlink scenario, but it seems to work with bash.)\n\nMarcel\n"},{"id":"96457","messageId":"492B9321.8090706@oak.homeunix.org","threadId":"16339","inReplyTo":"49290203.7060808@op5.se","subject":"Re: [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir","fromName":"Marcel M. Cary","fromEmail":"marcel@oak.homeunix.org","sentAt":"2008-11-25T05:54:41Z","receivedAt":"2008-11-25T05:54:41Z","isPatch":true,"sender":{"key":"marcel@oak.homeunix.org","avatar":"https://gravatar.com/avatar/2bb524e4f383167b7e256bb93256c88353748d9873c34cde0fd461f1165baa0f?d=mp&s=160"},"body":"> AFAIR, it was introduced to make test-builds of really large projects in\n> really deep directories with a ton of symlinks leading to the path work a\n> lot faster.\n\nAndreas,\n\nI see value in keeping Git very fast.  That is, after all, why I chose\nGit over Mercurial.  Do you know where that discussion was, if was in\nthe archives?  I found these reasons to avoid absolute paths in the git\narchives:\n\n* paths with more components are slower to work with (in the context of\n  add and diff, which deal with many many paths)\n* absolute paths may exceed PATH_MAX while relative ones didn't\n* getcwd() will fail if parent directories are not executable, or on\n  some platforms, if parent directories are not readable\n\nMy impression is that the performance issue is probably not significant\nfor cd_to_toplevel since it's not in a tight inner loop, and dito for\nother potential callers of --show-cdup.  The PATH_MAX seems to be a\nrestriction elsewhere in the code already.\n\nEven if there were a scenario that put --show-cdup in a tight loop, I\nwonder whether current implementation provides much performance benefit,\nat least when bash is the calling language: bash seems to make the\nrelative path absolute anyway inside the \"cd\" builtin.\n\nThe commit (5f94c730) that introduces that code doesn't mention\nperformance.  It compares to:\n\n  git rev-parse --show-prefix | sed -e 's|[^/][^/]*|..|g'\n\n\nI also noticed that this failure case with \"--show-cdup\" in a symlinked\ndirectory has come up more than once before.\nhttp://marc.info/?l=git&m=122452534912000&w=2\nhttp://marc.info/?l=git&m=121613416212958&w=2\nhttps://kerneltrap.org/mailarchive/git/2007/4/25/244653/thread\n\nMarcel\n"},{"id":"96461","messageId":"492BA024.7080506@op5.se","threadId":"16339","inReplyTo":"492B9321.8090706@oak.homeunix.org","subject":"Re: [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir","fromName":"Andreas Ericsson","fromEmail":"ae@op5.se","sentAt":"2008-11-25T06:50:12Z","receivedAt":"2008-11-25T06:50:12Z","isPatch":true,"sender":{"key":"ae@op5.se","avatar":"https://gravatar.com/avatar/426e89595c75a8f5252dd0c989e5fabe5bcac616e68557427ad9aef6b0ca342a?d=mp&s=160"},"body":"Marcel M. Cary wrote:\n>> AFAIR, it was introduced to make test-builds of really large projects in\n>> really deep directories with a ton of symlinks leading to the path work a\n>> lot faster.\n> \n> Andreas,\n> \n> I see value in keeping Git very fast.  That is, after all, why I chose\n> Git over Mercurial.  Do you know where that discussion was, if was in\n> the archives?  I found these reasons to avoid absolute paths in the git\n> archives:\n> \n> * paths with more components are slower to work with (in the context of\n>   add and diff, which deal with many many paths)\n> * absolute paths may exceed PATH_MAX while relative ones didn't\n> * getcwd() will fail if parent directories are not executable, or on\n>   some platforms, if parent directories are not readable\n> \n> My impression is that the performance issue is probably not significant\n> for cd_to_toplevel since it's not in a tight inner loop, and dito for\n> other potential callers of --show-cdup.  The PATH_MAX seems to be a\n> restriction elsewhere in the code already.\n> \n\nThe performance issue does not come from cd_to_toplevel itself, but from\nits callers. That is, if scripts start to use absolute paths from *other*\ntight loops, that's when we hit a problem.\n\n> Even if there were a scenario that put --show-cdup in a tight loop, I\n> wonder whether current implementation provides much performance benefit,\n> at least when bash is the calling language: bash seems to make the\n> relative path absolute anyway inside the \"cd\" builtin.\n> \n> The commit (5f94c730) that introduces that code doesn't mention\n> performance.  It compares to:\n> \n>   git rev-parse --show-prefix | sed -e 's|[^/][^/]*|..|g'\n> \n> \n> I also noticed that this failure case with \"--show-cdup\" in a symlinked\n> directory has come up more than once before.\n> http://marc.info/?l=git&m=122452534912000&w=2\n> http://marc.info/?l=git&m=121613416212958&w=2\n> https://kerneltrap.org/mailarchive/git/2007/4/25/244653/thread\n> \n\nI can imagine. However, --show-cdup has a different use too. It's nifty\nfor printing relative paths from commands running inside a subdirectory\nof the repository. If you need the absolute path to the root of the repo,\nI'd suggest you add \"--show-absolute-path\" instead.\n\n-- \nAndreas Ericsson                   andreas.ericsson@op5.se\nOP5 AB                             www.op5.se\nTel: +46 8-230225                  Fax: +46 8-230231\n"},{"id":"96462","messageId":"492BA998.5050106@viscovery.net","threadId":"16339","inReplyTo":"1227389614-10946-1-git-send-email-marcel@oak.homeunix.org","subject":"Re: [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2008-11-25T07:30:32Z","receivedAt":"2008-11-25T07:30:32Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Marcel M. Cary schrieb:\n> * Change \"git rev-parse --show-cdup\" to print a full path instead of\n>   a series of \"../\" when it prints anything\n\nhttp://thread.gmane.org/gmane.comp.version-control.git/88557/focus=88562\n\nI don't see that you bring in any new arguments.\n\n-- Hannes\n"},{"id":"96477","messageId":"492C24D4.1010306@oak.homeunix.org","threadId":"16339","inReplyTo":"492BA998.5050106@viscovery.net","subject":"Re: [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir","fromName":"Marcel M. Cary","fromEmail":"marcel@oak.homeunix.org","sentAt":"2008-11-25T16:16:20Z","receivedAt":"2008-11-25T16:16:20Z","isPatch":true,"sender":{"key":"marcel@oak.homeunix.org","avatar":"https://gravatar.com/avatar/2bb524e4f383167b7e256bb93256c88353748d9873c34cde0fd461f1165baa0f?d=mp&s=160"},"body":"Johannes Sixt wrote:\n> Marcel M. Cary schrieb:\n>> * Change \"git rev-parse --show-cdup\" to print a full path instead of\n>>   a series of \"../\" when it prints anything\n> \n> http://thread.gmane.org/gmane.comp.version-control.git/88557/focus=88562\n> \n> I don't see that you bring in any new arguments.\n\nTo be clear, as mentioned here:\n\nhttp://thread.gmane.org/gmane.comp.version-control.git/88557/focus=88573\n\nI'm not talking about a situation where the symlink is in the working\ntree pointing outwards.  I'm talking about a symlink outside pointing\nin.  And as mentioned later in that thread, the --work-tree workaround\ndoesn't actually work.\n\n\nOne new thing I have to add is that the reason --show-cdup prints a\ncorrect path but pull fails is because it's the *shell* who\nmisinterprets the path.  So telling git rev-parse where the work-tree is\nhelps nothing.  It already knows.\n\nhttp://thread.gmane.org/gmane.comp.version-control.git/88557/focus=88581\n\nSo far I've seen no response to the idea, which Yves mentions, about\ntrying to restrict the absolute path behavior to times when bash would\ninterpret the \"../\" incorrectly.\n\nNor have I seen a response to the idea of correcting the shell's\nbehavior in cd_to_toplevel, for example by adding a \"cd `pwd`\", and I\ndon't really understand the scenario where this would be a performance\nconcern; I think I haven't found a particular discussion that several\npeople have referenced.  Perhaps I should prepare a patch for that so I\ncan verify that it works as I expect and so we have something more\nconcrete to discuss?\n\nAny tips on how to follow the reference\n7vk5sly3h9.fsf@assigned-by-dhcp.cox.net in the first url above?  It\nlooks to be about performance.  Message-Id seems to not be indexed for\nsearching.\n\nMarcel\n"},{"id":"96479","messageId":"492C2829.1000108@viscovery.net","threadId":"16339","inReplyTo":"492C24D4.1010306@oak.homeunix.org","subject":"Re: [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2008-11-25T16:30:33Z","receivedAt":"2008-11-25T16:30:33Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Marcel M. Cary schrieb:\n> Any tips on how to follow the reference\n> 7vk5sly3h9.fsf@assigned-by-dhcp.cox.net in the first url above?  It\n> looks to be about performance.  Message-Id seems to not be indexed for\n> searching.\n\nhttp://mid.gmane.org/7vk5sly3h9.fsf@assigned-by-dhcp.cox.net\n\n-- Hannes\n"},{"id":"96484","messageId":"7vtz9vk6uj.fsf@gitster.siamese.dyndns.org","threadId":"16339","inReplyTo":"492C24D4.1010306@oak.homeunix.org","subject":"Re: [PATCH] rev-parse: Fix shell scripts whose cwd is a symlink into a git work-dir","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-11-25T18:17:56Z","receivedAt":"2008-11-25T18:17:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Marcel M. Cary\" <marcel@oak.homeunix.org> writes:\n\n> Nor have I seen a response to the idea of correcting the shell's\n> behavior in cd_to_toplevel, for example by adding a \"cd `pwd`\",...\n\nI think you probably could fool the shell by unsetting PWD or something\nsilly like that (or \"cd -P\" which may not be supported by non POSIX shells\nbut I suspect the ones we care about do support it).\n\nDoing a 'cd \"$(pwd)\"' inside cd_to_toplevel would be a less objectionable\nand arguably more portable workaround for the case where you have a\nsymlink pointing into somewhere in your work tree.\n"},{"id":"97022","messageId":"1228282020-2294-1-git-send-email-marcel@oak.homeunix.org","threadId":"16339","inReplyTo":"7vtz9vk6uj.fsf@gitster.siamese.dyndns.org","subject":"[PATCH] git-sh-setup: Fix scripts whose PWD is a symlink into a git work-dir","fromName":"Marcel M. Cary","fromEmail":"marcel@oak.homeunix.org","sentAt":"2008-12-03T05:27:00Z","receivedAt":"2008-12-03T05:27:00Z","isPatch":true,"sender":{"key":"marcel@oak.homeunix.org","avatar":"https://gravatar.com/avatar/2bb524e4f383167b7e256bb93256c88353748d9873c34cde0fd461f1165baa0f?d=mp&s=160"},"body":"* Before interpretting an upward path (../) in cd_to_toplevel,\n  cd to a path without symlinks given by /bin/pwd\n* Add tests for cd_to_toplevel and \"git pull\" in a symlinked\n  directory that failed before this fix, plus constrasting\n  scenarios that already worked\n\nSigned-off-by: Marcel M. Cary <marcel@oak.homeunix.org>\n---\n\nI hope this patch will address concerns both about changes\nto existing APIs and speed of the new behavior.\n\nA few notes on implementation choices:\n\nI used /bin/pwd because of this precedent for choosing it over\n\"cd -P\" for compatibility.\nhttp://article.gmane.org/gmane.comp.version-control.git/46918\n\nIf cd_to_toplevel had concatenated $(/bin/pwd) with $cdup to\navoid the separate \"cd\", it would require checking for $cdup\nbeing an absolute path.  I wasn't sure how to check that in\na way that is both portable and clearly faster than \"cd\",\nso cd_to_toplevel runs \"cd\" twice.  I'm assuming that\nrunning an external command like expr or grep is slower than\njust doing the \"cd\".\n\ncd_to_toplevel doesn't check $PWD to see whether to do the\nfirst cd, because some shells allegedly don't update it\nreliably.\n\nSince cd_to_toplevel doesn't know whether it's at a\nsymlinked PWD or not, I wrote it to treat the \n\"cd $(/bin/pwd)\" as mandatory, even when it might not\nactually be.  So on systems without /bin/pwd, it will fail\neven when there are no symlinks.  I thought that was better\nthan inconsistent behavior depending on whether /bin/pwd is\navailable.\n\nThe extra \"cd\" will be skipped when the script is already at\nthe top of the working tree.\n\n\n git-sh-setup.sh           |   11 +++++++\n t/t2300-cd-to-toplevel.sh |   37 +++++++++++++++++++++++++\n t/t5521-pull-symlink.sh   |   67 +++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 115 insertions(+), 0 deletions(-)\n create mode 100755 t/t2300-cd-to-toplevel.sh\n create mode 100755 t/t5521-pull-symlink.sh\n\ndiff --git a/git-sh-setup.sh b/git-sh-setup.sh\nindex dbdf209..377700b 100755\n--- a/git-sh-setup.sh\n+++ b/git-sh-setup.sh\n@@ -85,6 +85,17 @@ cd_to_toplevel () {\n \tcdup=$(git rev-parse --show-cdup)\n \tif test ! -z \"$cdup\"\n \tthen\n+\t\t# Interpret $cdup relative to the physical, not logical, cwd.\n+\t\t# Probably /bin/pwd is more portable than passing -P to cd or pwd.\n+\t\tphys=\"$(/bin/pwd)\" || {\n+\t\t\techo >&2 \"Cannot determine the physical path to the current dir\"\n+\t\t\texit 1\n+\t\t}\n+\t\tcd \"$phys\" || {\n+\t\t\techo >&2 \"Cannot chdir to the physical path to current dir: $phys\"\n+\t\t\texit 1\n+\t\t}\n+\n \t\tcd \"$cdup\" || {\n \t\t\techo >&2 \"Cannot chdir to $cdup, the toplevel of the working tree\"\n \t\t\texit 1\ndiff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh\nnew file mode 100755\nindex 0000000..293dc35\n--- /dev/null\n+++ b/t/t2300-cd-to-toplevel.sh\n@@ -0,0 +1,37 @@\n+#!/bin/sh\n+\n+test_description='cd_to_toplevel'\n+\n+. ./test-lib.sh\n+\n+test_cd_to_toplevel () {\n+\ttest_expect_success \"$2\" '\n+\t\t(\n+\t\t\tcd '\"'$1'\"' &&\n+\t\t\t. git-sh-setup &&\n+\t\t\tcd_to_toplevel &&\n+\t\t\t[ \"$(pwd -P)\" = \"$TOPLEVEL\" ]\n+\t\t)\n+\t'\n+}\n+\n+TOPLEVEL=\"$(pwd -P)/repo\"\n+mkdir -p repo/sub/dir\n+mv .git repo/\n+SUBDIRECTORY_OK=1\n+\n+test_cd_to_toplevel repo 'at physical root'\n+\n+test_cd_to_toplevel repo/sub/dir 'at physical subdir'\n+\n+ln -s repo symrepo\n+test_cd_to_toplevel symrepo 'at symbolic root'\n+\n+ln -s repo/sub/dir subdir-link\n+test_cd_to_toplevel subdir-link 'at symbolic subdir'\n+\n+cd repo\n+ln -s sub/dir internal-link\n+test_cd_to_toplevel internal-link 'at internal symbolic subdir'\n+\n+test_done\ndiff --git a/t/t5521-pull-symlink.sh b/t/t5521-pull-symlink.sh\nnew file mode 100755\nindex 0000000..f18fec7\n--- /dev/null\n+++ b/t/t5521-pull-symlink.sh\n@@ -0,0 +1,67 @@\n+#!/bin/sh\n+\n+test_description='pulling from symlinked subdir'\n+\n+. ./test-lib.sh\n+\n+D=`pwd`\n+\n+# The scenario we are building:\n+#\n+#   trash\\ directory/\n+#     clone-repo/\n+#       subdir/\n+#         bar\n+#     subdir-link -> clone-repo/subdir/\n+#\n+# The working directory is subdir-link.\n+#\n+test_expect_success setup '\n+\n+    mkdir subdir &&\n+    touch subdir/bar &&\n+    git add subdir/bar &&\n+    git commit -m empty &&\n+    git clone . clone-repo &&\n+    # demonstrate that things work without the symlink\n+    test_debug \"cd clone-repo/subdir/ && git pull; cd ../..\" &&\n+    ln -s clone-repo/subdir/ subdir-link &&\n+    cd subdir-link/ &&\n+    test_debug \"set +x\"\n+'\n+\n+# From subdir-link, pulling should work as it does from\n+# clone-repo/subdir/.\n+#\n+# Instead, the error pull gave was:\n+#\n+#   fatal: 'origin': unable to chdir or not a git archive\n+#   fatal: The remote end hung up unexpectedly\n+#\n+# because git would find the .git/config for the \"trash directory\"\n+# repo, not for the clone-repo repo.  The \"trash directory\" repo\n+# had no entry for origin.  Git found the wrong .git because\n+# git rev-parse --show-cdup printed a path relative to\n+# clone-repo/subdir/, not subdir-link/.  Git rev-parse --show-cdup\n+# used the correct .git, but when the git pull shell script did\n+# \"cd `git rev-parse --show-cdup`\", it ended up in the wrong\n+# directory.  Shell \"cd\" works a little different from chdir() in C.\n+# Bash's \"cd -P\" works like chdir() in C.\n+#\n+test_expect_success 'pulling from symlinked subdir' '\n+\n+    git pull\n+'\n+\n+# Prove that the remote end really is a repo, and other commands\n+# work fine in this context.\n+#\n+test_debug \"\n+    test_expect_success 'pushing from symlinked subdir' '\n+\n+        git push\n+    '\n+\"\n+cd \"$D\"\n+\n+test_done\n-- \n1.6.0.3\n"},{"id":"97026","messageId":"7viqq1hghw.fsf@gitster.siamese.dyndns.org","threadId":"16339","inReplyTo":"1228282020-2294-1-git-send-email-marcel@oak.homeunix.org","subject":"Re: [PATCH] git-sh-setup: Fix scripts whose PWD is a symlink into a git work-dir","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-12-03T07:20:27Z","receivedAt":"2008-12-03T07:20:27Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Marcel M. Cary\" <marcel@oak.homeunix.org> writes:\n\n> If cd_to_toplevel had concatenated $(/bin/pwd) with $cdup to\n> avoid the separate \"cd\", it would require checking for $cdup\n> being an absolute path.  I wasn't sure how to check that in\n> a way that is both portable and clearly faster than \"cd\",\n\n    case \"$v\" in\n    /*) : handle absolute path ;;\n    *) : everything else ;;\n    esac\n\nIn all shells that support \"case..esac\", it is built-in.\n\nHaving said that, I think it would probably be better to bite the bullet\nand start using \"cd -P\" soon after 1.6.1 goes final, and at the same time\nexisting places that use \"cd `pwd`\" as a workaround if there are some.\n"},{"id":"97491","messageId":"1228921454-22416-1-git-send-email-marcel@oak.homeunix.org","threadId":"16339","inReplyTo":"7viqq1hghw.fsf@gitster.siamese.dyndns.org","subject":"[PATCH v2] git-sh-setup: Fix scripts whose PWD is a symlink into a git work-dir","fromName":"Marcel M. Cary","fromEmail":"marcel@oak.homeunix.org","sentAt":"2008-12-10T15:04:14Z","receivedAt":"2008-12-10T15:04:14Z","isPatch":true,"sender":{"key":"marcel@oak.homeunix.org","avatar":"https://gravatar.com/avatar/2bb524e4f383167b7e256bb93256c88353748d9873c34cde0fd461f1165baa0f?d=mp&s=160"},"body":"* When interpretting a relative upward (../) path in cd_to_toplevel,\n  prepend the cwd without symlinks, given by /bin/pwd\n* Add tests for cd_to_toplevel and \"git pull\" in a symlinked\n  directory that failed before this fix, plus constrasting\n  scenarios that already worked\n\nSigned-off-by: Marcel M. Cary <marcel@oak.homeunix.org>\n---\n\nNow /bin/pwd is only used when $cdup both is relative\nand contains a \"..\" component, which I think is most of\nthe time that git didn't start out in the top-level\ndirectory.\n\nI can't seem to exercise the case that show-cdup prints\nsomething other than \"../\" or \"\", even when setting\nGIT_WORK_TREE in or out of the work tree.  Is it premature\nto anticipate that show-cdup might print an arbitrary path\nsometime in the future, given the \n\"if (!is_inside_work_tree())\" branch of show-cdup?  Or maybe\nit does now and I just don't see the use case.\n\nAlso, the additional invocation of \"cd\" is now removed.\n\n\n git-sh-setup.sh           |   23 ++++++++++++++-\n t/t2300-cd-to-toplevel.sh |   37 +++++++++++++++++++++++++\n t/t5521-pull-symlink.sh   |   67 +++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 125 insertions(+), 2 deletions(-)\n create mode 100755 t/t2300-cd-to-toplevel.sh\n create mode 100755 t/t5521-pull-symlink.sh\n\ndiff --git a/git-sh-setup.sh b/git-sh-setup.sh\nindex dbdf209..f07d96b 100755\n--- a/git-sh-setup.sh\n+++ b/git-sh-setup.sh\n@@ -85,8 +85,27 @@ cd_to_toplevel () {\n \tcdup=$(git rev-parse --show-cdup)\n \tif test ! -z \"$cdup\"\n \tthen\n-\t\tcd \"$cdup\" || {\n-\t\t\techo >&2 \"Cannot chdir to $cdup, the toplevel of the working tree\"\n+\t\tcase \"$cdup\" in\n+\t\t/*)\n+\t\t\t# Not quite the same as if we did \"cd -P '$cdup'\" when\n+\t\t\t# $cdup contains \"..\" after symlink path components.\n+\t\t\t# Don't fix that case at least until Git switches to\n+\t\t\t# \"cd -P\" across the board.\n+\t\t\tphys=\"$cdup\"\n+\t\t\t;;\n+\t\t..|../*|*/..|*/../*)\n+\t\t\t# Interpret $cdup relative to the physical, not logical, cwd.\n+\t\t\t# Probably /bin/pwd is more portable than passing -P to cd or pwd.\n+\t\t\tphys=\"$(/bin/pwd)/$cdup\"\n+\t\t\t;;\n+\t\t*)\n+\t\t\t# There's no \"..\", so no need to make things absolute.\n+\t\t\tphys=\"$cdup\"\n+\t\t\t;;\n+\t\tesac\n+\n+\t\tcd \"$phys\" || {\n+\t\t\techo >&2 \"Cannot chdir to $phys, the toplevel of the working tree\"\n \t\t\texit 1\n \t\t}\n \tfi\ndiff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh\nnew file mode 100755\nindex 0000000..293dc35\n--- /dev/null\n+++ b/t/t2300-cd-to-toplevel.sh\n@@ -0,0 +1,37 @@\n+#!/bin/sh\n+\n+test_description='cd_to_toplevel'\n+\n+. ./test-lib.sh\n+\n+test_cd_to_toplevel () {\n+\ttest_expect_success \"$2\" '\n+\t\t(\n+\t\t\tcd '\"'$1'\"' &&\n+\t\t\t. git-sh-setup &&\n+\t\t\tcd_to_toplevel &&\n+\t\t\t[ \"$(pwd -P)\" = \"$TOPLEVEL\" ]\n+\t\t)\n+\t'\n+}\n+\n+TOPLEVEL=\"$(pwd -P)/repo\"\n+mkdir -p repo/sub/dir\n+mv .git repo/\n+SUBDIRECTORY_OK=1\n+\n+test_cd_to_toplevel repo 'at physical root'\n+\n+test_cd_to_toplevel repo/sub/dir 'at physical subdir'\n+\n+ln -s repo symrepo\n+test_cd_to_toplevel symrepo 'at symbolic root'\n+\n+ln -s repo/sub/dir subdir-link\n+test_cd_to_toplevel subdir-link 'at symbolic subdir'\n+\n+cd repo\n+ln -s sub/dir internal-link\n+test_cd_to_toplevel internal-link 'at internal symbolic subdir'\n+\n+test_done\ndiff --git a/t/t5521-pull-symlink.sh b/t/t5521-pull-symlink.sh\nnew file mode 100755\nindex 0000000..f18fec7\n--- /dev/null\n+++ b/t/t5521-pull-symlink.sh\n@@ -0,0 +1,67 @@\n+#!/bin/sh\n+\n+test_description='pulling from symlinked subdir'\n+\n+. ./test-lib.sh\n+\n+D=`pwd`\n+\n+# The scenario we are building:\n+#\n+#   trash\\ directory/\n+#     clone-repo/\n+#       subdir/\n+#         bar\n+#     subdir-link -> clone-repo/subdir/\n+#\n+# The working directory is subdir-link.\n+#\n+test_expect_success setup '\n+\n+    mkdir subdir &&\n+    touch subdir/bar &&\n+    git add subdir/bar &&\n+    git commit -m empty &&\n+    git clone . clone-repo &&\n+    # demonstrate that things work without the symlink\n+    test_debug \"cd clone-repo/subdir/ && git pull; cd ../..\" &&\n+    ln -s clone-repo/subdir/ subdir-link &&\n+    cd subdir-link/ &&\n+    test_debug \"set +x\"\n+'\n+\n+# From subdir-link, pulling should work as it does from\n+# clone-repo/subdir/.\n+#\n+# Instead, the error pull gave was:\n+#\n+#   fatal: 'origin': unable to chdir or not a git archive\n+#   fatal: The remote end hung up unexpectedly\n+#\n+# because git would find the .git/config for the \"trash directory\"\n+# repo, not for the clone-repo repo.  The \"trash directory\" repo\n+# had no entry for origin.  Git found the wrong .git because\n+# git rev-parse --show-cdup printed a path relative to\n+# clone-repo/subdir/, not subdir-link/.  Git rev-parse --show-cdup\n+# used the correct .git, but when the git pull shell script did\n+# \"cd `git rev-parse --show-cdup`\", it ended up in the wrong\n+# directory.  Shell \"cd\" works a little different from chdir() in C.\n+# Bash's \"cd -P\" works like chdir() in C.\n+#\n+test_expect_success 'pulling from symlinked subdir' '\n+\n+    git pull\n+'\n+\n+# Prove that the remote end really is a repo, and other commands\n+# work fine in this context.\n+#\n+test_debug \"\n+    test_expect_success 'pushing from symlinked subdir' '\n+\n+        git push\n+    '\n+\"\n+cd \"$D\"\n+\n+test_done\n-- \n1.6.0.3\n"},{"id":"97514","messageId":"7viqprzsvs.fsf@gitster.siamese.dyndns.org","threadId":"16339","inReplyTo":"1228921454-22416-1-git-send-email-marcel@oak.homeunix.org","subject":"Re: [PATCH v2] git-sh-setup: Fix scripts whose PWD is a symlink into a git work-dir","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-12-10T20:18:15Z","receivedAt":"2008-12-10T20:18:15Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Marcel M. Cary\" <marcel@oak.homeunix.org> writes:\n\n> * When interpretting a relative upward (../) path in cd_to_toplevel,\n>   prepend the cwd without symlinks, given by /bin/pwd\n> * Add tests for cd_to_toplevel and \"git pull\" in a symlinked\n>   directory that failed before this fix, plus constrasting\n>   scenarios that already worked\n\nThese are descriptions of changes (and good ones at that, but\n\"constrasting?\").\n\nIt however is a good idea to describe the problem the patch tries to solve\n*before* going into details of what you did.  \"If A is B, operation C\ntries to incorrectly access directory D; it should use directory E.  This\nbreakage is because F is confused by G...\"\n\nYes, the \"Subject:\" already hints about the \"If A is B\" part, and the\nsecond bullet point uses the word \"failed\" to hint that there was a\nbreakage, but that will not be sufficient description to recall the\nanalysis you did of the problem, when you have read the commit log message\n6 months from now what the breakage was about.\n\nIn order to justify the change against \"Doctor if A is B, it hurts ---\ndon't do it then\" rebuttals, it further may make sense to defend why it is\nsometimes useful to be able to satisify the precondition that triggers the\nexisting problem.  That would come before the problem description to\nprepare readers with the context of the patch.\n\n> diff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh\n> new file mode 100755\n> index 0000000..293dc35\n> --- /dev/null\n> +++ b/t/t2300-cd-to-toplevel.sh\n> @@ -0,0 +1,37 @@\n> +#!/bin/sh\n> +\n> +test_description='cd_to_toplevel'\n> +\n> +. ./test-lib.sh\n> +\n> +test_cd_to_toplevel () {\n> +\ttest_expect_success \"$2\" '\n> +\t\t(\n> +\t\t\tcd '\"'$1'\"' &&\n> +\t\t\t. git-sh-setup &&\n> +\t\t\tcd_to_toplevel &&\n> +\t\t\t[ \"$(pwd -P)\" = \"$TOPLEVEL\" ]\n> +\t\t)\n> +\t'\n> +}\n> +\n> +TOPLEVEL=\"$(pwd -P)/repo\"\n\nHmm.  Does it make sense to assume everybody's pwd can take -P when the\nprimary change this patch introduces carefully avoids assuming the\navailability of -P for \"cd\"?\n\n> +ln -s repo symrepo\n> +test_cd_to_toplevel symrepo 'at symbolic root'\n> +\n> +ln -s repo/sub/dir subdir-link\n> +test_cd_to_toplevel subdir-link 'at symbolic subdir'\n> +\n> +cd repo\n> +ln -s sub/dir internal-link\n> +test_cd_to_toplevel internal-link 'at internal symbolic subdir'\n\nTo be very honest, although it is good that you made them work, I am still\nnot getting why the latter two scenarios are worth supporting.  The first\none I am Ok with, though.\n\n> diff --git a/t/t5521-pull-symlink.sh b/t/t5521-pull-symlink.sh\n> new file mode 100755\n> index 0000000..f18fec7\n> --- /dev/null\n> +++ b/t/t5521-pull-symlink.sh\n> @@ -0,0 +1,67 @@\n> +#!/bin/sh\n> +\n> +test_description='pulling from symlinked subdir'\n> +\n> +. ./test-lib.sh\n> +\n> +D=`pwd`\n> +\n> +# The scenario we are building:\n> +#\n> +#   trash\\ directory/\n> +#     clone-repo/\n> +#       subdir/\n> +#         bar\n> +#     subdir-link -> clone-repo/subdir/\n> +#\n> +# The working directory is subdir-link.\n> +#\n\nIt is great to see the scenario explained like this.  It makes it easier\nto follow what the tests are trying to do.\n\n> +test_expect_success setup '\n> +\n> +    mkdir subdir &&\n> +    touch subdir/bar &&\n> +    git add subdir/bar &&\n> +    git commit -m empty &&\n> +    git clone . clone-repo &&\n> +    # demonstrate that things work without the symlink\n> +    test_debug \"cd clone-repo/subdir/ && git pull; cd ../..\" &&\n> +    ln -s clone-repo/subdir/ subdir-link &&\n> +    cd subdir-link/ &&\n> +    test_debug \"set +x\"\n> +'\n> +\n> +# From subdir-link, pulling should work as it does from\n> +# clone-repo/subdir/.\n> +#\n> +# Instead, the error pull gave was:\n> +#\n> +#   fatal: 'origin': unable to chdir or not a git archive\n> +#   fatal: The remote end hung up unexpectedly\n> +#\n> +# because git would find the .git/config for the \"trash directory\"\n> +# repo, not for the clone-repo repo.  The \"trash directory\" repo\n> +# had no entry for origin.  Git found the wrong .git because\n> +# git rev-parse --show-cdup printed a path relative to\n> +# clone-repo/subdir/, not subdir-link/.  Git rev-parse --show-cdup\n> +# used the correct .git, but when the git pull shell script did\n> +# \"cd `git rev-parse --show-cdup`\", it ended up in the wrong\n> +# directory.  Shell \"cd\" works a little different from chdir() in C.\n> +# Bash's \"cd -P\" works like chdir() in C.\n\nThis is a very good analysis.  s/Bash's \"cd -P\"/\"cd -P\" in POSIX shells/,\nthough.\n\n> +#\n> +test_expect_success 'pulling from symlinked subdir' '\n> +\n> +    git pull\n> +'\n\nI'd prefer to see each test_expect_success be able to fail independently,\nwhich would mean (1) when you chdir around, do so in a subshell, and (2)\neach test_expect_success assumes it begins in the same directory.\n\nIn the case of these tests, I think it is just the matter of moving the\nlast two lines from the previous test to the beginning of this test and\nenclosing this test in (), right?\n\n> +\n> +# Prove that the remote end really is a repo, and other commands\n> +# work fine in this context.\n> +#\n> +test_debug \"\n> +    test_expect_success 'pushing from symlinked subdir' '\n> +\n> +        git push\n> +    '\n> +\"\n\nWhy should this be hidden inside test_debug?\n"},{"id":"97812","messageId":"1229201231-12586-1-git-send-email-marcel@oak.homeunix.org","threadId":"16339","inReplyTo":"7viqprzsvs.fsf@gitster.siamese.dyndns.org","subject":"[PATCH v3] git-sh-setup: Fix scripts whose PWD is a symlink into a git work-dir","fromName":"Marcel M. Cary","fromEmail":"marcel@oak.homeunix.org","sentAt":"2008-12-13T20:47:11Z","receivedAt":"2008-12-13T20:47:11Z","isPatch":true,"sender":{"key":"marcel@oak.homeunix.org","avatar":"https://gravatar.com/avatar/2bb524e4f383167b7e256bb93256c88353748d9873c34cde0fd461f1165baa0f?d=mp&s=160"},"body":"I want directories of my working tree to be linked to from various\npaths on my filesystem where third-party components expect them, both\nin development and production environments.  A build system's install\nstep could solve this, but we develop scripts and web pages that don't\nneed to be built.  Git's submodule system could solve this, but we\ntend to develop, branch, and test those directories all in unison, so\none big repository feels more natural.  We prefer to edit and commit\non the symlinked paths, not the canonical ones, and in that setting,\n\"git pull\" fails to find the top-level directory of the working tree\nand the .git directory in it.\n\n\"git pull\" fails because POSIX shells have a notion of current working\ndirectory that is different from getcwd().  The shell stores this path\nin PWD.  As a result, \"cd ../\" in a shell script can be interpretted\ndifferently in a shell than chdir(\"../\") in a C program.  The shell\ninterprets \"../\" by essentially stripping the last textual path\ncomponent from PWD, whereas C chdir() follows the \"..\" link in the\ncurrent directory on the filesystem.  When PWD is a symlink, these are\ndifferent destinations.  As a result, Git's C commands find the\ncorrect top-level working tree, and shell scripts do not.\n\nChanges:\n\n* When interpretting a relative upward (../) path in cd_to_toplevel,\n  prepend the cwd without symlinks, given by /bin/pwd\n* Add tests for cd_to_toplevel and \"git pull\" in a symlinked\n  directory that failed before this fix, plus contrasting scenarios\n  that already worked\n\nSigned-off-by: Marcel M. Cary <marcel@oak.homeunix.org>\n---\n\nHopefully the new commit message adequately describes the problem and\nmotivation for solving it without getting too long-winded or bogged down\nin personal details.\n\nI also removed the \"pwd -P\" from the unit test.  I originally worried\nthat it was little like testing an algorithm by running it twice and\nchecking the results against eachother.  But I guess having the unit\ntests run on unusual platforms is more important.\n\nThe pull-symlink test cases should now fail independently.  I also\nmoved the setup out of the test_expect_success block for symetry and\nsince I see that other tests don't check for setup failure.  There's\nno \"set -e\" or anything to catch a setup failure other than the\neventual test cases push/pull not working.  So is it good form in this\nsituation to not check the setup steps for success?  Or would it make\nsense to put them in their own 'setup' test case?  Or would it be better\nto just \"exit 1\" if they fail?\n\n> > +ln -s repo symrepo\n> > +test_cd_to_toplevel symrepo 'at symbolic root'\n> > +\n> > +ln -s repo/sub/dir subdir-link\n> > +test_cd_to_toplevel subdir-link 'at symbolic subdir'\n> > +\n> > +cd repo\n> > +ln -s sub/dir internal-link\n> > +test_cd_to_toplevel internal-link 'at internal symbolic subdir'\n> \n> To be very honest, although it is good that you made them work, I am still\n> not getting why the latter two scenarios are worth supporting.  The first\n> one I am Ok with, though.\n\nThe middle scenario is the one I want most.  I hope the first\nparagraph of the commit message sheds more light on the reason.  \n\nThe third is really just there for completeness (although there are\nother cases I didn't include...).  Since Git supports operation below\nthe top-level, and it supports symlinks, it seems useful to test the\ncooperation of those features.  I wouldn't miss it much if you thought\nit was not interesting enough.\n\n> > +\n> > +# Prove that the remote end really is a repo, and other commands\n> > +# work fine in this context.\n> > +#\n> > +test_debug \"\n> > +    test_expect_success 'pushing from symlinked subdir' '\n> > +\n> > +        git push\n> > +    '\n> > +\"\n> \n> Why should this be hidden inside test_debug?\n\nI'm not particularly trying to test \"git push\" or \"git pull\" in\ngeneral here.  That's also why the other \"git pull\" was in a\ntest_debug.  I thought it was really only useful to someone trying to\nunderstand the contents of the test file.  There are other files that\ncover push and pull.  Do you think these test cases should run all the\ntime here?\n\n\n git-sh-setup.sh           |   23 +++++++++++++-\n t/t2300-cd-to-toplevel.sh |   37 +++++++++++++++++++++++\n t/t5521-pull-symlink.sh   |   73 +++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 131 insertions(+), 2 deletions(-)\n create mode 100755 t/t2300-cd-to-toplevel.sh\n create mode 100755 t/t5521-pull-symlink.sh\n\ndiff --git a/git-sh-setup.sh b/git-sh-setup.sh\nindex dbdf209..f07d96b 100755\n--- a/git-sh-setup.sh\n+++ b/git-sh-setup.sh\n@@ -85,8 +85,27 @@ cd_to_toplevel () {\n \tcdup=$(git rev-parse --show-cdup)\n \tif test ! -z \"$cdup\"\n \tthen\n-\t\tcd \"$cdup\" || {\n-\t\t\techo >&2 \"Cannot chdir to $cdup, the toplevel of the working tree\"\n+\t\tcase \"$cdup\" in\n+\t\t/*)\n+\t\t\t# Not quite the same as if we did \"cd -P '$cdup'\" when\n+\t\t\t# $cdup contains \"..\" after symlink path components.\n+\t\t\t# Don't fix that case at least until Git switches to\n+\t\t\t# \"cd -P\" across the board.\n+\t\t\tphys=\"$cdup\"\n+\t\t\t;;\n+\t\t..|../*|*/..|*/../*)\n+\t\t\t# Interpret $cdup relative to the physical, not logical, cwd.\n+\t\t\t# Probably /bin/pwd is more portable than passing -P to cd or pwd.\n+\t\t\tphys=\"$(/bin/pwd)/$cdup\"\n+\t\t\t;;\n+\t\t*)\n+\t\t\t# There's no \"..\", so no need to make things absolute.\n+\t\t\tphys=\"$cdup\"\n+\t\t\t;;\n+\t\tesac\n+\n+\t\tcd \"$phys\" || {\n+\t\t\techo >&2 \"Cannot chdir to $phys, the toplevel of the working tree\"\n \t\t\texit 1\n \t\t}\n \tfi\ndiff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh\nnew file mode 100755\nindex 0000000..05854b4\n--- /dev/null\n+++ b/t/t2300-cd-to-toplevel.sh\n@@ -0,0 +1,37 @@\n+#!/bin/sh\n+\n+test_description='cd_to_toplevel'\n+\n+. ./test-lib.sh\n+\n+test_cd_to_toplevel () {\n+\ttest_expect_success \"$2\" '\n+\t\t(\n+\t\t\tcd '\"'$1'\"' &&\n+\t\t\t. git-sh-setup &&\n+\t\t\tcd_to_toplevel &&\n+\t\t\t[ \"$(pwd -P)\" = \"$TOPLEVEL\" ]\n+\t\t)\n+\t'\n+}\n+\n+TOPLEVEL=\"$(/bin/pwd)/repo\"\n+mkdir -p repo/sub/dir\n+mv .git repo/\n+SUBDIRECTORY_OK=1\n+\n+test_cd_to_toplevel repo 'at physical root'\n+\n+test_cd_to_toplevel repo/sub/dir 'at physical subdir'\n+\n+ln -s repo symrepo\n+test_cd_to_toplevel symrepo 'at symbolic root'\n+\n+ln -s repo/sub/dir subdir-link\n+test_cd_to_toplevel subdir-link 'at symbolic subdir'\n+\n+cd repo\n+ln -s sub/dir internal-link\n+test_cd_to_toplevel internal-link 'at internal symbolic subdir'\n+\n+test_done\ndiff --git a/t/t5521-pull-symlink.sh b/t/t5521-pull-symlink.sh\nnew file mode 100755\nindex 0000000..8869262\n--- /dev/null\n+++ b/t/t5521-pull-symlink.sh\n@@ -0,0 +1,73 @@\n+#!/bin/sh\n+\n+test_description='pulling from symlinked subdir'\n+\n+. ./test-lib.sh\n+\n+# The scenario we are building:\n+#\n+#   trash\\ directory/\n+#     clone-repo/\n+#       subdir/\n+#         bar\n+#     subdir-link -> clone-repo/subdir/\n+#\n+# The working directory is subdir-link.\n+\n+mkdir subdir\n+touch subdir/bar\n+git add subdir/bar\n+git commit -m empty\n+git clone . clone-repo\n+ln -s clone-repo/subdir/ subdir-link\n+\n+\n+# Demonstrate that things work if we just avoid the symlink\n+#\n+test_debug \"\n+\ttest_expect_success 'pulling from real subdir' '\n+\t\t(\n+\t\t\tcd clone-repo/subdir/ &&\n+\t\t\tgit pull\n+\t\t)\n+\t'\n+\"\n+\n+# From subdir-link, pulling should work as it does from\n+# clone-repo/subdir/.\n+#\n+# Instead, the error pull gave was:\n+#\n+#   fatal: 'origin': unable to chdir or not a git archive\n+#   fatal: The remote end hung up unexpectedly\n+#\n+# because git would find the .git/config for the \"trash directory\"\n+# repo, not for the clone-repo repo.  The \"trash directory\" repo\n+# had no entry for origin.  Git found the wrong .git because\n+# git rev-parse --show-cdup printed a path relative to\n+# clone-repo/subdir/, not subdir-link/.  Git rev-parse --show-cdup\n+# used the correct .git, but when the git pull shell script did\n+# \"cd `git rev-parse --show-cdup`\", it ended up in the wrong\n+# directory.  A POSIX shell's \"cd\" works a little differently\n+# than chdir() in C; \"cd -P\" is much closer to chdir().\n+#\n+test_expect_success 'pulling from symlinked subdir' '\n+\t(\n+\t\tcd subdir-link/ &&\n+\t\tgit pull\n+\t)\n+'\n+\n+# Prove that the remote end really is a repo, and other commands\n+# work fine in this context.  It's just that \"git pull\" breaks.\n+#\n+test_debug \"\n+\ttest_expect_success 'pushing from symlinked subdir' '\n+\t\t(\n+\t\t\tcd subdir-link/ &&\n+\t\t\tgit push\n+\t\t)\n+\t'\n+\"\n+\n+test_done\n-- \n1.6.0.3\n"},{"id":"97842","messageId":"7v4p174diu.fsf@gitster.siamese.dyndns.org","threadId":"16339","inReplyTo":"1229201231-12586-1-git-send-email-marcel@oak.homeunix.org","subject":"Re: [PATCH v3] git-sh-setup: Fix scripts whose PWD is a symlink into a git work-dir","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-12-14T03:54:49Z","receivedAt":"2008-12-14T03:54:49Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Marcel M. Cary\" <marcel@oak.homeunix.org> writes:\n\n> I also removed the \"pwd -P\" from the unit test.\n\nHmm, really...?\n\n>> > +# Prove that the remote end really is a repo, and other commands\n>> > +# work fine in this context.\n>> > +#\n>> > +test_debug \"\n>> > +    test_expect_success 'pushing from symlinked subdir' '\n>> > +\n>> > +        git push\n>> > +    '\n>> > +\"\n>> \n>> Why should this be hidden inside test_debug?\n>\n> I'm not particularly trying to test \"git push\" or \"git pull\" in general\n> here.  That's also why the other \"git pull\" was in a test_debug.  I\n> thought it was really only useful to someone trying to understand the\n> contents of the test file.  There are other files that cover push and\n> pull.  Do you think these test cases should run all the time here?\n\nI'd say so.  Your supporting argument could be \"See, push works just fine\nwith this layout, but pull doesn't because it is a shell script that can\nbe fooled, and this change is to fix the inconsistencies between them.\"\nHaving these test enabled would be a good way to do so.  Then it becomes\nirrelevant if \"jump into the middle of a directory hierarchy sideways via\nsymlink\" is worth supporting or not ;-)\n\nBut whether it is inside test_debug or not, the test should check not just\nthe exit status from 'git push' but also check what happened to the\nreceiving repository at least to make sure it is pushing to the location\nyou are expecting it to.\n\n> diff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh\n> new file mode 100755\n> index 0000000..05854b4\n> --- /dev/null\n> +++ b/t/t2300-cd-to-toplevel.sh\n> @@ -0,0 +1,37 @@\n> +#!/bin/sh\n> +\n> +test_description='cd_to_toplevel'\n> +\n> +. ./test-lib.sh\n> +\n> +test_cd_to_toplevel () {\n> +\ttest_expect_success \"$2\" '\n> +\t\t(\n> +\t\t\tcd '\"'$1'\"' &&\n> +\t\t\t. git-sh-setup &&\n> +\t\t\tcd_to_toplevel &&\n> +\t\t\t[ \"$(pwd -P)\" = \"$TOPLEVEL\" ]\n> +\t\t)\n> +\t'\n> +}\n\nThe quoting of $1 here is a bit tricky, but I think it is good enough for\ndirectory names used in tests that use this function.\n"},{"id":"97982","messageId":"1229362477-22538-1-git-send-email-marcel@oak.homeunix.org","threadId":"16339","inReplyTo":"7v4p174diu.fsf@gitster.siamese.dyndns.org","subject":"[PATCH v3] git-sh-setup: Fix scripts whose PWD is a symlink into a git work-dir","fromName":"Marcel M. Cary","fromEmail":"marcel@oak.homeunix.org","sentAt":"2008-12-15T17:34:37Z","receivedAt":"2008-12-15T17:34:37Z","isPatch":true,"sender":{"key":"marcel@oak.homeunix.org","avatar":"https://gravatar.com/avatar/2bb524e4f383167b7e256bb93256c88353748d9873c34cde0fd461f1165baa0f?d=mp&s=160"},"body":"I want directories of my working tree to be linked to from various\npaths on my filesystem where third-party components expect them, both\nin development and production environments.  A build system's install\nstep could solve this, but I develop scripts and web pages that don't\nneed to be built.  Git's submodule system could solve this, but we\ntend to develop, branch, and test those directories all in unison, so\none big repository feels more natural.  We prefer to edit and commit\non the symlinked paths, not the canonical ones, and in that setting,\n\"git pull\" fails to find the top-level directory of the repository\nwhile other commands work fine.\n\n\"git pull\" fails because POSIX shells have a notion of current working\ndirectory that is different from getcwd().  The shell stores this path\nin PWD.  As a result, \"cd ../\" can be interpreted differently in a\nshell script than chdir(\"../\") in a C program.  The shell interprets\n\"../\" by essentially stripping the last textual path component from\nPWD, whereas C chdir() follows the \"..\" link in the current directory\non the filesystem.  When PWD is a symlink, these are different\ndestinations.  As a result, Git's C commands find the correct\ntop-level working tree, and shell scripts do not.\n\nChanges:\n\n* When interpreting a relative upward (../) path in cd_to_toplevel,\n  prepend the cwd without symlinks, given by /bin/pwd\n* Add tests for cd_to_toplevel and \"git pull\" in a symlinked\n  directory that failed before this fix, plus contrasting scenarios\n  that already worked\n\nSigned-off-by: Marcel M. Cary <marcel@oak.homeunix.org>\n---\n\n> > I also removed the \"pwd -P\" from the unit test.\n>\n> Hmm, really...?\n\nOuch.  Removing just one occurrence won't help much, will it.\n\n> > Do you think these test cases should run all the time here?\n>\n> I'd say so.  Your supporting argument could be \"See, push works just\n> fine with this layout, but pull doesn't because it is a shell script\n> that can be fooled, and this change is to fix the inconsistencies\n> between them.\"\n\nOk, removed those cases from test_debug and emphasized in the first\nparagraph of the commit message that other commands support this kind\nof \"sideways jumping.\"\n\n> But whether it is inside test_debug or not, the test should check\n> not just the exit status from 'git push' but also check what\n> happened to the receiving repository at least to make sure it is\n> pushing to the location you are expecting it to.\n\nOk, I did this by adding an additional file each time and checking the\nsame path in the other repository.\n\n\n git-sh-setup.sh           |   23 ++++++++++++-\n t/t2300-cd-to-toplevel.sh |   37 +++++++++++++++++++++\n t/t5521-pull-symlink.sh   |   78 +++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 136 insertions(+), 2 deletions(-)\n create mode 100755 t/t2300-cd-to-toplevel.sh\n create mode 100755 t/t5521-pull-symlink.sh\n\ndiff --git a/git-sh-setup.sh b/git-sh-setup.sh\nindex dbdf209..f07d96b 100755\n--- a/git-sh-setup.sh\n+++ b/git-sh-setup.sh\n@@ -85,8 +85,27 @@ cd_to_toplevel () {\n \tcdup=$(git rev-parse --show-cdup)\n \tif test ! -z \"$cdup\"\n \tthen\n-\t\tcd \"$cdup\" || {\n-\t\t\techo >&2 \"Cannot chdir to $cdup, the toplevel of the working tree\"\n+\t\tcase \"$cdup\" in\n+\t\t/*)\n+\t\t\t# Not quite the same as if we did \"cd -P '$cdup'\" when\n+\t\t\t# $cdup contains \"..\" after symlink path components.\n+\t\t\t# Don't fix that case at least until Git switches to\n+\t\t\t# \"cd -P\" across the board.\n+\t\t\tphys=\"$cdup\"\n+\t\t\t;;\n+\t\t..|../*|*/..|*/../*)\n+\t\t\t# Interpret $cdup relative to the physical, not logical, cwd.\n+\t\t\t# Probably /bin/pwd is more portable than passing -P to cd or pwd.\n+\t\t\tphys=\"$(/bin/pwd)/$cdup\"\n+\t\t\t;;\n+\t\t*)\n+\t\t\t# There's no \"..\", so no need to make things absolute.\n+\t\t\tphys=\"$cdup\"\n+\t\t\t;;\n+\t\tesac\n+\n+\t\tcd \"$phys\" || {\n+\t\t\techo >&2 \"Cannot chdir to $phys, the toplevel of the working tree\"\n \t\t\texit 1\n \t\t}\n \tfi\ndiff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh\nnew file mode 100755\nindex 0000000..beddb4e\n--- /dev/null\n+++ b/t/t2300-cd-to-toplevel.sh\n@@ -0,0 +1,37 @@\n+#!/bin/sh\n+\n+test_description='cd_to_toplevel'\n+\n+. ./test-lib.sh\n+\n+test_cd_to_toplevel () {\n+\ttest_expect_success \"$2\" '\n+\t\t(\n+\t\t\tcd '\"'$1'\"' &&\n+\t\t\t. git-sh-setup &&\n+\t\t\tcd_to_toplevel &&\n+\t\t\t[ \"$(/bin/pwd)\" = \"$TOPLEVEL\" ]\n+\t\t)\n+\t'\n+}\n+\n+TOPLEVEL=\"$(/bin/pwd)/repo\"\n+mkdir -p repo/sub/dir\n+mv .git repo/\n+SUBDIRECTORY_OK=1\n+\n+test_cd_to_toplevel repo 'at physical root'\n+\n+test_cd_to_toplevel repo/sub/dir 'at physical subdir'\n+\n+ln -s repo symrepo\n+test_cd_to_toplevel symrepo 'at symbolic root'\n+\n+ln -s repo/sub/dir subdir-link\n+test_cd_to_toplevel subdir-link 'at symbolic subdir'\n+\n+cd repo\n+ln -s sub/dir internal-link\n+test_cd_to_toplevel internal-link 'at internal symbolic subdir'\n+\n+test_done\ndiff --git a/t/t5521-pull-symlink.sh b/t/t5521-pull-symlink.sh\nnew file mode 100755\nindex 0000000..5672b51\n--- /dev/null\n+++ b/t/t5521-pull-symlink.sh\n@@ -0,0 +1,78 @@\n+#!/bin/sh\n+\n+test_description='pulling from symlinked subdir'\n+\n+. ./test-lib.sh\n+\n+# The scenario we are building:\n+#\n+#   trash\\ directory/\n+#     clone-repo/\n+#       subdir/\n+#         bar\n+#     subdir-link -> clone-repo/subdir/\n+#\n+# The working directory is subdir-link.\n+\n+mkdir subdir\n+echo file >subdir/file\n+git add subdir/file\n+git commit -q -m file\n+git clone -q . clone-repo\n+ln -s clone-repo/subdir/ subdir-link\n+\n+\n+# Demonstrate that things work if we just avoid the symlink\n+#\n+test_expect_success 'pulling from real subdir' '\n+\t(\n+\t\techo real >subdir/file &&\n+\t\tgit commit -m real subdir/file &&\n+\t\tcd clone-repo/subdir/ &&\n+\t\tgit pull &&\n+\t\ttest real = $(cat file)\n+\t)\n+'\n+\n+# From subdir-link, pulling should work as it does from\n+# clone-repo/subdir/.\n+#\n+# Instead, the error pull gave was:\n+#\n+#   fatal: 'origin': unable to chdir or not a git archive\n+#   fatal: The remote end hung up unexpectedly\n+#\n+# because git would find the .git/config for the \"trash directory\"\n+# repo, not for the clone-repo repo.  The \"trash directory\" repo\n+# had no entry for origin.  Git found the wrong .git because\n+# git rev-parse --show-cdup printed a path relative to\n+# clone-repo/subdir/, not subdir-link/.  Git rev-parse --show-cdup\n+# used the correct .git, but when the git pull shell script did\n+# \"cd `git rev-parse --show-cdup`\", it ended up in the wrong\n+# directory.  A POSIX shell's \"cd\" works a little differently\n+# than chdir() in C; \"cd -P\" is much closer to chdir().\n+#\n+test_expect_success 'pulling from symlinked subdir' '\n+\t(\n+\t\techo link >subdir/file &&\n+\t\tgit commit -m link subdir/file &&\n+\t\tcd subdir-link/ &&\n+\t\tgit pull &&\n+\t\ttest link = $(cat file)\n+\t)\n+'\n+\n+# Prove that the remote end really is a repo, and other commands\n+# work fine in this context.  It's just that \"git pull\" breaks.\n+#\n+test_expect_success 'pushing from symlinked subdir' '\n+\t(\n+\t\tcd subdir-link/ &&\n+\t\techo push >file &&\n+\t\tgit commit -m push ./file &&\n+\t\tgit push\n+\t) &&\n+\ttest push = $(git show HEAD:subdir/file)\n+'\n+\n+test_done\n-- \n1.6.0.3\n"},{"id":"97984","messageId":"Pine.LNX.4.64.0812150936570.7986@ordinateur.home.org","threadId":"16339","inReplyTo":"1229362477-22538-1-git-send-email-marcel@oak.homeunix.org","subject":"Re: [PATCH v3] <-- really v4","fromName":"Marcel M. Cary","fromEmail":"marcel@oak.homeunix.org","sentAt":"2008-12-15T17:38:04Z","receivedAt":"2008-12-15T17:38:04Z","isPatch":true,"sender":{"key":"marcel@oak.homeunix.org","avatar":"https://gravatar.com/avatar/2bb524e4f383167b7e256bb93256c88353748d9873c34cde0fd461f1165baa0f?d=mp&s=160"},"body":"I guess I'm really on v4, sorry.\n\nMarcel\n"},{"id":"103578","messageId":"1233977068-24861-1-git-send-email-marcel@oak.homeunix.org","threadId":"16339","inReplyTo":"7viqq1hghw.fsf@gitster.siamese.dyndns.org","subject":"[RFC PATCH] git-sh-setup: Use \"cd\" option, not /bin/pwd, for symlinked work tree","fromName":"Marcel M. Cary","fromEmail":"marcel@oak.homeunix.org","sentAt":"2009-02-07T03:24:28Z","receivedAt":"2009-02-07T03:24:28Z","isPatch":true,"sender":{"key":"marcel@oak.homeunix.org","avatar":"https://gravatar.com/avatar/2bb524e4f383167b7e256bb93256c88353748d9873c34cde0fd461f1165baa0f?d=mp&s=160"},"body":"In cd_to_toplevel, instead of 'cd $(unset PWD; /bin/pwd)/$path'\nuse 'cd -P $path'.  The \"-P\" option yields a desirable similarity to\nC chdir.\n\nWhile the \"-P\" option may be slightly less commonly supported than\n/bin/pwd, it is more concise, better tested, and less error prone.\nI've already added the 'unset PWD' to fix the /bin/pwd solution on\nBSD; there may be more edge cases out there.\n\nThis still passes all the same test cases in t5521-pull-symlink.sh and\nt2300-cd-to-toplevel.sh, even before updating them to use 'pwd -P'.\n---\n\n> ... I think it would probably be better to bite the bullet\n> and start using \"cd -P\" soon after 1.6.1 goes final, ...\n\nHere's a post-1.6.1 way to make Git shell scripts work like C programs\nwhen in symlinked directories.\n\n> ... and at the same time\n> existing places that use \"cd `pwd`\" as a workaround if there are some.\n\nI haven't found other places that use the \"cd `/bin/pwd`\" workaround.\n\nI also wasn't able to think of a test case that fails under the previous\nway and works under this new way either.\n\nAny opinions on whether this is worthwhile?  It seems more standardized\nif less supported, odd as that seems to me.\n\nMarcel\n\n git-sh-setup.sh           |   29 ++++++++---------------------\n t/t2300-cd-to-toplevel.sh |    4 ++--\n 2 files changed, 10 insertions(+), 23 deletions(-)\n\ndiff --git a/git-sh-setup.sh b/git-sh-setup.sh\nindex 2142308..8382339 100755\n--- a/git-sh-setup.sh\n+++ b/git-sh-setup.sh\n@@ -85,27 +85,14 @@ cd_to_toplevel () {\n \tcdup=$(git rev-parse --show-cdup)\n \tif test ! -z \"$cdup\"\n \tthen\n-\t\tcase \"$cdup\" in\n-\t\t/*)\n-\t\t\t# Not quite the same as if we did \"cd -P '$cdup'\" when\n-\t\t\t# $cdup contains \"..\" after symlink path components.\n-\t\t\t# Don't fix that case at least until Git switches to\n-\t\t\t# \"cd -P\" across the board.\n-\t\t\tphys=\"$cdup\"\n-\t\t\t;;\n-\t\t..|../*|*/..|*/../*)\n-\t\t\t# Interpret $cdup relative to the physical, not logical, cwd.\n-\t\t\t# Probably /bin/pwd is more portable than passing -P to cd or pwd.\n-\t\t\tphys=\"$(unset PWD; /bin/pwd)/$cdup\"\n-\t\t\t;;\n-\t\t*)\n-\t\t\t# There's no \"..\", so no need to make things absolute.\n-\t\t\tphys=\"$cdup\"\n-\t\t\t;;\n-\t\tesac\n-\n-\t\tcd \"$phys\" || {\n-\t\t\techo >&2 \"Cannot chdir to $phys, the toplevel of the working tree\"\n+\t\t# The \"-P\" option says to follow \"physical\" directory\n+\t\t# structure instead of following symbolic links.  When cdup is\n+\t\t# \"../\", this means following the \"..\" entry in the current\n+\t\t# directory instead textually removing a symlink path element\n+\t\t# from the PWD shell variable.  The \"-P\" behavior is more\n+\t\t# consistent with the C-style chdir used by most of Git.\n+\t\tcd -P \"$cdup\" || {\n+\t\t\techo >&2 \"Cannot chdir to $cdup, the toplevel of the working tree\"\n \t\t\texit 1\n \t\t}\n \tfi\ndiff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh\nindex e42cbfe..293dc35 100755\n--- a/t/t2300-cd-to-toplevel.sh\n+++ b/t/t2300-cd-to-toplevel.sh\n@@ -10,12 +10,12 @@ test_cd_to_toplevel () {\n \t\t\tcd '\"'$1'\"' &&\n \t\t\t. git-sh-setup &&\n \t\t\tcd_to_toplevel &&\n-\t\t\t[ \"$(unset PWD; /bin/pwd)\" = \"$TOPLEVEL\" ]\n+\t\t\t[ \"$(pwd -P)\" = \"$TOPLEVEL\" ]\n \t\t)\n \t'\n }\n \n-TOPLEVEL=\"$(unset PWD; /bin/pwd)/repo\"\n+TOPLEVEL=\"$(pwd -P)/repo\"\n mkdir -p repo/sub/dir\n mv .git repo/\n SUBDIRECTORY_OK=1\n-- \n1.6.1\n"},{"id":"103614","messageId":"alpine.DEB.1.00.0902071324230.10279@pacific.mpi-cbg.de","threadId":"16339","inReplyTo":"1233977068-24861-1-git-send-email-marcel@oak.homeunix.org","subject":"Re: [RFC PATCH] git-sh-setup: Use \"cd\" option, not /bin/pwd, for symlinked work tree","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-02-07T12:25:23Z","receivedAt":"2009-02-07T12:25:23Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 6 Feb 2009, Marcel M. Cary wrote:\n\n> While the \"-P\" option may be slightly less commonly supported than\n> /bin/pwd,\n\nDoes this not suggest that your patch should at least fall back to using \n/bin/pwd when it was detected that \"cd -P\" does not work?\n\nCiao,\nDscho\n"},{"id":"103766","messageId":"498F2049.9030608@oak.homeunix.org","threadId":"16339","inReplyTo":"alpine.DEB.1.00.0902071324230.10279@pacific.mpi-cbg.de","subject":"Re: [RFC PATCH] git-sh-setup: Use \"cd\" option, not /bin/pwd, for symlinked work tree","fromName":"Marcel M. Cary","fromEmail":"marcel@oak.homeunix.org","sentAt":"2009-02-08T18:11:21Z","receivedAt":"2009-02-08T18:11:21Z","isPatch":true,"sender":{"key":"marcel@oak.homeunix.org","avatar":"https://gravatar.com/avatar/2bb524e4f383167b7e256bb93256c88353748d9873c34cde0fd461f1165baa0f?d=mp&s=160"},"body":"Johannes Schindelin wrote:\n> On Fri, 6 Feb 2009, Marcel M. Cary wrote:\n>> While the \"-P\" option may be slightly less commonly supported than\n>> /bin/pwd,\n>\n> Does this not suggest that your patch should at least fall back to\n> using /bin/pwd when it was detected that \"cd -P\" does not work?\n\nHaving the \"cd -P\" strategy fall back to /bin/pwd negates most of the\nvalue I saw in using the simpler strategy.\n\nI haven't found cases where \"cd -P\" is more correct.  Are there other\nreasons to bother with \"cd -P\" at all?  Maybe performance: \"cd -P\"\nwould save a fork, which seems to make it ~10x faster.  Dropping buffer\ncaches doesn't seem to widen or narrow the gap, so I don't think the\nfilesystem access is much different, performance-wise.  But I don't\nexpect this \"cd\" to be a performance bottleneck; most scripts that do\nsomething repetitive can just start off in the work tree root to avoid\nthe issue.\n\nFalling back to /bin/pwd would help compatibility if it were easy to\ndetect when \"cd -P\" failed.  But since its failure is hypothetical for\nme at this point -- I don't know of an environment where it fails -- I'm\nnot sure whether to expect it to fail with non-zero exit status or by\nsilently ignoring the \"-P\".  And to handle the cases of silently\nignoring the \"-P\" I'd guess cd_to_toplevel would have to run /bin/pwd\njust to check that it ended up in the right place, which seems\ncounterproductive to me.  Do you think it would be reasonable to just\nassume \"cd -P\" will exit non-zero if \"cd\" doesn't understand \"-P\", send\nits stderr to /dev/null, and try again using /bin/pwd?\n\nMarcel\n"},{"id":"103783","messageId":"alpine.DEB.1.00.0902082154450.10279@pacific.mpi-cbg.de","threadId":"16339","inReplyTo":"498F2049.9030608@oak.homeunix.org","subject":"Re: [RFC PATCH] git-sh-setup: Use \"cd\" option, not /bin/pwd, for symlinked work tree","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-02-08T20:56:14Z","receivedAt":"2009-02-08T20:56:14Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 8 Feb 2009, Marcel M. Cary wrote:\n\n> Johannes Schindelin wrote:\n> > On Fri, 6 Feb 2009, Marcel M. Cary wrote:\n> >> While the \"-P\" option may be slightly less commonly supported than\n> >> /bin/pwd,\n> >\n> > Does this not suggest that your patch should at least fall back to\n> > using /bin/pwd when it was detected that \"cd -P\" does not work?\n> \n> Having the \"cd -P\" strategy fall back to /bin/pwd negates most of the\n> value I saw in using the simpler strategy.\n> \n> I haven't found cases where \"cd -P\" is more correct.\n\nActually, it was not clear for me how much you researched the portability \nof \"cd -P\".\n\nAs long as it is not proven that your patch keeps working setups working, \nI think you'll have to put in a bit more effort, research it, and then put \nthe discussion into the commit message.\n\nCiao,\nDscho\n"},{"id":"104189","messageId":"4992E459.1060401@oak.homeunix.org","threadId":"16339","inReplyTo":"alpine.DEB.1.00.0902082154450.10279@pacific.mpi-cbg.de","subject":"Re: [RFC PATCH] git-sh-setup: Use \"cd\" option, not /bin/pwd, for symlinked work tree","fromName":"Marcel M. Cary","fromEmail":"marcel@oak.homeunix.org","sentAt":"2009-02-11T14:44:41Z","receivedAt":"2009-02-11T14:44:41Z","isPatch":true,"sender":{"key":"marcel@oak.homeunix.org","avatar":"https://gravatar.com/avatar/2bb524e4f383167b7e256bb93256c88353748d9873c34cde0fd461f1165baa0f?d=mp&s=160"},"body":"Johannes Schindelin wrote:\n> On Sun, 8 Feb 2009, Marcel M. Cary wrote:\n>> Johannes Schindelin wrote:\n>>> On Fri, 6 Feb 2009, Marcel M. Cary wrote:\n>>>> While the \"-P\" option may be slightly less commonly supported than\n>>>> /bin/pwd,\n>>> Does this not suggest that your patch should at least fall back to\n>>> using /bin/pwd when it was detected that \"cd -P\" does not work?\n>> Having the \"cd -P\" strategy fall back to /bin/pwd negates most of the\n>> value I saw in using the simpler strategy.\n>>\n>> I haven't found cases where \"cd -P\" is more correct.\n> \n> Actually, it was not clear for me how much you researched the portability \n> of \"cd -P\".\n\nI have not.  I've seen only that it's POSIX, is on BSD and Linux, and\nwas suggested by Junio.\n\n> As long as it is not proven that your patch keeps working setups working, \n> I think you'll have to put in a bit more effort, research it, and then put \n> the discussion into the commit message.\n\nActually, since I haven't heard any continued interest in following up\nwith the suggestion to use \"cd -P\", I don't see much benefit myself, and\nthere is concern about it not being compatible enough, I'm content to\njust table this.\n\nI agree that keeping working setups working is important, and it seems\nlike a major project to research portability of \"cd -P\" on a list of\nplatforms that I'm guessing I'd have to collect myself.\n\nMarcel\n"},{"id":"104241","messageId":"20090211181653.GD19749@coredump.intra.peff.net","threadId":"16339","inReplyTo":"4992E459.1060401@oak.homeunix.org","subject":"Re: [RFC PATCH] git-sh-setup: Use \"cd\" option, not /bin/pwd, for symlinked work tree","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2009-02-11T18:16:53Z","receivedAt":"2009-02-11T18:16:53Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Feb 11, 2009 at 06:44:41AM -0800, Marcel M. Cary wrote:\n\n> > Actually, it was not clear for me how much you researched the portability \n> > of \"cd -P\".\n> \n> I have not.  I've seen only that it's POSIX, is on BSD and Linux, and\n> was suggested by Junio.\n\nEven Solaris /usr/xpg4/bin/sh has it. Their /bin/sh does not, but that\nis not a surprise: that shell is useless and already unsupported by git.\n\nI don't know about other obscure platforms (wasn't there some guy\nrunning git on antique SCO machines or something?).\n\nI think it is nice to shoot for \"more portable\" in general, and I don't\nparticularly care one way or the other about this feature. But I think\nwe are somewhat hampered by having no clue what the supported set of\nplatforms is. I'm pretty sure we support at least:\n\n  - various recent Linux distributions\n  - FreeBSD 6.x (maybe as far back as 4.x)\n  - OS X\n  - NetBSD and OpenBSD, but no idea which versions\n  - Solaris >= 2.8\n  - AIX 5.3\n\nand I suspect most of those have somebody building them regularly enough\nthat breakages are caught. I have no idea what people are using beyond\nthat, and how quickly they might catch a portability breakage.\n\n-Peff\n"}]}