{"thread":{"id":"24480","subject":"[PATCH 1/2] worktree setup: return to original cwd if prefix is set NULL","startedAt":"2010-07-23T12:04:10Z","lastAt":"2010-07-24T12:15:56Z","messageCount":20,"participants":["Nguyễn Thái Ngọc Duy","Ævar Arnfjörð Bjarmason","Nguyen Thai Ngoc Duy","Jonathan Nieder"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"146065","messageId":"1279886651-14590-1-git-send-email-pclouds@gmail.com","threadId":"24480","inReplyTo":null,"subject":"[PATCH 1/2] worktree setup: return to original cwd if prefix is set NULL","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-07-23T12:04:10Z","receivedAt":"2010-07-23T12:04:10Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Commit a672ea6 (rehabilitate 'git index-pack' inside the object\nstore - 2008-10-20) worked around a fault in\nsetup_git_directory_gently(). When walking up from inside a git\nrepository, we will return NULL as prefix.\n\nPrefix and cwd should be consistent. That is if cwd is moved, prefix\nreflects that. If prefix is NULL, cwd is unmoved. In this case, to\nretain current behavior, we move cwd back, with an eye on gitdir\nbecause gitdir may be relative to cwd.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n setup.c             |    7 +++++++\n t/t1501-worktree.sh |   21 +++++++++++++++++++++\n 2 files changed, 28 insertions(+), 0 deletions(-)\n\ndiff --git a/setup.c b/setup.c\nindex 87c21f0..33eb253 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -413,6 +413,13 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t\t\tif (!work_tree_env)\n \t\t\t\tinside_work_tree = 0;\n \t\t\tif (offset != len) {\n+\t\t\t\t/*\n+\t\t\t\t * The returned prefix in this code path is NULL\n+\t\t\t\t * chdir() back to match NULL prefix, i.e. unmoved cwd\n+\t\t\t\t */\n+\t\t\t\tif (chdir(cwd))\n+\t\t\t\t\tdie_errno(\"Cannot come back to cwd\");\n+\n \t\t\t\troot_len = offset_1st_component(cwd);\n \t\t\t\tcwd[offset > root_len ? offset : root_len] = '\\0';\n \t\t\t\tset_git_dir(cwd);\ndiff --git a/t/t1501-worktree.sh b/t/t1501-worktree.sh\nindex bd8b607..edd81ce 100755\n--- a/t/t1501-worktree.sh\n+++ b/t/t1501-worktree.sh\n@@ -33,6 +33,27 @@ mkdir -p work/sub/dir || exit 1\n mkdir -p work2 || exit 1\n mv .git repo.git || exit 1\n \n+cat >repo.git/objects/patch <<\\EOF\n+diff one one\n+--- one\n++++ one\n+@@ -1 +1,2 @@\n+ 1\n++2\n+EOF\n+\n+test_expect_success 'cwd is unchanged when prefix is NULL (from within a repo)' '\n+\t(\n+\t\tcd repo.git/objects &&\n+\t\techo 1 > one &&\n+\t\tcp one expected &&\n+\t\techo 2 >> expected &&\n+\t\tgit apply patch &&\n+\t\ttest_cmp expected one &&\n+\t\trm one expected patch\n+\t)\n+'\n+\n say \"core.worktree = relative path\"\n GIT_DIR=repo.git\n GIT_CONFIG=\"$(pwd)\"/$GIT_DIR/config\n-- \n1.7.1.rc1.69.g24c2f7\n"},{"id":"146066","messageId":"1279886651-14590-2-git-send-email-pclouds@gmail.com","threadId":"24480","inReplyTo":"1279886651-14590-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 2/2] Revert \"rehabilitate 'git index-pack' inside the object store\"","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-07-23T12:04:11Z","receivedAt":"2010-07-23T12:04:11Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This reverts code change in commit a672ea6ac5a1b876bc7adfe6534b16fa2a32c94b.\n\nThe cwd behavior now fits index-pack well, i.e. NULL prefix means\nno cwd changes.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/index-pack.c |   24 +++++-------------------\n 1 files changed, 5 insertions(+), 19 deletions(-)\n\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex a89ae83..89a1f12 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -880,29 +880,15 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)\n \tchar *index_name_buf = NULL, *keep_name_buf = NULL;\n \tstruct pack_idx_entry **idx_objects;\n \tunsigned char pack_sha1[20];\n+\tint nongit;\n \n \tif (argc == 2 && !strcmp(argv[1], \"-h\"))\n \t\tusage(index_pack_usage);\n \n-\t/*\n-\t * We wish to read the repository's config file if any, and\n-\t * for that it is necessary to call setup_git_directory_gently().\n-\t * However if the cwd was inside .git/objects/pack/ then we need\n-\t * to go back there or all the pack name arguments will be wrong.\n-\t * And in that case we cannot rely on any prefix returned by\n-\t * setup_git_directory_gently() either.\n-\t */\n-\t{\n-\t\tchar cwd[PATH_MAX+1];\n-\t\tint nongit;\n-\n-\t\tif (!getcwd(cwd, sizeof(cwd)-1))\n-\t\t\tdie(\"Unable to get current working directory\");\n-\t\tsetup_git_directory_gently(&nongit);\n-\t\tgit_config(git_index_pack_config, NULL);\n-\t\tif (chdir(cwd))\n-\t\t\tdie(\"Cannot come back to cwd\");\n-\t}\n+\tprefix = setup_git_directory_gently(&nongit);\n+\tgit_config(git_index_pack_config, NULL);\n+\tif (prefix && chdir(prefix))\n+\t\tdie(\"Cannot come back to cwd\");\n \n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\n-- \n1.7.1.rc1.69.g24c2f7\n"},{"id":"146073","messageId":"AANLkTimkwfetLWynKCGVxMT0ZzHOZQp_iknrohoV8A79@mail.gmail.com","threadId":"24480","inReplyTo":"1279886651-14590-1-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH 1/2] worktree setup: return to original cwd if prefix is set NULL","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2010-07-23T14:38:21Z","receivedAt":"2010-07-23T14:38:21Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"2010/7/23 Nguyễn Thái Ngọc Duy <pclouds@gmail.com>:\n\n> +test_expect_success 'cwd is unchanged when prefix is NULL (from within a repo)' '\n> +       (\n> +               cd repo.git/objects &&\n> +               echo 1 > one &&\n> +               cp one expected &&\n> +               echo 2 >> expected &&\n> +               git apply patch &&\n> +               test_cmp expected one &&\n> +               rm one expected patch\n> +       )\n> +'\n\nIs the rm at the end needed here?\n\nThis is a minor nit, but it's generally helpful for debugging tests\nthat things aren't removed if the --debug option is specified.\n"},{"id":"146140","messageId":"1279914472-6544-1-git-send-email-pclouds@gmail.com","threadId":"24480","inReplyTo":"AANLkTilTmddAdEtLWvZy1wmB-kRPUL3E54lyKKWwfDqG@mail.gmail.com","subject":"[PATCH 1/2] worktree setup: return to original cwd if prefix is set NULL","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-07-23T19:47:52Z","receivedAt":"2010-07-23T19:47:52Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Commit a672ea6 (rehabilitate 'git index-pack' inside the object\nstore - 2008-10-20) worked around a fault in\nsetup_git_directory_gently(). When walking up from inside a git\nrepository, we will return NULL as prefix.\n\nPrefix and cwd should be consistent. That is if cwd is moved, prefix\nreflects that. If prefix is NULL, cwd is unmoved. In this case, to\nretain current behavior, we move cwd back, with an eye on gitdir\nbecause gitdir may be relative to cwd.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n  On Sat, Jul 24, 2010 at 01:16:00AM +0000, Ævar Arnfjörð Bjarmason wrote:\n  > On Sat, Jul 24, 2010 at 00:50, Nguyen Thai Ngoc Duy <pclouds@gmail.com> wrote:\n  > \n  > > I don't want to pollute the repo early. If the test fails, rm would not be run.\n  > \n  > Sure, I'm just asking if there's a reason to run rm in this\n  > case. Because usually we defer the whole rm to be done inside\n  > test-lib.sh once the entire test completes.\n  \n  \"rm\" removed. The rest of the tests do not seem to care whatelse in objects..\n\n setup.c             |    7 +++++++\n t/t1501-worktree.sh |   20 ++++++++++++++++++++\n 2 files changed, 27 insertions(+), 0 deletions(-)\n\ndiff --git a/setup.c b/setup.c\nindex 87c21f0..33eb253 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -413,6 +413,13 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t\t\tif (!work_tree_env)\n \t\t\t\tinside_work_tree = 0;\n \t\t\tif (offset != len) {\n+\t\t\t\t/*\n+\t\t\t\t * The returned prefix in this code path is NULL\n+\t\t\t\t * chdir() back to match NULL prefix, i.e. unmoved cwd\n+\t\t\t\t */\n+\t\t\t\tif (chdir(cwd))\n+\t\t\t\t\tdie_errno(\"Cannot come back to cwd\");\n+\n \t\t\t\troot_len = offset_1st_component(cwd);\n \t\t\t\tcwd[offset > root_len ? offset : root_len] = '\\0';\n \t\t\t\tset_git_dir(cwd);\ndiff --git a/t/t1501-worktree.sh b/t/t1501-worktree.sh\nindex bd8b607..a024056 100755\n--- a/t/t1501-worktree.sh\n+++ b/t/t1501-worktree.sh\n@@ -33,6 +33,26 @@ mkdir -p work/sub/dir || exit 1\n mkdir -p work2 || exit 1\n mv .git repo.git || exit 1\n \n+cat >repo.git/objects/patch <<\\EOF\n+diff one one\n+--- one\n++++ one\n+@@ -1 +1,2 @@\n+ 1\n++2\n+EOF\n+\n+test_expect_success 'cwd is unchanged when prefix is NULL (from within a repo)' '\n+\t(\n+\t\tcd repo.git/objects &&\n+\t\techo 1 > one &&\n+\t\tcp one expected &&\n+\t\techo 2 >> expected &&\n+\t\tgit apply patch &&\n+\t\ttest_cmp expected one\n+\t)\n+'\n+\n say \"core.worktree = relative path\"\n GIT_DIR=repo.git\n GIT_CONFIG=\"$(pwd)\"/$GIT_DIR/config\n-- \n1.7.1.rc1.69.g24c2f7\n"},{"id":"146124","messageId":"AANLkTin6xGRz7wFyWtYg4ysPPytEW-uQn8ij1YbjJ_m9@mail.gmail.com","threadId":"24480","inReplyTo":"AANLkTimkwfetLWynKCGVxMT0ZzHOZQp_iknrohoV8A79@mail.gmail.com","subject":"Re: [PATCH 1/2] worktree setup: return to original cwd if prefix is set NULL","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-07-24T00:50:09Z","receivedAt":"2010-07-24T00:50:09Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"2010/7/24 Ævar Arnfjörð Bjarmason <avarab@gmail.com>:\n> 2010/7/23 Nguyễn Thái Ngọc Duy <pclouds@gmail.com>:\n>\n>> +test_expect_success 'cwd is unchanged when prefix is NULL (from within a repo)' '\n>> +       (\n>> +               cd repo.git/objects &&\n>> +               echo 1 > one &&\n>> +               cp one expected &&\n>> +               echo 2 >> expected &&\n>> +               git apply patch &&\n>> +               test_cmp expected one &&\n>> +               rm one expected patch\n>> +       )\n>> +'\n>\n> Is the rm at the end needed here?\n>\n> This is a minor nit, but it's generally helpful for debugging tests\n> that things aren't removed if the --debug option is specified.\n>\n\nI don't want to pollute the repo early. If the test fails, rm would not be run.\n-- \nDuy\n"},{"id":"146131","messageId":"AANLkTilTmddAdEtLWvZy1wmB-kRPUL3E54lyKKWwfDqG@mail.gmail.com","threadId":"24480","inReplyTo":"AANLkTin6xGRz7wFyWtYg4ysPPytEW-uQn8ij1YbjJ_m9@mail.gmail.com","subject":"Re: [PATCH 1/2] worktree setup: return to original cwd if prefix is set NULL","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2010-07-24T01:16:00Z","receivedAt":"2010-07-24T01:16:00Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Sat, Jul 24, 2010 at 00:50, Nguyen Thai Ngoc Duy <pclouds@gmail.com> wrote:\n\n> I don't want to pollute the repo early. If the test fails, rm would not be run.\n\nSure, I'm just asking if there's a reason to run rm in this\ncase. Because usually we defer the whole rm to be done inside\ntest-lib.sh once the entire test completes.\n"},{"id":"146149","messageId":"20100724111505.GC7150@burratino","threadId":"24480","inReplyTo":"1279886651-14590-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 0/9] setup_git_directory(): return to original cwd upon reaching .git","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-07-24T11:15:06Z","receivedAt":"2010-07-24T11:15:06Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Hi Duy,\n\nNguyễn Thái Ngọc Duy wrote:\n\n> Prefix and cwd should be consistent.\n\nI agree with this, but it took me a while to figure out why your fix\nis safe.  Here’s how I figured it out.\n\nPatch 1 cleans up the test script you added a test to.  After cleaning\nit up, it is clearer the test does not belong there.\n\nPatch 2 creates a proper home for the new test.\n\nPatches 3-7 split up setup_git_directory_gently() into small enough\npieces that a person with a short attention span can read it now.\nNo functional change intended.\n\nPatch 8 is your fix.  I removed the comment (which was just confusing\nme) and clarified the commit message to compensate\n\nPatch 9 is your patch to revert the other, now redundant fix, also\nwith commit message tweaks.\n\nAfter this exercise, your patches still look good. :)  Maybe these\nby-products could be useful somehow.\n\nThoughts (especially improvements) welcome.\n\nJonathan Nieder (7):\n  t1501 (rev-parse): clarify\n  tests: try git apply from subdir of toplevel\n  setup: split off $GIT_DIR-set case from setup_git_directory_gently\n  setup: split off a function to checks working dir for .git file\n  setup: split off code to handle stumbling upon a repository\n  setup: split off a function to handle hitting ceiling in repo search\n  setup: split off get_device_or_die function\n\nNguyễn Thái Ngọc Duy (2):\n  setup: do not forget working dir from subdir of gitdir\n  Revert \"rehabilitate 'git index-pack' inside the object store\"\n\n builtin/index-pack.c    |   24 +--\n setup.c                 |  171 ++++++++++--------\n t/t1501-worktree.sh     |  467 ++++++++++++++++++++++++++++++-----------------\n t/t4111-apply-subdir.sh |  141 ++++++++++++++\n 4 files changed, 547 insertions(+), 256 deletions(-)\n create mode 100755 t/t4111-apply-subdir.sh\n\n-- \n1.7.2.rc3\n"},{"id":"146150","messageId":"20100724111634.GA16054@burratino","threadId":"24480","inReplyTo":"20100724111505.GC7150@burratino","subject":"[PATCH 1/9] t1501 (rev-parse): clarify","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-07-24T11:16:35Z","receivedAt":"2010-07-24T11:16:35Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Tweak the style of these tests to make them easier to read.\n\n - Replace test_rev_parse() which produced multiple mini-tests with a\n   simple function that can be used with the test body.\n\n - Combine multiple mini-tests into larger chunks that are easier\n   to read.\n\n - Do not hard-code object IDs.  We may use a different hash some day.\n\n - Use test_cmp in preference to the test builtin.  The former\n   produces useful output when tests are run with the \"-v\" option.\n\n - Guard all test code with test_expect_success.  This makes it much\n   easier to visually scan through the test and find code of interest.\n\n - Use subshells to make the current directory easier to track.\n   Outside of any subshell, the current directory is always\n   $TEST_DIRECTORY now.\n\nAlso add a new test demonstrating a possible bug noticed in the\nprocess of cleaning up:  “git rev-parse --show-prefix” leaves out\nthe trailing newline after an empty prefix when cwd is at the\ntoplevel of the work tree.\n\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\n t/t1501-worktree.sh |  467 +++++++++++++++++++++++++++++++++------------------\n 1 files changed, 302 insertions(+), 165 deletions(-)\n\ndiff --git a/t/t1501-worktree.sh b/t/t1501-worktree.sh\nindex bd8b607..2c8f01f 100755\n--- a/t/t1501-worktree.sh\n+++ b/t/t1501-worktree.sh\n@@ -3,183 +3,320 @@\n test_description='test separate work tree'\n . ./test-lib.sh\n \n-test_rev_parse() {\n-\tname=$1\n-\tshift\n-\n-\ttest_expect_success \"$name: is-bare-repository\" \\\n-\t\"test '$1' = \\\"\\$(git rev-parse --is-bare-repository)\\\"\"\n-\tshift\n-\t[ $# -eq 0 ] && return\n-\n-\ttest_expect_success \"$name: is-inside-git-dir\" \\\n-\t\"test '$1' = \\\"\\$(git rev-parse --is-inside-git-dir)\\\"\"\n-\tshift\n-\t[ $# -eq 0 ] && return\n-\n-\ttest_expect_success \"$name: is-inside-work-tree\" \\\n-\t\"test '$1' = \\\"\\$(git rev-parse --is-inside-work-tree)\\\"\"\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-EMPTY_TREE=$(git write-tree)\n-mkdir -p work/sub/dir || exit 1\n-mkdir -p work2 || exit 1\n-mv .git repo.git || exit 1\n-\n-say \"core.worktree = relative path\"\n-GIT_DIR=repo.git\n-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-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-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-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-cd work2\n-test_rev_parse 'outside2'     false false false\n-cd ../work || exit 1\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-cd ../../.. || exit 1\n-\n-say \"GIT_WORK_TREE=relative path (override core.worktree)\"\n-GIT_DIR=$(pwd)/repo.git\n-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-cd work2\n-test_rev_parse 'outside'      false false false\n-cd ../work || exit 1\n-GIT_WORK_TREE=.\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-cd ../../.. || exit 1\n-\n-mv work repo.git/work\n-mv work2 repo.git/work2\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-cd repo.git || exit 1\n-test_rev_parse 'in repo.git'              false true  false\n-cd objects || exit 1\n-test_rev_parse 'in repo.git/objects'      false true  false\n-cd ../work2 || exit 1\n-test_rev_parse 'in repo.git/work2'      false true  false\n-cd ../work || exit 1\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-cd ../../../.. || exit 1\n-\n-test_expect_success 'repo finds its work tree' '\n-\t(cd repo.git &&\n-\t : > work/sub/dir/untracked &&\n-\t test sub/dir/untracked = \"$(git ls-files --others)\")\n-'\n-\n-test_expect_success 'repo finds its work tree from work tree, too' '\n-\t(cd repo.git/work/sub/dir &&\n-\t : > tracked &&\n-\t git --git-dir=../../.. add tracked &&\n-\t cd ../../.. &&\n-\t test sub/dir/tracked = \"$(git ls-files)\")\n+test_expect_success 'setup' '\n+\tEMPTY_TREE=$(git write-tree) &&\n+\tEMPTY_BLOB=$(git hash-object -t blob --stdin </dev/null) &&\n+\tCHANGED_BLOB=$(echo changed | git hash-object -t blob --stdin) &&\n+\tZEROES=0000000000000000000000000000000000000000 &&\n+\tEMPTY_BLOB7=$(echo $EMPTY_BLOB | sed \"s/\\(.......\\).*/\\1/\") &&\n+\tCHANGED_BLOB7=$(echo $CHANGED_BLOB | sed \"s/\\(.......\\).*/\\1/\") &&\n+\n+\tmkdir -p work/sub/dir &&\n+\tmkdir -p work2 &&\n+\tmv .git repo.git\n+'\n+\n+test_expect_success 'setup: helper for testing rev-parse' '\n+\ttest_rev_parse() {\n+\t\techo $1 >expected.bare &&\n+\t\techo $2 >expected.inside-git &&\n+\t\techo $3 >expected.inside-worktree &&\n+\t\tif test $# -ge 4\n+\t\tthen\n+\t\t\techo $4 >expected.prefix\n+\t\tfi &&\n+\n+\t\tgit rev-parse --is-bare-repository >actual.bare &&\n+\t\tgit rev-parse --is-inside-git-dir >actual.inside-git &&\n+\t\tgit rev-parse --is-inside-work-tree >actual.inside-worktree &&\n+\t\tif test $# -ge 4\n+\t\tthen\n+\t\t\tgit rev-parse --show-prefix >actual.prefix\n+\t\tfi &&\n+\n+\t\ttest_cmp expected.bare actual.bare &&\n+\t\ttest_cmp expected.inside-git actual.inside-git &&\n+\t\ttest_cmp expected.inside-worktree actual.inside-worktree &&\n+\t\tif test $# -ge 4\n+\t\tthen\n+\t\t\t# rev-parse --show-prefix should output\n+\t\t\t# a single newline when at the top of the work tree,\n+\t\t\t# but we test for that separately.\n+\t\t\ttest -z \"$4\" && ! test -s actual.prefix ||\n+\t\t\ttest_cmp expected.prefix actual.prefix\n+\t\tfi\n+\t}\n+'\n+\n+test_expect_success 'setup: core.worktree = relative path' '\n+\tunset GIT_WORK_TREE;\n+\tGIT_DIR=repo.git &&\n+\tGIT_CONFIG=\"$(pwd)\"/$GIT_DIR/config &&\n+\texport GIT_DIR GIT_CONFIG &&\n+\tgit config core.worktree ../work\n+'\n+\n+test_expect_success 'outside' '\n+\ttest_rev_parse false false false\n+'\n+\n+test_expect_success 'inside work tree' '\n+\t(\n+\t\tcd work &&\n+\t\tGIT_DIR=../repo.git &&\n+\t\tGIT_CONFIG=\"$(pwd)\"/$GIT_DIR/config &&\n+\t\ttest_rev_parse false false true \"\"\n+\t)\n+'\n+\n+test_expect_failure 'empty prefix is actually written out' '\n+\techo >expected &&\n+\t(\n+\t\tcd work &&\n+\t\tGIT_DIR=../repo.git &&\n+\t\tGIT_CONFIG=\"$(pwd)\"/$GIT_DIR/config &&\n+\t\tgit rev-parse --show-prefix >../actual\n+\t) &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'subdir of work tree' '\n+\t(\n+\t\tcd work/sub/dir &&\n+\t\tGIT_DIR=../../../repo.git &&\n+\t\tGIT_CONFIG=\"$(pwd)\"/$GIT_DIR/config &&\n+\t\ttest_rev_parse false false true sub/dir/\n+\t)\n+'\n+\n+test_expect_success 'setup: core.worktree = absolute path' '\n+\tunset GIT_WORK_TREE;\n+\tGIT_DIR=$(pwd)/repo.git &&\n+\tGIT_CONFIG=$GIT_DIR/config &&\n+\texport GIT_DIR GIT_CONFIG &&\n+\tgit config core.worktree \"$(pwd)/work\"\n+'\n+\n+test_expect_success 'outside' '\n+\ttest_rev_parse false false false &&\n+\t(\n+\t\tcd work2 &&\n+\t\ttest_rev_parse false false false\n+\t)\n+'\n+\n+test_expect_success 'inside work tree' '\n+\t(\n+\t\tcd work &&\n+\t\ttest_rev_parse false false true \"\"\n+\t)\n+'\n+\n+test_expect_success 'subdir of work tree' '\n+\t(\n+\t\tcd work/sub/dir &&\n+\t\ttest_rev_parse false false true sub/dir/\n+\t)\n+'\n+\n+test_expect_success 'setup: GIT_WORK_TREE=relative (override core.worktree)' '\n+\tGIT_DIR=$(pwd)/repo.git &&\n+\tGIT_CONFIG=$GIT_DIR/config &&\n+\tgit config core.worktree non-existent &&\n+\tGIT_WORK_TREE=work &&\n+\texport GIT_DIR GIT_CONFIG GIT_WORK_TREE\n+'\n+\n+test_expect_success 'outside' '\n+\ttest_rev_parse false false false &&\n+\t(\n+\t\tcd work2 &&\n+\t\ttest_rev_parse false false false\n+\t)\n+'\n+\n+test_expect_success 'inside work tree' '\n+\t(\n+\t\tcd work &&\n+\t\tGIT_WORK_TREE=. &&\n+\t\ttest_rev_parse false false true \"\"\n+\t)\n+'\n+\n+test_expect_success 'subdir of work tree' '\n+\t(\n+\t\tcd work/sub/dir &&\n+\t\tGIT_WORK_TREE=../.. &&\n+\t\ttest_rev_parse false false true sub/dir/\n+\t)\n+'\n+\n+test_expect_success 'setup: GIT_WORK_TREE=absolute, below git dir' '\n+\tmv work repo.git/work &&\n+\tmv work2 repo.git/work2 &&\n+\tGIT_DIR=$(pwd)/repo.git &&\n+\tGIT_CONFIG=$GIT_DIR/config &&\n+\tGIT_WORK_TREE=$(pwd)/repo.git/work &&\n+\texport GIT_DIR GIT_CONFIG GIT_WORK_TREE\n+'\n+\n+test_expect_success 'outside' '\n+\techo outside &&\n+\ttest_rev_parse false false false\n+'\n+\n+test_expect_success 'in repo.git' '\n+\t(\n+\t\tcd repo.git &&\n+\t\ttest_rev_parse false true false\n+\t) &&\n+\t(\n+\t\tcd repo.git/objects &&\n+\t\ttest_rev_parse false true false\n+\t) &&\n+\t(\n+\t\tcd repo.git/work2 &&\n+\t\ttest_rev_parse false true false\n+\t)\n+'\n+\n+test_expect_success 'inside work tree' '\n+\t(\n+\t\tcd repo.git/work &&\n+\t\ttest_rev_parse false true true \"\"\n+\t)\n+'\n+\n+test_expect_success 'subdir of work tree' '\n+\t(\n+\t\tcd repo.git/work/sub/dir &&\n+\t\ttest_rev_parse false true true sub/dir/\n+\t)\n+'\n+\n+test_expect_success 'find work tree from repo' '\n+\techo sub/dir/untracked >expected &&\n+\tcat <<-\\EOF >repo.git/work/.gitignore &&\n+\texpected.*\n+\tactual.*\n+\t.gitignore\n+\tEOF\n+\t>repo.git/work/sub/dir/untracked &&\n+\t(\n+\t\tcd repo.git &&\n+\t\tgit ls-files --others --exclude-standard >../actual\n+\t) &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'find work tree from work tree' '\n+\techo sub/dir/tracked >expected &&\n+\t>repo.git/work/sub/dir/tracked &&\n+\t(\n+\t\tcd repo.git/work/sub/dir &&\n+\t\tgit --git-dir=../../.. add tracked\n+\t) &&\n+\t(\n+\t\tcd repo.git &&\n+\t\tgit ls-files >../actual\n+\t) &&\n+\ttest_cmp expected actual\n '\n \n test_expect_success '_gently() groks relative GIT_DIR & GIT_WORK_TREE' '\n-\t(cd repo.git/work/sub/dir &&\n-\tGIT_DIR=../../.. GIT_WORK_TREE=../.. GIT_PAGER= \\\n+\t(\n+\t\tcd repo.git/work/sub/dir &&\n+\t\tGIT_DIR=../../.. &&\n+\t\tGIT_WORK_TREE=../.. &&\n+\t\tGIT_PAGER= &&\n+\t\texport GIT_DIR GIT_WORK_TREE GIT_PAGER &&\n+\n \t\tgit diff --exit-code tracked &&\n-\techo changed > tracked &&\n-\t! GIT_DIR=../../.. GIT_WORK_TREE=../.. GIT_PAGER= \\\n-\t\tgit diff --exit-code tracked)\n+\t\techo changed >tracked &&\n+\t\ttest_must_fail git diff --exit-code tracked\n+\t)\n '\n-cat > diff-index-cached.expected <<\\EOF\n-:000000 100644 0000000000000000000000000000000000000000 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 A\tsub/dir/tracked\n-EOF\n-cat > diff-index.expected <<\\EOF\n-:000000 100644 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 A\tsub/dir/tracked\n-EOF\n \n+test_expect_success 'diff-index respects work tree under .git dir' '\n+\tcat >diff-index-cached.expected <<-EOF &&\n+\t:000000 100644 $ZEROES $EMPTY_BLOB A\tsub/dir/tracked\n+\tEOF\n+\tcat >diff-index.expected <<-EOF &&\n+\t:000000 100644 $ZEROES $ZEROES A\tsub/dir/tracked\n+\tEOF\n \n-test_expect_success 'git diff-index' '\n-\tGIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff-index $EMPTY_TREE > result &&\n-\ttest_cmp diff-index.expected result &&\n-\tGIT_DIR=repo.git git diff-index --cached $EMPTY_TREE > result &&\n-\ttest_cmp diff-index-cached.expected result\n+\t(\n+\t\tGIT_DIR=repo.git &&\n+\t\tGIT_WORK_TREE=repo.git/work &&\n+\t\texport GIT_DIR GIT_WORK_TREE &&\n+\t\tgit diff-index $EMPTY_TREE >diff-index.actual &&\n+\t\tgit diff-index --cached $EMPTY_TREE >diff-index-cached.actual\n+\t) &&\n+\ttest_cmp diff-index.expected diff-index.actual &&\n+\ttest_cmp diff-index-cached.expected diff-index-cached.actual\n '\n-cat >diff-files.expected <<\\EOF\n-:100644 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0000000000000000000000000000000000000000 M\tsub/dir/tracked\n-EOF\n \n-test_expect_success 'git diff-files' '\n-\tGIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff-files > result &&\n-\ttest_cmp diff-files.expected result\n+test_expect_success 'diff-files respects work tree under .git dir' '\n+\tcat >diff-files.expected <<-EOF &&\n+\t:100644 100644 $EMPTY_BLOB $ZEROES M\tsub/dir/tracked\n+\tEOF\n+\n+\t(\n+\t\tGIT_DIR=repo.git &&\n+\t\tGIT_WORK_TREE=repo.git/work &&\n+\t\texport GIT_DIR GIT_WORK_TREE &&\n+\t\tgit diff-files >diff-files.actual\n+\t) &&\n+\ttest_cmp diff-files.expected diff-files.actual\n '\n \n-cat >diff-TREE.expected <<\\EOF\n-diff --git a/sub/dir/tracked b/sub/dir/tracked\n-new file mode 100644\n-index 0000000..5ea2ed4\n---- /dev/null\n-+++ b/sub/dir/tracked\n-@@ -0,0 +1 @@\n-+changed\n-EOF\n-cat >diff-TREE-cached.expected <<\\EOF\n-diff --git a/sub/dir/tracked b/sub/dir/tracked\n-new file mode 100644\n-index 0000000..e69de29\n-EOF\n-cat >diff-FILES.expected <<\\EOF\n-diff --git a/sub/dir/tracked b/sub/dir/tracked\n-index e69de29..5ea2ed4 100644\n---- a/sub/dir/tracked\n-+++ b/sub/dir/tracked\n-@@ -0,0 +1 @@\n-+changed\n-EOF\n+test_expect_success 'git diff respects work tree under .git dir' '\n+\tcat >diff-TREE.expected <<-EOF &&\n+\tdiff --git a/sub/dir/tracked b/sub/dir/tracked\n+\tnew file mode 100644\n+\tindex 0000000..$CHANGED_BLOB7\n+\t--- /dev/null\n+\t+++ b/sub/dir/tracked\n+\t@@ -0,0 +1 @@\n+\t+changed\n+\tEOF\n+\tcat >diff-TREE-cached.expected <<-EOF &&\n+\tdiff --git a/sub/dir/tracked b/sub/dir/tracked\n+\tnew file mode 100644\n+\tindex 0000000..$EMPTY_BLOB7\n+\tEOF\n+\tcat >diff-FILES.expected <<-EOF &&\n+\tdiff --git a/sub/dir/tracked b/sub/dir/tracked\n+\tindex $EMPTY_BLOB7..$CHANGED_BLOB7 100644\n+\t--- a/sub/dir/tracked\n+\t+++ b/sub/dir/tracked\n+\t@@ -0,0 +1 @@\n+\t+changed\n+\tEOF\n \n-test_expect_success 'git diff' '\n-\tGIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff $EMPTY_TREE > result &&\n-\ttest_cmp diff-TREE.expected result &&\n-\tGIT_DIR=repo.git git diff --cached $EMPTY_TREE > result &&\n-\ttest_cmp diff-TREE-cached.expected result &&\n-\tGIT_DIR=repo.git GIT_WORK_TREE=repo.git/work git diff > result &&\n-\ttest_cmp diff-FILES.expected result\n+\t(\n+\t\tGIT_DIR=repo.git &&\n+\t\tGIT_WORK_TREE=repo.git/work &&\n+\t\texport GIT_DIR GIT_WORK_TREE &&\n+\t\tgit diff $EMPTY_TREE >diff-TREE.actual &&\n+\t\tgit diff --cached $EMPTY_TREE >diff-TREE-cached.actual &&\n+\t\tgit diff >diff-FILES.actual\n+\t) &&\n+\ttest_cmp diff-TREE.expected diff-TREE.actual &&\n+\ttest_cmp diff-TREE-cached.expected diff-TREE-cached.actual &&\n+\ttest_cmp diff-FILES.expected diff-FILES.actual\n '\n \n test_expect_success 'git grep' '\n-\t(cd repo.git/work/sub &&\n-\tGIT_DIR=../.. GIT_WORK_TREE=.. git grep -l changed | grep dir/tracked)\n+\techo dir/tracked >expected.grep &&\n+\t(\n+\t\tcd repo.git/work/sub &&\n+\t\tGIT_DIR=../.. &&\n+\t\tGIT_WORK_TREE=.. &&\n+\t\texport GIT_DIR GIT_WORK_TREE &&\n+\t\tgit grep -l changed >../../../actual.grep\n+\t) &&\n+\ttest_cmp expected.grep actual.grep\n '\n \n test_expect_success 'git commit' '\n@@ -191,14 +328,14 @@ test_expect_success 'git commit' '\n \n test_expect_success 'absolute pathspec should fail gracefully' '\n \t(\n-\t\tcd repo.git || exit 1\n-\t\tgit config --unset core.worktree\n+\t\tcd repo.git &&\n+\t\ttest_might_fail git config --unset core.worktree &&\n \t\ttest_must_fail git log HEAD -- /home\n \t)\n '\n \n test_expect_success 'make_relative_path handles double slashes in GIT_DIR' '\n-\t: > dummy_file\n+\t>dummy_file\n \techo git --git-dir=\"$(pwd)//repo.git\" --work-tree=\"$(pwd)\" add dummy_file &&\n \tgit --git-dir=\"$(pwd)//repo.git\" --work-tree=\"$(pwd)\" add dummy_file\n '\n-- \n1.7.2.rc3\n"},{"id":"146151","messageId":"20100724111838.GB16054@burratino","threadId":"24480","inReplyTo":"20100724111505.GC7150@burratino","subject":"[PATCH 2/9] tests: try git apply from subdir of toplevel","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-07-24T11:18:38Z","receivedAt":"2010-07-24T11:18:38Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Make sure git apply can apply patches with paths relative to the\ntoplevel of a work tree, a subdirectory, or within the repository\nmetadata directory.\n\nRelative paths are broken for most commands when run from a\nsubdirectory of $GIT_DIR, \"git apply\" being no exception.  The other\ntests are meant to keep the demonstration of that company.\n\nBased on a test by Duy.\n\nCc: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\n t/t4111-apply-subdir.sh |  141 +++++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 141 insertions(+), 0 deletions(-)\n create mode 100755 t/t4111-apply-subdir.sh\n\ndiff --git a/t/t4111-apply-subdir.sh b/t/t4111-apply-subdir.sh\nnew file mode 100755\nindex 0000000..60c2237\n--- /dev/null\n+++ b/t/t4111-apply-subdir.sh\n@@ -0,0 +1,141 @@\n+#!/bin/sh\n+\n+test_description='patching from inconvenient places'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'setup' '\n+\tcat >patch <<-\\EOF &&\n+\tdiff file.orig file\n+\t--- a/file.orig\n+\t+++ b/file\n+\t@@ -1 +1,2 @@\n+\t 1\n+\t+2\n+\tEOF\n+\tpatch=\"$(pwd)/patch\" &&\n+\n+\techo 1 >preimage &&\n+\tprintf \"%s\\n\" 1 2 >postimage &&\n+\techo 3 >other &&\n+\n+\ttest_tick &&\n+\tgit commit --allow-empty -m basis\n+'\n+\n+test_expect_success 'setup: subdir' '\n+\treset_subdir() {\n+\t\tgit reset &&\n+\t\tmkdir -p sub/dir/b &&\n+\t\tmkdir -p objects &&\n+\t\tcp \"$1\" file &&\n+\t\tcp \"$1\" objects/file &&\n+\t\tcp \"$1\" sub/dir/file &&\n+\t\tcp \"$1\" sub/dir/b/file &&\n+\t\tgit add file sub/dir/file sub/dir/b/file objects/file &&\n+\t\tcp \"$2\" file &&\n+\t\tcp \"$2\" sub/dir/file &&\n+\t\tcp \"$2\" sub/dir/b/file &&\n+\t\tcp \"$2\" objects/file\n+\t}\n+'\n+\n+test_expect_success 'apply from subdir of toplevel' '\n+\tcp postimage expected &&\n+\treset_subdir other preimage &&\n+\t(\n+\t\tcd sub/dir &&\n+\t\tgit apply \"$patch\"\n+\t) &&\n+\ttest_cmp expected sub/dir/file\n+'\n+\n+test_expect_success 'apply --cached from subdir of toplevel' '\n+\tcp postimage expected &&\n+\tcp other expected.working &&\n+\treset_subdir preimage other &&\n+\t(\n+\t\tcd sub/dir &&\n+\t\tgit apply --cached \"$patch\"\n+\t) &&\n+\tgit show :sub/dir/file >actual &&\n+\ttest_cmp expected actual &&\n+\ttest_cmp expected.working sub/dir/file\n+'\n+\n+test_expect_success 'apply --index from subdir of toplevel' '\n+\tcp postimage expected &&\n+\treset_subdir preimage other &&\n+\t(\n+\t\tcd sub/dir &&\n+\t\ttest_must_fail git apply --index \"$patch\"\n+\t) &&\n+\treset_subdir other preimage &&\n+\t(\n+\t\tcd sub/dir &&\n+\t\ttest_must_fail git apply --index \"$patch\"\n+\t) &&\n+\treset_subdir preimage preimage &&\n+\t(\n+\t\tcd sub/dir &&\n+\t\tgit apply --index \"$patch\"\n+\t) &&\n+\tgit show :sub/dir/file >actual &&\n+\ttest_cmp expected actual &&\n+\ttest_cmp expected sub/dir/file\n+'\n+\n+test_expect_success 'apply from .git dir' '\n+\tcp postimage expected &&\n+\tcp preimage .git/file &&\n+\tcp preimage .git/objects/file\n+\t(\n+\t\tcd .git &&\n+\t\tgit apply \"$patch\"\n+\t) &&\n+\ttest_cmp expected .git/file\n+'\n+\n+test_expect_failure 'apply from subdir of .git dir' '\n+\tcp postimage expected &&\n+\tcp preimage .git/file &&\n+\tcp preimage .git/objects/file\n+\t(\n+\t\tcd .git/objects &&\n+\t\tgit apply \"$patch\"\n+\t) &&\n+\ttest_cmp expected .git/objects/file\n+'\n+\n+test_expect_success 'apply --cached from .git dir' '\n+\tcp postimage expected &&\n+\tcp other expected.working &&\n+\tcp other .git/file &&\n+\treset_subdir preimage other &&\n+\t(\n+\t\tcd .git &&\n+\t\tgit apply --cached \"$patch\"\n+\t) &&\n+\tgit show :file >actual &&\n+\ttest_cmp expected actual &&\n+\ttest_cmp expected.working file &&\n+\ttest_cmp expected.working .git/file\n+'\n+\n+test_expect_success 'apply --cached from subdir of .git dir' '\n+\tcp postimage expected &&\n+\tcp preimage expected.subdir &&\n+\tcp other .git/file &&\n+\tcp other .git/objects/file &&\n+\treset_subdir preimage other &&\n+\t(\n+\t\tcd .git/objects &&\n+\t\tgit apply --cached \"$patch\"\n+\t) &&\n+\tgit show :file >actual &&\n+\tgit show :objects/file >actual.subdir &&\n+\ttest_cmp expected actual &&\n+\ttest_cmp expected.subdir actual.subdir\n+'\n+\n+test_done\n-- \n1.7.2.rc3\n"},{"id":"146152","messageId":"20100724111944.GC16054@burratino","threadId":"24480","inReplyTo":"20100724111505.GC7150@burratino","subject":"[PATCH 3/9] setup: split off $GIT_DIR-set case from setup_git_directory_gently","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-07-24T11:19:44Z","receivedAt":"2010-07-24T11:19:44Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"If $GIT_DIR is set, setup_git_directory_gently does not have\nto do any repository discovery at all.  Split off a function\nfor the validation it still does do, in the hope that this will\nmake setup_git_directory_gently proper less daunting to read.\n\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\n setup.c |   69 +++++++++++++++++++++++++++++++++-----------------------------\n 1 files changed, 37 insertions(+), 32 deletions(-)\n\ndiff --git a/setup.c b/setup.c\nindex 2769160..16bee6d 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -313,6 +313,41 @@ const char *read_gitfile_gently(const char *path)\n \treturn path;\n }\n \n+static const char *setup_explicit_git_dir(const char *gitdirenv,\n+\t\t\t\tconst char *work_tree_env, int *nongit_ok)\n+{\n+\tstatic char buffer[1024 + 1];\n+\tconst char *retval;\n+\n+\tif (PATH_MAX - 40 < strlen(gitdirenv))\n+\t\tdie(\"'$%s' too big\", GIT_DIR_ENVIRONMENT);\n+\tif (!is_git_directory(gitdirenv)) {\n+\t\tif (nongit_ok) {\n+\t\t\t*nongit_ok = 1;\n+\t\t\treturn NULL;\n+\t\t}\n+\t\tdie(\"Not a git repository: '%s'\", gitdirenv);\n+\t}\n+\tif (!work_tree_env) {\n+\t\tretval = set_work_tree(gitdirenv);\n+\t\t/* config may override worktree */\n+\t\tif (check_repository_format_gently(nongit_ok))\n+\t\t\treturn NULL;\n+\t\treturn retval;\n+\t}\n+\tif (check_repository_format_gently(nongit_ok))\n+\t\treturn NULL;\n+\tretval = get_relative_cwd(buffer, sizeof(buffer) - 1,\n+\t\t\tget_git_work_tree());\n+\tif (!retval || !*retval)\n+\t\treturn NULL;\n+\tset_git_dir(make_absolute_path(gitdirenv));\n+\tif (chdir(work_tree_env) < 0)\n+\t\tdie_errno (\"Could not chdir to '%s'\", work_tree_env);\n+\tstrcat(buffer, \"/\");\n+\treturn retval;\n+}\n+\n /*\n  * We cannot decide in this function whether we are in the work tree or\n  * not, since the config can only be read _after_ this function was called.\n@@ -343,38 +378,8 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t * validation.\n \t */\n \tgitdirenv = getenv(GIT_DIR_ENVIRONMENT);\n-\tif (gitdirenv) {\n-\t\tif (PATH_MAX - 40 < strlen(gitdirenv))\n-\t\t\tdie(\"'$%s' too big\", GIT_DIR_ENVIRONMENT);\n-\t\tif (is_git_directory(gitdirenv)) {\n-\t\t\tstatic char buffer[1024 + 1];\n-\t\t\tconst char *retval;\n-\n-\t\t\tif (!work_tree_env) {\n-\t\t\t\tretval = set_work_tree(gitdirenv);\n-\t\t\t\t/* config may override worktree */\n-\t\t\t\tif (check_repository_format_gently(nongit_ok))\n-\t\t\t\t\treturn NULL;\n-\t\t\t\treturn retval;\n-\t\t\t}\n-\t\t\tif (check_repository_format_gently(nongit_ok))\n-\t\t\t\treturn NULL;\n-\t\t\tretval = get_relative_cwd(buffer, sizeof(buffer) - 1,\n-\t\t\t\t\tget_git_work_tree());\n-\t\t\tif (!retval || !*retval)\n-\t\t\t\treturn NULL;\n-\t\t\tset_git_dir(make_absolute_path(gitdirenv));\n-\t\t\tif (chdir(work_tree_env) < 0)\n-\t\t\t\tdie_errno (\"Could not chdir to '%s'\", work_tree_env);\n-\t\t\tstrcat(buffer, \"/\");\n-\t\t\treturn retval;\n-\t\t}\n-\t\tif (nongit_ok) {\n-\t\t\t*nongit_ok = 1;\n-\t\t\treturn NULL;\n-\t\t}\n-\t\tdie(\"Not a git repository: '%s'\", gitdirenv);\n-\t}\n+\tif (gitdirenv)\n+\t\treturn setup_explicit_git_dir(gitdirenv, work_tree_env, nongit_ok);\n \n \tif (!getcwd(cwd, sizeof(cwd)-1))\n \t\tdie_errno(\"Unable to read current working directory\");\n-- \n1.7.2.rc3.593.g19611.dirty\n"},{"id":"146153","messageId":"20100724112015.GD16054@burratino","threadId":"24480","inReplyTo":"20100724111505.GC7150@burratino","subject":"[PATCH 4/9] setup: split off a function to checks working dir for .git file","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-07-24T11:20:15Z","receivedAt":"2010-07-24T11:20:15Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"The repository discovery procedure looks something like this:\n\n\twhile (same filesystem) {\n\t\tcheck .git in working dir\n\t\tcheck .\n\t\tchdir(..)\n\t}\n\nAdd a function for the first step to make the actual code look a bit\ncloser to that pseudocode.\n\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\n setup.c |   20 +++++++++++++-------\n 1 files changed, 13 insertions(+), 7 deletions(-)\n\ndiff --git a/setup.c b/setup.c\nindex 16bee6d..3d25d0f 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -348,6 +348,18 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,\n \treturn retval;\n }\n \n+static int cwd_contains_git_dir(const char **gitfile_dirp)\n+{\n+\tconst char *gitfile_dir = read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT);\n+\t*gitfile_dirp = gitfile_dir;\n+\tif (gitfile_dir) {\n+\t\tif (set_git_dir(gitfile_dir))\n+\t\t\tdie(\"Repository setup failed\");\n+\t\treturn 1;\n+\t}\n+\treturn is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT);\n+}\n+\n /*\n  * We cannot decide in this function whether we are in the work tree or\n  * not, since the config can only be read _after_ this function was called.\n@@ -407,13 +419,7 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t\tcurrent_device = buf.st_dev;\n \t}\n \tfor (;;) {\n-\t\tgitfile_dir = read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT);\n-\t\tif (gitfile_dir) {\n-\t\t\tif (set_git_dir(gitfile_dir))\n-\t\t\t\tdie(\"Repository setup failed\");\n-\t\t\tbreak;\n-\t\t}\n-\t\tif (is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT))\n+\t\tif (cwd_contains_git_dir(&gitfile_dir))\n \t\t\tbreak;\n \t\tif (is_git_directory(\".\")) {\n \t\t\tinside_git_dir = 1;\n-- \n1.7.2.rc3.593.g19611.dirty\n"},{"id":"146154","messageId":"20100724112532.GE16054@burratino","threadId":"24480","inReplyTo":"20100724111505.GC7150@burratino","subject":"[PATCH 5/9] setup: split off code to handle stumbling upon a repository","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-07-24T11:25:32Z","receivedAt":"2010-07-24T11:25:32Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"If a repository is found as an ancestor of the original\nworking directory, it is assumed by default to be bare.\nHandle this case with its own function.\n\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\n setup.c |   34 +++++++++++++++++++++-------------\n 1 files changed, 21 insertions(+), 13 deletions(-)\n\ndiff --git a/setup.c b/setup.c\nindex 3d25d0f..ec11c46 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -360,6 +360,24 @@ static int cwd_contains_git_dir(const char **gitfile_dirp)\n \treturn is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT);\n }\n \n+static const char *setup_bare_git_dir(const char *work_tree_env,\n+\t\tint offset, int len, char *cwd, int *nongit_ok)\n+{\n+\tint root_len;\n+\n+\tinside_git_dir = 1;\n+\tif (!work_tree_env)\n+\t\tinside_work_tree = 0;\n+\tif (offset != len) {\n+\t\troot_len = offset_1st_component(cwd);\n+\t\tcwd[offset > root_len ? offset : root_len] = '\\0';\n+\t\tset_git_dir(cwd);\n+\t} else\n+\t\tset_git_dir(\".\");\n+\tcheck_repository_format_gently(nongit_ok);\n+\treturn NULL;\n+}\n+\n /*\n  * We cannot decide in this function whether we are in the work tree or\n  * not, since the config can only be read _after_ this function was called.\n@@ -421,19 +439,9 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \tfor (;;) {\n \t\tif (cwd_contains_git_dir(&gitfile_dir))\n \t\t\tbreak;\n-\t\tif (is_git_directory(\".\")) {\n-\t\t\tinside_git_dir = 1;\n-\t\t\tif (!work_tree_env)\n-\t\t\t\tinside_work_tree = 0;\n-\t\t\tif (offset != len) {\n-\t\t\t\troot_len = offset_1st_component(cwd);\n-\t\t\t\tcwd[offset > root_len ? offset : root_len] = '\\0';\n-\t\t\t\tset_git_dir(cwd);\n-\t\t\t} else\n-\t\t\t\tset_git_dir(\".\");\n-\t\t\tcheck_repository_format_gently(nongit_ok);\n-\t\t\treturn NULL;\n-\t\t}\n+\t\tif (is_git_directory(\".\"))\n+\t\t\treturn setup_bare_git_dir(work_tree_env, offset,\n+\t\t\t\t\t\t\tlen, cwd, nongit_ok);\n \t\twhile (--offset > ceil_offset && cwd[offset] != '/');\n \t\tif (offset <= ceil_offset) {\n \t\t\tif (nongit_ok) {\n-- \n1.7.2.rc3.593.g19611.dirty\n"},{"id":"146155","messageId":"20100724112640.GF16054@burratino","threadId":"24480","inReplyTo":"20100724111505.GC7150@burratino","subject":"[PATCH 6/9] setup: split off a function to handle hitting ceiling in repo search","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-07-24T11:26:41Z","receivedAt":"2010-07-24T11:26:41Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Perhaps some day, other similar conditions (hitting the mount point,\nhitting the root of the file system) will share this code.\n\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\n setup.c |   21 ++++++++++++---------\n 1 files changed, 12 insertions(+), 9 deletions(-)\n\ndiff --git a/setup.c b/setup.c\nindex ec11c46..9fc05e2 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -378,6 +378,16 @@ static const char *setup_bare_git_dir(const char *work_tree_env,\n \treturn NULL;\n }\n \n+static const char *setup_nongit(const char *cwd, int *nongit_ok)\n+{\n+\tif (!nongit_ok)\n+\t\tdie(\"Not a git repository (or any of the parent directories): %s\", DEFAULT_GIT_DIR_ENVIRONMENT);\n+\tif (chdir(cwd))\n+\t\tdie_errno(\"Cannot come back to cwd\");\n+\t*nongit_ok = 1;\n+\treturn NULL;\n+}\n+\n /*\n  * We cannot decide in this function whether we are in the work tree or\n  * not, since the config can only be read _after_ this function was called.\n@@ -443,15 +453,8 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t\t\treturn setup_bare_git_dir(work_tree_env, offset,\n \t\t\t\t\t\t\tlen, cwd, nongit_ok);\n \t\twhile (--offset > ceil_offset && cwd[offset] != '/');\n-\t\tif (offset <= ceil_offset) {\n-\t\t\tif (nongit_ok) {\n-\t\t\t\tif (chdir(cwd))\n-\t\t\t\t\tdie_errno(\"Cannot come back to cwd\");\n-\t\t\t\t*nongit_ok = 1;\n-\t\t\t\treturn NULL;\n-\t\t\t}\n-\t\t\tdie(\"Not a git repository (or any of the parent directories): %s\", DEFAULT_GIT_DIR_ENVIRONMENT);\n-\t\t}\n+\t\tif (offset <= ceil_offset)\n+\t\t\treturn setup_nongit(cwd, nongit_ok);\n \t\tif (one_filesystem) {\n \t\t\tif (stat(\"..\", &buf)) {\n \t\t\t\tcwd[offset] = '\\0';\n-- \n1.7.2.rc3.593.g19611.dirty\n"},{"id":"146156","messageId":"20100724112758.GG16054@burratino","threadId":"24480","inReplyTo":"20100724111505.GC7150@burratino","subject":"[PATCH 7/9] setup: split off get_device_or_die helper","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-07-24T11:27:58Z","receivedAt":"2010-07-24T11:27:58Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"This does not eliminate any code, but it skims some off of\nthe main loop of setup_git_directory_gently so that can be\nunderstood more easily.\n\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\n setup.c |   25 ++++++++++++++-----------\n 1 files changed, 14 insertions(+), 11 deletions(-)\n\ndiff --git a/setup.c b/setup.c\nindex 9fc05e2..5fb9c54 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -388,6 +388,16 @@ static const char *setup_nongit(const char *cwd, int *nongit_ok)\n \treturn NULL;\n }\n \n+static dev_t get_device_or_die(const char *path, const char *prefix)\n+{\n+\tstruct stat buf;\n+\tif (stat(path, &buf))\n+\t\tdie_errno(\"failed to stat '%s%s%s'\",\n+\t\t\t\tprefix ? prefix : \"\",\n+\t\t\t\tprefix ? \"/\" : \"\", path);\n+\treturn buf.st_dev;\n+}\n+\n /*\n  * We cannot decide in this function whether we are in the work tree or\n  * not, since the config can only be read _after_ this function was called.\n@@ -402,7 +412,6 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \tint len, offset, ceil_offset, root_len;\n \tdev_t current_device = 0;\n \tint one_filesystem = 1;\n-\tstruct stat buf;\n \n \t/*\n \t * Let's assume that we are in a git repository.\n@@ -441,11 +450,8 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t */\n \toffset = len = strlen(cwd);\n \tone_filesystem = !git_env_bool(\"GIT_DISCOVERY_ACROSS_FILESYSTEM\", 0);\n-\tif (one_filesystem) {\n-\t\tif (stat(\".\", &buf))\n-\t\t\tdie_errno(\"failed to stat '.'\");\n-\t\tcurrent_device = buf.st_dev;\n-\t}\n+\tif (one_filesystem)\n+\t\tcurrent_device = get_device_or_die(\".\", NULL);\n \tfor (;;) {\n \t\tif (cwd_contains_git_dir(&gitfile_dir))\n \t\t\tbreak;\n@@ -456,11 +462,8 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t\tif (offset <= ceil_offset)\n \t\t\treturn setup_nongit(cwd, nongit_ok);\n \t\tif (one_filesystem) {\n-\t\t\tif (stat(\"..\", &buf)) {\n-\t\t\t\tcwd[offset] = '\\0';\n-\t\t\t\tdie_errno(\"failed to stat '%s/..'\", cwd);\n-\t\t\t}\n-\t\t\tif (buf.st_dev != current_device) {\n+\t\t\tdev_t parent_device = get_device_or_die(\"..\", cwd);\n+\t\t\tif (parent_device != current_device) {\n \t\t\t\tif (nongit_ok) {\n \t\t\t\t\tif (chdir(cwd))\n \t\t\t\t\t\tdie_errno(\"Cannot come back to cwd\");\n-- \n1.7.2.rc3.593.g19611.dirty\n"},{"id":"146157","messageId":"20100724112941.GA16338@burratino","threadId":"24480","inReplyTo":"20100724111505.GC7150@burratino","subject":"[PATCH 8/9] setup: do not forget working dir from subdir of gitdir","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-07-24T11:29:41Z","receivedAt":"2010-07-24T11:29:41Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"From: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n\nv1.6.1.3~4^2 (Fix gitdir detection when in subdir of gitdir,\n2009-01-16) did not go far enough: when a git directory is\nan ancestor of the original working directory, not only\nshould GIT_DIR be set to point to the .git directory, but\nthe original working directory should be restored before\ncarrying out the relevant command.\n\nThis way, the effect of running a git command from a subdir\nof .git will be the same whether or not GIT_DIR is explicitly\nset.\n\nNoticed while investigating v1.6.0.3~1 (rehabilitate 'git\nindex-pack' inside the object store, 2008-10-20).\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\n setup.c                 |    2 ++\n t/t4111-apply-subdir.sh |    2 +-\n 2 files changed, 3 insertions(+), 1 deletions(-)\n\ndiff --git a/setup.c b/setup.c\nindex 5fb9c54..5734a1f 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -369,6 +369,8 @@ static const char *setup_bare_git_dir(const char *work_tree_env,\n \tif (!work_tree_env)\n \t\tinside_work_tree = 0;\n \tif (offset != len) {\n+\t\tif (chdir(cwd))\n+\t\t\tdie_errno(\"Cannot come back to cwd\");\n \t\troot_len = offset_1st_component(cwd);\n \t\tcwd[offset > root_len ? offset : root_len] = '\\0';\n \t\tset_git_dir(cwd);\ndiff --git a/t/t4111-apply-subdir.sh b/t/t4111-apply-subdir.sh\nindex 60c2237..57cae50 100755\n--- a/t/t4111-apply-subdir.sh\n+++ b/t/t4111-apply-subdir.sh\n@@ -96,7 +96,7 @@ test_expect_success 'apply from .git dir' '\n \ttest_cmp expected .git/file\n '\n \n-test_expect_failure 'apply from subdir of .git dir' '\n+test_expect_success 'apply from subdir of .git dir' '\n \tcp postimage expected &&\n \tcp preimage .git/file &&\n \tcp preimage .git/objects/file\n-- \n1.7.2.rc3\n"},{"id":"146158","messageId":"20100724113049.GB16338@burratino","threadId":"24480","inReplyTo":"20100724111505.GC7150@burratino","subject":"[PATCH 9/9] Revert \"rehabilitate 'git index-pack' inside the object store\"","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-07-24T11:30:49Z","receivedAt":"2010-07-24T11:30:49Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"From: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n\nNow setup_git_directory_gently behaves sanely even from subdirs of\n.git, so simplify index-pack by no longer protecting against that.\n\nThis reverts commit a672ea6ac5a1b876bc7adfe6534b16fa2a32c94b\n(excluding tests).\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\nThat’s the end of the series.  Thanks for reading.\n\nGood night,\nJonathan\n\n builtin/index-pack.c |   24 +++++-------------------\n 1 files changed, 5 insertions(+), 19 deletions(-)\n\ndiff --git a/builtin/index-pack.c b/builtin/index-pack.c\nindex a89ae83..89a1f12 100644\n--- a/builtin/index-pack.c\n+++ b/builtin/index-pack.c\n@@ -880,29 +880,15 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)\n \tchar *index_name_buf = NULL, *keep_name_buf = NULL;\n \tstruct pack_idx_entry **idx_objects;\n \tunsigned char pack_sha1[20];\n+\tint nongit;\n \n \tif (argc == 2 && !strcmp(argv[1], \"-h\"))\n \t\tusage(index_pack_usage);\n \n-\t/*\n-\t * We wish to read the repository's config file if any, and\n-\t * for that it is necessary to call setup_git_directory_gently().\n-\t * However if the cwd was inside .git/objects/pack/ then we need\n-\t * to go back there or all the pack name arguments will be wrong.\n-\t * And in that case we cannot rely on any prefix returned by\n-\t * setup_git_directory_gently() either.\n-\t */\n-\t{\n-\t\tchar cwd[PATH_MAX+1];\n-\t\tint nongit;\n-\n-\t\tif (!getcwd(cwd, sizeof(cwd)-1))\n-\t\t\tdie(\"Unable to get current working directory\");\n-\t\tsetup_git_directory_gently(&nongit);\n-\t\tgit_config(git_index_pack_config, NULL);\n-\t\tif (chdir(cwd))\n-\t\t\tdie(\"Cannot come back to cwd\");\n-\t}\n+\tprefix = setup_git_directory_gently(&nongit);\n+\tgit_config(git_index_pack_config, NULL);\n+\tif (prefix && chdir(prefix))\n+\t\tdie(\"Cannot come back to cwd\");\n \n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\n-- \n1.7.2.rc3.593.g19611.dirty\n"},{"id":"146159","messageId":"AANLkTik44c_piRQopbK9utUS30E37LnjTMLs_Wp_8TV9@mail.gmail.com","threadId":"24480","inReplyTo":"20100724111505.GC7150@burratino","subject":"Re: [PATCH 0/9] setup_git_directory(): return to original cwd upon reaching .git","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-07-24T11:45:23Z","receivedAt":"2010-07-24T11:45:23Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"2010/7/24 Jonathan Nieder <jrnieder@gmail.com>:\n> Hi Duy,\n>\n> Nguyễn Thái Ngọc Duy wrote:\n>\n>> Prefix and cwd should be consistent.\n>\n> I agree with this, but it took me a while to figure out why your fix\n> is safe.  Here’s how I figured it out.\n>\n> Patch 1 cleans up the test script you added a test to.  After cleaning\n> it up, it is clearer the test does not belong there.\n>\n> Patch 2 creates a proper home for the new test.\n\nThe test was originally to demostrate the breakage and apply was\nchosen because it's the first command I found applicable. I doubt if\nonly \"apply\" (and index-pack) were affected.\n\nBut anyway, more tests can't harm git.\n\n>\n> Patches 3-7 split up setup_git_directory_gently() into small enough\n> pieces that a person with a short attention span can read it now.\n> No functional change intended.\n\nYeah. I tempted to clean up setup_*_gently too, by splitting the\ndiscovery path ($GIT_DIR check, chdir up...) and the real setup (bunch\nof global variables, prefix, check_format, set_git_dir) apart. The was\npainful and did not improve readability as much. I gave up.\n\n> Patch 8 is your fix.  I removed the comment (which was just confusing\n> me) and clarified the commit message to compensate\n\nIf that makes it easier to understand, I'm OK.\n\n> Patch 9 is your patch to revert the other, now redundant fix, also\n> with commit message tweaks.\n>\n> After this exercise, your patches still look good. :)  Maybe these\n> by-products could be useful somehow.\n>\n> Thoughts (especially improvements) welcome.\n-- \nDuy\n"},{"id":"146160","messageId":"AANLkTim7C-byLb9txD11OrB6aC3uO=kBjQx2Q8HGLxL+@mail.gmail.com","threadId":"24480","inReplyTo":"20100724112015.GD16054@burratino","subject":"Re: [PATCH 4/9] setup: split off a function to checks working dir for .git file","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-07-24T11:56:50Z","receivedAt":"2010-07-24T11:56:50Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"2010/7/24 Jonathan Nieder <jrnieder@gmail.com>:\n> The repository discovery procedure looks something like this:\n>\n>        while (same filesystem) {\n>                check .git in working dir\n>                check .\n>                chdir(..)\n>        }\n>\n> Add a function for the first step to make the actual code look a bit\n> closer to that pseudocode.\n>\n> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>\n> ---\n>  setup.c |   20 +++++++++++++-------\n>  1 files changed, 13 insertions(+), 7 deletions(-)\n>\n> diff --git a/setup.c b/setup.c\n> index 16bee6d..3d25d0f 100644\n> --- a/setup.c\n> +++ b/setup.c\n> @@ -348,6 +348,18 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,\n>        return retval;\n>  }\n>\n> +static int cwd_contains_git_dir(const char **gitfile_dirp)\n> +{\n> +       const char *gitfile_dir = read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT);\n> +       *gitfile_dirp = gitfile_dir;\n> +       if (gitfile_dir) {\n> +               if (set_git_dir(gitfile_dir))\n> +                       die(\"Repository setup failed\");\n> +               return 1;\n> +       }\n> +       return is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT);\n> +}\n> +\n>  /*\n>  * We cannot decide in this function whether we are in the work tree or\n>  * not, since the config can only be read _after_ this function was called.\n> @@ -407,13 +419,7 @@ const char *setup_git_directory_gently(int *nongit_ok)\n>                current_device = buf.st_dev;\n>        }\n>        for (;;) {\n> -               gitfile_dir = read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT);\n> -               if (gitfile_dir) {\n> -                       if (set_git_dir(gitfile_dir))\n> -                               die(\"Repository setup failed\");\n> -                       break;\n> -               }\n> -               if (is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT))\n> +               if (cwd_contains_git_dir(&gitfile_dir))\n>                        break;\n\nNotice the two \"break;\" here, which is the only way to reach out the\ncode below the loop. Perhaps you should move that code into\ncwd_contains_git_dir() too and change its name appropriately.\nsetup_git_directory_gently() would become \"discovery only\" as real\nsetup would be done by three new functions.\n\nSomething like this on top (won't even compile):\n\ndiff --git a/setup.c b/setup.c\nindex 8901149..45b9860 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -346,16 +346,36 @@ static const char *setup_explicit_git_dir(const\nchar *gitdirenv,\n \treturn retval;\n }\n\n-static int cwd_contains_git_dir(const char **gitfile_dirp)\n+static int cwd_contains_git_dir(const char **gitfile_dirp, char *cwd)\n {\n \tconst char *gitfile_dir = read_gitfile_gently(DEFAULT_GIT_DIR_ENVIRONMENT);\n \t*gitfile_dirp = gitfile_dir;\n \tif (gitfile_dir) {\n \t\tif (set_git_dir(gitfile_dir))\n \t\t\tdie(\"Repository setup failed\");\n-\t\treturn 1;\n+\t\tgoto found;\n \t}\n-\treturn is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT);\n+\tif (is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT))\n+\t\tgoto found;\n+\n+\treturn NULL;\n+\n+found:\n+\tinside_git_dir = 0;\n+\tif (!work_tree_env)\n+\t\tinside_work_tree = 1;\n+\troot_len = offset_1st_component(cwd);\n+\tgit_work_tree_cfg = xstrndup(cwd, offset > root_len ? offset : root_len);\n+\tif (check_repository_format_gently(nongit_ok))\n+\t\treturn NULL;\n+\tif (offset == len)\n+\t\treturn NULL;\n+\n+\t/* Make \"offset\" point to past the '/', and add a '/' at the end */\n+\toffset++;\n+\tcwd[len++] = '/';\n+\tcwd[len] = 0;\n+\treturn cwd + offset;\n }\n\n /*\n@@ -369,6 +389,7 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \tstatic char cwd[PATH_MAX+1];\n \tconst char *gitdirenv;\n \tconst char *gitfile_dir;\n+\tconst char *prefix;\n \tint len, offset, ceil_offset, root_len;\n \tdev_t current_device = 0;\n \tint one_filesystem = 1;\n@@ -417,8 +438,9 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t\tcurrent_device = buf.st_dev;\n \t}\n \tfor (;;) {\n-\t\tif (cwd_contains_git_dir(&gitfile_dir))\n-\t\t\tbreak;\n+\t\tif ((prefix = cwd_contains_git_dir(&gitfile_dir, cwd)))\n+\t\t\treturn prefix;\n+\n \t\tif (is_git_directory(\".\")) {\n \t\t\tinside_git_dir = 1;\n \t\t\tif (!work_tree_env)\n@@ -464,22 +486,6 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t\t\tdie_errno(\"Cannot change to '%s/..'\", cwd);\n \t\t}\n \t}\n-\n-\tinside_git_dir = 0;\n-\tif (!work_tree_env)\n-\t\tinside_work_tree = 1;\n-\troot_len = offset_1st_component(cwd);\n-\tgit_work_tree_cfg = xstrndup(cwd, offset > root_len ? offset : root_len);\n-\tif (check_repository_format_gently(nongit_ok))\n-\t\treturn NULL;\n-\tif (offset == len)\n-\t\treturn NULL;\n-\n-\t/* Make \"offset\" point to past the '/', and add a '/' at the end */\n-\toffset++;\n-\tcwd[len++] = '/';\n-\tcwd[len] = 0;\n-\treturn cwd + offset;\n }\n\n int git_config_perm(const char *var, const char *value)\n\n-- \nDuy\n"},{"id":"146162","messageId":"20100724121157.GB16602@burratino","threadId":"24480","inReplyTo":"AANLkTim7C-byLb9txD11OrB6aC3uO=kBjQx2Q8HGLxL+@mail.gmail.com","subject":"Re: [PATCH 4/9] setup: split off a function to checks working dir for .git file","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-07-24T12:11:58Z","receivedAt":"2010-07-24T12:11:58Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Nguyen Thai Ngoc Duy wrote:\n\n> Notice the two \"break;\" here, which is the only way to reach out the\n> code below the loop. Perhaps you should move that code into\n> cwd_contains_git_dir() too and change its name appropriately.\n> setup_git_directory_gently() would become \"discovery only\" as real\n> setup would be done by three new functions.\n\nNeat.\n\n-- %< --\nFrom: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\nSubject: setup: split off a function to handle ordinary .git directories\n\nFinish the clean-up of setup_git_directory_gently() by splitting the\nlast case of validation+setup (global variables, prefix, check_format,\nset_git_dir) into its own function.  Now setup_git_git_directory_gently\nitself takes care of discovery only and the functions that pick up\nfrom there are nearby in the source file so they can be easily\ncompared.\n\nSigned-off-by: Jonathan Nieder <jrnieder@gmail.com>\n---\ndiff --git i/setup.c w/setup.c\nindex 5734a1f..d19aa7d 100644\n--- i/setup.c\n+++ w/setup.c\n@@ -360,6 +360,28 @@ static int cwd_contains_git_dir(const char **gitfile_dirp)\n \treturn is_git_directory(DEFAULT_GIT_DIR_ENVIRONMENT);\n }\n \n+static const char *setup_discovered_git_dir(const char *work_tree_env,\n+\t\tint offset, int len, char *cwd, int *nongit_ok)\n+{\n+\tint root_len;\n+\n+\tinside_git_dir = 0;\n+\tif (!work_tree_env)\n+\t\tinside_work_tree = 1;\n+\troot_len = offset_1st_component(cwd);\n+\tgit_work_tree_cfg = xstrndup(cwd, offset > root_len ? offset : root_len);\n+\tif (check_repository_format_gently(nongit_ok))\n+\t\treturn NULL;\n+\tif (offset == len)\n+\t\treturn NULL;\n+\n+\t/* Make \"offset\" point to past the '/', and add a '/' at the end */\n+\toffset++;\n+\tcwd[len++] = '/';\n+\tcwd[len] = 0;\n+\treturn cwd + offset;\n+}\n+\n static const char *setup_bare_git_dir(const char *work_tree_env,\n \t\tint offset, int len, char *cwd, int *nongit_ok)\n {\n@@ -411,7 +433,7 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \tstatic char cwd[PATH_MAX+1];\n \tconst char *gitdirenv;\n \tconst char *gitfile_dir;\n-\tint len, offset, ceil_offset, root_len;\n+\tint len, offset, ceil_offset;\n \tdev_t current_device = 0;\n \tint one_filesystem = 1;\n \n@@ -456,7 +478,8 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t\tcurrent_device = get_device_or_die(\".\", NULL);\n \tfor (;;) {\n \t\tif (cwd_contains_git_dir(&gitfile_dir))\n-\t\t\tbreak;\n+\t\t\treturn setup_discovered_git_dir(work_tree_env, offset,\n+\t\t\t\t\t\t\tlen, cwd, nongit_ok);\n \t\tif (is_git_directory(\".\"))\n \t\t\treturn setup_bare_git_dir(work_tree_env, offset,\n \t\t\t\t\t\t\tlen, cwd, nongit_ok);\n@@ -482,22 +505,6 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t\t\tdie_errno(\"Cannot change to '%s/..'\", cwd);\n \t\t}\n \t}\n-\n-\tinside_git_dir = 0;\n-\tif (!work_tree_env)\n-\t\tinside_work_tree = 1;\n-\troot_len = offset_1st_component(cwd);\n-\tgit_work_tree_cfg = xstrndup(cwd, offset > root_len ? offset : root_len);\n-\tif (check_repository_format_gently(nongit_ok))\n-\t\treturn NULL;\n-\tif (offset == len)\n-\t\treturn NULL;\n-\n-\t/* Make \"offset\" point to past the '/', and add a '/' at the end */\n-\toffset++;\n-\tcwd[len++] = '/';\n-\tcwd[len] = 0;\n-\treturn cwd + offset;\n }\n \n int git_config_perm(const char *var, const char *value)\n-- \n"},{"id":"146163","messageId":"AANLkTikvG8qUgd0p=moft1+7L+L-knVt0AZP0o=rsEmM@mail.gmail.com","threadId":"24480","inReplyTo":"20100724111944.GC16054@burratino","subject":"Re: [PATCH 3/9] setup: split off $GIT_DIR-set case from setup_git_directory_gently","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-07-24T12:15:56Z","receivedAt":"2010-07-24T12:15:56Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"2010/7/24 Jonathan Nieder <jrnieder@gmail.com>:\n> +static const char *setup_explicit_git_dir(const char *gitdirenv,\n> +                               const char *work_tree_env, int *nongit_ok)\n> +{\n> +       static char buffer[1024 + 1];\n> +       const char *retval;\n> +\n> +       if (PATH_MAX - 40 < strlen(gitdirenv))\n> +               die(\"'$%s' too big\", GIT_DIR_ENVIRONMENT);\n> +       if (!is_git_directory(gitdirenv)) {\n> +               if (nongit_ok) {\n> +                       *nongit_ok = 1;\n> +                       return NULL;\n> +               }\n> +               die(\"Not a git repository: '%s'\", gitdirenv);\n> +       }\n> +       if (!work_tree_env) {\n> +               retval = set_work_tree(gitdirenv);\n> +               /* config may override worktree */\n> +               if (check_repository_format_gently(nongit_ok))\n> +                       return NULL;\n> +               return retval;\n> +       }\n> +       if (check_repository_format_gently(nongit_ok))\n> +               return NULL;\n> +       retval = get_relative_cwd(buffer, sizeof(buffer) - 1,\n> +                       get_git_work_tree());\n\nNote to self, cwd should be passed to setup_explicit_git_dir, then\ndrop get_relative_cwd() in favor of prefixcmp(). One less getcwd call,\nbuffer will not be not needed. And probably easier to understand.\n-- \nDuy\n"}]}