On Sun, Sep 01, 2013 at 12:48:23AM -0400, Eric Sunshine wrote: > On Fri, Aug 30, 2013 at 9:35 AM, Nazri Ramliy <ayiehere@xxxxxxxxx> wrote: >> With this new option, the above can be done with less keystrokes: > > Grammar: s/less/fewer/ > > More below... Thanks for taking the time to review this patch! The fix for the above, and the following issues are in the re-roll below. > The synopsis at the top of git.txt mentions --git-dir and --work-tree. > For consistency, -C probably ought to be mentioned there, as well. Fixed. > Other options which accept a directory, such as --git-dir and > --work-tree, are documented as accepting <path>, but -C is > inconsistently documented as accepting <directory>. Fixed. >> + Run as if git were started in <directory> instead of the current >> + working directory. If multiple -C options are given, subsequent >> + directory arguments are interpreted relative to the previous one: -C >> + /usr -C src is equivalent to -C /usr/src. This option affects options > > The fragment "interpreted relative" seems ambiguous when absolute > paths are involved. In this re-roll the above text is now: -C <path>:: Run as if git were started in <path> instead of the current working directory. If multiple -C options are given, subsequent relative <path> arguments is interpreted relative to the previous effective directory: "-C /usr -C src" is equivalent to "-C /usr/src", while "-C src -C /usr" is equivalent to "C /usr". This option ... > For existing options accepting an argument, the argument is formatted > as <argument>. The -C option does not follow suit. > > As mentioned above, all other options accepting a directory are > documented as taking <path>, but -C is inconsistent and is documented > as taking 'directory' instead. Fixed as "[-C <path>]" >> +test_description='"-C <directory>" option and it effects on other path-related options' > > s/it/its/ > s/<directory>/<path>/ Fixed. >> +test_expect_success '"git -C <dir>" runs git from the directory <dir>' ' > > s/<dir>/<path>/g Fixed. > Modern git tests tend to place the expected and actual outputs in > files and then use test_cmp to verify that they are identical. For > instance: > > echo "initial in dir1" >expected && > git -C dir1 log --format="%s" >actual && > test_cmp expected actual Fixed. > It would make sense also to test multiple -C options with combinations > of absolute and and relative paths. Fixed - I've added one more test for testing that "-C ./here -C /there" is equivalent to "-C /there" at the end of t0056-git-C.sh. nazri -- >8 -- Subject: [PATCH] Teach git to change to a given directory using -C option This is similar in spirit to to "make -C dir ..." and "tar -C dir ...". Currently it takes more effort (keypresses) to invoke git command in a different directory than the current one without leaving the current directory: 1. (cd ~/foo && git status) git --git-dir=~/foo/.git --work-dir=~/foo status GIT_DIR=~/foo/.git GIT_WORK_TREE=~/foo git status 2. (cd ../..; git grep foo) 3. for d in d1 d2 d3; do (cd $d && git svn rebase); done While doable the methods shown above are arguably more suitable for scripting than quick command line invocations. With this new option, the above can be done with fewer keystrokes: 1. git -C ~/foo status 2. git -C ../.. grep foo 3. for d in d1 d2 d3; do git -C $d svn rebase; done A new test script is added to verify the behavior of this option with other path-related options like --git-dir and --work-tree. Signed-off-by: Nazri Ramliy <ayiehere@xxxxxxxxx> --- Documentation/git.txt | 16 +++++++++- git.c | 15 ++++++++-- t/t0056-git-C.sh | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 3 deletions(-) create mode 100755 t/t0056-git-C.sh diff --git a/Documentation/git.txt b/Documentation/git.txt index 83edf30..7a1369a 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -9,7 +9,7 @@ git - the stupid content tracker SYNOPSIS -------- [verse] -'git' [--version] [--help] [-c <name>=<value>] +'git' [--version] [--help] [-C <path>] [-c <name>=<value>] [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path] [-p|--paginate|--no-pager] [--no-replace-objects] [--bare] [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>] @@ -395,6 +395,20 @@ displayed. See linkgit:git-help[1] for more information, because `git --help ...` is converted internally into `git help ...`. +-C <path>:: + Run as if git were started in <path> instead of the current working + directory. If multiple -C options are given, subsequent relative <path> + arguments are interpreted relative to the previous effective directory: + "-C /usr -C src" is equivalent to "-C /usr/src", while "-C src -C /usr" + is equivalent to "C /usr". This option affects options that expect path + name like --git-dir and --work-tree in that their interpretations of + the path names would be made relative to the effective working + directory caused by the -C option. For example the following + invocations are equivalent: + + git --git-dir=a.git --work-tree=b -C c status + git --git-dir=c/a.git --work-tree=c/b status + -c <name>=<value>:: Pass a configuration parameter to the command. The value given will override values from configuration files. diff --git a/git.c b/git.c index 2025f77..52bce74 100644 --- a/git.c +++ b/git.c @@ -7,7 +7,7 @@ #include "commit.h" const char git_usage_string[] = - "git [--version] [--help] [-c name=value]\n" + "git [--version] [--help] [-C <path>] [-c name=value]\n" " [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]\n" " [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]\n" " [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]\n" @@ -54,7 +54,18 @@ static int handle_options(const char ***argv, int *argc, int *envchanged) /* * Check remaining flags. */ - if (!prefixcmp(cmd, "--exec-path")) { + if (!strcmp(cmd, "-C")) { + if (*argc < 2) { + fprintf(stderr, "No directory given for -C.\n" ); + usage(git_usage_string); + } + if (chdir((*argv)[1])) + die_errno("Cannot change to '%s'", (*argv)[1]); + if (envchanged) + *envchanged = 1; + (*argv)++; + (*argc)--; + } else if (!prefixcmp(cmd, "--exec-path")) { cmd += 11; if (*cmd == '=') git_set_argv_exec_path(cmd + 1); diff --git a/t/t0056-git-C.sh b/t/t0056-git-C.sh new file mode 100755 index 0000000..7dc1e48 --- /dev/null +++ b/t/t0056-git-C.sh @@ -0,0 +1,83 @@ +#!/bin/sh + +test_description='"-C <path>" option and its effects on other path-related options' + +. ./test-lib.sh + +test_expect_success '"git -C <path>" runs git from the directory <path>' ' + test_create_repo dir1 && + echo 1 >dir1/a.txt && + (cd dir1 && git add a.txt && git commit -m "initial in dir1") && + echo "initial in dir1" >expected && + git -C dir1 log --format=%s >actual && + test_cmp expected actual +' + +test_expect_success 'Multiple -C options: "-C dir1 -C dir2" is equivalent to "-C dir1/dir2"' ' + test_create_repo dir1/dir2 && + echo 1 >dir1/dir2/a.txt && + git -C dir1/dir2 add a.txt && + expected="initial in dir1/dir2" + echo $expected >expected && + git -C dir1/dir2 commit -m "$expected" && + git -C dir1 -C dir2 log --format=%s >actual && + test_cmp expected actual +' + +test_expect_success 'Effect on --git-dir option: "-C c --git-dir=a.git" is equivalent to "--git-dir c/a.git"' ' + mkdir c && + mkdir c/a && + mkdir c/a.git && + (cd c/a.git && git init --bare) && + echo 1 >c/a/a.txt && + git --git-dir c/a.git --work-tree=c/a add a.txt && + git --git-dir c/a.git --work-tree=c/a commit -m "initial" && + git --git-dir=c/a.git log -1 --format=%s >expected && + git -C c --git-dir=a.git log -1 --format=%s >actual && + test_cmp expected actual +' + +test_expect_success 'Order should not matter: "--git-dir=a.git -C c" is equivalent to "-C c --git-dir=a.git"' ' + git -C c --git-dir=a.git log -1 --format=%s >expected && + git --git-dir=a.git -C c log -1 --format=%s >actual && + test_cmp expected actual +' + +test_expect_success 'Effect on --work-tree option: "-C c/a.git --work-tree=../a" is equivalent to "--work-tree=c/a --git-dir=c/a.git"' ' + rm c/a/a.txt && + git --git-dir=c/a.git --work-tree=c/a status >expected && + git -C c/a.git --work-tree=../a status >actual && + test_cmp expected actual +' + +test_expect_success 'Order should not matter: "--work-tree=../a -C c/a.git" is equivalent to "-C c/a.git --work-tree=../a"' ' + git -C c/a.git --work-tree=../a status >expected && + git --work-tree=../a -C c/a.git status >actual && + test_cmp expected actual +' + +test_expect_success 'Effect on --git-dir and --work-tree options - "-C c --git-dir=a.git --work-tree=a" is equivalent to "--git-dir=c/a.git --work-tree=c/a"' ' + git --git-dir=c/a.git --work-tree=c/a status >expected && + git -C c --git-dir=a.git --work-tree=a status >actual && + test_cmp expected actual +' + +test_expect_success 'Order should not matter: "-C c --git-dir=a.git --work-tree=a" is equivalent to "--git-dir=a.git -C c --work-tree=a"' ' + git -C c --git-dir=a.git --work-tree=a status >expected && + git --git-dir=a.git -C c --work-tree=a status >actual && + test_cmp expected actual +' + +test_expect_success 'Order should not matter: "-C c --git-dir=a.git --work-tree=a" is equivalent to "--git-dir=a.git --work-tree=a -C c"' ' + git -C c --git-dir=a.git --work-tree=a status >expected && + git --git-dir=a.git --work-tree=a -C c status >actual && + test_cmp expected actual +' + +test_expect_success 'Relative followed by fullpath: "-C ./here -C /there" is equivalent to "-C /there"' ' + echo "initial in dir1/dir2" >expected && + git -C dir1 -C "$PWD/dir1/dir2" log --format=%s >actual && + test_cmp expected actual +' + +test_done -- 1.8.4.24.g5fcd118 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html