{"thread":{"id":"12342","subject":"[PATCH 1/9] \"git read-tree -m\" and the like require worktree","startedAt":"2008-02-27T16:38:10Z","lastAt":"2011-04-05T11:32:31Z","messageCount":24,"participants":["Nguyễn Thái Ngọc Duy","Junio C Hamano","Nguyen Thai Ngoc Duy","Johannes Schindelin","Jonathan Nieder"],"isPatch":true,"patchVersion":1,"patchTotal":9},"messages":[{"id":"70088","messageId":"20080227163810.GA28016@laptop","threadId":"12342","inReplyTo":"cover.1204130175.git.pclouds@gmail.com","subject":"[PATCH 1/9] \"git read-tree -m\" and the like require worktree","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2008-02-27T16:38:10Z","receivedAt":"2008-02-27T16:38:10Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin-read-tree.c |    3 +++\n 1 files changed, 3 insertions(+), 0 deletions(-)\n\ndiff --git a/builtin-read-tree.c b/builtin-read-tree.c\nindex e78cf69..95318e3 100644\n--- a/builtin-read-tree.c\n+++ b/builtin-read-tree.c\n@@ -219,6 +219,9 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n \tif ((opts.dir && !opts.update))\n \t\tdie(\"--exclude-per-directory is meaningless unless -u\");\n \n+\tif (opts.merge)\n+\t\tsetup_work_tree();\n+\n \tif (opts.prefix) {\n \t\tint pfxlen = strlen(opts.prefix);\n \t\tint pos;\n-- \n1.5.4.2.281.g28d0e\n"},{"id":"70091","messageId":"20080227163829.GA28031@laptop","threadId":"12342","inReplyTo":"cover.1204130175.git.pclouds@gmail.com","subject":"[PATCH 2/9] Make sure setup_git_directory is called before accessing repository","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2008-02-27T16:38:29Z","receivedAt":"2008-02-27T16:38:29Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Right now setup_git_env is called automatically when needed and\nwill not die out if $GIT_DIR is invalid. The next patch no longer\nguarantee that, so make sure all commands have environment properly\nsetup before using.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n fast-import.c |    1 +\n hash-object.c |   10 +++++-----\n index-pack.c  |    2 ++\n 3 files changed, 8 insertions(+), 5 deletions(-)\n\ndiff --git a/fast-import.c b/fast-import.c\nindex 0d3449f..7f197d5 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -2377,6 +2377,7 @@ int main(int argc, const char **argv)\n {\n \tunsigned int i, show_stats = 1;\n \n+\tsetup_git_directory();\n \tgit_config(git_pack_config);\n \tif (!pack_compression_seen && core_compression_seen)\n \t\tpack_compression_level = core_compression_level;\ndiff --git a/hash-object.c b/hash-object.c\nindex 61e7160..46d57ad 100644\n--- a/hash-object.c\n+++ b/hash-object.c\n@@ -42,7 +42,10 @@ int main(int argc, char **argv)\n \tint prefix_length = -1;\n \tint no_more_flags = 0;\n \tint hashstdin = 0;\n+\tint nongit = 0;\n \n+\tprefix = setup_git_directory_gently(&nongit);\n+\tprefix_length = prefix ? strlen(prefix) : 0;\n \tgit_config(git_default_config);\n \n \tfor (i = 1 ; i < argc; i++) {\n@@ -53,11 +56,8 @@ int main(int argc, char **argv)\n \t\t\t\ttype = argv[i];\n \t\t\t}\n \t\t\telse if (!strcmp(argv[i], \"-w\")) {\n-\t\t\t\tif (prefix_length < 0) {\n-\t\t\t\t\tprefix = setup_git_directory();\n-\t\t\t\t\tprefix_length =\n-\t\t\t\t\t\tprefix ? strlen(prefix) : 0;\n-\t\t\t\t}\n+\t\t\t\tif (nongit)\n+\t\t\t\t\tdie(\"Not a git repository\");\n \t\t\t\twrite_object = 1;\n \t\t\t}\n \t\t\telse if (!strcmp(argv[i], \"--\")) {\ndiff --git a/index-pack.c b/index-pack.c\nindex 9fd6982..b4c2310 100644\n--- a/index-pack.c\n+++ b/index-pack.c\n@@ -703,7 +703,9 @@ int main(int argc, char **argv)\n \tchar *index_name_buf = NULL, *keep_name_buf = NULL;\n \tstruct pack_idx_entry **idx_objects;\n \tunsigned char sha1[20];\n+\tint nongit = 0;\n \n+\tsetup_git_directory_gently(&nongit);\n \tgit_config(git_index_pack_config);\n \n \tfor (i = 1; i < argc; i++) {\n-- \n1.5.4.2.281.g28d0e\n"},{"id":"70090","messageId":"20080227163845.GA28045@laptop","threadId":"12342","inReplyTo":"cover.1204130175.git.pclouds@gmail.com","subject":"[PATCH 3/9] Make get_git_dir() and 'git rev-parse --git-dir' absolute path","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2008-02-27T16:38:45Z","receivedAt":"2008-02-27T16:38:45Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin-rev-parse.c    |   14 +-------------\n environment.c          |    1 +\n t/t1300-repo-config.sh |    2 +-\n t/t1400-update-ref.sh  |    4 ++--\n t/t9300-fast-import.sh |    2 +-\n 5 files changed, 6 insertions(+), 17 deletions(-)\n\ndiff --git a/builtin-rev-parse.c b/builtin-rev-parse.c\nindex b9af1a5..651b5e6 100644\n--- a/builtin-rev-parse.c\n+++ b/builtin-rev-parse.c\n@@ -496,19 +496,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"--git-dir\")) {\n-\t\t\t\tconst char *gitdir = getenv(GIT_DIR_ENVIRONMENT);\n-\t\t\t\tstatic char cwd[PATH_MAX];\n-\t\t\t\tif (gitdir) {\n-\t\t\t\t\tputs(gitdir);\n-\t\t\t\t\tcontinue;\n-\t\t\t\t}\n-\t\t\t\tif (!prefix) {\n-\t\t\t\t\tputs(\".git\");\n-\t\t\t\t\tcontinue;\n-\t\t\t\t}\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/.git\\n\", cwd);\n+\t\t\t\tputs(get_git_dir());\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"--is-inside-git-dir\")) {\ndiff --git a/environment.c b/environment.c\nindex 6739a3f..ab7e54c 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -51,6 +51,7 @@ static void setup_git_env(void)\n \tgit_dir = getenv(GIT_DIR_ENVIRONMENT);\n \tif (!git_dir)\n \t\tgit_dir = DEFAULT_GIT_DIR_ENVIRONMENT;\n+\tgit_dir = xstrdup(make_absolute_path(git_dir));\n \tgit_object_dir = getenv(DB_ENVIRONMENT);\n \tif (!git_object_dir) {\n \t\tgit_object_dir = xmalloc(strlen(git_dir) + 9);\ndiff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh\nindex 4928a57..45b26d5 100755\n--- a/t/t1300-repo-config.sh\n+++ b/t/t1300-repo-config.sh\n@@ -497,7 +497,7 @@ test_expect_success numbers '\n '\n \n cat > expect <<EOF\n-fatal: bad config value for 'aninvalid.unit' in .git/config\n+fatal: bad config value for 'aninvalid.unit' in $(pwd)/.git/config\n EOF\n \n test_expect_success 'invalid unit' '\ndiff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh\nindex 78cd412..4099c66 100755\n--- a/t/t1400-update-ref.sh\n+++ b/t/t1400-update-ref.sh\n@@ -169,7 +169,7 @@ test_expect_success \\\n \t'rm -f o e\n \t git rev-parse --verify \"master@{2005-05-26 23:33:01}\" >o 2>e &&\n \t test '\"$B\"' = $(cat o) &&\n-\t test \"warning: Log .git/logs/'\"$m has gap after $gd\"'.\" = \"$(cat e)\"'\n+\t test \"warning: Log '\"$(pwd)\"'/.git/logs/'\"$m has gap after $gd\"'.\" = \"$(cat e)\"'\n test_expect_success \\\n \t'Query \"master@{2005-05-26 23:38:00}\" (middle of history)' \\\n \t'rm -f o e\n@@ -187,7 +187,7 @@ test_expect_success \\\n \t'rm -f o e\n \t git rev-parse --verify \"master@{2005-05-28}\" >o 2>e &&\n \t test '\"$D\"' = $(cat o) &&\n-\t test \"warning: Log .git/logs/'\"$m unexpectedly ended on $ld\"'.\" = \"$(cat e)\"'\n+\t test \"warning: Log '\"$(pwd)\"'/.git/logs/'\"$m unexpectedly ended on $ld\"'.\" = \"$(cat e)\"'\n \n \n rm -f .git/$m .git/logs/$m expect\ndiff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh\nindex cceedbb..98a0cdf 100755\n--- a/t/t9300-fast-import.sh\n+++ b/t/t9300-fast-import.sh\n@@ -510,7 +510,7 @@ test_expect_success \\\n     'git-fast-import --export-pack-edges=edges.list <input'\n \n cat >expect <<EOF\n-.git/objects/pack/pack-.pack: `git rev-parse --verify export-boundary`\n+$(pwd)/.git/objects/pack/pack-.pack: `git rev-parse --verify export-boundary`\n EOF\n test_expect_success \\\n \t'I: verify edge list' \\\n-- \n1.5.4.2.281.g28d0e\n"},{"id":"70092","messageId":"20080227163902.GA28058@laptop","threadId":"12342","inReplyTo":"cover.1204130175.git.pclouds@gmail.com","subject":"[PATCH 4/9] Make setup_work_tree() return new prefix","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2008-02-27T16:39:02Z","receivedAt":"2008-02-27T16:39:02Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"worktree setup inside setup_git_directory*() is not perfect. It does\nnot take core.worktree into account. So when you do setup_work_tree(),\nthe real work tree may be not the one setup_git_directory*() gives you.\nYou need a new prefix in that case.\n\nThis also effectively reverts dd5c8af (Fix\nsetup_git_directory_gently() with relative GIT_DIR & GIT_WORK_TREE).\nThe problem is IMHO that git-diff does not setup worktree when it\nneeds it, so setting up worktree from setup_git_directory_gently() is\na fix in a wrong place.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin-blame.c      |    4 +-\n builtin-diff-files.c |    4 ++-\n builtin-diff.c       |    4 ++-\n builtin-ls-files.c   |    8 ++--\n builtin-read-tree.c  |    2 +-\n builtin-rev-parse.c  |    2 +\n builtin-rm.c         |    2 +-\n cache.h              |    2 +-\n git.c                |    2 +-\n setup.c              |   84 ++++++++++++++++----------------------------------\n 10 files changed, 45 insertions(+), 69 deletions(-)\n\ndiff --git a/builtin-blame.c b/builtin-blame.c\nindex bfd562d..f5a878b 100644\n--- a/builtin-blame.c\n+++ b/builtin-blame.c\n@@ -2291,6 +2291,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \t\t\t/* (3) */\n \t\t\tif (argc <= i)\n \t\t\t\tusage(blame_usage);\n+\t\t\tprefix = setup_work_tree(prefix);\n \t\t\tpath = add_prefix(prefix, argv[i]);\n \t\t\tif (i + 1 == argc - 1) {\n \t\t\t\tfinal_commit_name = argv[i + 1];\n@@ -2306,7 +2307,6 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \t\t\telse if (i != argc - 1)\n \t\t\t\tusage(blame_usage); /* garbage at end */\n \n-\t\t\tsetup_work_tree();\n \t\t\tif (!has_path_in_work_tree(path))\n \t\t\t\tdie(\"cannot stat path %s: %s\",\n \t\t\t\t    path, strerror(errno));\n@@ -2354,7 +2354,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)\n \t\t * do not default to HEAD, but use the working tree\n \t\t * or \"--contents\".\n \t\t */\n-\t\tsetup_work_tree();\n+\t\tsetup_work_tree(prefix);\n \t\tsb.final = fake_working_tree_commit(path, contents_from);\n \t\tadd_pending_object(&revs, &(sb.final->object), \":\");\n \t}\ndiff --git a/builtin-diff-files.c b/builtin-diff-files.c\nindex 4abe3c2..11671a8 100644\n--- a/builtin-diff-files.c\n+++ b/builtin-diff-files.c\n@@ -26,8 +26,10 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix)\n \n \tif (!setup_diff_no_index(&rev, argc, argv, nongit, prefix))\n \t\targc = 0;\n-\telse\n+\telse {\n+\t\trev.prefix = setup_work_tree(prefix);\n \t\targc = setup_revisions(argc, argv, &rev, NULL);\n+\t}\n \tif (!rev.diffopt.output_format)\n \t\trev.diffopt.output_format = DIFF_FORMAT_RAW;\n \tresult = run_diff_files_cmd(&rev, argc, argv);\ndiff --git a/builtin-diff.c b/builtin-diff.c\nindex 444ff2f..254e5a0 100644\n--- a/builtin-diff.c\n+++ b/builtin-diff.c\n@@ -244,8 +244,10 @@ int cmd_diff(int argc, const char **argv, const char *prefix)\n \n \tif (!setup_diff_no_index(&rev, argc, argv, nongit, prefix))\n \t\targc = 0;\n-\telse\n+\telse {\n+\t\trev.prefix = setup_work_tree(prefix);\n \t\targc = setup_revisions(argc, argv, &rev, NULL);\n+\t}\n \tif (!rev.diffopt.output_format) {\n \t\trev.diffopt.output_format = DIFF_FORMAT_PATCH;\n \t\tif (diff_setup_done(&rev.diffopt) < 0)\ndiff --git a/builtin-ls-files.c b/builtin-ls-files.c\nindex 25dbfb4..cf4c492 100644\n--- a/builtin-ls-files.c\n+++ b/builtin-ls-files.c\n@@ -23,7 +23,7 @@ static int show_valid_bit;\n static int line_terminator = '\\n';\n \n static int prefix_len;\n-static int prefix_offset;\n+static int prefix_offset = -1;\n static const char **pathspec;\n static int error_unmatch;\n static char *ps_matched;\n@@ -435,8 +435,6 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)\n \tstruct dir_struct dir;\n \n \tmemset(&dir, 0, sizeof(dir));\n-\tif (prefix)\n-\t\tprefix_offset = strlen(prefix);\n \tgit_config(git_default_config);\n \n \tfor (i = 1; i < argc; i++) {\n@@ -569,7 +567,9 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)\n \t}\n \n \tif (require_work_tree && !is_inside_work_tree())\n-\t\tsetup_work_tree();\n+\t\tprefix = setup_work_tree(prefix);\n+\tif (prefix_offset == -1)\n+\t\tprefix_offset = prefix ? strlen(prefix) : 0;\n \n \tpathspec = get_pathspec(prefix, argv + i);\n \ndiff --git a/builtin-read-tree.c b/builtin-read-tree.c\nindex 95318e3..0a398f9 100644\n--- a/builtin-read-tree.c\n+++ b/builtin-read-tree.c\n@@ -220,7 +220,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n \t\tdie(\"--exclude-per-directory is meaningless unless -u\");\n \n \tif (opts.merge)\n-\t\tsetup_work_tree();\n+\t\tsetup_work_tree(NULL);\n \n \tif (opts.prefix) {\n \t\tint pfxlen = strlen(opts.prefix);\ndiff --git a/builtin-rev-parse.c b/builtin-rev-parse.c\nindex 651b5e6..e82cac2 100644\n--- a/builtin-rev-parse.c\n+++ b/builtin-rev-parse.c\n@@ -472,6 +472,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"--show-prefix\")) {\n+\t\t\t\tif (is_inside_work_tree())\n+\t\t\t\t\tprefix = setup_work_tree(prefix);\n \t\t\t\tif (prefix)\n \t\t\t\t\tputs(prefix);\n \t\t\t\tcontinue;\ndiff --git a/builtin-rm.c b/builtin-rm.c\nindex c0a8bb6..2c15d66 100644\n--- a/builtin-rm.c\n+++ b/builtin-rm.c\n@@ -156,7 +156,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)\n \t\tusage_with_options(builtin_rm_usage, builtin_rm_options);\n \n \tif (!index_only)\n-\t\tsetup_work_tree();\n+\t\tprefix = setup_work_tree(prefix);\n \n \tpathspec = get_pathspec(prefix, argv);\n \tseen = NULL;\ndiff --git a/cache.h b/cache.h\nindex a5b9ffd..dc768db 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -282,7 +282,7 @@ extern const char *get_git_work_tree(void);\n #define ALTERNATE_DB_ENVIRONMENT \"GIT_ALTERNATE_OBJECT_DIRECTORIES\"\n \n extern const char **get_pathspec(const char *prefix, const char **pathspec);\n-extern void setup_work_tree(void);\n+extern const char *setup_work_tree(const char *prefix);\n extern const char *setup_git_directory_gently(int *);\n extern const char *setup_git_directory(void);\n extern const char *prefix_path(const char *prefix, int len, const char *path);\ndiff --git a/git.c b/git.c\nindex 4f804a2..90451ee 100644\n--- a/git.c\n+++ b/git.c\n@@ -252,7 +252,7 @@ static int run_command(struct cmd_struct *p, int argc, const char **argv)\n \tif (p->option & USE_PAGER)\n \t\tsetup_pager();\n \tif (p->option & NEED_WORK_TREE)\n-\t\tsetup_work_tree();\n+\t\tprefix = setup_work_tree(prefix);\n \n \ttrace_argv_printf(argv, \"trace: built-in: git\");\n \ndiff --git a/setup.c b/setup.c\nindex 89c81e5..6c908a5 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -262,38 +262,23 @@ int is_inside_work_tree(void)\n \treturn inside_work_tree;\n }\n \n-/*\n- * set_work_tree() is only ever called if you set GIT_DIR explicitely.\n- * The old behaviour (which we retain here) is to set the work tree root\n- * to the cwd, unless overridden by the config, the command line, or\n- * GIT_WORK_TREE.\n- */\n-static const char *set_work_tree(const char *dir)\n-{\n-\tchar buffer[PATH_MAX + 1];\n-\n-\tif (!getcwd(buffer, sizeof(buffer)))\n-\t\tdie (\"Could not get the current working directory\");\n-\tgit_work_tree_cfg = xstrdup(buffer);\n-\tinside_work_tree = 1;\n-\n-\treturn NULL;\n-}\n-\n-void setup_work_tree(void)\n+const char *setup_work_tree(const char *prefix)\n {\n-\tconst char *work_tree, *git_dir;\n-\tstatic int initialized = 0;\n+\tconst char *work_tree;\n+\tstatic char buffer[PATH_MAX + 1];\n+\tchar *rel;\n \n-\tif (initialized)\n-\t\treturn;\n+\tget_git_dir(); /* ensure git_dir has been initialized as cwd will change */\n \twork_tree = get_git_work_tree();\n-\tgit_dir = get_git_dir();\n-\tif (!is_absolute_path(git_dir))\n-\t\tset_git_dir(make_absolute_path(git_dir));\n-\tif (!work_tree || chdir(work_tree))\n+\tif (!work_tree)\n \t\tdie(\"This operation must be run in a work tree\");\n-\tinitialized = 1;\n+\tif (prefix && chdir(prefix))\n+\t\tdie (\"Could not jump back into original cwd\");\n+\trel = get_relative_cwd(buffer, PATH_MAX, work_tree);\n+\ttrace_printf(\"test: worktree = %s\\n\", rel ? rel : \"NULL\");\n+\tif (chdir(work_tree))\n+\t\tdie(\"This operation must be run in a work tree\");\n+\treturn rel && *rel ? strcat(rel, \"/\") : NULL;\n }\n \n static int check_repository_format_gently(int *nongit_ok)\n@@ -336,24 +321,21 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t\t\tstatic char buffer[1024 + 1];\n \t\t\tconst char *retval;\n \n+\t\t\t/*\n+\t\t\t * The old behaviour (which we retain here) is to set\n+\t\t\t * the work tree root to the cwd, unless overridden by\n+\t\t\t * the config, the command line, or GIT_WORK_TREE.\n+\t\t\t */\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\tchar buffer[PATH_MAX + 1];\n+\n+\t\t\t\tif (!getcwd(buffer, sizeof(buffer)))\n+\t\t\t\t\tdie (\"Could not get the current working directory\");\n+\t\t\t\tgit_work_tree_cfg = xstrdup(buffer);\n+\t\t\t\tinside_work_tree = 1;\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 (\"Could not chdir to %s\", work_tree_env);\n-\t\t\tstrcat(buffer, \"/\");\n-\t\t\treturn retval;\n+\t\t\tcheck_repository_format_gently(nongit_ok);\n+\t\t\treturn NULL;\n \t\t}\n \t\tif (nongit_ok) {\n \t\t\t*nongit_ok = 1;\n@@ -462,17 +444,5 @@ int check_repository_format(void)\n \n const char *setup_git_directory(void)\n {\n-\tconst char *retval = setup_git_directory_gently(NULL);\n-\n-\t/* If the work tree is not the default one, recompute prefix */\n-\tif (inside_work_tree < 0) {\n-\t\tstatic char buffer[PATH_MAX + 1];\n-\t\tchar *rel;\n-\t\tif (retval && chdir(retval))\n-\t\t\tdie (\"Could not jump back into original cwd\");\n-\t\trel = get_relative_cwd(buffer, PATH_MAX, get_git_work_tree());\n-\t\treturn rel && *rel ? strcat(rel, \"/\") : NULL;\n-\t}\n-\n-\treturn retval;\n+\treturn setup_git_directory_gently(NULL);\n }\n-- \n1.5.4.2.281.g28d0e\n"},{"id":"70093","messageId":"20080227163918.GA28071@laptop","threadId":"12342","inReplyTo":"cover.1204130175.git.pclouds@gmail.com","subject":"[PATCH 5/9] http-push: Avoid calling setup_git_directory() twice","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2008-02-27T16:39:18Z","receivedAt":"2008-02-27T16:39:18Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n http-push.c |    4 ++--\n 1 files changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/http-push.c b/http-push.c\nindex 406270f..1dd78e8 100644\n--- a/http-push.c\n+++ b/http-push.c\n@@ -2173,7 +2173,7 @@ int main(int argc, char **argv)\n \tstruct ref *ref;\n \tchar *rewritten_url = NULL;\n \n-\tsetup_git_directory();\n+\tconst char *prefix = setup_git_directory();\n \n \tremote = xcalloc(sizeof(*remote), 1);\n \n@@ -2375,7 +2375,7 @@ int main(int argc, char **argv)\n \t\t\tcommit_argv[3] = old_sha1_hex;\n \t\t\tcommit_argc++;\n \t\t}\n-\t\tinit_revisions(&revs, setup_git_directory());\n+\t\tinit_revisions(&revs, prefix);\n \t\tsetup_revisions(commit_argc, commit_argv, &revs, NULL);\n \t\tfree(new_sha1_hex);\n \t\tif (old_sha1_hex) {\n-- \n1.5.4.2.281.g28d0e\n"},{"id":"70094","messageId":"20080227163934.GA28084@laptop","threadId":"12342","inReplyTo":"cover.1204130175.git.pclouds@gmail.com","subject":"[PATCH 6/9] Completely move out worktree setup from setup_git_directory_gently()","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2008-02-27T16:39:34Z","receivedAt":"2008-02-27T16:39:34Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This was impossible earlier because git_dir can be relative. Now that\ngit_dir is absolute, I see no reason for worktree setup inside\nsetup_git_directory_gently(). The semantic is now clearer: if you need\nworktree, call setup_work_tree yourself (well, I will clean up\nsetup_git_directory() part later)\n\nThis patch will free some commands from prefix handling if they don't\never need worktree.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin-apply.c          |    7 +++++--\n builtin-bundle.c         |    9 ++-------\n builtin-config.c         |   15 +++++----------\n builtin-diff-files.c     |   10 +++++-----\n builtin-diff.c           |   11 ++++++-----\n builtin-upload-archive.c |    4 ++--\n cache.h                  |    2 +-\n git.c                    |    6 +-----\n hash-object.c            |    8 +-------\n setup.c                  |   34 +++++++++++++++++-----------------\n 10 files changed, 45 insertions(+), 61 deletions(-)\n\ndiff --git a/builtin-apply.c b/builtin-apply.c\nindex 12e85a4..c50ae32 100644\n--- a/builtin-apply.c\n+++ b/builtin-apply.c\n@@ -3103,8 +3103,11 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)\n \n \tconst char *whitespace_option = NULL;\n \n-\tprefix = setup_git_directory_gently(&is_not_gitdir);\n-\tprefix_length = prefix ? strlen(prefix) : 0;\n+\tsetup_git_directory_gently(&is_not_gitdir);\n+\tif (!is_not_gitdir && is_inside_work_tree()) {\n+\t\tprefix = setup_work_tree(NULL);\n+\t\tprefix_length = prefix ? strlen(prefix) : 0;\n+\t}\n \tgit_config(git_apply_config);\n \tif (apply_default_whitespace)\n \t\tparse_whitespace_option(apply_default_whitespace);\ndiff --git a/builtin-bundle.c b/builtin-bundle.c\nindex 9f38e21..2a7687e 100644\n--- a/builtin-bundle.c\n+++ b/builtin-bundle.c\n@@ -11,7 +11,7 @@\n \n static const char *bundle_usage=\"git-bundle (create <bundle> <git-rev-list args> | verify <bundle> | list-heads <bundle> [refname]... | unbundle <bundle> [refname]... )\";\n \n-int cmd_bundle(int argc, const char **argv, const char *prefix)\n+int cmd_bundle(int argc, const char **argv, const char *unused_prefix)\n {\n \tstruct bundle_header header;\n \tint nongit = 0;\n@@ -27,12 +27,7 @@ int cmd_bundle(int argc, const char **argv, const char *prefix)\n \targc -= 2;\n \targv += 2;\n \n-\tprefix = setup_git_directory_gently(&nongit);\n-\tif (prefix && bundle_file[0] != '/') {\n-\t\tsnprintf(buffer, sizeof(buffer), \"%s/%s\", prefix, bundle_file);\n-\t\tbundle_file = buffer;\n-\t}\n-\n+\tsetup_git_directory_gently(&nongit);\n \tmemset(&header, 0, sizeof(header));\n \tif (strcmp(cmd, \"create\") && (bundle_fd =\n \t\t\t\tread_bundle_header(bundle_file, &header)) < 0)\ndiff --git a/builtin-config.c b/builtin-config.c\nindex 2b9a426..ae6be9b 100644\n--- a/builtin-config.c\n+++ b/builtin-config.c\n@@ -262,11 +262,11 @@ static int get_colorbool(int argc, const char **argv)\n \t}\n }\n \n-int cmd_config(int argc, const char **argv, const char *prefix)\n+int cmd_config(int argc, const char **argv, const char *unused_prefix)\n {\n \tint nongit = 0;\n \tchar* value;\n-\tconst char *file = setup_git_directory_gently(&nongit);\n+\tsetup_git_directory_gently(&nongit);\n \n \twhile (1 < argc) {\n \t\tif (!strcmp(argv[1], \"--int\"))\n@@ -276,8 +276,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\telse if (!strcmp(argv[1], \"--list\") || !strcmp(argv[1], \"-l\")) {\n \t\t\tif (argc != 2)\n \t\t\t\tusage(git_config_set_usage);\n-\t\t\tif (git_config(show_all_config) < 0 && file && errno)\n-\t\t\t\tdie(\"unable to read config file %s: %s\", file,\n+\t\t\tif (git_config(show_all_config) < 0 && errno)\n+\t\t\t\tdie(\"unable to read config file: %s\",\n \t\t\t\t    strerror(errno));\n \t\t\treturn 0;\n \t\t}\n@@ -296,12 +296,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\telse if (!strcmp(argv[1], \"--file\") || !strcmp(argv[1], \"-f\")) {\n \t\t\tif (argc < 3)\n \t\t\t\tusage(git_config_set_usage);\n-\t\t\tif (!is_absolute_path(argv[2]) && file)\n-\t\t\t\tfile = prefix_filename(file, strlen(file),\n-\t\t\t\t\t\t       argv[2]);\n-\t\t\telse\n-\t\t\t\tfile = argv[2];\n-\t\t\tsetenv(CONFIG_ENVIRONMENT, file, 1);\n+\t\t\tsetenv(CONFIG_ENVIRONMENT, argv[2], 1);\n \t\t\targc--;\n \t\t\targv++;\n \t\t}\ndiff --git a/builtin-diff-files.c b/builtin-diff-files.c\nindex 11671a8..2529900 100644\n--- a/builtin-diff-files.c\n+++ b/builtin-diff-files.c\n@@ -13,21 +13,21 @@ static const char diff_files_usage[] =\n \"git-diff-files [-q] [-0/-1/2/3 |-c|--cc|--no-index] [<common diff options>] [<path>...]\"\n COMMON_DIFF_OPTIONS_HELP;\n \n-int cmd_diff_files(int argc, const char **argv, const char *prefix)\n+int cmd_diff_files(int argc, const char **argv, const char *unused_prefix)\n {\n \tstruct rev_info rev;\n \tint nongit = 0;\n \tint result;\n \n-\tprefix = setup_git_directory_gently(&nongit);\n-\tinit_revisions(&rev, prefix);\n+\tsetup_git_directory_gently(&nongit);\n+\tinit_revisions(&rev, NULL);\n \tgit_config(git_diff_basic_config); /* no \"diff\" UI options */\n \trev.abbrev = 0;\n \n-\tif (!setup_diff_no_index(&rev, argc, argv, nongit, prefix))\n+\tif (!setup_diff_no_index(&rev, argc, argv, nongit, NULL))\n \t\targc = 0;\n \telse {\n-\t\trev.prefix = setup_work_tree(prefix);\n+\t\trev.prefix = setup_work_tree(NULL);\n \t\targc = setup_revisions(argc, argv, &rev, NULL);\n \t}\n \tif (!rev.diffopt.output_format)\ndiff --git a/builtin-diff.c b/builtin-diff.c\nindex 254e5a0..61b30e6 100644\n--- a/builtin-diff.c\n+++ b/builtin-diff.c\n@@ -202,7 +202,7 @@ static void refresh_index_quietly(void)\n \trollback_lock_file(lock_file);\n }\n \n-int cmd_diff(int argc, const char **argv, const char *prefix)\n+int cmd_diff(int argc, const char **argv, const char *unused_prefix)\n {\n \tint i;\n \tstruct rev_info rev;\n@@ -233,19 +233,20 @@ int cmd_diff(int argc, const char **argv, const char *prefix)\n \t * Other cases are errors.\n \t */\n \n-\tprefix = setup_git_directory_gently(&nongit);\n+\tsetup_git_directory_gently(&nongit);\n \tgit_config(git_diff_ui_config);\n \n \tif (diff_use_color_default == -1)\n \t\tdiff_use_color_default = git_use_color_default;\n \n-\tinit_revisions(&rev, prefix);\n+\tinit_revisions(&rev, NULL);\n \trev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;\n \n-\tif (!setup_diff_no_index(&rev, argc, argv, nongit, prefix))\n+\tif (!setup_diff_no_index(&rev, argc, argv, nongit, NULL))\n \t\targc = 0;\n \telse {\n-\t\trev.prefix = setup_work_tree(prefix);\n+\t\trev.prefix = setup_work_tree(NULL);\n+\t\trev.diffopt.skip_stat_unmatch = !!diff_auto_refresh_index;\n \t\targc = setup_revisions(argc, argv, &rev, NULL);\n \t}\n \tif (!rev.diffopt.output_format) {\ndiff --git a/builtin-upload-archive.c b/builtin-upload-archive.c\nindex 48ae09e..4f7fa35 100644\n--- a/builtin-upload-archive.c\n+++ b/builtin-upload-archive.c\n@@ -17,7 +17,7 @@ static const char lostchild[] =\n \"git-upload-archive: archiver process was lost\";\n \n \n-static int run_upload_archive(int argc, const char **argv, const char *prefix)\n+static int run_upload_archive(int argc, const char **argv, const char *unused_prefix)\n {\n \tstruct archiver ar;\n \tconst char *sent_argv[MAX_ARGS];\n@@ -67,7 +67,7 @@ static int run_upload_archive(int argc, const char **argv, const char *prefix)\n \t/* parse all options sent by the client */\n \ttreeish_idx = parse_archive_args(sent_argc, sent_argv, &ar);\n \n-\tparse_treeish_arg(sent_argv + treeish_idx, &ar.args, prefix);\n+\tparse_treeish_arg(sent_argv + treeish_idx, &ar.args, NULL);\n \tparse_pathspec_arg(sent_argv + treeish_idx + 1, &ar.args);\n \n \treturn ar.write_archive(&ar.args);\ndiff --git a/cache.h b/cache.h\nindex dc768db..a5952db 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -283,7 +283,7 @@ extern const char *get_git_work_tree(void);\n \n extern const char **get_pathspec(const char *prefix, const char **pathspec);\n extern const char *setup_work_tree(const char *prefix);\n-extern const char *setup_git_directory_gently(int *);\n+extern void setup_git_directory_gently(int *);\n extern const char *setup_git_directory(void);\n extern const char *prefix_path(const char *prefix, int len, const char *path);\n extern const char *prefix_filename(const char *prefix, int len, const char *path);\ndiff --git a/git.c b/git.c\nindex 90451ee..ffdf6b9 100644\n--- a/git.c\n+++ b/git.c\n@@ -156,11 +156,10 @@ static int split_cmdline(char *cmdline, const char ***argv)\n static int handle_alias(int *argcp, const char ***argv)\n {\n \tint nongit = 0, envchanged = 0, ret = 0, saved_errno = errno;\n-\tconst char *subdir;\n \tint count, option_count;\n \tconst char** new_argv;\n \n-\tsubdir = setup_git_directory_gently(&nongit);\n+\tsetup_git_directory_gently(&nongit);\n \n \talias_command = (*argv)[0];\n \tgit_config(git_alias_config);\n@@ -216,9 +215,6 @@ static int handle_alias(int *argcp, const char ***argv)\n \t\tret = 1;\n \t}\n \n-\tif (subdir)\n-\t\tchdir(subdir);\n-\n \terrno = saved_errno;\n \n \treturn ret;\ndiff --git a/hash-object.c b/hash-object.c\nindex 46d57ad..5986701 100644\n--- a/hash-object.c\n+++ b/hash-object.c\n@@ -38,14 +38,11 @@ int main(int argc, char **argv)\n \tint i;\n \tconst char *type = blob_type;\n \tint write_object = 0;\n-\tconst char *prefix = NULL;\n-\tint prefix_length = -1;\n \tint no_more_flags = 0;\n \tint hashstdin = 0;\n \tint nongit = 0;\n \n-\tprefix = setup_git_directory_gently(&nongit);\n-\tprefix_length = prefix ? strlen(prefix) : 0;\n+\tsetup_git_directory_gently(&nongit);\n \tgit_config(git_default_config);\n \n \tfor (i = 1 ; i < argc; i++) {\n@@ -80,9 +77,6 @@ int main(int argc, char **argv)\n \t\t\t\thash_stdin(type, write_object);\n \t\t\t\thashstdin = 0;\n \t\t\t}\n-\t\t\tif (0 <= prefix_length)\n-\t\t\t\targ = prefix_filename(prefix, prefix_length,\n-\t\t\t\t\t\t      arg);\n \t\t\thash_object(arg, type_from_string(type), write_object);\n \t\t\tno_more_flags = 1;\n \t\t}\ndiff --git a/setup.c b/setup.c\nindex 6c908a5..78ae2f9 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -301,7 +301,7 @@ static int check_repository_format_gently(int *nongit_ok)\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  */\n-const char *setup_git_directory_gently(int *nongit_ok)\n+void setup_git_directory_gently(int *nongit_ok)\n {\n \tconst char *work_tree_env = getenv(GIT_WORK_TREE_ENVIRONMENT);\n \tstatic char cwd[PATH_MAX+1];\n@@ -335,11 +335,11 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t\t\t\tinside_work_tree = 1;\n \t\t\t}\n \t\t\tcheck_repository_format_gently(nongit_ok);\n-\t\t\treturn NULL;\n+\t\t\treturn;\n \t\t}\n \t\tif (nongit_ok) {\n \t\t\t*nongit_ok = 1;\n-\t\t\treturn NULL;\n+\t\t\treturn;\n \t\t}\n \t\tdie(\"Not a git repository: '%s'\", gitdirenv);\n \t}\n@@ -364,9 +364,12 @@ const char *setup_git_directory_gently(int *nongit_ok)\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\tsetenv(GIT_DIR_ENVIRONMENT, \".\", 1);\n+\t\t\tif (chdir(cwd))\n+\t\t\t\tdie(\"Cannot come back to cwd\");\n+\t\t\tcwd[offset] = '\\0';\n+\t\t\tsetenv(GIT_DIR_ENVIRONMENT, cwd, 1);\n \t\t\tcheck_repository_format_gently(nongit_ok);\n-\t\t\treturn NULL;\n+\t\t\treturn;\n \t\t}\n \t\tchdir(\"..\");\n \t\tdo {\n@@ -375,27 +378,23 @@ const char *setup_git_directory_gently(int *nongit_ok)\n \t\t\t\t\tif (chdir(cwd))\n \t\t\t\t\t\tdie(\"Cannot come back to cwd\");\n \t\t\t\t\t*nongit_ok = 1;\n-\t\t\t\t\treturn NULL;\n+\t\t\t\t\treturn;\n \t\t\t\t}\n \t\t\t\tdie(\"Not a git repository\");\n \t\t\t}\n \t\t} while (cwd[--offset] != '/');\n \t}\n \n+\tif (chdir(cwd))\n+\t\tdie(\"Cannot come back to cwd\");\n \tinside_git_dir = 0;\n \tif (!work_tree_env)\n \t\tinside_work_tree = 1;\n \tgit_work_tree_cfg = xstrndup(cwd, offset);\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+\tcwd[offset] = '/';\n+\tstrcpy(cwd+offset+1, DEFAULT_GIT_DIR_ENVIRONMENT);\n+\tsetenv(GIT_DIR_ENVIRONMENT, cwd, 1);\n+\tcheck_repository_format_gently(nongit_ok);\n }\n \n int git_config_perm(const char *var, const char *value)\n@@ -444,5 +443,6 @@ int check_repository_format(void)\n \n const char *setup_git_directory(void)\n {\n-\treturn setup_git_directory_gently(NULL);\n+\tsetup_git_directory_gently(NULL);\n+\treturn is_inside_work_tree() ? setup_work_tree(NULL) : NULL;\n }\n-- \n1.5.4.2.281.g28d0e\n"},{"id":"70096","messageId":"20080227164007.GA28099@laptop","threadId":"12342","inReplyTo":"cover.1204130175.git.pclouds@gmail.com","subject":"[PATCH 7/9] builtin-archive: mark unused prefix \"unused_prefix\"","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2008-02-27T16:40:07Z","receivedAt":"2008-02-27T16:40:07Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"cmd_archive() is registered without RUN_SETUP so its prefix\nwill be NULL forever. Let's make that clear.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin-archive.c |    6 +++---\n 1 files changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/builtin-archive.c b/builtin-archive.c\nindex c2e0c1e..84405df 100644\n--- a/builtin-archive.c\n+++ b/builtin-archive.c\n@@ -236,11 +236,12 @@ static const char *extract_remote_arg(int *ac, const char **av)\n \treturn remote;\n }\n \n-int cmd_archive(int argc, const char **argv, const char *prefix)\n+int cmd_archive(int argc, const char **argv, const char *unused_prefix)\n {\n \tstruct archiver ar;\n \tint tree_idx;\n \tconst char *remote = NULL;\n+\tconst char *prefix;\n \n \tremote = extract_remote_arg(&argc, argv);\n \tif (remote)\n@@ -250,9 +251,8 @@ int cmd_archive(int argc, const char **argv, const char *prefix)\n \n \tmemset(&ar, 0, sizeof(ar));\n \ttree_idx = parse_archive_args(argc, argv, &ar);\n-\tif (prefix == NULL)\n-\t\tprefix = setup_git_directory();\n \n+\tprefix = setup_git_directory();\n \targv += tree_idx;\n \tparse_treeish_arg(argv, &ar.args, prefix);\n \tparse_pathspec_arg(argv + 1, &ar.args);\n-- \n1.5.4.2.281.g28d0e\n"},{"id":"70095","messageId":"20080227164027.GA28128@laptop","threadId":"12342","inReplyTo":"cover.1204130175.git.pclouds@gmail.com","subject":"[PATCH 8/9] Make setup_git_directory() auto-setup worktree if found","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2008-02-27T16:40:27Z","receivedAt":"2008-02-27T16:40:27Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"The semantic is simpler: if worktree is found, use it or die.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin-ls-files.c  |    4 ++--\n builtin-rev-parse.c |    7 +++++--\n builtin-rm.c        |    5 ++---\n setup.c             |    2 +-\n 4 files changed, 10 insertions(+), 8 deletions(-)\n\ndiff --git a/builtin-ls-files.c b/builtin-ls-files.c\nindex cf4c492..a53881d 100644\n--- a/builtin-ls-files.c\n+++ b/builtin-ls-files.c\n@@ -566,8 +566,8 @@ int cmd_ls_files(int argc, const char **argv, const char *prefix)\n \t\tbreak;\n \t}\n \n-\tif (require_work_tree && !is_inside_work_tree())\n-\t\tprefix = setup_work_tree(prefix);\n+\tif (require_work_tree && !get_git_work_tree())\n+\t\tdie(\"This operation must be run in a work tree\");\n \tif (prefix_offset == -1)\n \t\tprefix_offset = prefix ? strlen(prefix) : 0;\n \ndiff --git a/builtin-rev-parse.c b/builtin-rev-parse.c\nindex e82cac2..384e23f 100644\n--- a/builtin-rev-parse.c\n+++ b/builtin-rev-parse.c\n@@ -359,15 +359,16 @@ static int cmd_parseopt(int argc, const char **argv, const char *prefix)\n \treturn 0;\n }\n \n-int cmd_rev_parse(int argc, const char **argv, const char *prefix)\n+int cmd_rev_parse(int argc, const char **argv, const char *unused_prefix)\n {\n \tint i, as_is = 0, verify = 0;\n \tunsigned char sha1[20];\n+\tconst char *prefix = NULL;\n \n \tif (argc > 1 && !strcmp(\"--parseopt\", argv[1]))\n \t\treturn cmd_parseopt(argc - 1, argv + 1, prefix);\n \n-\tprefix = setup_git_directory();\n+\tsetup_git_directory_gently(NULL);\n \tgit_config(git_default_config);\n \tfor (i = 1; i < argc; i++) {\n \t\tconst char *arg = argv[i];\n@@ -487,6 +488,8 @@ 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\telse\n+\t\t\t\t\tpfx = prefix = setup_work_tree(prefix);\n \t\t\t\twhile (pfx) {\n \t\t\t\t\tpfx = strchr(pfx, '/');\n \t\t\t\t\tif (pfx) {\ndiff --git a/builtin-rm.c b/builtin-rm.c\nindex 2c15d66..dedef9f 100644\n--- a/builtin-rm.c\n+++ b/builtin-rm.c\n@@ -155,10 +155,9 @@ int cmd_rm(int argc, const char **argv, const char *prefix)\n \tif (!argc)\n \t\tusage_with_options(builtin_rm_usage, builtin_rm_options);\n \n-\tif (!index_only)\n-\t\tprefix = setup_work_tree(prefix);\n-\n \tpathspec = get_pathspec(prefix, argv);\n+\tif (!pathspec)\n+\t\tdie(\"No valid pathspec\");\n \tseen = NULL;\n \tfor (i = 0; pathspec[i] ; i++)\n \t\t/* nothing */;\ndiff --git a/setup.c b/setup.c\nindex 78ae2f9..f0de42f 100644\n--- a/setup.c\n+++ b/setup.c\n@@ -444,5 +444,5 @@ int check_repository_format(void)\n const char *setup_git_directory(void)\n {\n \tsetup_git_directory_gently(NULL);\n-\treturn is_inside_work_tree() ? setup_work_tree(NULL) : NULL;\n+\treturn get_git_work_tree() ? setup_work_tree(NULL) : NULL;\n }\n-- \n1.5.4.2.281.g28d0e\n"},{"id":"70097","messageId":"20080227164045.GA28142@laptop","threadId":"12342","inReplyTo":"cover.1204130175.git.pclouds@gmail.com","subject":"[PATCH 9/9] Documentation: update api-builtin and api-setup","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2008-02-27T16:40:45Z","receivedAt":"2008-02-27T16:40:45Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/technical/api-builtin.txt |   10 ++++\n Documentation/technical/api-setup.txt   |   70 +++++++++++++++++++++++++++----\n 2 files changed, 72 insertions(+), 8 deletions(-)\n\ndiff --git a/Documentation/technical/api-builtin.txt b/Documentation/technical/api-builtin.txt\nindex 52cdb4c..f0d988b 100644\n--- a/Documentation/technical/api-builtin.txt\n+++ b/Documentation/technical/api-builtin.txt\n@@ -33,6 +33,10 @@ git:\n \tIf the standard output is connected to a tty, spawn a pager and\n \tfeed our output to it.\n \n+`NEED_WORK_TREE`::\n+\n+\tMake sure there is a work tree to work on.\n+\n . Add `builtin-foo.o` to `BUILTIN_OBJS` in `Makefile`.\n \n Additionally, if `foo` is a new command, there are 3 more things to do:\n@@ -59,5 +63,11 @@ to the subdirectory the command started from.  This allows you to\n convert a user-supplied pathname (typically relative to that directory)\n to a pathname relative to the top of the work tree.\n \n+`NEED_WORK_TREE` also set `prefix` like `RUN_SETUP`. But it will `die()`\n+if there is no work tree.\n+\n+If neither `NEED_WORK_TREE` nor `RUN_SETUP` is set, `prefix` is always `NULL`.\n+No chdir(2) will be done.\n+\n The return value from `cmd_foo()` becomes the exit status of the\n command.\ndiff --git a/Documentation/technical/api-setup.txt b/Documentation/technical/api-setup.txt\nindex 4f63a04..43e5a81 100644\n--- a/Documentation/technical/api-setup.txt\n+++ b/Documentation/technical/api-setup.txt\n@@ -1,13 +1,67 @@\n setup API\n =========\n \n-Talk about\n+End-user point-of-view how the setup works\n+------------------------------------------\n \n-* setup_git_directory()\n-* setup_git_directory_gently()\n-* is_inside_git_dir()\n-* is_inside_work_tree()\n-* setup_work_tree()\n-* get_pathspec()\n+. If you have `GIT_DIR` exported, then no discovery is attempted.\n+  We use the `GIT_DIR` you set it, and the repository lives\n+  there.  `$GIT_DIR/config` is the repository config.\n \n-(Dscho)\n+. Otherwise we do the usual discovery going up to find the\n+  repository.\n+\n+. If you have `GIT_WORK_TREE` exported, or otherwise if the\n+  config has `core.worktree`, that's where your worktree is.\n+  If these variables point to an invalid place, you have no worktree.\n+\n+. Otherwise, if you have `GIT_DIR` exported, you do not have a\n+  worktree.  Else one level above your `$GIT_DIR` is the toplevel\n+  of your worktree.\n+\n+Repository setup\n+----------------\n+\n+At startup:\n+\n+. If the command always need a repository, call\n+  `setup_git_directory()`. It will ensure you have a valid\n+  repository. It will `die()` otherwise. If a worktree is detected,\n+  it will be setup automatically.\n+\n+. If the command can optionally run in a repository, use\n+  `setup_git_directory_gently(&nongit_ok)`,which is similar\n+  to `setup_git_directory()` except it won't `die()`\n+  but sets `nongit_ok` to true if run outside a repository.\n+  No chdir(2) is done.\n+\n+. If you don't want worktree setup at all, but always need a git repository,\n+  you can use `setup_git_directory_gently(NULL)`.\n+\n+Do not access git repository (even indirectly like `git_config()`) before\n+calling one of these functions. Otherwise you may encounter `die()` if git\n+fails to automatically find/setup a repository.\n+\n+Working directory setup\n+-----------------------\n+\n+If `setup_git_directory()` is used, worktree can be optionally setup already.\n+To check if work tree has been setup, use `get_git_work_tree()`. The return\n+value is `NULL` if no work tree is setup or work tree directory otherwise.\n+\n+If you need a working directory, use `setup_work_tree()`. It will\n+move current directory to top-level working directory and return\n+a prefix. It will `die()` if unable to setup working directory.\n+\n+Miscellanous functions\n+----------------------\n+\n+To know where `$GIT_DIR` is, use `get_git_dir()`. It will always return\n+an absolute path. To know where `$GIT_WORK_TREE` is, use\n+`get_git_work_tree()`. To check if you are inside a worktree or a git\n+repository, use `is_inside_work_tree()` or `is_inside_git_dir()` respectively.\n+There functions may be not valid until `setup_git_directory*()` is called.\n+\n+When working with pathspecs and prefix, you can use `get_pathspec()`\n+to auto prepend a given prefix to pathspecs. Other helpful functions\n+are `prefix_path()`, `prefix_filename()`\n-- \n1.5.4.2.281.g28d0e\n"},{"id":"70193","messageId":"7vhcftnbxx.fsf@gitster.siamese.dyndns.org","threadId":"12342","inReplyTo":"20080227163810.GA28016@laptop","subject":"Re: [PATCH 1/9] \"git read-tree -m\" and the like require worktree","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-28T00:48:10Z","receivedAt":"2008-02-28T00:48:10Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:\n\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n>  builtin-read-tree.c |    3 +++\n>  1 files changed, 3 insertions(+), 0 deletions(-)\n>\n> diff --git a/builtin-read-tree.c b/builtin-read-tree.c\n> index e78cf69..95318e3 100644\n> --- a/builtin-read-tree.c\n> +++ b/builtin-read-tree.c\n> @@ -219,6 +219,9 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n>  \tif ((opts.dir && !opts.update))\n>  \t\tdie(\"--exclude-per-directory is meaningless unless -u\");\n>  \n> +\tif (opts.merge)\n> +\t\tsetup_work_tree();\n> +\n>  \tif (opts.prefix) {\n>  \t\tint pfxlen = strlen(opts.prefix);\n>  \t\tint pos;\n\nHow would this interact with \"read-tree -m -i\"?\n"},{"id":"70194","messageId":"7vd4qhnbui.fsf@gitster.siamese.dyndns.org","threadId":"12342","inReplyTo":"20080227163918.GA28071@laptop","subject":"Re: [PATCH 5/9] http-push: Avoid calling setup_git_directory() twice","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-28T00:50:13Z","receivedAt":"2008-02-28T00:50:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:\n\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n>  http-push.c |    4 ++--\n>  1 files changed, 2 insertions(+), 2 deletions(-)\n\nCalling setup more than once is now an error?  I do not mind the\nnew restriction but is it documented clearly somewhere?\n"},{"id":"70196","messageId":"7vy795lt89.fsf@gitster.siamese.dyndns.org","threadId":"12342","inReplyTo":"20080227163934.GA28084@laptop","subject":"Re: [PATCH 6/9] Completely move out worktree setup from setup_git_directory_gently()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-28T02:17:42Z","receivedAt":"2008-02-28T02:17:42Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:\n\n> -\tprefix = setup_git_directory_gently(&nongit);\n> -\tinit_revisions(&rev, prefix);\n> +\tsetup_git_directory_gently(&nongit);\n> +\tinit_revisions(&rev, NULL);\n\n\n> @@ -233,19 +233,20 @@ int cmd_diff(int argc, const char **argv, const char *prefix)\n> ...\n> -\tinit_revisions(&rev, prefix);\n> +\tinit_revisions(&rev, NULL);\n\nHmm.  How is the effect of this change compensated later to give\nproper prefix value to rev.diffopt.prefix?\n"},{"id":"70199","messageId":"fcaeb9bf0802271922j41fbdcaag2d761728379d06ad@mail.gmail.com","threadId":"12342","inReplyTo":"7vhcftnbxx.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 1/9] \"git read-tree -m\" and the like require worktree","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2008-02-28T03:22:29Z","receivedAt":"2008-02-28T03:22:29Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Feb 28, 2008 at 7:48 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:\n>\n>  > Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n>  > ---\n>  >  builtin-read-tree.c |    3 +++\n>  >  1 files changed, 3 insertions(+), 0 deletions(-)\n>  >\n>  > diff --git a/builtin-read-tree.c b/builtin-read-tree.c\n>  > index e78cf69..95318e3 100644\n>  > --- a/builtin-read-tree.c\n>  > +++ b/builtin-read-tree.c\n>  > @@ -219,6 +219,9 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix)\n>  >       if ((opts.dir && !opts.update))\n>  >               die(\"--exclude-per-directory is meaningless unless -u\");\n>  >\n>  > +     if (opts.merge)\n>  > +             setup_work_tree();\n>  > +\n>  >       if (opts.prefix) {\n>  >               int pfxlen = strlen(opts.prefix);\n>  >               int pos;\n>\n>  How would this interact with \"read-tree -m -i\"?\n>\n\nIt setups worktree anyway. Bad. The following would be better\n\n+     if (opts.merge && !opts.index_only)\n+             setup_work_tree();\n+\n-- \nDuy\n"},{"id":"70200","messageId":"fcaeb9bf0802271926icf626d9s5dd762ce56d7a5a0@mail.gmail.com","threadId":"12342","inReplyTo":"7vd4qhnbui.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 5/9] http-push: Avoid calling setup_git_directory() twice","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2008-02-28T03:26:03Z","receivedAt":"2008-02-28T03:26:03Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Feb 28, 2008 at 7:50 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:\n>\n>  > Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n>  > ---\n>  >  http-push.c |    4 ++--\n>  >  1 files changed, 2 insertions(+), 2 deletions(-)\n>\n>  Calling setup more than once is now an error?  I do not mind the\n>  new restriction but is it documented clearly somewhere?\n>\n\nThis part was left from my attempt to make setup_git_directory()\nreturn no prefix. The attempt failed but I thought it was a still good\ncleanup. Now think it again. I agree calling setup_git_directory()\ntwice is an error as it may call setup_work_tree(NULL) twice. Yes it\nneeds to be documented. Will amend the documentation patch.\n-- \nDuy\n"},{"id":"70201","messageId":"fcaeb9bf0802271931t559d4bd1n86bb5c644b082274@mail.gmail.com","threadId":"12342","inReplyTo":"7vy795lt89.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 6/9] Completely move out worktree setup from setup_git_directory_gently()","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2008-02-28T03:31:01Z","receivedAt":"2008-02-28T03:31:01Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Feb 28, 2008 at 9:17 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:\n>\n>  > -     prefix = setup_git_directory_gently(&nongit);\n>  > -     init_revisions(&rev, prefix);\n>  > +     setup_git_directory_gently(&nongit);\n>  > +     init_revisions(&rev, NULL);\n>\n>\n>\n> > @@ -233,19 +233,20 @@ int cmd_diff(int argc, const char **argv, const char *prefix)\n>  > ...\n>\n> > -     init_revisions(&rev, prefix);\n>  > +     init_revisions(&rev, NULL);\n>\n>  Hmm.  How is the effect of this change compensated later to give\n>  proper prefix value to rev.diffopt.prefix?\n>\n\nI assume you meant rev.prefix? rev.prefix is set right before\nsetup_revisions(). (grr.. I think I left an redundant\nrev.diffopt.skip_stat_unmatch assignment)\n-- \nDuy\n"},{"id":"70202","messageId":"7vk5kplpj2.fsf@gitster.siamese.dyndns.org","threadId":"12342","inReplyTo":"fcaeb9bf0802271931t559d4bd1n86bb5c644b082274@mail.gmail.com","subject":"Re: [PATCH 6/9] Completely move out worktree setup from setup_git_directory_gently()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-02-28T03:37:37Z","receivedAt":"2008-02-28T03:37:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Nguyen Thai Ngoc Duy\" <pclouds@gmail.com> writes:\n\n> On Thu, Feb 28, 2008 at 9:17 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>> Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:\n>>\n>>  > -     prefix = setup_git_directory_gently(&nongit);\n>>  > -     init_revisions(&rev, prefix);\n>>  > +     setup_git_directory_gently(&nongit);\n>>  > +     init_revisions(&rev, NULL);\n>>\n>>\n>>\n>> > @@ -233,19 +233,20 @@ int cmd_diff(int argc, const char **argv, const char *prefix)\n>>  > ...\n>>\n>> > -     init_revisions(&rev, prefix);\n>>  > +     init_revisions(&rev, NULL);\n>>\n>>  Hmm.  How is the effect of this change compensated later to give\n>>  proper prefix value to rev.diffopt.prefix?\n>>\n>\n> I assume you meant rev.prefix? rev.prefix is set right before\n> setup_revisions(). (grr.. I think I left an redundant\n> rev.diffopt.skip_stat_unmatch assignment)\n\nI did mean rev.diffopt.prefix that is initialized by the last\nfour lines in init_revisions() from the value of prefix you\npass.\n"},{"id":"70206","messageId":"fcaeb9bf0802272009s4ea773b3i6123ac5012b471a@mail.gmail.com","threadId":"12342","inReplyTo":"7vk5kplpj2.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH 6/9] Completely move out worktree setup from setup_git_directory_gently()","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2008-02-28T04:09:54Z","receivedAt":"2008-02-28T04:09:54Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Feb 28, 2008 at 10:37 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>\n> \"Nguyen Thai Ngoc Duy\" <pclouds@gmail.com> writes:\n>\n>  > On Thu, Feb 28, 2008 at 9:17 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>  >> Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:\n>  >>\n>  >>  > -     prefix = setup_git_directory_gently(&nongit);\n>  >>  > -     init_revisions(&rev, prefix);\n>  >>  > +     setup_git_directory_gently(&nongit);\n>  >>  > +     init_revisions(&rev, NULL);\n>  >>\n>  >>\n>  >>\n>  >> > @@ -233,19 +233,20 @@ int cmd_diff(int argc, const char **argv, const char *prefix)\n>  >>  > ...\n>  >>\n>  >> > -     init_revisions(&rev, prefix);\n>  >>  > +     init_revisions(&rev, NULL);\n>  >>\n>  >>  Hmm.  How is the effect of this change compensated later to give\n>  >>  proper prefix value to rev.diffopt.prefix?\n>  >>\n>  >\n>  > I assume you meant rev.prefix? rev.prefix is set right before\n>  > setup_revisions(). (grr.. I think I left an redundant\n>  > rev.diffopt.skip_stat_unmatch assignment)\n>\n>  I did mean rev.diffopt.prefix that is initialized by the last\n>  four lines in init_revisions() from the value of prefix you\n>  pass.\n\nUm.. I missed commit \"diff --relative\". Thanks for noticing.\n-- \nDuy\n"},{"id":"70242","messageId":"alpine.LSU.1.00.0802281124420.22527@racer.site","threadId":"12342","inReplyTo":"20080227163934.GA28084@laptop","subject":"Re: [PATCH 6/9] Completely move out worktree setup from setup_git_directory_gently()","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-28T11:26:55Z","receivedAt":"2008-02-28T11:26:55Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 27 Feb 2008, Nguyễn Thái Ngọc Duy wrote:\n\n> This was impossible earlier because git_dir can be relative. Now that\n> git_dir is absolute, I see no reason for worktree setup inside\n> setup_git_directory_gently().\n\nI do see it, though.  Why make the users work harder?  If you want to get \nthe git directory, chances are that you want to work with a worktree, too.\n\nAnd you really cannot properly separate worktree detection from git \ndirectory detection: in most of the cases, you will find them at the \n_same_ time (if .git/ is the git directory, the working directory is .).\n\nSo I am mildly negative on the thrust of your patch series.\n\nCiao,\nDscho\n"},{"id":"70243","messageId":"alpine.LSU.1.00.0802281130140.22527@racer.site","threadId":"12342","inReplyTo":"20080227163902.GA28058@laptop","subject":"Re: [PATCH 4/9] Make setup_work_tree() return new prefix","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-28T11:30:24Z","receivedAt":"2008-02-28T11:30:24Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 27 Feb 2008, Nguyễn Thái Ngọc Duy wrote:\n\n> @@ -336,24 +321,21 @@ const char *setup_git_directory_gently(int *nongit_ok)\n>  \t\t\tstatic char buffer[1024 + 1];\n>  \t\t\tconst char *retval;\n>  \n> +\t\t\t/*\n> +\t\t\t * The old behaviour (which we retain here) is to set\n> +\t\t\t * the work tree root to the cwd, unless overridden by\n> +\t\t\t * the config, the command line, or GIT_WORK_TREE.\n> +\t\t\t */\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\tchar buffer[PATH_MAX + 1];\n> +\n> +\t\t\t\tif (!getcwd(buffer, sizeof(buffer)))\n> +\t\t\t\t\tdie (\"Could not get the current working directory\");\n> +\t\t\t\tgit_work_tree_cfg = xstrdup(buffer);\n> +\t\t\t\tinside_work_tree = 1;\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 (\"Could not chdir to %s\", work_tree_env);\n> -\t\t\tstrcat(buffer, \"/\");\n> -\t\t\treturn retval;\n> +\t\t\tcheck_repository_format_gently(nongit_ok);\n> +\t\t\treturn NULL;\n\nWhat about the situation where you are in a subdirectory of core.worktree?  \nYou return prefix NULL?  That's wrong.\n\nI am sorry, but with all these intrusive changes, I get a very uneasy \nfeeling.  As uneasy as with the original series, which I tried to fix up, \nnot really succeeding.\n\nCiao,\nDscho\n"},{"id":"70250","messageId":"fcaeb9bf0802280452h1180c4f2gdc92874a3627d0c5@mail.gmail.com","threadId":"12342","inReplyTo":"alpine.LSU.1.00.0802281124420.22527@racer.site","subject":"Re: [PATCH 6/9] Completely move out worktree setup from setup_git_directory_gently()","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2008-02-28T12:52:02Z","receivedAt":"2008-02-28T12:52:02Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Feb 28, 2008 at 6:26 PM, Johannes Schindelin\n<Johannes.Schindelin@gmx.de> wrote:\n> Hi,\n>\n>\n>  On Wed, 27 Feb 2008, Nguyễn Thái Ngọc Duy wrote:\n>\n>  > This was impossible earlier because git_dir can be relative. Now that\n>  > git_dir is absolute, I see no reason for worktree setup inside\n>  > setup_git_directory_gently().\n>\n>  I do see it, though.  Why make the users work harder?\n\nTo make clear separation of worktree usage? I think it's good to add\nsetup_work_tree() where you really need it. Right now in commands that\nuse setup_git_directory_gently(), it is (to me) really hard to tell\nwhether an option require worktree.\n\nAnother point of removing worktree setup from _gently(): worktree\nsetup can die() while _gently()'s purpose is, well, do it gently. If\nit's not safe, let the caller decide.\n\nAlso having to deal with prefix while you don't need worktree at all\nis a bit of work that can be eliminated with this series.\n\n>  If you want to get\n>  the git directory, chances are that you want to work with a worktree, too.\n\nYes. That's why I keep worktree setup in setup_git_directory().\n\n>  And you really cannot properly separate worktree detection from git\n>  directory detection: in most of the cases, you will find them at the\n>  _same_ time (if .git/ is the git directory, the working directory is .).\n\nNo I don't separate worktree detection. I only avoid moving to\nworktree unless necessary. Right after _gently() you can tell if you\nhave a worktree and where it is.\n\n>  So I am mildly negative on the thrust of your patch series.\n>\n>  Ciao,\n>  Dscho\n>\n\n\n\n-- \nDuy\n"},{"id":"70253","messageId":"fcaeb9bf0802280502m2cfc967bt792be98d81a2996@mail.gmail.com","threadId":"12342","inReplyTo":"alpine.LSU.1.00.0802281130140.22527@racer.site","subject":"Re: [PATCH 4/9] Make setup_work_tree() return new prefix","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2008-02-28T13:02:58Z","receivedAt":"2008-02-28T13:02:58Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Feb 28, 2008 at 6:30 PM, Johannes Schindelin\n<Johannes.Schindelin@gmx.de> wrote:\n> Hi,\n>\n>\n>\n>  On Wed, 27 Feb 2008, Nguyễn Thái Ngọc Duy wrote:\n>\n>  > @@ -336,24 +321,21 @@ const char *setup_git_directory_gently(int *nongit_ok)\n>  >                       static char buffer[1024 + 1];\n>  >                       const char *retval;\n>  >\n>  > +                     /*\n>  > +                      * The old behaviour (which we retain here) is to set\n>  > +                      * the work tree root to the cwd, unless overridden by\n>  > +                      * the config, the command line, or GIT_WORK_TREE.\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>  > +                             char buffer[PATH_MAX + 1];\n>  > +\n>  > +                             if (!getcwd(buffer, sizeof(buffer)))\n>  > +                                     die (\"Could not get the current working directory\");\n>  > +                             git_work_tree_cfg = xstrdup(buffer);\n>  > +                             inside_work_tree = 1;\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>  > -                     if (!retval || !*retval)\n>  > -                             return NULL;\n>  > -                     set_git_dir(make_absolute_path(gitdirenv));\n>  > -                     if (chdir(work_tree_env) < 0)\n>  > -                             die (\"Could not chdir to %s\", work_tree_env);\n>  > -                     strcat(buffer, \"/\");\n>  > -                     return retval;\n>  > +                     check_repository_format_gently(nongit_ok);\n>  > +                     return NULL;\n>\n>  What about the situation where you are in a subdirectory of core.worktree?\n>  You return prefix NULL?  That's wrong.\n\nThis is an intermediate patch. At the end of the series, you will see\nthat _gently() does not return prefix. I split it for easier review.\n\n>  I am sorry, but with all these intrusive changes, I get a very uneasy\n>  feeling.  As uneasy as with the original series, which I tried to fix up,\n>  not really succeeding.\n\nIn constrast I feel good :) To me setup_git_directory*() at the end\nlook really nice. No chdir() all over the place\n(temporary chdir() for detecting .git does not count). It also gives a\nchance to get rid of worktree to commands that do not care about\nworktree at all.\n\n>  Ciao,\n>  Dscho\n>\n\n\n\n-- \nDuy\n"},{"id":"70272","messageId":"alpine.LSU.1.00.0802281552530.22527@racer.site","threadId":"12342","inReplyTo":"fcaeb9bf0802280502m2cfc967bt792be98d81a2996@mail.gmail.com","subject":"Re: [PATCH 4/9] Make setup_work_tree() return new prefix","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-02-28T15:53:48Z","receivedAt":"2008-02-28T15:53:48Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 28 Feb 2008, Nguyen Thai Ngoc Duy wrote:\n\n> On Thu, Feb 28, 2008 at 6:30 PM, Johannes Schindelin \n> <Johannes.Schindelin@gmx.de> wrote:\n>\n> > I am sorry, but with all these intrusive changes, I get a very uneasy \n> > feeling.  As uneasy as with the original series, which I tried to fix \n> > up, not really succeeding.\n> \n> In constrast I feel good :) To me setup_git_directory*() at the end look \n> really nice. No chdir() all over the place (temporary chdir() for \n> detecting .git does not count). It also gives a chance to get rid of \n> worktree to commands that do not care about worktree at all.\n\nWell, I'll have to review your patches in depth, then.  Which will take \nsome days, because I wanted to submit builtin-remote first.\n\nCiao,\nDscho\n\n"},{"id":"165171","messageId":"20110405080729.GA25921@elie","threadId":"12342","inReplyTo":"20080227164045.GA28142@laptop","subject":"Re: [PATCH 9/9] Documentation: update api-builtin and api-setup","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2011-04-05T08:07:29Z","receivedAt":"2011-04-05T08:07:29Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Hi,\n\nOn 2008-02-27, Nguyễn Thái Ngọc Duy wrote:\n\n>  Documentation/technical/api-builtin.txt |   10 ++++\n>  Documentation/technical/api-setup.txt   |   70 +++++++++++++++++++++++++++----\n>  2 files changed, 72 insertions(+), 8 deletions(-)\n\nI'm curious --- did anything ever come of this patch?\n\n> --- a/Documentation/technical/api-setup.txt\n> +++ b/Documentation/technical/api-setup.txt\n> @@ -1,13 +1,67 @@\n>  setup API\n>  =========\n>  \n> +End-user point-of-view how the setup works\n> +------------------------------------------\n\nI suppose this is scattered through git(1) and git-config(1) now.\nMaybe it would make sense to centralized in git-repository-layout(5)\nor gitcli(7) and put cross-references elsewhere.\n\n> +. If you have `GIT_DIR` exported, then no discovery is attempted.\n> +  We use the `GIT_DIR` you set it, and the repository lives\n> +  there.  `$GIT_DIR/config` is the repository config.\n> +\n> +. Otherwise we do the usual discovery going up to find the\n> +  repository.\n> +\n> +. If you have `GIT_WORK_TREE` exported, or otherwise if the\n> +  config has `core.worktree`, that's where your worktree is.\n> +  If these variables point to an invalid place, you have no worktree.\n> +\n> +. Otherwise, if you have `GIT_DIR` exported, you do not have a\n> +  worktree.  Else one level above your `$GIT_DIR` is the toplevel\n> +  of your worktree.\n\nE.g., like this (but simpler somehow):\n\n\tLocating the repository\n\t-----------------------\n\tTypically git is run from within a work tree with a `.git`\n\tsubdirectory at its top level or within a `<project>.git` directory\n\tassociated to a bare repository.  To find the toplevel directory,\n\tgit will repeatedly chdir(\"..\") and at each level check for (in\n\torder of preference):\n\n\t a) a subdirectory named \".git\" with readable \"objects\" and\n\t    \"refs\" subdirectories and a readable \"HEAD\" file;\n\t b) a file named \".git\";\n\t c) readable \"objects\" and \"refs\" subdirectories and a\n\t    readable \"HEAD\" file.\n\n\tEach is interpreted differently:\n\n\t a) a .git subdirectory is the repository and the directory\n\t    containing it is the top of the work tree.\n\t b) a .git file is used to locate the repository (see\n\t    \"Platform-independent .git symlink\" below) and the\n\t    directory containing a .git file is the top of the\n\t    work tree.\n\t c) an ancestory of the starting cwd containing objects/,\n\t    refs/, and HEAD is treated as a bare repository.\n\t    There is no work tree in that case.\n\n\tLimiting the repository search\n\t------------------------------\n\tGit will not chdir(\"..\") into a directory named in the\n\tGIT_CEILING_DIRECTORIES environment variable, nor will it\n\tchdir(\"..\") into a directory on a different filesystem unless\n\tthe GIT_DISCOVERY_ACROSS_FILESYSTEM variable is set.\n\n\tUnusual repository layouts\n\t--------------------------\n\tIf the GIT_DIR environment variable is set, it will be used\n\tand no repository search performed.  The work tree defaults\n\tto \".\".\n\n\tThe GIT_WORK_TREE environment variable can be used to\n\tspecify the top level of the work tree.  It can even be used\n\tfrom within a bare repository, to set up a temporary work\n\ttree.\n\n\tThe \"core.worktree\" configuration variable in a repository\n\tcan be used to specify the top level of the work tree,\n\trelative to the repository root.  This can be useful in\n\tsituations in which the work tree must be completely pristine\n\t(so that it is not possible to put a .git symlink or .git file\n\tin the top level).\n\n\tSome files usually found in the repository can be placed\n\telsewhere if requested through the environment.\n\n\t * GIT_CONFIG - .git/config\n\t * GIT_OBJECT_DIRECTORY - .git/objects\n\t * GIT_INDEX_FILE - .git/index\n\t * GIT_GRAFT_FILE - .git/info/grafts\n\n> +\n> +Repository setup\n> +----------------\n> +\n> +At startup:\n> +\n> +. If the command always need a repository, call\n> +  `setup_git_directory()`. It will ensure you have a valid\n> +  repository. It will `die()` otherwise. If a worktree is detected,\n> +  it will be setup automatically.\n> +\n> +. If the command can optionally run in a repository, use\n> +  `setup_git_directory_gently(&nongit_ok)`,which is similar\n> +  to `setup_git_directory()` except it won't `die()`\n> +  but sets `nongit_ok` to true if run outside a repository.\n> +  No chdir(2) is done.\n> +\n> +. If you don't want worktree setup at all, but always need a git repository,\n> +  you can use `setup_git_directory_gently(NULL)`.\n\nSimpler advice might be:\n\n . If the command is builtin and always needs a repository,\n   use the RUN_SETUP flag in the builtin table.\n . If the command is builtin and can benefit from a repository,\n   use RUN_SETUP_GENTLY.\n . If you have to run a repository search later, call\n   \"setup_git_directory_gently\" or the shortcut \"setup_git_directory\"\n   (which means \"setup_git_directory_gently(NULL)\").\n\n> +\n> +Do not access git repository (even indirectly like `git_config()`) before\n> +calling one of these functions. Otherwise you may encounter `die()` if git\n> +fails to automatically find/setup a repository.\n\n . If you try to access the git repository (even indirectly like\n   `git_config()`) before calling setup_git_directory_gently then git\n   will look in the wrong place.\n . When changing the value of the GIT_DIR environment variable, call\n   set_git_dir.  setup_git_directory_gently does this already.\n\n> +\n> +Working directory setup\n> +-----------------------\n> +\n> +If `setup_git_directory()` is used, worktree can be optionally setup already.\n> +To check if work tree has been setup, use `get_git_work_tree()`. The return\n> +value is `NULL` if no work tree is setup or work tree directory otherwise.\n> +\n> +If you need a working directory, use `setup_work_tree()`. It will\n> +move current directory to top-level working directory and return\n> +a prefix. It will `die()` if unable to setup working directory.\n\nDid we ever figure out what happens/should happen when the requested\nworktree is not an ancestor of cwd?\n\n> +\n> +Miscellanous functions\n> +----------------------\n> +\n> +To know where `$GIT_DIR` is, use `get_git_dir()`. It will always return\n> +an absolute path. To know where `$GIT_WORK_TREE` is, use\n> +`get_git_work_tree()`. To check if you are inside a worktree or a git\n> +repository, use `is_inside_work_tree()` or `is_inside_git_dir()` respectively.\n> +There functions may be not valid until `setup_git_directory*()` is called.\n> +\n> +When working with pathspecs and prefix, you can use `get_pathspec()`\n> +to auto prepend a given prefix to pathspecs. Other helpful functions\n> +are `prefix_path()`, `prefix_filename()`\n\nWhat do prefix_* do when there is no worktree?\n\n> -Talk about\n> -\n> +\n> -* setup_git_directory()\n> -* setup_git_directory_gently()\n> -* is_inside_git_dir()\n> -* is_inside_work_tree()\n> -* setup_work_tree()\n> -* get_pathspec()\n> -\n> -(Dscho)\n> -- \n> 1.5.4.2.281.g28d0e\n> \n"},{"id":"165178","messageId":"BANLkTi=opkt7=BSCknKzN9396+urvVkhVQ@mail.gmail.com","threadId":"12342","inReplyTo":"20110405080729.GA25921@elie","subject":"Re: [PATCH 9/9] Documentation: update api-builtin and api-setup","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-04-05T11:32:31Z","receivedAt":"2011-04-05T11:32:31Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"2011/4/5 Jonathan Nieder <jrnieder@gmail.com>:\n> Hi,\n>\n> On 2008-02-27, Nguyễn Thái Ngọc Duy wrote:\n>\n>>  Documentation/technical/api-builtin.txt |   10 ++++\n>>  Documentation/technical/api-setup.txt   |   70 +++++++++++++++++++++++++++----\n>>  2 files changed, 72 insertions(+), 8 deletions(-)\n>\n> I'm curious --- did anything ever come of this patch?\n\nNo idea. Perhaps nothing :) You should submit a new patch. Your\ndescription looks very good. Some comments..\n\n> Simpler advice might be:\n>\n>  . If the command is builtin and always needs a repository,\n>   use the RUN_SETUP flag in the builtin table.\n>  . If the command is builtin and can benefit from a repository,\n>   use RUN_SETUP_GENTLY.\n>  . If you have to run a repository search later, call\n>   \"setup_git_directory_gently\" or the shortcut \"setup_git_directory\"\n>   (which means \"setup_git_directory_gently(NULL)\").\n\nI would discourage people from calling setup_git_directory_* directly,\nat least for builtins. It complicates setup handling because there\nwill be a short time since main() until that function where we are not\nsure if we can access repo. There's also alias handling which may set\nthings up while the command may not want it\n\nI'd rather explicitly mark (RUN_SETUP_NO_THANKS?) commands that want\nto setup repo manually (few of them, init/clone and server commands).\nThen main() just goes ahead and calls setup_gently() at the very\nbeginning. Setup hack around alias handling would be gone. If it ends\nup with a RUN_SETUP_NO_THANKS one, it undoes the setup. Hmm... I need\nto get back to this.\n\n>> +\n>> +Do not access git repository (even indirectly like `git_config()`) before\n>> +calling one of these functions. Otherwise you may encounter `die()` if git\n>> +fails to automatically find/setup a repository.\n>\n>  . If you try to access the git repository (even indirectly like\n>   `git_config()`) before calling setup_git_directory_gently then git\n>   will look in the wrong place.\n>  . When changing the value of the GIT_DIR environment variable, call\n>   set_git_dir.  setup_git_directory_gently does this already.\n\nYou can also check startup_info.have_repository before you access repo\nbecause setup*gently may find no repo.\n\n> Did we ever figure out what happens/should happen when the requested\n> worktree is not an ancestor of cwd?\n\nprefix is NULL, cwd is unchanged. Repo-wide commands should work fine.\ncwd-sensitive ones may cry.\n\n>> +When working with pathspecs and prefix, you can use `get_pathspec()`\n>> +to auto prepend a given prefix to pathspecs. Other helpful functions\n>> +are `prefix_path()`, `prefix_filename()`\n>\n> What do prefix_* do when there is no worktree?\n\nThese functions are purely string manipulation. If there is no\nworktree, prefix would be NULL and be passed to the functions as such.\n-- \nDuy\n"}]}