{"thread":{"id":"15967","subject":"[PATCH v2] Add command line option --chdir/-C to allow setting git process work directory.","startedAt":"2008-10-19T16:18:19Z","lastAt":"2008-10-19T21:02:41Z","messageCount":2,"participants":["Maciej Pasternacki","Jeff King"],"isPatch":true,"patchVersion":2,"patchTotal":null},"messages":[{"id":"93440","messageId":"20081019161819.GA12495@charybdis.dreamhost.com","threadId":"15967","inReplyTo":null,"subject":"[PATCH v2] Add command line option --chdir/-C to allow setting git process work directory.","fromName":"Maciej Pasternacki","fromEmail":"maciej@pasternacki.net","sentAt":"2008-10-19T16:18:19Z","receivedAt":"2008-10-19T16:18:19Z","isPatch":true,"sender":{"key":"maciej@pasternacki.net","avatar":"https://gravatar.com/avatar/6485c5851d08fb9492fd6b9528e10b730c82320a0665560401c417a5f9209773?d=mp&s=160"},"body":"When \"git pull\" is ran outside of work tree, it is unable to update work tree\nwith pulled changes; specifying --git-dir and --work-tree does not help here\nbecause \"cd_to_toplevel\" call in git-pull occurs after \"require_work_tree\";\nchanging order may break the commend if there is no working tree.  Some more\ncommands behave in a similar way.\n\nIn my project, I need to call \"git pull\" from outside of work tree, but I need\nit to update the work tree.  It seems to require doing chdir() before running\ngit, but this is problematic thing to do in the calling program because of\nportability issues.  Proper solution seems to be providing -C / --chdir command\nline option, similar to this of Make, that would make main git program perform\nchdir() to specified directory before running the specific command.  This would\nmake using git from outside programs much more straightforward.\n\nThis patch provides -C and --chdir command line options that behave as\ndescribed above.\n\nSigned-off-by: Maciej Pasternacki <maciej@pasternacki.net>\n---\n Documentation/git.txt |    6 +++++-\n git.c                 |   19 ++++++++++++++++++-\n 2 files changed, 23 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git.txt b/Documentation/git.txt\nindex df420ae..6676d68 100644\n--- a/Documentation/git.txt\n+++ b/Documentation/git.txt\n@@ -12,7 +12,7 @@ SYNOPSIS\n 'git' [--version] [--exec-path[=GIT_EXEC_PATH]]\n     [-p|--paginate|--no-pager]\n     [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]\n-    [--help] COMMAND [ARGS]\n+    [-C DIRECTORY|--chdir=DIRECTORY] [--help] COMMAND [ARGS]\n \n DESCRIPTION\n -----------\n@@ -185,6 +185,10 @@ help ...`.\n \tenvironment is not set, it is set to the current working\n \tdirectory.\n \n+-C <directory>::\n+--chdir=<directory>::\n+\tChange working directory before doing anything.\n+\n \n FURTHER DOCUMENTATION\n ---------------------\ndiff --git a/git.c b/git.c\nindex 89feb0b..c63d754 100644\n--- a/git.c\n+++ b/git.c\n@@ -4,7 +4,7 @@\n #include \"quote.h\"\n \n const char git_usage_string[] =\n-\t\"git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]\";\n+\t\"git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [-C DIR|--chdir=DIR] [--help] COMMAND [ARGS]\";\n \n const char git_more_info_string[] =\n \t\"See 'git help COMMAND' for more information on a specific command.\";\n@@ -115,6 +115,23 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)\n \t\t\tsetenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 0);\n \t\t\tif (envchanged)\n \t\t\t\t*envchanged = 1;\n+\t\t} else if (!strcmp(cmd, \"-C\") || !strcmp(cmd, \"--chdir\")) {\n+\t\t\tif (*argc < 2) {\n+\t\t\t\tfprintf(stderr, \"No directory given for --chdir or -C.\\n\" );\n+\t\t\t\tusage(git_usage_string);\n+\t\t\t}\n+\t\t\tif (chdir((*argv)[1])) {\n+\t\t\t\tfprintf(stderr, \"Cannot change directory to %s: %s\\n\", (*argv)[1], strerror(errno));\n+\t\t\t\tusage(git_usage_string);\n+\t\t\t}\n+\t\t\t(*argv)++;\n+\t\t\t(*argc)--;\n+\t\t\thandled++;\n+\t\t} else if (!prefixcmp(cmd,\"--chdir=\")) {\n+\t\t\tif (chdir(cmd+8)) {\n+\t\t\t\tfprintf(stderr, \"Cannot change directory to %s: %s\\n\", cmd+8, strerror(errno));\t\t\t\t     \n+\t\t\t\tusage(git_usage_string);\n+\t\t\t}\n \t\t} else {\n \t\t\tfprintf(stderr, \"Unknown option: %s\\n\", cmd);\n \t\t\tusage(git_usage_string);\n-- \n1.6.0.1\n"},{"id":"93454","messageId":"20081019210241.GA32589@coredump.intra.peff.net","threadId":"15967","inReplyTo":"20081019161819.GA12495@charybdis.dreamhost.com","subject":"Re: [PATCH v2] Add command line option --chdir/-C to allow setting git process work directory.","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2008-10-19T21:02:41Z","receivedAt":"2008-10-19T21:02:41Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Oct 19, 2008 at 09:18:19AM -0700, Maciej Pasternacki wrote:\n\n> When \"git pull\" is ran outside of work tree, it is unable to update work tree\n> with pulled changes; specifying --git-dir and --work-tree does not help here\n> because \"cd_to_toplevel\" call in git-pull occurs after \"require_work_tree\";\n> changing order may break the commend if there is no working tree.  Some more\n> commands behave in a similar way.\n\nI took a closer look at this. I'm not sure that there is actually a\nproblem with moving the cd_to_toplevel before require_work_tree.\ncd_to_toplevel makes sure there is actually something to cdup to. In my\ntest without a work-tree, \"git rev-parse --show-cdup\" simply printed\nnothing, causing no \"cd\" to occur.\n\nMoreover, git-pull is not the only script with this problem. There are\nquite a few with\n\n  require_work_tree\n  cd_to_toplevel\n\nwhich will break in the same way with --work-tree. And there are even\nmore with just require_work_tree that don't cd_to_toplevel at all. So I\nsuspect that --work-tree is largely broken in our scripts and nobody has\nactually tried it.\n\nSo:\n\n  1. I think we can fix this breakage by swapping the two.\n\n  2. There is still breakage in other scripts, some of which may need\n     quite in-depth fixes (e.g., git-bisect requires a work tree but\n     does not chdir at all. For the require_work_tree test to work, it\n     needs to be inside the work tree, and the script will need a\n     careful looking over to see what ramifications that has).\n\n  3. I think your -C option has some merit independent of this, since\n     it allows you to chdir and still use the usual lookup rules (e.g.,\n     see if it is bare vs a regular repository). But I don't feel\n     strongly about it one way or the other.\n\n-Peff\n"}]}