Subject: [PATCH] Report errors related to .git access during repository discovery

From: Nguyễn Thái Ngọc Duy <[email-masked]>
Date: Wed, 5 Oct 2011 19:17:31 +1100

If $GIT_DIR is not given, we go up step by step and look for potential
repository directory, may see .git directory but for some reasons we
decide to skip and move on.

It's probably better to report along the line, so users can stop
wondering "hey, but I have .git directory _there_".

Signed-off-by: Nguyễn Thái Ngọc Duy <[email-masked]>
---
 On Wed, Oct 5, 2011 at 5:11 PM, Johannes Sixt <[email-masked]> wrote:
 > Am 10/4/2011 23:24, schrieb Federico Lucifredi:
 >> Hello Git list,
 >>  Found a minor bug in git today - the error message reported is not
 >> correct when trying to access a repo that is not accessible
 >> permission-wise:
 >>
 >>> federico@skyplex:/etc$ git log
 >>> fatal: Not a git repository (or any of the parent directories): .git
 >>
 >> with correct access permissions, everything works as expected.
 >
 > And the correct error message is...?

 That's a correct message. But it'd be even better if we help diagnose
 why. Even when you have proper access to .git dir, git can still
 refuse to accept the directory as a repository, because "HEAD" is
 invalid for example.

 I think a patch like this is an improvement. There may be many
 situations git refuses a directory but I don't cover here. Well, we
 may when users report them

 setup.c |   23 +++++++++++++++++++----
 1 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/setup.c b/setup.c
index 27c1d47..b6028e5 100644
--- a/setup.c
+++ b/setup.c
@@ -269,6 +269,19 @@ const char *pathspec_prefix(const char *prefix, const char **pathspec)
 }
 
 /*
+ * This function is used during .git detection phase. If .git does not
+ * exist, it's OK not to report because that happens a lot if you stay
+ * inside a subdirectory and git checks every level back to topdir.
+ */
+static int access_and_warn(const char *path, int perm)
+{
+	int ret = access(path, perm);
+	if (ret && errno != ENOENT)
+		error("%s: %s", absolute_path(path), strerror(errno));
+	return ret;
+}
+
+/*
  * Test if it looks like we're at a git directory.
  * We want to see:
  *
@@ -288,22 +301,24 @@ static int is_git_directory(const char *suspect)
 		die("Too long path: %.*s", 60, suspect);
 	strcpy(path, suspect);
 	if (getenv(DB_ENVIRONMENT)) {
-		if (access(getenv(DB_ENVIRONMENT), X_OK))
+		if (access_and_warn(getenv(DB_ENVIRONMENT), X_OK))
 			return 0;
 	}
 	else {
 		strcpy(path + len, "/objects");
-		if (access(path, X_OK))
+		if (access_and_warn(path, X_OK))
 			return 0;
 	}
 
 	strcpy(path + len, "/refs");
-	if (access(path, X_OK))
+	if (access_and_warn(path, X_OK))
 		return 0;
 
 	strcpy(path + len, "/HEAD");
-	if (validate_headref(path))
+	if (validate_headref(path)) {
+		error("invalid HEAD at %s", absolute_path(path));
 		return 0;
+	}
 
 	return 1;
 }
-- 
1.7.3.1.256.g2539c.dirty