git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] setup: do not change to work tree prematurely

From
Clemens Buchacher <drizzd@aon.at>
Date
May 23, 2010, 00:07 UTC
Message-ID
<20100523000719.GA32380@localhost>

If the work tree is known and a git command is invoked from within a git directory, git_setup_directory() will try to find the relative path from the work tree to the git dir. After doing so it changes directories to the work tree. It fails to update the relative path to the git directory, however.

Instead, do not change the working directory at this point and wait for git_setup_work_tree() to handle this correctly.

This fixes the following bug.

$ cd .git $ git --work-tree=/tmp/git symbolic-ref HEAD fatal: ref HEAD is not a symbolic ref

Reported-by: Frédéric Brière <fbriere@fbriere.net>
Signed-off-by: Clemens Buchacher <drizzd@aon.at>
---

I am not 100% certain that my analysis is correct, since I still do not understand the setup code. But as far as setup_git_directory() is concerned, I think this is the intended behavior.

Clemens
 dir.c   |   33 +++++++++++++++++++--------------
 dir.h   |    1 +
 setup.c |   14 +++++++++-----
 3 files changed, 29 insertions(+), 19 deletions(-)
diff --git a/dir.c b/dir.c
index cb83332..7bf208d 100644
--- a/dir.c
+++ b/dir.c
@@ -926,6 +926,24 @@ int file_exists(const char *f)
 	return lstat(f, &sb) == 0;
 }
 
+char *get_relative_path(char *cwd, const char *dir)
+{
+	if (!dir)
+		return NULL;
+	if (!is_absolute_path(dir))
+		dir = make_absolute_path(dir);
+
+	while (*dir && *dir == *cwd) {
+		dir++;
+		cwd++;
+	}
+	if (*dir)
+		return NULL;
+	if (*cwd == '/')
+		return cwd + 1;
+	return cwd;
+}
+
 /*
  * get_relative_cwd() gets the prefix of the current working directory
  * relative to 'dir'.  If we are not inside 'dir', it returns NULL.
@@ -942,25 +960,12 @@ int file_exists(const char *f)
  */
 char *get_relative_cwd(char *buffer, int size, const char *dir)
 {
-	char *cwd = buffer;
-
 	if (!dir)
 		return NULL;
 	if (!getcwd(buffer, size))
 		die_errno("can't find the current directory");
 
-	if (!is_absolute_path(dir))
-		dir = make_absolute_path(dir);
-
-	while (*dir && *dir == *cwd) {
-		dir++;
-		cwd++;
-	}
-	if (*dir)
-		return NULL;
-	if (*cwd == '/')
-		return cwd + 1;
-	return cwd;
+	return get_relative_path(buffer, dir);
 }
 
 int is_inside_dir(const char *dir)
diff --git a/dir.h b/dir.h
index 3bead5f..3bcda1f 100644
--- a/dir.h
+++ b/dir.h
@@ -79,6 +79,7 @@ extern void add_exclude(const char *string, const char *base,
 			int baselen, struct exclude_list *which);
 extern int file_exists(const char *);
 
+extern char *get_relative_path(char *cwd, const char *dir);
 extern char *get_relative_cwd(char *buffer, int size, const char *dir);
 extern int is_inside_dir(const char *dir);
 
diff --git a/setup.c b/setup.c
index 5716d90..67b5122 100644
--- a/setup.c
+++ b/setup.c
@@ -525,13 +525,17 @@ const char *setup_git_directory(void)
 
 	/* If the work tree is not the default one, recompute prefix */
 	if (inside_work_tree < 0) {
+		const char *work_tree = get_git_work_tree();
 		static char buffer[PATH_MAX + 1];
 		char *rel;
-		if (retval && chdir(retval))
-			die_errno ("Could not jump back into original cwd");
-		rel = get_relative_cwd(buffer, PATH_MAX, get_git_work_tree());
-		if (rel && *rel && chdir(get_git_work_tree()))
-			die_errno ("Could not jump to working directory");
+		if (retval) {
+			if (!is_absolute_path(retval))
+				retval = make_absolute_path(retval);
+			strncpy(buffer, retval, PATH_MAX);
+			buffer[PATH_MAX] = '\0';
+			rel = get_relative_path(buffer, work_tree);
+		} else
+			rel = get_relative_cwd(buffer, PATH_MAX, work_tree);
 		return rel && *rel ? strcat(rel, "/") : NULL;
 	}
 
-- 
1.7.0.5.3.ga76e
Next: Jonathan Nieder
Message 1 of 3 in “setup: do not change to work tree prematurely”
  1. setup: do not change to work tree prematurelyClemens Buchacher, May 23, 2010
  2. Jonathan NiederMay 23, 2010
  3. Clemens BuchacherMay 23, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.