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