* [PATCH v3] Teach git to change to a given directory using -C option
@ 2013-09-03 11:59 Nazri Ramliy
2013-09-03 22:46 ` Junio C Hamano
0 siblings, 1 reply; 14+ messages in thread
From: Nazri Ramliy @ 2013-09-03 11:59 UTC (permalink / raw)
To: Eric Sunshine; +Cc: Git List, Jeff King, Jonathan Nieder
On Tue, Sep 3, 2013 at 3:42 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:
> No wish to bike-shed, however, I find "effective directory" somewhat
> difficult to digest due to its jargony feel. It also seems ambiguous
> (to me) since "previous effective directory" may mean "directory when
> git was run" or "directory set by most recent -C". My earlier
> suggestion
>
> When multiple -C options are given, each subsequent non-absolute
> -C <path> is interpreted relative to the preceding -C <path>.
>
> avoided jargon and left no room for ambiguity.
>
> However, perhaps the examples are clear enough to make excessive prose
> explanation unnecessary, thus:
>
> Run as if git was started in <path> instead of the current
> working directory. Multiple -C options are allowed and acted upon
> in the order given, thus "-C /usr -C src" is equivalent to "-C
> /usr/src", and "-C src -C /usr" is equivalent to "C /usr". This
> option affects ...
I did feel that the explanation is becoming wordy. I'll take the former
as it is terser. I've split the part that explain the effects on other
options that take path argument into a separate paragraph.
> It's curious that this test uses a variable ($expected) to avoid
> repeating literal "initial in dir1/dir2", however, the previous test
> repeats its literal "initial in dir1". (IMHO, the repeated literal
> actually makes the test a bit easier to read, and it's not likely to
> be a maintenance burden.)
Fixed.
> It is suggested in t/README that, for Windows (MSYS bash)
> compatibility, you should use $(pwd) rather than $PWD.
Fixed.
Thanks for another round of review!
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@gmail.com>
---
Documentation/git.txt | 16 +++++++++-
git.c | 15 ++++++++--
t/t0056-git-C.sh | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 110 insertions(+), 3 deletions(-)
create mode 100755 t/t0056-git-C.sh
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 83edf30..6105cb0 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 was started in <path> instead of the current working
+ directory. When multiple -C options are given, each subsequent
+ non-absolute "-C <path>" is interpreted relative to the preceding "-C
+ <path>".
+
+ 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 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..c0006da
--- /dev/null
+++ b/t/t0056-git-C.sh
@@ -0,0 +1,82 @@
+#!/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 &&
+ echo "initial in dir1/dir2" >expected &&
+ git -C dir1/dir2 commit -m "initial in dir1/dir2" &&
+ 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.22.g38647a4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v3] Teach git to change to a given directory using -C option
2013-09-03 11:59 [PATCH v3] Teach git to change to a given directory using -C option Nazri Ramliy
@ 2013-09-03 22:46 ` Junio C Hamano
2013-09-03 23:37 ` Eric Sunshine
2013-09-04 6:36 ` Nazri Ramliy
0 siblings, 2 replies; 14+ messages in thread
From: Junio C Hamano @ 2013-09-03 22:46 UTC (permalink / raw)
To: Nazri Ramliy; +Cc: Eric Sunshine, Git List, Jeff King, Jonathan Nieder
Nazri Ramliy <ayiehere@gmail.com> writes:
> -- >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@gmail.com>
> ---
Thanks; will tentatively queue on 'pu' with some rephrasing of the
log message, but I have a few comments.
> Documentation/git.txt | 16 +++++++++-
> git.c | 15 ++++++++--
> t/t0056-git-C.sh | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 110 insertions(+), 3 deletions(-)
> create mode 100755 t/t0056-git-C.sh
>
> diff --git a/Documentation/git.txt b/Documentation/git.txt
> index 83edf30..6105cb0 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>]
I do not care too deeply either way, but I am curious if there was a
reason why you changed the earlier <directory> to <path>? Somehow,
when we _know_ a path has to be a directory, I find it easier on the
readers to spell that out, instead of saying "this is a path",
implying that it could be a directory, a regular file, or even
non-existent.
> [--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 was started in <path> instead of the current working
> + directory. When multiple -C options are given, each subsequent
> + non-absolute "-C <path>" is interpreted relative to the preceding "-C
> + <path>".
> +
> + 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 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
> +
Does the above format correctly without the usual "second and
subsequent paragraphs are not indented, but has '+' in place of
a blank line"?
> 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")) {
We usually do not prepend to an existing if/else if/ chain unless
there is a very good reason (e.g. the new "if" condition is very
often triggered and we are better off checking it early) exactly
because doing so would make a patch that is ugly like the above.
You are not touching the codepath that deal with --exec-path, but
the resulting patch makes it appear as if you are doing something to
it.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3] Teach git to change to a given directory using -C option
2013-09-03 22:46 ` Junio C Hamano
@ 2013-09-03 23:37 ` Eric Sunshine
2013-09-04 6:36 ` Nazri Ramliy
1 sibling, 0 replies; 14+ messages in thread
From: Eric Sunshine @ 2013-09-03 23:37 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Nazri Ramliy, Git List, Jeff King, Jonathan Nieder
On Tue, Sep 3, 2013 at 6:46 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Nazri Ramliy <ayiehere@gmail.com> writes:
>
>> -- >8 --
>> diff --git a/Documentation/git.txt b/Documentation/git.txt
>> index 83edf30..6105cb0 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>]
>
> I do not care too deeply either way, but I am curious if there was a
> reason why you changed the earlier <directory> to <path>? Somehow,
> when we _know_ a path has to be a directory, I find it easier on the
> readers to spell that out, instead of saying "this is a path",
> implying that it could be a directory, a regular file, or even
> non-existent.
That change was in response to my review [1] in which I mentioned:
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>.
>> [--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>]
Thus <directory> was inconsistent with existing text in git.txt, such
as what is visible here for --git-dir and --work-tree, as well as
later in git.txt where --git-dir and --work-tree are described in more
detail (also using <path>).
[1]: http://thread.gmane.org/gmane.comp.version-control.git/233441/focus=233564
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3] Teach git to change to a given directory using -C option
2013-09-03 22:46 ` Junio C Hamano
2013-09-03 23:37 ` Eric Sunshine
@ 2013-09-04 6:36 ` Nazri Ramliy
2013-09-04 6:45 ` Eric Sunshine
2013-09-04 12:20 ` Nazri Ramliy
1 sibling, 2 replies; 14+ messages in thread
From: Nazri Ramliy @ 2013-09-04 6:36 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Eric Sunshine, Git List, Jeff King, Jonathan Nieder
On Wed, Sep 4, 2013 at 6:46 AM, Junio C Hamano <gitster@pobox.com> wrote:
> I do not care too deeply either way, but I am curious if there was a
> reason why you changed the earlier <directory> to <path>? Somehow,
> when we _know_ a path has to be a directory, I find it easier on the
> readers to spell that out, instead of saying "this is a path",
> implying that it could be a directory, a regular file, or even
> non-existent.
Eric made me do it :). Personally I prefer the non-ambiguous "directory"
over "path". In fact, "directory" is used in the error message spat out
by git:
$ git --work-tree
No directory given for --work-tree.
...
$ git --git-dir
No directory given for --git-dir.
...
$
I think changing "<path>" to "<directory>" wherever appropriate in
git.txt would be an improvement. Tangent: <dir> is shorter but that
might not be easy on the translators.
>> +-C <path>::
>> + Run as if git was started in <path> instead of the current working
>> + directory. When multiple -C options are given, each subsequent
>> + non-absolute "-C <path>" is interpreted relative to the preceding "-C
>> + <path>".
>> +
>> + 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 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
>> +
>
> Does the above format correctly without the usual "second and
> subsequent paragraphs are not indented, but has '+' in place of
> a blank line"?
No it doesn't. I'll fix it in the next reroll.
>> - 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")) {
>
> We usually do not prepend to an existing if/else if/ chain unless
> there is a very good reason (e.g. the new "if" condition is very
> often triggered and we are better off checking it early) exactly
> because doing so would make a patch that is ugly like the above.
> You are not touching the codepath that deal with --exec-path, but
> the resulting patch makes it appear as if you are doing something to
> it.
I agree with you here. I'll send the reroll later.
nazri
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3] Teach git to change to a given directory using -C option
2013-09-04 6:36 ` Nazri Ramliy
@ 2013-09-04 6:45 ` Eric Sunshine
2013-09-04 12:20 ` Nazri Ramliy
1 sibling, 0 replies; 14+ messages in thread
From: Eric Sunshine @ 2013-09-04 6:45 UTC (permalink / raw)
To: Nazri Ramliy; +Cc: Junio C Hamano, Git List, Jeff King, Jonathan Nieder
On Wed, Sep 4, 2013 at 2:36 AM, Nazri Ramliy <ayiehere@gmail.com> wrote:
> On Wed, Sep 4, 2013 at 6:46 AM, Junio C Hamano <gitster@pobox.com> wrote:
>> I do not care too deeply either way, but I am curious if there was a
>> reason why you changed the earlier <directory> to <path>? Somehow,
>> when we _know_ a path has to be a directory, I find it easier on the
>> readers to spell that out, instead of saying "this is a path",
>> implying that it could be a directory, a regular file, or even
>> non-existent.
>
> Eric made me do it :). Personally I prefer the non-ambiguous "directory"
> over "path". In fact, "directory" is used in the error message spat out
> by git:
>
> $ git --work-tree
> No directory given for --work-tree.
> ...
>
> $ git --git-dir
> No directory given for --git-dir.
> ...
> $
>
> I think changing "<path>" to "<directory>" wherever appropriate in
> git.txt would be an improvement. Tangent: <dir> is shorter but that
> might not be easy on the translators.
Such a terminology change is orthogonal to the patch adding -C
support, so if you do pursue it, the terminology change should be a
separate patch (either preparatory or follow-up to the -C patch).
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3] Teach git to change to a given directory using -C option
2013-09-04 6:36 ` Nazri Ramliy
2013-09-04 6:45 ` Eric Sunshine
@ 2013-09-04 12:20 ` Nazri Ramliy
2013-09-08 10:32 ` Eric Sunshine
1 sibling, 1 reply; 14+ messages in thread
From: Nazri Ramliy @ 2013-09-04 12:20 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Eric Sunshine, Git List, Jeff King, Jonathan Nieder
On Wed, Sep 04, 2013 at 02:36:47PM +0800, Nazri Ramliy wrote:
> On Wed, Sep 4, 2013 at 6:46 AM, Junio C Hamano <gitster@pobox.com> wrote:
> > Does the above format correctly without the usual "second and
> > subsequent paragraphs are not indented, but has '+' in place of
> > a blank line"?
>
> No it doesn't. I'll fix it in the next reroll.
>
> >> - 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")) {
> >
> > We usually do not prepend to an existing if/else if/ chain unless
> > there is a very good reason (e.g. the new "if" condition is very
> > often triggered and we are better off checking it early) exactly
> > because doing so would make a patch that is ugly like the above.
> > You are not touching the codepath that deal with --exec-path, but
> > the resulting patch makes it appear as if you are doing something to
> > it.
>
> I agree with you here. I'll send the reroll later.
Here it is.
Eric: Care to give your "Reviewed-by:" stamp?
nazri
-- >8 --
Subject: git: run in a directory given with -C option
This is similar in spirit to to "make -C dir ..." and "tar -C dir ...".
It takes more 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@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
Documentation/git.txt | 16 +++++++++-
git.c | 13 +++++++-
t/t0056-git-C.sh | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 109 insertions(+), 2 deletions(-)
create mode 100755 t/t0056-git-C.sh
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 83edf30..ae049da 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 was started in <path> instead of the current working
+ directory. When multiple -C options are given, each subsequent
+ non-absolute "-C <path>" is interpreted relative to the preceding "-C
+ <path>".
++
+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 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..a2d99a7 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"
@@ -153,6 +153,17 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
set_alternate_shallow_file((*argv)[0]);
if (envchanged)
*envchanged = 1;
+ } else 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 {
fprintf(stderr, "Unknown option: %s\n", cmd);
usage(git_usage_string);
diff --git a/t/t0056-git-C.sh b/t/t0056-git-C.sh
new file mode 100755
index 0000000..c0006da
--- /dev/null
+++ b/t/t0056-git-C.sh
@@ -0,0 +1,82 @@
+#!/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 &&
+ echo "initial in dir1/dir2" >expected &&
+ git -C dir1/dir2 commit -m "initial in dir1/dir2" &&
+ 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.22.g38647a4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v3] Teach git to change to a given directory using -C option
2013-09-04 12:20 ` Nazri Ramliy
@ 2013-09-08 10:32 ` Eric Sunshine
2013-09-09 1:49 ` Nazri Ramliy
0 siblings, 1 reply; 14+ messages in thread
From: Eric Sunshine @ 2013-09-08 10:32 UTC (permalink / raw)
To: Nazri Ramliy; +Cc: Junio C Hamano, Git List, Jeff King, Jonathan Nieder
On Wed, Sep 4, 2013 at 8:20 AM, Nazri Ramliy <ayiehere@gmail.com> wrote:
> Subject: git: run in a directory given with -C option
>
> This is similar in spirit to to "make -C dir ..." and "tar -C dir ...".
> ---
> diff --git a/Documentation/git.txt b/Documentation/git.txt
> index 83edf30..ae049da 100644
> --- a/Documentation/git.txt
> +++ b/Documentation/git.txt
> @@ -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 was started in <path> instead of the current working
> + directory. When multiple -C options are given, each subsequent
> + non-absolute "-C <path>" is interpreted relative to the preceding "-C
> + <path>".
For consistency with existing formatting in git.txt, you may want to
squash in the following fixes (sans gmail whitespace damage):
--- >8 ---
diff --git a/Documentation/git.txt b/Documentation/git.txt
index ae049da..6622037 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -396,14 +396,14 @@ because `git --help ...` is converted internally into `git
help ...`.
-C <path>::
- Run as if git was started in <path> instead of the current working
- directory. When multiple -C options are given, each subsequent
- non-absolute "-C <path>" is interpreted relative to the preceding "-C
- <path>".
+ Run as if git was started in '<path>' instead of the current working
+ directory. When multiple '-C' options are given, each subsequent
+ non-absolute `-C <path>` is interpreted relative to the preceding `-C
+ <path>`.
+
-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 working directory caused by the -C option. For
+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 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
--- >8 ---
> +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 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
Is the interaction of -C with --work-tree and --git-dir desirable or
useful? (I'm genuinely curious.) Do you have use-cases in mind? Would
mentioning them in the commit message help to justify the interaction?
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v3] Teach git to change to a given directory using -C option
2013-09-08 10:32 ` Eric Sunshine
@ 2013-09-09 1:49 ` Nazri Ramliy
2013-09-09 5:01 ` Eric Sunshine
0 siblings, 1 reply; 14+ messages in thread
From: Nazri Ramliy @ 2013-09-09 1:49 UTC (permalink / raw)
To: Eric Sunshine; +Cc: Junio C Hamano, Git List, Jeff King, Jonathan Nieder
On Sun, Sep 8, 2013 at 6:32 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:
> For consistency with existing formatting in git.txt, you may want to
> squash in the following fixes (sans gmail whitespace damage):
>
> --- >8 ---
[ diff snipped ]
> --- >8 ---
Thanks. I'll submit a reroll later.
>> +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 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
>
> Is the interaction of -C with --work-tree and --git-dir desirable or
> useful? (I'm genuinely curious.) Do you have use-cases in mind? Would
> mentioning them in the commit message help to justify the interaction?
The example is meant to clarify the effect of the -C option, rather than a
proposed usage with the --work-tree and --git-dir options. The example came out
due to the following discussions from an earlier version of this patch [1]:
On Sat, Apr 20, 2013 at 12:12 AM, Jeff King <peff@peff.net> wrote:
> On Fri, Apr 19, 2013 at 08:21:48PM +0800, Nazri Ramliy wrote:
>> diff --git a/Documentation/git.txt b/Documentation/git.txt
>> index 6a875f2..20bba86 100644
>> --- a/Documentation/git.txt
>> +++ b/Documentation/git.txt
>> @@ -379,6 +379,9 @@ displayed. See linkgit:git-help[1] for more information,
>> because `git --help ...` is converted internally into `git
>> help ...`.
>>
>> +-C <directory>::
>> + Change to given directory before doing anything else.
>> +
>
> It might make sense to clarify this as "...anything else, including
> determining the location of the git repository directory". If you think
> hard about it, doing anything else would not really make much sense, but
> spelling it out makes it clear what the option can be used for.
and [2]:
On Sun, Apr 21, 2013 at 6:18 AM, Jonathan Nieder <jrnieder@gmail.com> wrote:
> All that said, I don't mind -C terribly as long as it can maintain
> itself, which means including thorough documentation that covers the
> purpose and how pathname parameters and envvars interact with the new
> option and including tests under t/ to ensure it continues to work
> correctly in the future.
nazri
[1] http://article.gmane.org/gmane.comp.version-control.git/221766
[2] http://article.gmane.org/gmane.comp.version-control.git/221878
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3] Teach git to change to a given directory using -C option
2013-09-09 1:49 ` Nazri Ramliy
@ 2013-09-09 5:01 ` Eric Sunshine
2013-09-09 13:47 ` Nazri Ramliy
0 siblings, 1 reply; 14+ messages in thread
From: Eric Sunshine @ 2013-09-09 5:01 UTC (permalink / raw)
To: Nazri Ramliy; +Cc: Junio C Hamano, Git List, Jeff King, Jonathan Nieder
On Sun, Sep 8, 2013 at 9:49 PM, Nazri Ramliy <ayiehere@gmail.com> wrote:
> On Sun, Sep 8, 2013 at 6:32 PM, Eric Sunshine <sunshine@sunshineco.com> wrote:
>>> +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 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
>>
>> Is the interaction of -C with --work-tree and --git-dir desirable or
>> useful? (I'm genuinely curious.) Do you have use-cases in mind? Would
>> mentioning them in the commit message help to justify the interaction?
>
> The example is meant to clarify the effect of the -C option, rather than a
> proposed usage with the --work-tree and --git-dir options. The example came out
> due to the following discussions from an earlier version of this patch [1]:
> [1] http://article.gmane.org/gmane.comp.version-control.git/221766
Thanks for the reference. I did read that thread earlier. It doesn't
really answer my question, but perhaps it's not terribly important
since the interaction is documented. I was mainly asking if the choice
of locking in one particular interpretation was deliberate even though
other potentially valid (and perhaps more intuitive) interpretations
exists. More below TL;DR if you care to read on.
TL;DR
I was interested in knowing whether the exact interaction between -C
and --work-tree and --git-dir was intentional (and desirable) or an
"accident of implementation". I can see it going either way.
As implemented by the patch, -C is acted upon immediately (via
chdir()), whereas --work-tree and --git-dir have a delayed effect, so:
git -C foo --work-tree=bar -C baz --git-dir=moo
means:
work-tree = foo/baz/bar
git-dir = foo/baz/moo
However, it would be equally valid for a user to expect the options to
be evaluated sequentially such that the above command line would mean:
work-tree = foo/bar
git-dir = foo/baz/moo
Is the former interpretation better than the latter possibly more
intuitive interpretation? This is a genuine question. I'm not
suggesting that one interpretation is better than the other, and it's
possible that it won't matter in practice [1], but it might be good to
know that alternate interpretations have been taken into consideration
before locking in a particular behavior.
This is why I was asking if you had particular use-cases in mind where
the former made more sense than the latter (or some other [2])
interpretation. Since there are multiple potential interpretations, it
might make sense to explain in the commit message why the one was
chosen over the other(s), and such use-cases could help solidify that
explanation.
[1]: Mixing of -C, --work-tree, and --git-dir may be sufficiently
unlikely that the reason the patch's behavior was chosen becomes
immaterial. Since the behavior is documented, a person can choose to
avoid -C if it doesn't work in a way suitable to his situation.
[2]: For example, a user might reasonably expect -C to be relative to
--work-tree or GIT_WORK_TREE rather than the other way around. So,
"git --work-tree=foo -C bar" or "git -C bar --work-tree=foo" would
chdir("foo/bar") before performing the git operation, and --git-dir
would be unaffected. Yet another possibility is that -C would impact
neither --work-tree nor --git-dir.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3] Teach git to change to a given directory using -C option
2013-09-09 5:01 ` Eric Sunshine
@ 2013-09-09 13:47 ` Nazri Ramliy
2013-09-09 16:32 ` Junio C Hamano
0 siblings, 1 reply; 14+ messages in thread
From: Nazri Ramliy @ 2013-09-09 13:47 UTC (permalink / raw)
To: Eric Sunshine; +Cc: Junio C Hamano, Git List, Jeff King, Jonathan Nieder
On Mon, Sep 09, 2013 at 01:01:33AM -0400, Eric Sunshine wrote:
> On Sun, Sep 8, 2013 at 9:49 PM, Nazri Ramliy <ayiehere@gmail.com> wrote:
> Thanks for the reference. I did read that thread earlier. It doesn't
> really answer my question, but perhaps it's not terribly important
> since the interaction is documented. I was mainly asking if the choice
> of locking in one particular interpretation was deliberate even though
> other potentially valid (and perhaps more intuitive) interpretations
> exists. More below TL;DR if you care to read on.
Thanks for the clarification. Reroll of the patch to fix the
documentation is at the end of this mail.
> TL;DR
>
> I was interested in knowing whether the exact interaction between -C
> and --work-tree and --git-dir was intentional (and desirable) or an
> "accident of implementation". I can see it going either way.
The implementation was the simplest one that I could think of for
achieving what I wanted -C to do. I can agree that the side effects with
any other options that handles path argument are "accident of
implementation" and there might be room for improvements, at the expense
of complexity.
> However, it would be equally valid for a user to expect the options to
> be evaluated sequentially such that the above command line would mean:
>
> work-tree = foo/bar
> git-dir = foo/baz/moo
>
> Is the former interpretation better than the latter possibly more
> intuitive interpretation? This is a genuine question. I'm not
> suggesting that one interpretation is better than the other, and it's
> possible that it won't matter in practice [1], but it might be good to
> know that alternate interpretations have been taken into consideration
> before locking in a particular behavior.
>
> This is why I was asking if you had particular use-cases in mind where
> the former made more sense than the latter (or some other [2])
> interpretation. Since there are multiple potential interpretations, it
> might make sense to explain in the commit message why the one was
> chosen over the other(s), and such use-cases could help solidify that
> explanation.
>
When I first experimented the interaction of -C with --git-dir and
--work-tree, I did feel its counter-intuitiveness side effect due to the
implementation. Consider -C's interaction with format-patch:
$ git -C foo format-patch HEAD~3..
Based on the current implementation, the patch files generated by the
above would in the directory "foo" instead of where git was started
from.
Is it worth the complexity to ensure that subsequent git options,
builtin options, or builtins be aware of where git was started from vs.
the effective "new" directory that it chdir'd into due to the -C option?
I'm not sure about that at the moment. I foresee that it might not be
that simple to get that to work.
I took a look at GNU tar's -C implementation and it seems that for the
equivalent case,:
$ tar Ccf foo/ foo.tar bar.txt baz.txt
GNU tar is aware of where it was called from and created the file
foo.tar there (instead of in foo/).
Tangent: This now reminds me of a feature that I wished git-grep had -
when run on a non-bare repository, I'd like git-grep to show me the
"usable" path from the point of view of where I started it from,
assuming $PWD is $HOME and my non-bare clone of git.git is in $HOME/src:
$ git -C src/git grep main git.c
src/git/git.c: * Check remaining flags.
src/git/git.c:int main(int argc, char **av)
instead of the what we have in the current behavior:
$ git -C src/git grep main git.c
git.c: * Check remaining flags.
git.c:int main(int argc, char **av)
Nazri
-- >8 --
Subject: git: run in a directory given with -C option
This is similar in spirit to to "make -C dir ..." and "tar -C dir ...".
It takes more 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@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
Documentation/git.txt | 16 +++++++++-
git.c | 13 +++++++-
t/t0056-git-C.sh | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 109 insertions(+), 2 deletions(-)
create mode 100755 t/t0056-git-C.sh
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 83edf30..6622037 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 was started in '<path>' instead of the current working
+ directory. When multiple '-C' options are given, each subsequent
+ non-absolute `-C <path>` is interpreted relative to the preceding `-C
+ <path>`.
++
+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 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..a2d99a7 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"
@@ -153,6 +153,17 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
set_alternate_shallow_file((*argv)[0]);
if (envchanged)
*envchanged = 1;
+ } else 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 {
fprintf(stderr, "Unknown option: %s\n", cmd);
usage(git_usage_string);
diff --git a/t/t0056-git-C.sh b/t/t0056-git-C.sh
new file mode 100755
index 0000000..c0006da
--- /dev/null
+++ b/t/t0056-git-C.sh
@@ -0,0 +1,82 @@
+#!/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 &&
+ echo "initial in dir1/dir2" >expected &&
+ git -C dir1/dir2 commit -m "initial in dir1/dir2" &&
+ 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.100.gd06f3e9
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v3] Teach git to change to a given directory using -C option
2013-09-09 13:47 ` Nazri Ramliy
@ 2013-09-09 16:32 ` Junio C Hamano
2013-09-09 17:42 ` Eric Sunshine
2013-09-09 18:43 ` Eric Sunshine
0 siblings, 2 replies; 14+ messages in thread
From: Junio C Hamano @ 2013-09-09 16:32 UTC (permalink / raw)
To: Nazri Ramliy; +Cc: Eric Sunshine, Git List, Jeff King, Jonathan Nieder
Nazri Ramliy <ayiehere@gmail.com> writes:
> Subject: git: run in a directory given with -C option
>
> This is similar in spirit to to "make -C dir ..." and "tar -C dir ...".
The doubled-"to to" which I locally fixed when I queued the last one
(together with other rewording to make it more agreeable and easier
to read) somehow came back ;-) Will fix locally again.
> +-C <path>::
> + Run as if git was started in '<path>' instead of the current working
> + directory. When multiple '-C' options are given, each subsequent
I think this should be `-C` to typeset it as "typed literally".
> + non-absolute `-C <path>` is interpreted relative to the preceding `-C
> + <path>`.
> ++
> +This option affects options that expect path name like '--git-dir' and
> +'--work-tree' in that their interpretations of the path names would be
Likewise for `--git-dir` and `--work-tree`.
> +made relative to the working directory caused by the '-C' option. For
and here.
> diff --git a/t/t0056-git-C.sh b/t/t0056-git-C.sh
> new file mode 100755
> index 0000000..c0006da
> --- /dev/null
> +++ b/t/t0056-git-C.sh
> @@ -0,0 +1,82 @@
> +#!/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") &&
Curious why this does not use -C here.
> + 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 &&
Because "a.txt" exists in both dir1 and dir1/dir2, this has less
chance of catching a bug (if somebody breaks the feature to run it
in dir1 not dir1/dir2, "add" will happily say "Oh, I found something
to add", instead of saying "Huh? there is no such path".
If you used b.txt instead, you would catch such a breakage.
Remember, tests are not about demonstrating how cool the new feature
is and/or how well it works in an expected setting. Imagine ways
other people can break your spiffy new feature in later patches, and
design tests that are more likely to catch them.
The same comment applies throughout the remainder of this script.
> + echo "initial in dir1/dir2" >expected &&
> + git -C dir1/dir2 commit -m "initial in dir1/dir2" &&
to reduce possibilities of breaking this test in the future due to
typos (e.g. somebody may want to say "initial commit in dir1/dir2"),
doing this may be a better idea:
msg="initial in dir1/dir2" &&
echo "$msg" >expected &&
git -C dir1/dir2 commit -m "$msg" &&
The same comment applies to the previous one.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3] Teach git to change to a given directory using -C option
2013-09-09 16:32 ` Junio C Hamano
@ 2013-09-09 17:42 ` Eric Sunshine
2013-09-09 17:59 ` Junio C Hamano
2013-09-09 18:43 ` Eric Sunshine
1 sibling, 1 reply; 14+ messages in thread
From: Eric Sunshine @ 2013-09-09 17:42 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Nazri Ramliy, Git List, Jeff King, Jonathan Nieder
On Mon, Sep 9, 2013 at 12:32 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Nazri Ramliy <ayiehere@gmail.com> writes:
>
>> Subject: git: run in a directory given with -C option
>>
>> +-C <path>::
>> + Run as if git was started in '<path>' instead of the current working
>> + directory. When multiple '-C' options are given, each subsequent
>
> I think this should be `-C` to typeset it as "typed literally".
>
>> + non-absolute `-C <path>` is interpreted relative to the preceding `-C
>> + <path>`.
>> ++
>> +This option affects options that expect path name like '--git-dir' and
>> +'--work-tree' in that their interpretations of the path names would be
>
> Likewise for `--git-dir` and `--work-tree`.
>
>> +made relative to the working directory caused by the '-C' option. For
>
> and here.
I agree with all of the above, however, the unfortunate typesetting in
these cases was chosen deliberately to be consistent with the
immediately surrounding text. A separate typesetting normalization
patch, either before or after this patch, would not be unwelcome. (I
forgot to make such a suggestion in [1].)
[1]: http://thread.gmane.org/gmane.comp.version-control.git/233719/focus=234234
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3] Teach git to change to a given directory using -C option
2013-09-09 17:42 ` Eric Sunshine
@ 2013-09-09 17:59 ` Junio C Hamano
0 siblings, 0 replies; 14+ messages in thread
From: Junio C Hamano @ 2013-09-09 17:59 UTC (permalink / raw)
To: Eric Sunshine; +Cc: Nazri Ramliy, Git List, Jeff King, Jonathan Nieder
Eric Sunshine <sunshine@sunshineco.com> writes:
> On Mon, Sep 9, 2013 at 12:32 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> Nazri Ramliy <ayiehere@gmail.com> writes:
>>
>>> Subject: git: run in a directory given with -C option
>>>
>>> +-C <path>::
>>> + Run as if git was started in '<path>' instead of the current working
>>> + directory. When multiple '-C' options are given, each subsequent
>>
>> I think this should be `-C` to typeset it as "typed literally".
>>
>>> + non-absolute `-C <path>` is interpreted relative to the preceding `-C
>>> + <path>`.
>>> ++
>>> +This option affects options that expect path name like '--git-dir' and
>>> +'--work-tree' in that their interpretations of the path names would be
>>
>> Likewise for `--git-dir` and `--work-tree`.
>>
>>> +made relative to the working directory caused by the '-C' option. For
>>
>> and here.
>
> I agree with all of the above, however, the unfortunate typesetting in
> these cases was chosen deliberately to be consistent with the
> immediately surrounding text. A separate typesetting normalization
> patch, either before or after this patch, would not be unwelcome. (I
> forgot to make such a suggestion in [1].)
>
> [1]: http://thread.gmane.org/gmane.comp.version-control.git/233719/focus=234234
OK, thanks for clarification.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3] Teach git to change to a given directory using -C option
2013-09-09 16:32 ` Junio C Hamano
2013-09-09 17:42 ` Eric Sunshine
@ 2013-09-09 18:43 ` Eric Sunshine
1 sibling, 0 replies; 14+ messages in thread
From: Eric Sunshine @ 2013-09-09 18:43 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Nazri Ramliy, Git List, Jeff King, Jonathan Nieder
On Mon, Sep 9, 2013 at 12:32 PM, Junio C Hamano <gitster@pobox.com> wrote:
>> + echo "initial in dir1/dir2" >expected &&
>> + git -C dir1/dir2 commit -m "initial in dir1/dir2" &&
>
> to reduce possibilities of breaking this test in the future due to
> typos (e.g. somebody may want to say "initial commit in dir1/dir2"),
> doing this may be a better idea:
>
> msg="initial in dir1/dir2" &&
> echo "$msg" >expected &&
> git -C dir1/dir2 commit -m "$msg" &&
>
> The same comment applies to the previous one.
In his original submission, Nazri actually had it the way you suggest
for this test (though not the preceding test), but changed it in
response to a silly parenthetical "IMHO" in my review [1].
[1]: http://thread.gmane.org/gmane.comp.version-control.git/233636/focus=233704
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2013-09-09 18:43 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-03 11:59 [PATCH v3] Teach git to change to a given directory using -C option Nazri Ramliy
2013-09-03 22:46 ` Junio C Hamano
2013-09-03 23:37 ` Eric Sunshine
2013-09-04 6:36 ` Nazri Ramliy
2013-09-04 6:45 ` Eric Sunshine
2013-09-04 12:20 ` Nazri Ramliy
2013-09-08 10:32 ` Eric Sunshine
2013-09-09 1:49 ` Nazri Ramliy
2013-09-09 5:01 ` Eric Sunshine
2013-09-09 13:47 ` Nazri Ramliy
2013-09-09 16:32 ` Junio C Hamano
2013-09-09 17:42 ` Eric Sunshine
2013-09-09 17:59 ` Junio C Hamano
2013-09-09 18:43 ` Eric Sunshine
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).