On Thu, Nov 02, 2017 at 11:45:55PM +0000, Andrew Baumann wrote:
> I have a workaround for this, but someone on stack overflow [1]
> suggested reporting it upstream, so here you go:
>
> I have a fancy shell prompt that executes "git rev-parse
> --is-inside-work-tree" to determine whether we're currently inside a
> working directory. This causes git to walk up the directory hierarchy
> looking for a containing git repo. For example, when invoked from my
> home directory, it stats the following paths, in order:
>
> /home/me/.git
> /home/me/.git/HEAD
> /home/me/HEAD
> /home
> /home/.git
> /home/.git/HEAD
> /home/HEAD
> /
> /.git
> /.git/HEAD
> //HEAD
>
> The last name (//HEAD) interacts badly with Cygwin, which interprets
> it as a UNC file share, and so demand-loads a bunch of extra DLLs and
> attempts to resolve/contact the server named HEAD. This obviously
> doesn't work too well, especially over a slow network link.
>
> I've tested with the latest Cygwin git (2.15.0); this was also present
> in a prior version.
Interesting. I can reproduce on Linux (but of course "//HEAD" is cheap
to look at there). It bisects to ce9b8aab5d (setup_git_directory_1():
avoid changing global state, 2017-03-13). Before that, the end of the
strace for "git rev-parse --git-dir" looks like:
chdir("..") = 0
stat(".git", 0x7fffba398e00) = -1 ENOENT (No such file or
directory)
lstat(".git/HEAD", 0x7fffba398dd0) = -1 ENOENT (No such file or
directory)
lstat("./HEAD", 0x7fffba398dd0) = -1 ENOENT (No such file or
directory)
write(2, "fatal: Not a git repository (or "..., 69) = 69
and after:
stat("/.git", 0x7ffdb28b7eb0) = -1 ENOENT (No such file or
directory)
lstat("/.git/HEAD", 0x7ffdb28b7e80) = -1 ENOENT (No such file or
directory)
lstat("//HEAD", 0x7ffdb28b7e80) = -1 ENOENT (No such file or
directory)
write(2, "fatal: Not a git repository (or "..., 69) = 69
Switching to using absolute paths rather than chdir-ing around is
intentional for that commit, but it looks like we just need to
special-case the construction of the root path.
Like this, perhaps:
diff --git a/setup.c b/setup.c
index 27a31de33f..5d0b6a88e3 100644
--- a/setup.c
+++ b/setup.c
@@ -283,7 +283,9 @@ int is_git_directory(const char *suspect)
size_t len;
/* Check worktree-related signatures */
- strbuf_addf(&path, "%s/HEAD", suspect);
+ strbuf_addstr(&path, suspect);
+ strbuf_complete(&path, '/');
+ strbuf_addstr(&path, "HEAD");
if (validate_headref(path.buf))
goto done;
-Peff