Thread (20 messages) 20 messages, 3 authors, 6d ago

Re: [RFC PATCH v2 3/4] setup: introduce new helper 'is_git_directory_verbose'

flat view

From: Patrick Steinhardt <hidden>
Date: 2026-09-30 16:03:13

On Tue, Sep 29, 2026 at 03:55:09PM +0530, Kaartic Sivaraam wrote:
quoted hunk ↗ jump to hunk
diff --git a/setup.c b/setup.c
index e9a9ecda19..a0fb68f7f6 100644
--- a/setup.c
+++ b/setup.c
@@ -347,7 +347,7 @@ int get_common_dir_noenv(struct strbuf *sb, const char *gitdir)
 	return ret;
 }
 
-static int validate_headref(const char *path)
+static int validate_headref(const char *path, struct strbuf *err)
 {
 	struct stat st;
 	char buffer[256];
If only we had structured errors.
quoted hunk ↗ jump to hunk
@@ -356,14 +356,23 @@ static int validate_headref(const char *path)
 	int fd;
 	ssize_t len;
 
-	if (lstat(path, &st) < 0)
+	if (lstat(path, &st) < 0) {
+		if (err)
+			strbuf_addf(err, _("could not stat HEAD at '%s'"), path);
Shouldn't this also include `strerror(errno)`? Otherwise you're still
not that much wiser what the root cause of this is.
quoted hunk ↗ jump to hunk
 		return -1;
+	}
 
 	/* Make sure it is a "refs/.." symlink */
 	if (S_ISLNK(st.st_mode)) {
 		len = readlink(path, buffer, sizeof(buffer)-1);
 		if (len >= 5 && !memcmp("refs/", buffer, 5))
 			return 0;
+		if (len == -1 && err)
+			strbuf_addf(err, _("could not read the symlink HEAD at '%s'"),
+				    path);
Same here, we should include `errno`. Other sites should probably be
updated, too.
quoted hunk ↗ jump to hunk
@@ -396,9 +411,71 @@ static int validate_headref(const char *path)
 	if (get_oid_hex_any(buffer, &oid) != GIT_HASH_UNKNOWN)
 		return 0;
 
+	if (err)
+		strbuf_addf(err, _("HEAD at '%s' does not point to a valid symbolic"
+				   " link or an object ID"), path);
+
 	return -1;
 }
 
+/*
+ * A variant of is_git_directory that gives additional
+ * context via 'err' about why a given suspect is not
+ * a valid git repository.
+ */
+static int is_git_directory_verbose(const char *suspect, struct strbuf *err)
+{
+	struct strbuf path = STRBUF_INIT;
+	char *objdir;
+	int ret = 0;
+	size_t len;
+
+	/* Check worktree-related signatures */
+	strbuf_addstr(&path, suspect);
+	strbuf_complete(&path, '/');
+	strbuf_addstr(&path, "HEAD");
+	if (validate_headref(path.buf, err))
+		goto done;
+
+	strbuf_reset(&path);
+	get_common_dir(&path, suspect);
+	len = path.len;
+
+	/* Check non-worktree-related signatures */
+	objdir = getenv(DB_ENVIRONMENT);
+	if (objdir) {
+		if (access(objdir, X_OK)) {
+			if (err)
+				strbuf_addf(err, _("cannot access object directory '%s'"
+						   " set via $%s\n"), objdir, DB_ENVIRONMENT);
+			goto done;
+		}
+	} else {
+		strbuf_setlen(&path, len);
+		strbuf_addstr(&path, "/objects");
+		if (access(path.buf, X_OK)) {
+			if (err)
+				strbuf_addf(err, _("cannot access object directory '%s'"),
+					    path.buf);
+			goto done;
+		}
+	}
+
+	strbuf_setlen(&path, len);
+	strbuf_addstr(&path, "/refs");
+	if (access(path.buf, X_OK)) {
+		if (err)
+			strbuf_addf(err, _("cannot access refs directory '%s'"), path.buf);
+		goto done;
+	}
+
+	ret = 1;
+done:
+	strbuf_release(&path);
+	return ret;
+
+}
+
 /*
  * Test if it looks like we're at a git directory.
  * We want to see:
It would've been helpful to move the function up in a separate commit.
Like this it's hard to see what exactly has changed.

Patrick
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help