Re: Versioning configuration files on a server: fatal: Unable to create '//etc/.git/index.lock': No such file or directory
- From
Matthijs Kooijman <matthijs@stdin.nl>
- Date
- Nov 18, 2010, 20:36 UTC
- Message-ID
- <20101118203617.GH22067@login.drsnuggles.stderr.nl>
- In-Reply-To
- <20101118171751.GG22067@login.drsnuggles.stderr.nl>
Hi folks,
Show 5 quoted lines
> > I think 490544b (get_cwd_relative(): do not misinterpret suffix as > > subdirectory - 2010-05-22) causes it. Haven't fully understood what's > > going on in that function though :P > Seems you're right. I just reverted this commit and the problem seems to > go away.
A bit more gdb'ing with -O0, I found the following. get_cwd_relative is called with dir="/". The cwd is "/etc". The stack looks like:
#0 get_relative_cwd (buffer=0x7a44c0 "/etc", size=4096, dir=0x7b1041 "") at dir.c:961 #1 0x00000000004dfdf1 in setup_git_directory () at setup.c:612 #2 0x0000000000404f69 in run_builtin (p=0x75ea10, argc=2, argv=0x7fffffffc918) at git.c:257 #3 0x00000000004051e3 in handle_internal_command (argc=2, argv=0x7fffffffc918) at git.c:431 #4 0x000000000040538a in main (argc=2, argv=0x7fffffffc918) at git.c:516
After the following code runs:
while (*dir && *dir == *cwd) {
dir++;
cwd++;
}I have dir="" and cwd="etc". Then the following code runs:
switch (*cwd) {
case '\0':
return cwd;
case '/':
return cwd + 1;
default:
return NULL;
}Since *cwd='e', it returns NULL.
The old code (before 490544b) was:
if (*cwd == '/') return cwd + 1; return cwd;
So this would return "etc".
So, that's what is happens. I think this happens because get_relative_cwd expects dir to not contain a trailing slash. Normally, there is no trailing slash, but in the special case of dir="/" there is (sort of) a trailing slash.
I'm not completely sure how to fix this. Looking at 72ec8ba (Support working directory located at root - 2010-02-14), perhaps something like this?
diff --git a/dir.c b/dir.c index d1e5e5e..5408db9 100644 --- a/dir.c +++ b/dir.c @@ -943,6 +943,7 @@ int file_exists(const char *f) char *get_relative_cwd(char *buffer, int size, const char *dir) { char *cwd = buffer; + size_t len, root_len; if (!dir) return NULL; @@ -952,6 +953,15 @@ char *get_relative_cwd(char *buffer, int size, const char *dir) if (!is_absolute_path(dir)) dir = make_absolute_path(dir); + len = strlen(dir); + root_len = offset_1st_component(dir); + + if (root_len >= len) { + /* dir is the filesystem root, so the cwd is always inside */ + root_len = offset_1st_component(cwd); + return cwd + root_len; + } + while (*dir && *dir == *cwd) { dir++; cwd++; I'm not sure how this stuff really works, though. I think this works for *nix, but I'm unsure about Windows. Gr. Matthijs