[PATCH] Support working directory located at root

Subsystems: the rest

DORMANTno replies

5 messages, 3 authors, 2016-06-15 · open the first message on its own page

[PATCH] Support working directory located at root

From: Nguyễn Thái Ngọc Duy <hidden>
Date: 2016-06-15 22:48:12

Git should work regardless where the working directory is located,
even at root. This patch fixes two places where it assumes working
directory always have parent directory.

In setup_git_directory_gently(), when Git goes up to root and finds
.git there, it happily sets worktree to "".

In prefix_path(), loosen the outside repo check a little bit. Usually
when a path XXX is inside worktree /foo, it must be either "/foo", or
"/foo/...". When worktree is simply "/", we can safely ignore the
check: we have a slash at the beginning already.

Not related to worktree, but also set gitdir correctly if a bare repo
is placed (insanely?) at root.

Thanks João Carlos Mendes Luís for pointing out this problem.

Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
 Tell me if this patch is rejected, I'll send another one that makes
 setup_git_* die() if worktree/gitdir is to be set empty. I don't think we
 expect gitdir or worktree to be empty anywhere.

 setup.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/setup.c b/setup.c
index b38cbee..0fcd2fd 100644
--- a/setup.c
+++ b/setup.c
@@ -25,7 +25,7 @@ const char *prefix_path(const char *prefix, int len, const char *path)
 		len = strlen(work_tree);
 		total = strlen(sanitized) + 1;
 		if (strncmp(sanitized, work_tree, len) ||
-		    (sanitized[len] != '\0' && sanitized[len] != '/')) {
+		    (len > 1 && sanitized[len] != '\0' && sanitized[len] != '/')) {
 		error_out:
 			die("'%s' is outside repository", orig);
 		}
@@ -403,7 +403,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
 			if (!work_tree_env)
 				inside_work_tree = 0;
 			if (offset != len) {
-				cwd[offset] = '\0';
+				cwd[offset ? offset : 1] = '\0';
 				set_git_dir(cwd);
 			} else
 				set_git_dir(".");
@@ -427,6 +427,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
 	inside_git_dir = 0;
 	if (!work_tree_env)
 		inside_work_tree = 1;
+	if (offset == 0) /* reached root, set worktree to '/' */
+		offset = 1;
 	git_work_tree_cfg = xstrndup(cwd, offset);
 	if (check_repository_format_gently(nongit_ok))
 		return NULL;
-- 
1.7.0.rc0.54.gd33ef

Re: [PATCH] Support working directory located at root

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:48:12

Nguyễn Thái Ngọc Duy [off-list ref] writes:
Git should work regardless where the working directory is located,
even at root. This patch fixes two places where it assumes working
directory always have parent directory.

In setup_git_directory_gently(), when Git goes up to root and finds
.git there, it happily sets worktree to "".
If you mean "instead set it to "/" and things will work much better."
I agree with the reasoning (not suggesting to reword---just trying to
make sure I understood what you meant).
In prefix_path(), loosen the outside repo check a little bit. Usually
when a path XXX is inside worktree /foo, it must be either "/foo", or
"/foo/...". When worktree is simply "/", we can safely ignore the
check: we have a slash at the beginning already.
The logic for the "are we inside?" check above sounds correct.  When
work_tree is at root, have "/" in it, and len inside the "if orig is
absolute" block is 1, so memmove() strips out the leading '/' and makes
the result relative to the root level.  Am I reading the code right?
Not related to worktree, but also set gitdir correctly if a bare repo
is placed (insanely?) at root.
Yuck, but looks correct.

Re: [PATCH] Support working directory located at root

From: Johannes Sixt <hidden>
Date: 2016-06-15 22:48:12

On Montag, 8. Februar 2010, Nguyễn Thái Ngọc Duy wrote:
quoted hunk
@@ -25,7 +25,7 @@ const char *prefix_path(const char *prefix, int len,
const char *path) len = strlen(work_tree);
 		total = strlen(sanitized) + 1;
 		if (strncmp(sanitized, work_tree, len) ||
-		    (sanitized[len] != '\0' && sanitized[len] != '/')) {
+		    (len > 1 && sanitized[len] != '\0' && sanitized[len] != '/')) {
 		error_out:
 			die("'%s' is outside repository", orig);
 		}
@@ -403,7 +403,7 @@ const char *setup_git_directory_gently(int *nongit_ok)
 			if (!work_tree_env)
 				inside_work_tree = 0;
 			if (offset != len) {
-				cwd[offset] = '\0';
+				cwd[offset ? offset : 1] = '\0';
 				set_git_dir(cwd);
 			} else
 				set_git_dir(".");
@@ -427,6 +427,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
 	inside_git_dir = 0;
 	if (!work_tree_env)
 		inside_work_tree = 1;
+	if (offset == 0) /* reached root, set worktree to '/' */
+		offset = 1;
 	git_work_tree_cfg = xstrndup(cwd, offset);
 	if (check_repository_format_gently(nongit_ok))
 		return NULL;
Does not work:

etc@master:1028> ~/Src/git/git/git add resolv.conf
fatal: pathspec 'tc/resolv.conf' did not match any files

I wonder how this works on Windows where we do not want to strip the slash 
from C:/ either.

-- Hannes

Re: [PATCH] Support working directory located at root

From: Nguyen Thai Ngoc Duy <hidden>
Date: 2016-06-15 22:48:12

2010/2/9 Junio C Hamano [off-list ref]:
Nguyễn Thái Ngọc Duy [off-list ref] writes:
quoted
Git should work regardless where the working directory is located,
even at root. This patch fixes two places where it assumes working
directory always have parent directory.

In setup_git_directory_gently(), when Git goes up to root and finds
.git there, it happily sets worktree to "".
If you mean "instead set it to "/" and things will work much better."
I agree with the reasoning (not suggesting to reword---just trying to
make sure I understood what you meant).
Yes.
quoted
In prefix_path(), loosen the outside repo check a little bit. Usually
when a path XXX is inside worktree /foo, it must be either "/foo", or
"/foo/...". When worktree is simply "/", we can safely ignore the
check: we have a slash at the beginning already.
The logic for the "are we inside?" check above sounds correct.  When
work_tree is at root, have "/" in it, and len inside the "if orig is
absolute" block is 1, so memmove() strips out the leading '/' and makes
the result relative to the root level.  Am I reading the code right?
You are. But I suspect my change in this code is not enough and caused
the problem (on msys?) for Hannes. If the worktree somehow is '//' and
sanitized is '/etc/resolv.conf', then we could end up eating two
chars, leading to "'tc/resolv.conf' not match" error.

Hannes, can you put a "printf("%s\n", work_tree);" in prefix_path() to
see if it's the case?
-- 
Duy

Re: [PATCH] Support working directory located at root

From: Nguyen Thai Ngoc Duy <hidden>
Date: 2016-06-15 22:48:12

2010/2/9 Nguyen Thai Ngoc Duy [off-list ref]:
But I suspect my change in this code is not enough and caused
the problem (on msys?) for Hannes. If the worktree somehow is '//' and
sanitized is '/etc/resolv.conf', then we could end up eating two
chars, leading to "'tc/resolv.conf' not match" error.

Hannes, can you put a "printf("%s\n", work_tree);" in prefix_path() to
see if it's the case?
Silly me. You used relative path, so that code path was untouched.
-- 
Duy
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help