* [BUG] bare repository detection does not work with aliases
@ 2013-03-07 22:47 Mark Lodato
2013-03-08 5:48 ` Jeff King
0 siblings, 1 reply; 16+ messages in thread
From: Mark Lodato @ 2013-03-07 22:47 UTC (permalink / raw)
To: git list
It seems that the fallback bare repository detection in the absence of
core.bare fails for aliases.
$ git init --bare foo
$ cd foo
$ git config alias.s 'status -sb'
$ git s
fatal: This operation must be run in a work tree
$ sed -i -e '/bare =/d' config
$ git s
## Initial commit on master
?? HEAD
?? config
?? description
?? hooks
?? info/
$ git status -sb
fatal: This operation must be run in a work tree
The reason I am using the fallback is to use a single bare repository
with multiple working directories (via git-new-workdir) as suggested
in 8fa0ee3b [1].
[1] https://github.com/git/git/commit/8fa0ee3b50736eb869a3e13375bb041c1bf5aa12
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [BUG] bare repository detection does not work with aliases
2013-03-07 22:47 [BUG] bare repository detection does not work with aliases Mark Lodato
@ 2013-03-08 5:48 ` Jeff King
2013-03-08 6:27 ` Junio C Hamano
2013-03-08 7:15 ` [PATCH] setup: suppress implicit "." work-tree for bare repos Jeff King
0 siblings, 2 replies; 16+ messages in thread
From: Jeff King @ 2013-03-08 5:48 UTC (permalink / raw)
To: Mark Lodato; +Cc: git list
On Thu, Mar 07, 2013 at 05:47:45PM -0500, Mark Lodato wrote:
> It seems that the fallback bare repository detection in the absence of
> core.bare fails for aliases.
This triggered some deja vu for me, so I went digging. And indeed, this
has been a bug since at least 2008. This patch (which never got applied)
fixed it:
http://thread.gmane.org/gmane.comp.version-control.git/72792
The issue is that we treat:
GIT_DIR=/some/path git ...
as if the current directory is the work tree, unless core.bare is
explicitly set, or unless an explicit work tree is given (via
GIT_WORK_TREE, "git --work-tree", or in the config). This is handy, and
backwards compatible.
Inside setup_git_directory, when we find the directory we put it in
$GIT_DIR for later reference by ourselves or sub-programs (since we are
typically moving to the top of the working tree next, we need to record
the original path, and can't rely on discovery finding the same path
again). But we don't set $GIT_WORK_TREE. So if you don't have core.bare
set, the above rule will kick in for sub-programs, or for aliases (which
will call setup_git_directory again).
The solution is that when we set $GIT_DIR like this, we need to also say
"no, there is no working tree; we are bare". And that's what that patch
does. It's 5 years old now, so not surprisingly, it does not apply
cleanly. The moral equivalent in today's code base would be something
like:
diff --git a/environment.c b/environment.c
index 89d6c70..8edaedd 100644
--- a/environment.c
+++ b/environment.c
@@ -200,7 +200,8 @@ void set_git_work_tree(const char *new_work_tree)
return;
}
git_work_tree_initialized = 1;
- work_tree = xstrdup(real_path(new_work_tree));
+ if (*new_work_tree)
+ work_tree = xstrdup(real_path(new_work_tree));
}
const char *get_git_work_tree(void)
diff --git a/setup.c b/setup.c
index e1cfa48..f0e1251 100644
--- a/setup.c
+++ b/setup.c
@@ -544,7 +544,7 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
worktree = get_git_work_tree();
/* both get_git_work_tree() and cwd are already normalized */
- if (!strcmp(cwd, worktree)) { /* cwd == worktree */
+ if (!worktree || !strcmp(cwd, worktree)) { /* cwd == worktree */
set_git_dir(gitdirenv);
free(gitfile);
return NULL;
@@ -636,6 +636,8 @@ static const char *setup_bare_git_dir(char *cwd, int offset, int len, int *nongi
}
else
set_git_dir(".");
+
+ setenv(GIT_WORK_TREE_ENVIRONMENT, "", 1);
return NULL;
}
which passes your test. Unfortunately, this patch runs afoul of the same
complaints that prevented the original from being acceptable (weirdness
on Windows with empty environment variables).
Having read the discussion again, I _think_ the more sane thing is to
actually just have a new variable, $GIT_BARE, which overrides any
core.bare config (just as $GIT_WORK_TREE override core.worktree). And
then we set that explicitly when we are in a bare $GIT_DIR, propagating
our auto-detection to sub-processes.
-Peff
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [BUG] bare repository detection does not work with aliases
2013-03-08 5:48 ` Jeff King
@ 2013-03-08 6:27 ` Junio C Hamano
2013-03-08 6:37 ` Jeff King
2013-03-08 7:15 ` [PATCH] setup: suppress implicit "." work-tree for bare repos Jeff King
1 sibling, 1 reply; 16+ messages in thread
From: Junio C Hamano @ 2013-03-08 6:27 UTC (permalink / raw)
To: Jeff King; +Cc: git
The $GIT_BARE idea sounds very sensible to me.
Jeff King <peff@peff.net> wrote:
>On Thu, Mar 07, 2013 at 05:47:45PM -0500, Mark Lodato wrote:
>
>> It seems that the fallback bare repository detection in the absence
>of
>> core.bare fails for aliases.
>
>This triggered some deja vu for me, so I went digging. And indeed, this
>has been a bug since at least 2008. This patch (which never got
>applied)
>fixed it:
>
> http://thread.gmane.org/gmane.comp.version-control.git/72792
>
>The issue is that we treat:
>
> GIT_DIR=/some/path git ...
>
>as if the current directory is the work tree, unless core.bare is
>explicitly set, or unless an explicit work tree is given (via
>GIT_WORK_TREE, "git --work-tree", or in the config). This is handy,
>and
>backwards compatible.
>
>Inside setup_git_directory, when we find the directory we put it in
>$GIT_DIR for later reference by ourselves or sub-programs (since we are
>typically moving to the top of the working tree next, we need to record
>the original path, and can't rely on discovery finding the same path
>again). But we don't set $GIT_WORK_TREE. So if you don't have core.bare
>set, the above rule will kick in for sub-programs, or for aliases
>(which
>will call setup_git_directory again).
>
>The solution is that when we set $GIT_DIR like this, we need to also
>say
>"no, there is no working tree; we are bare". And that's what that patch
>does. It's 5 years old now, so not surprisingly, it does not apply
>cleanly. The moral equivalent in today's code base would be something
>like:
>
>diff --git a/environment.c b/environment.c
>index 89d6c70..8edaedd 100644
>--- a/environment.c
>+++ b/environment.c
>@@ -200,7 +200,8 @@ void set_git_work_tree(const char *new_work_tree)
> return;
> }
> git_work_tree_initialized = 1;
>- work_tree = xstrdup(real_path(new_work_tree));
>+ if (*new_work_tree)
>+ work_tree = xstrdup(real_path(new_work_tree));
> }
>
> const char *get_git_work_tree(void)
>diff --git a/setup.c b/setup.c
>index e1cfa48..f0e1251 100644
>--- a/setup.c
>+++ b/setup.c
>@@ -544,7 +544,7 @@ static const char *setup_explicit_git_dir(const
>char *gitdirenv,
> worktree = get_git_work_tree();
>
> /* both get_git_work_tree() and cwd are already normalized */
>- if (!strcmp(cwd, worktree)) { /* cwd == worktree */
>+ if (!worktree || !strcmp(cwd, worktree)) { /* cwd == worktree */
> set_git_dir(gitdirenv);
> free(gitfile);
> return NULL;
>@@ -636,6 +636,8 @@ static const char *setup_bare_git_dir(char *cwd,
>int offset, int len, int *nongi
> }
> else
> set_git_dir(".");
>+
>+ setenv(GIT_WORK_TREE_ENVIRONMENT, "", 1);
> return NULL;
> }
>
>
>which passes your test. Unfortunately, this patch runs afoul of the
>same
>complaints that prevented the original from being acceptable (weirdness
>on Windows with empty environment variables).
>
>Having read the discussion again, I _think_ the more sane thing is to
>actually just have a new variable, $GIT_BARE, which overrides any
>core.bare config (just as $GIT_WORK_TREE override core.worktree). And
>then we set that explicitly when we are in a bare $GIT_DIR, propagating
>our auto-detection to sub-processes.
>
>-Peff
>--
>To unsubscribe from this list: send the line "unsubscribe git" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Pardon terseness, typo and HTML from a tablet.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [BUG] bare repository detection does not work with aliases
2013-03-08 6:27 ` Junio C Hamano
@ 2013-03-08 6:37 ` Jeff King
0 siblings, 0 replies; 16+ messages in thread
From: Jeff King @ 2013-03-08 6:37 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
On Thu, Mar 07, 2013 at 10:27:04PM -0800, Junio C Hamano wrote:
> The $GIT_BARE idea sounds very sensible to me.
Unfortunately, it is not quite as simple as that. I just wrote up the
patch, and it turns out that we are foiled by how core.bare is treated.
If it is true, the repo is definitely bare. If it is false, that is only
a hint for us.
So we cannot just look at is_bare_repository() after setup_git_directory
runs. Because we are not "definitely bare", only "maybe bare", it
returns false. We just happen not to have a work tree. We could do
something like:
if (is_bare_repository_cfg || !work_tree)
setenv("GIT_BARE", "1", 1);
which I think would work, but feels kind of wrong. We are bare in this
instance, but somebody setting GIT_WORK_TREE in a sub-process would
want to become unbare, presumably, but our variable would override them.
Just looking through all of the code paths, I am getting a little
nervous that I would not cover all the bases for such a $GIT_BARE to
work (e.g., doing GIT_BARE=0 would not do I would expect as a user,
because of the historical way we treat core.bare=false).
So rather than introduce something like $GIT_BARE which is going to
bring about all new kinds of corner cases, I think I'd rather just pass
along a $GIT_NO_IMPLICIT_WORK_TREE variable, which is much more direct
for solving this problem, and is less likely to end up having bugs of
its own.
-Peff
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH] setup: suppress implicit "." work-tree for bare repos
2013-03-08 5:48 ` Jeff King
2013-03-08 6:27 ` Junio C Hamano
@ 2013-03-08 7:15 ` Jeff King
2013-03-08 7:44 ` Johannes Sixt
2013-03-08 7:54 ` [PATCH] " Junio C Hamano
1 sibling, 2 replies; 16+ messages in thread
From: Jeff King @ 2013-03-08 7:15 UTC (permalink / raw)
To: Mark Lodato; +Cc: Junio C Hamano, git list
If an explicit GIT_DIR is given without a working tree, we
implicitly assume that the current working directory should
be used as the working tree. E.g.,:
GIT_DIR=/some/repo.git git status
would compare against the cwd.
Unfortunately, we fool this rule for sub-invocations of git
by setting GIT_DIR internally ourselves. For example:
git init foo
cd foo/.git
git status ;# fails, as we expect
git config alias.st status
git status ;# does not fail, but should
What happens is that we run setup_git_directory when doing
alias lookup (since we need to see the config), set GIT_DIR
as a result, and then leave GIT_WORK_TREE blank (because we
do not have one). Then when we actually run the status
command, we do setup_git_directory again, which sees our
explicit GIT_DIR and uses the cwd as an implicit worktree.
It's tempting to argue that we should be suppressing that
second invocation of setup_git_directory, as it could use
the values we already found in memory. However, the problem
still exists for sub-processes (e.g., if "git status" were
an external command).
You can see another example with the "--bare" option, which
sets GIT_DIR explicitly. For example:
git init foo
cd foo/.git
git status ;# fails
git --bare status ;# does NOT fail
We need some way of telling sub-processes "even though
GIT_DIR is set, do not use cwd as an implicit working tree".
We could do it by putting a special token into
GIT_WORK_TREE, but the obvious choice (an empty string) has
some portability problems, and could potentially be
triggered accidentally by a user.
Instead, we add a new boolean variable, GIT_IMPLICIT_WORK_TREE,
which suppresses the use of cwd as a working tree when
GIT_DIR is set. We trigger the new variable when we know we
are in a bare setting.
The variable is left intentionally undocumented, as this is
an internal detail (for now, anyway). If somebody comes up
with a good alternate use for it, and once we are confident
we have shaken any bugs out of it, we can consider promoting
it further.
Signed-off-by: Jeff King <peff@peff.net>
---
So I think this just ends up being a cleaner and smaller change than
trying to support $GIT_BARE. I think $GIT_BARE could allow more
flexibility, but it's flexibility nobody is particularly asking for, and
there are lots of nasty corner cases around it. I'm pretty sure this is
doing the right thing.
Having written this, I'm still tempted to signal the same thing by
putting /dev/null into GIT_WORK_TREE (Junio's suggestion from the old
thread). This one works OK because we only check GIT_WORK_TREE_IMPLICIT
_after_ exhausting all of the other working tree options, so it is
always subordinate to a later setting of GIT_WORK_TREE. But it seems a
little cleaner for somebody setting GIT_WORK_TREE To clear this
"implicit" flag automatically.
At the same time, I would wonder how other git implementations would
react to GIT_WORK_TREE=/dev/null. Would they try to chdir() there and
barf, when they could happily exist without a working tree? Doing it
this way seems a bit safer from regressions (those other implementations
do not get the _benefit_ of this patch unless they support
GIT_WORK_TREE_IMPLICIT, of course, but at least we are not breaking
them).
cache.h | 1 +
git.c | 1 +
setup.c | 8 ++++++++
t/t1510-repo-setup.sh | 19 +++++++++++++++++++
4 files changed, 29 insertions(+)
diff --git a/cache.h b/cache.h
index e493563..070169a 100644
--- a/cache.h
+++ b/cache.h
@@ -344,6 +344,7 @@ static inline enum object_type object_type(unsigned int mode)
#define GIT_DIR_ENVIRONMENT "GIT_DIR"
#define GIT_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE"
#define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
+#define GIT_IMPLICIT_WORK_TREE_ENVIRONMENT "GIT_IMPLICIT_WORK_TREE"
#define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
#define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
#define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
diff --git a/git.c b/git.c
index b10c18b..24b7984 100644
--- a/git.c
+++ b/git.c
@@ -125,6 +125,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
static char git_dir[PATH_MAX+1];
is_bare_repository_cfg = 1;
setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 0);
+ setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, "0", 1);
if (envchanged)
*envchanged = 1;
} else if (!strcmp(cmd, "-c")) {
diff --git a/setup.c b/setup.c
index 1dee47e..6c87660 100644
--- a/setup.c
+++ b/setup.c
@@ -523,6 +523,12 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
set_git_work_tree(core_worktree);
}
}
+ else if (!git_env_bool(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, 1)) {
+ /* #16d */
+ set_git_dir(gitdirenv);
+ free(gitfile);
+ return NULL;
+ }
else /* #2, #10 */
set_git_work_tree(".");
@@ -601,6 +607,8 @@ static const char *setup_bare_git_dir(char *cwd, int offset, int len, int *nongi
if (check_repository_format_gently(".", nongit_ok))
return NULL;
+ setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, "0", 1);
+
/* --work-tree is set without --git-dir; use discovered one */
if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
const char *gitdir;
diff --git a/t/t1510-repo-setup.sh b/t/t1510-repo-setup.sh
index 80aedfc..cf2ee78 100755
--- a/t/t1510-repo-setup.sh
+++ b/t/t1510-repo-setup.sh
@@ -517,6 +517,25 @@ test_expect_success '#16c: bare .git has no worktree' '
"$here/16c/.git" "(null)" "$here/16c/sub" "(null)"
'
+test_expect_success '#16d: bareness preserved across alias' '
+ setup_repo 16d unset "" unset &&
+ (
+ cd 16d/.git &&
+ test_must_fail git status &&
+ git config alias.st status &&
+ test_must_fail git st
+ )
+'
+
+test_expect_success '#16e: bareness preserved by --bare' '
+ setup_repo 16e unset "" unset &&
+ (
+ cd 16e/.git &&
+ test_must_fail git status &&
+ test_must_fail git --bare status
+ )
+'
+
test_expect_success '#17: GIT_WORK_TREE without explicit GIT_DIR is accepted (bare case)' '
# Just like #16.
setup_repo 17a unset "" true &&
--
1.8.2.rc2.4.g3e774bb
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH] setup: suppress implicit "." work-tree for bare repos
2013-03-08 7:15 ` [PATCH] setup: suppress implicit "." work-tree for bare repos Jeff King
@ 2013-03-08 7:44 ` Johannes Sixt
2013-03-08 8:42 ` Jeff King
2013-03-08 7:54 ` [PATCH] " Junio C Hamano
1 sibling, 1 reply; 16+ messages in thread
From: Johannes Sixt @ 2013-03-08 7:44 UTC (permalink / raw)
To: Jeff King; +Cc: Mark Lodato, Junio C Hamano, git list
Am 3/8/2013 8:15, schrieb Jeff King:
> --- a/cache.h
> +++ b/cache.h
> @@ -344,6 +344,7 @@ static inline enum object_type object_type(unsigned int mode)
> #define GIT_DIR_ENVIRONMENT "GIT_DIR"
> #define GIT_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE"
> #define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
> +#define GIT_IMPLICIT_WORK_TREE_ENVIRONMENT "GIT_IMPLICIT_WORK_TREE"
> #define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
> #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
> #define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
This new variable needs to be added to environment.c:local_repo_env, right?
-- Hannes
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH] setup: suppress implicit "." work-tree for bare repos
2013-03-08 7:15 ` [PATCH] setup: suppress implicit "." work-tree for bare repos Jeff King
2013-03-08 7:44 ` Johannes Sixt
@ 2013-03-08 7:54 ` Junio C Hamano
2013-03-08 8:43 ` Jeff King
1 sibling, 1 reply; 16+ messages in thread
From: Junio C Hamano @ 2013-03-08 7:54 UTC (permalink / raw)
To: Jeff King; +Cc: Mark Lodato, git list
Jeff King <peff@peff.net> writes:
> diff --git a/cache.h b/cache.h
> index e493563..070169a 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -344,6 +344,7 @@ static inline enum object_type object_type(unsigned int mode)
> #define GIT_DIR_ENVIRONMENT "GIT_DIR"
> #define GIT_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE"
> #define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
> +#define GIT_IMPLICIT_WORK_TREE_ENVIRONMENT "GIT_IMPLICIT_WORK_TREE"
> #define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
> #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
> #define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
Not adding any user documentation is fine (you explained why in the
log message), but I would really prefer to have some in-code comment
to clarify its meaning. Is it "Please do use implicit work tree"
boolean? Is it "This is the path to the work tree we have already
figured out" string? Is it something else? What is it used for,
who sets it, what other codepath that will be invented in the future
need to be careful to set it (or unset it) and how does one who
writes that new codepath decides that he needs to do so (or
shouldn't)?
I would know *today* that it is a bool to affect us, after having
discovered that we are in bare and we have set GIT_DIR (so if the
end user already had GIT_DIR, we shouldn't set it ourselves), and
also our child processes, but I am not confident that I will
remember this thread 6 months down the road.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH] setup: suppress implicit "." work-tree for bare repos
2013-03-08 7:44 ` Johannes Sixt
@ 2013-03-08 8:42 ` Jeff King
2013-03-08 9:28 ` [PATCHv2] setup and GIT_IMPLICIT_WORK_TREE Jeff King
0 siblings, 1 reply; 16+ messages in thread
From: Jeff King @ 2013-03-08 8:42 UTC (permalink / raw)
To: Johannes Sixt; +Cc: Mark Lodato, Junio C Hamano, git list
On Fri, Mar 08, 2013 at 08:44:20AM +0100, Johannes Sixt wrote:
> Am 3/8/2013 8:15, schrieb Jeff King:
> > --- a/cache.h
> > +++ b/cache.h
> > @@ -344,6 +344,7 @@ static inline enum object_type object_type(unsigned int mode)
> > #define GIT_DIR_ENVIRONMENT "GIT_DIR"
> > #define GIT_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE"
> > #define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
> > +#define GIT_IMPLICIT_WORK_TREE_ENVIRONMENT "GIT_IMPLICIT_WORK_TREE"
> > #define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
> > #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
> > #define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
>
> This new variable needs to be added to environment.c:local_repo_env, right?
It does; I had no idea local_repo_env existed. We should add a comment
to cache.h to that effect, too.
-Peff
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH] setup: suppress implicit "." work-tree for bare repos
2013-03-08 7:54 ` [PATCH] " Junio C Hamano
@ 2013-03-08 8:43 ` Jeff King
0 siblings, 0 replies; 16+ messages in thread
From: Jeff King @ 2013-03-08 8:43 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Mark Lodato, git list
On Thu, Mar 07, 2013 at 11:54:18PM -0800, Junio C Hamano wrote:
> Jeff King <peff@peff.net> writes:
>
> > diff --git a/cache.h b/cache.h
> > index e493563..070169a 100644
> > --- a/cache.h
> > +++ b/cache.h
> > @@ -344,6 +344,7 @@ static inline enum object_type object_type(unsigned int mode)
> > #define GIT_DIR_ENVIRONMENT "GIT_DIR"
> > #define GIT_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE"
> > #define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
> > +#define GIT_IMPLICIT_WORK_TREE_ENVIRONMENT "GIT_IMPLICIT_WORK_TREE"
> > #define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
> > #define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
> > #define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
>
> Not adding any user documentation is fine (you explained why in the
> log message), but I would really prefer to have some in-code comment
> to clarify its meaning. Is it "Please do use implicit work tree"
> boolean? Is it "This is the path to the work tree we have already
> figured out" string? Is it something else? What is it used for,
> who sets it, what other codepath that will be invented in the future
> need to be careful to set it (or unset it) and how does one who
> writes that new codepath decides that he needs to do so (or
> shouldn't)?
My intent was that the commit message would be enough to explain it, but
it is a pain for a later reader to have to blame the line back to that
commit to read it. I'll re-roll with a comment.
-Peff
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCHv2] setup and GIT_IMPLICIT_WORK_TREE
2013-03-08 8:42 ` Jeff King
@ 2013-03-08 9:28 ` Jeff King
2013-03-08 9:29 ` [PATCH v2 1/3] cache.h: drop LOCAL_REPO_ENV_SIZE Jeff King
` (2 more replies)
0 siblings, 3 replies; 16+ messages in thread
From: Jeff King @ 2013-03-08 9:28 UTC (permalink / raw)
To: git; +Cc: Johannes Sixt, Junio C Hamano, Mark Lodato
Here's a re-roll of the GIT_IMPLICIT_WORK_TREE patch which should
address the comments in the last round. I've added an explanatory
comment near the variable definition, and added it to local_repo_env.
While doing that, I noticed some cleanup opportunities around
local_repo_env, which resulted in the first two patches.
[1/3]: cache.h: drop LOCAL_REPO_ENV_SIZE
[2/3]: environment: add GIT_PREFIX to local_repo_env
[3/3]: setup: suppress implicit "." work-tree for bare repos
-Peff
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v2 1/3] cache.h: drop LOCAL_REPO_ENV_SIZE
2013-03-08 9:28 ` [PATCHv2] setup and GIT_IMPLICIT_WORK_TREE Jeff King
@ 2013-03-08 9:29 ` Jeff King
2013-03-08 9:30 ` [PATCH v2 2/3] environment: add GIT_PREFIX to local_repo_env Jeff King
2013-03-08 9:32 ` [PATCH v2 3/3] setup: suppress implicit "." work-tree for bare repos Jeff King
2 siblings, 0 replies; 16+ messages in thread
From: Jeff King @ 2013-03-08 9:29 UTC (permalink / raw)
To: git; +Cc: Johannes Sixt, Junio C Hamano, Mark Lodato
We keep a static array of variables that should be cleared
when invoking a sub-process on another repo. We statically
size the array with the LOCAL_REPO_ENV_SIZE macro so that
any readers do not have to count it themselves.
As it turns out, no readers actually use the macro, and it
creates a maintenance headache, as modifications to the
array need to happen in two places (one to add the new
element, and another to bump the size).
Since it's NULL-terminated, we can just drop the size macro
entirely. While we're at it, we'll clean up some comments
around it, and add a new mention of it at the top of the
list of environment variable macros. Even though
local_repo_env is right below that list, it's easy to miss,
and additions to that list should consider local_repo_env.
Signed-off-by: Jeff King <peff@peff.net>
---
cache.h | 12 ++++++------
environment.c | 6 ++----
2 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/cache.h b/cache.h
index e493563..b90044a 100644
--- a/cache.h
+++ b/cache.h
@@ -341,6 +341,7 @@ static inline enum object_type object_type(unsigned int mode)
OBJ_BLOB;
}
+/* Double-check local_repo_env below if you add to this list. */
#define GIT_DIR_ENVIRONMENT "GIT_DIR"
#define GIT_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE"
#define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
@@ -365,13 +366,12 @@ static inline enum object_type object_type(unsigned int mode)
#define GIT_LITERAL_PATHSPECS_ENVIRONMENT "GIT_LITERAL_PATHSPECS"
/*
- * Repository-local GIT_* environment variables
- * The array is NULL-terminated to simplify its usage in contexts such
- * environment creation or simple walk of the list.
- * The number of non-NULL entries is available as a macro.
+ * Repository-local GIT_* environment variables; these will be cleared
+ * when git spawns a sub-process that runs inside another repository.
+ * The array is NULL-terminated, which makes it easy to pass in the "env"
+ * parameter of a run-command invocation, or to do a simple walk.
*/
-#define LOCAL_REPO_ENV_SIZE 9
-extern const char *const local_repo_env[LOCAL_REPO_ENV_SIZE + 1];
+extern const char * const local_repo_env[];
extern int is_bare_repository_cfg;
extern int is_bare_repository(void);
diff --git a/environment.c b/environment.c
index 89d6c70..dc73927 100644
--- a/environment.c
+++ b/environment.c
@@ -83,11 +83,9 @@ static char *git_object_dir, *git_index_file, *git_graft_file;
static char *git_object_dir, *git_index_file, *git_graft_file;
/*
- * Repository-local GIT_* environment variables
- * Remember to update local_repo_env_size in cache.h when
- * the size of the list changes
+ * Repository-local GIT_* environment variables; see cache.h for details.
*/
-const char * const local_repo_env[LOCAL_REPO_ENV_SIZE + 1] = {
+const char * const local_repo_env[] = {
ALTERNATE_DB_ENVIRONMENT,
CONFIG_ENVIRONMENT,
CONFIG_DATA_ENVIRONMENT,
--
1.8.2.rc2.4.g3e774bb
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 2/3] environment: add GIT_PREFIX to local_repo_env
2013-03-08 9:28 ` [PATCHv2] setup and GIT_IMPLICIT_WORK_TREE Jeff King
2013-03-08 9:29 ` [PATCH v2 1/3] cache.h: drop LOCAL_REPO_ENV_SIZE Jeff King
@ 2013-03-08 9:30 ` Jeff King
2013-03-08 21:39 ` Eric Sunshine
2013-03-08 9:32 ` [PATCH v2 3/3] setup: suppress implicit "." work-tree for bare repos Jeff King
2 siblings, 1 reply; 16+ messages in thread
From: Jeff King @ 2013-03-08 9:30 UTC (permalink / raw)
To: git; +Cc: Johannes Sixt, Junio C Hamano, Mark Lodato
The GIT_PREFIX variable is set based on our location within
the working tree. It should therefore be cleared whenever
GIT_WORK_TREE is cleared.
In practice, this doesn't cause any bugs, because none of
the sub-programs we invoke with local_repo_env cleared
actually care about GIT_PREFIX. But this is the right thing
to do, and future proofs us again that assumption changing.
While we're at it, let's define a GIT_PREFIX_ENVIRONMENT
macro; this avoids repetition of the string literal, which
can help catch any spelling mistakes in the code.
Signed-off-by: Jeff King <peff@peff.net>
---
I noticed this one because it was near code I was touching in an earlier
iteration of patch 3. I gave a quick skim and did not notice any other
variables which would want to receive the same treatment.
cache.h | 1 +
environment.c | 1 +
setup.c | 4 ++--
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/cache.h b/cache.h
index b90044a..23e6e62 100644
--- a/cache.h
+++ b/cache.h
@@ -345,6 +345,7 @@ static inline enum object_type object_type(unsigned int mode)
#define GIT_DIR_ENVIRONMENT "GIT_DIR"
#define GIT_NAMESPACE_ENVIRONMENT "GIT_NAMESPACE"
#define GIT_WORK_TREE_ENVIRONMENT "GIT_WORK_TREE"
+#define GIT_PREFIX_ENVIRONMENT "GIT_PREFIX"
#define DEFAULT_GIT_DIR_ENVIRONMENT ".git"
#define DB_ENVIRONMENT "GIT_OBJECT_DIRECTORY"
#define INDEX_ENVIRONMENT "GIT_INDEX_FILE"
diff --git a/environment.c b/environment.c
index dc73927..2bd1c37 100644
--- a/environment.c
+++ b/environment.c
@@ -95,6 +95,7 @@ const char * const local_repo_env[] = {
GRAFT_ENVIRONMENT,
INDEX_ENVIRONMENT,
NO_REPLACE_OBJECTS_ENVIRONMENT,
+ GIT_PREFIX_ENVIRONMENT,
NULL
};
diff --git a/setup.c b/setup.c
index 1dee47e..1996295 100644
--- a/setup.c
+++ b/setup.c
@@ -794,9 +794,9 @@ const char *setup_git_directory_gently(int *nongit_ok)
prefix = setup_git_directory_gently_1(nongit_ok);
if (prefix)
- setenv("GIT_PREFIX", prefix, 1);
+ setenv(GIT_PREFIX_ENVIRONMENT, prefix, 1);
else
- setenv("GIT_PREFIX", "", 1);
+ setenv(GIT_PREFIX_ENVIRONMENT, "", 1);
if (startup_info) {
startup_info->have_repository = !nongit_ok || !*nongit_ok;
--
1.8.2.rc2.4.g3e774bb
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 3/3] setup: suppress implicit "." work-tree for bare repos
2013-03-08 9:28 ` [PATCHv2] setup and GIT_IMPLICIT_WORK_TREE Jeff King
2013-03-08 9:29 ` [PATCH v2 1/3] cache.h: drop LOCAL_REPO_ENV_SIZE Jeff King
2013-03-08 9:30 ` [PATCH v2 2/3] environment: add GIT_PREFIX to local_repo_env Jeff King
@ 2013-03-08 9:32 ` Jeff King
2 siblings, 0 replies; 16+ messages in thread
From: Jeff King @ 2013-03-08 9:32 UTC (permalink / raw)
To: git; +Cc: Johannes Sixt, Junio C Hamano, Mark Lodato
If an explicit GIT_DIR is given without a working tree, we
implicitly assume that the current working directory should
be used as the working tree. E.g.,:
GIT_DIR=/some/repo.git git status
would compare against the cwd.
Unfortunately, we fool this rule for sub-invocations of git
by setting GIT_DIR internally ourselves. For example:
git init foo
cd foo/.git
git status ;# fails, as we expect
git config alias.st status
git status ;# does not fail, but should
What happens is that we run setup_git_directory when doing
alias lookup (since we need to see the config), set GIT_DIR
as a result, and then leave GIT_WORK_TREE blank (because we
do not have one). Then when we actually run the status
command, we do setup_git_directory again, which sees our
explicit GIT_DIR and uses the cwd as an implicit worktree.
It's tempting to argue that we should be suppressing that
second invocation of setup_git_directory, as it could use
the values we already found in memory. However, the problem
still exists for sub-processes (e.g., if "git status" were
an external command).
You can see another example with the "--bare" option, which
sets GIT_DIR explicitly. For example:
git init foo
cd foo/.git
git status ;# fails
git --bare status ;# does NOT fail
We need some way of telling sub-processes "even though
GIT_DIR is set, do not use cwd as an implicit working tree".
We could do it by putting a special token into
GIT_WORK_TREE, but the obvious choice (an empty string) has
some portability problems.
Instead, we add a new boolean variable, GIT_IMPLICIT_WORK_TREE,
which suppresses the use of cwd as a working tree when
GIT_DIR is set. We trigger the new variable when we know we
are in a bare setting.
The variable is left intentionally undocumented, as this is
an internal detail (for now, anyway). If somebody comes up
with a good alternate use for it, and once we are confident
we have shaken any bugs out of it, we can consider promoting
it further.
Signed-off-by: Jeff King <peff@peff.net>
---
cache.h | 12 ++++++++++++
environment.c | 1 +
git.c | 1 +
setup.c | 8 ++++++++
t/t1510-repo-setup.sh | 19 +++++++++++++++++++
5 files changed, 41 insertions(+)
diff --git a/cache.h b/cache.h
index 23e6e62..635f2e9 100644
--- a/cache.h
+++ b/cache.h
@@ -367,6 +367,18 @@ static inline enum object_type object_type(unsigned int mode)
#define GIT_LITERAL_PATHSPECS_ENVIRONMENT "GIT_LITERAL_PATHSPECS"
/*
+ * This environment variable is expected to contain a boolean indicating
+ * whether we should or should not treat:
+ *
+ * GIT_DIR=foo.git git ...
+ *
+ * as if GIT_WORK_TREE=. was given. It's not expected that users will make use
+ * of this, but we use it internally to communicate to sub-processes that we
+ * are in a bare repo. If not set, defaults to true.
+ */
+#define GIT_IMPLICIT_WORK_TREE_ENVIRONMENT "GIT_IMPLICIT_WORK_TREE"
+
+/*
* Repository-local GIT_* environment variables; these will be cleared
* when git spawns a sub-process that runs inside another repository.
* The array is NULL-terminated, which makes it easy to pass in the "env"
diff --git a/environment.c b/environment.c
index 2bd1c37..e2e75c1 100644
--- a/environment.c
+++ b/environment.c
@@ -92,6 +92,7 @@ const char * const local_repo_env[] = {
DB_ENVIRONMENT,
GIT_DIR_ENVIRONMENT,
GIT_WORK_TREE_ENVIRONMENT,
+ GIT_IMPLICIT_WORK_TREE_ENVIRONMENT,
GRAFT_ENVIRONMENT,
INDEX_ENVIRONMENT,
NO_REPLACE_OBJECTS_ENVIRONMENT,
diff --git a/git.c b/git.c
index b10c18b..24b7984 100644
--- a/git.c
+++ b/git.c
@@ -125,6 +125,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
static char git_dir[PATH_MAX+1];
is_bare_repository_cfg = 1;
setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 0);
+ setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, "0", 1);
if (envchanged)
*envchanged = 1;
} else if (!strcmp(cmd, "-c")) {
diff --git a/setup.c b/setup.c
index 1996295..9107f54 100644
--- a/setup.c
+++ b/setup.c
@@ -523,6 +523,12 @@ static const char *setup_explicit_git_dir(const char *gitdirenv,
set_git_work_tree(core_worktree);
}
}
+ else if (!git_env_bool(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, 1)) {
+ /* #16d */
+ set_git_dir(gitdirenv);
+ free(gitfile);
+ return NULL;
+ }
else /* #2, #10 */
set_git_work_tree(".");
@@ -601,6 +607,8 @@ static const char *setup_bare_git_dir(char *cwd, int offset, int len, int *nongi
if (check_repository_format_gently(".", nongit_ok))
return NULL;
+ setenv(GIT_IMPLICIT_WORK_TREE_ENVIRONMENT, "0", 1);
+
/* --work-tree is set without --git-dir; use discovered one */
if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
const char *gitdir;
diff --git a/t/t1510-repo-setup.sh b/t/t1510-repo-setup.sh
index 80aedfc..cf2ee78 100755
--- a/t/t1510-repo-setup.sh
+++ b/t/t1510-repo-setup.sh
@@ -517,6 +517,25 @@ test_expect_success '#16c: bare .git has no worktree' '
"$here/16c/.git" "(null)" "$here/16c/sub" "(null)"
'
+test_expect_success '#16d: bareness preserved across alias' '
+ setup_repo 16d unset "" unset &&
+ (
+ cd 16d/.git &&
+ test_must_fail git status &&
+ git config alias.st status &&
+ test_must_fail git st
+ )
+'
+
+test_expect_success '#16e: bareness preserved by --bare' '
+ setup_repo 16e unset "" unset &&
+ (
+ cd 16e/.git &&
+ test_must_fail git status &&
+ test_must_fail git --bare status
+ )
+'
+
test_expect_success '#17: GIT_WORK_TREE without explicit GIT_DIR is accepted (bare case)' '
# Just like #16.
setup_repo 17a unset "" true &&
--
1.8.2.rc2.4.g3e774bb
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v2 2/3] environment: add GIT_PREFIX to local_repo_env
2013-03-08 9:30 ` [PATCH v2 2/3] environment: add GIT_PREFIX to local_repo_env Jeff King
@ 2013-03-08 21:39 ` Eric Sunshine
2013-03-08 21:44 ` Jeff King
0 siblings, 1 reply; 16+ messages in thread
From: Eric Sunshine @ 2013-03-08 21:39 UTC (permalink / raw)
To: Jeff King; +Cc: git, Johannes Sixt, Junio C Hamano, Mark Lodato
On Fri, Mar 8, 2013 at 4:30 AM, Jeff King <peff@peff.net> wrote:
> The GIT_PREFIX variable is set based on our location within
> the working tree. It should therefore be cleared whenever
> GIT_WORK_TREE is cleared.
>
> In practice, this doesn't cause any bugs, because none of
> the sub-programs we invoke with local_repo_env cleared
> actually care about GIT_PREFIX. But this is the right thing
> to do, and future proofs us again that assumption changing.
s/again/against/
-- ES
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 2/3] environment: add GIT_PREFIX to local_repo_env
2013-03-08 21:39 ` Eric Sunshine
@ 2013-03-08 21:44 ` Jeff King
2013-03-08 23:03 ` Junio C Hamano
0 siblings, 1 reply; 16+ messages in thread
From: Jeff King @ 2013-03-08 21:44 UTC (permalink / raw)
To: Eric Sunshine; +Cc: git, Johannes Sixt, Junio C Hamano, Mark Lodato
On Fri, Mar 08, 2013 at 04:39:02PM -0500, Eric Sunshine wrote:
> On Fri, Mar 8, 2013 at 4:30 AM, Jeff King <peff@peff.net> wrote:
> > The GIT_PREFIX variable is set based on our location within
> > the working tree. It should therefore be cleared whenever
> > GIT_WORK_TREE is cleared.
> >
> > In practice, this doesn't cause any bugs, because none of
> > the sub-programs we invoke with local_repo_env cleared
> > actually care about GIT_PREFIX. But this is the right thing
> > to do, and future proofs us again that assumption changing.
>
> s/again/against/
Yep, thanks.
-Peff
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 2/3] environment: add GIT_PREFIX to local_repo_env
2013-03-08 21:44 ` Jeff King
@ 2013-03-08 23:03 ` Junio C Hamano
0 siblings, 0 replies; 16+ messages in thread
From: Junio C Hamano @ 2013-03-08 23:03 UTC (permalink / raw)
To: Jeff King; +Cc: Eric Sunshine, git, Johannes Sixt, Mark Lodato
Jeff King <peff@peff.net> writes:
> On Fri, Mar 08, 2013 at 04:39:02PM -0500, Eric Sunshine wrote:
>
>> On Fri, Mar 8, 2013 at 4:30 AM, Jeff King <peff@peff.net> wrote:
>> > The GIT_PREFIX variable is set based on our location within
>> > the working tree. It should therefore be cleared whenever
>> > GIT_WORK_TREE is cleared.
>> >
>> > In practice, this doesn't cause any bugs, because none of
>> > the sub-programs we invoke with local_repo_env cleared
>> > actually care about GIT_PREFIX. But this is the right thing
>> > to do, and future proofs us again that assumption changing.
>>
>> s/again/against/
>
> Yep, thanks.
Thanks; squashed-in.
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2013-03-08 23:03 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-07 22:47 [BUG] bare repository detection does not work with aliases Mark Lodato
2013-03-08 5:48 ` Jeff King
2013-03-08 6:27 ` Junio C Hamano
2013-03-08 6:37 ` Jeff King
2013-03-08 7:15 ` [PATCH] setup: suppress implicit "." work-tree for bare repos Jeff King
2013-03-08 7:44 ` Johannes Sixt
2013-03-08 8:42 ` Jeff King
2013-03-08 9:28 ` [PATCHv2] setup and GIT_IMPLICIT_WORK_TREE Jeff King
2013-03-08 9:29 ` [PATCH v2 1/3] cache.h: drop LOCAL_REPO_ENV_SIZE Jeff King
2013-03-08 9:30 ` [PATCH v2 2/3] environment: add GIT_PREFIX to local_repo_env Jeff King
2013-03-08 21:39 ` Eric Sunshine
2013-03-08 21:44 ` Jeff King
2013-03-08 23:03 ` Junio C Hamano
2013-03-08 9:32 ` [PATCH v2 3/3] setup: suppress implicit "." work-tree for bare repos Jeff King
2013-03-08 7:54 ` [PATCH] " Junio C Hamano
2013-03-08 8:43 ` Jeff King
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).