The setup_git_directory_gently_1() function we modified earlier still
needs to return both the path to the .git/ directory as well as the
"cd-up" path to allow setup_git_directory() to retain its previous
behavior as if it changed the current working directory on its quest for
the .git/ directory.

This is a bit cumbersome to use if you only need to figure out the
(possibly absolute) path of the .git/ directory. Let's just provide
a convenient wrapper function with an easier signature that *just*
discovers the .git/ directory.

We will use it in a subsequent patch to support early config reading
better.

Signed-off-by: Johannes Schindelin <johannes.schinde...@gmx.de>
---
 cache.h |  2 ++
 setup.c | 31 +++++++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)

diff --git a/cache.h b/cache.h
index 80b6372cf76..4d8eb38de74 100644
--- a/cache.h
+++ b/cache.h
@@ -518,6 +518,8 @@ extern void set_git_work_tree(const char *tree);
 #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
 
 extern void setup_work_tree(void);
+/* Find GIT_DIR without changing the working directory or other global state */
+extern const char *discover_git_directory(struct strbuf *gitdir);
 extern const char *setup_git_directory_gently(int *);
 extern const char *setup_git_directory(void);
 extern char *prefix_path(const char *prefix, int len, const char *path);
diff --git a/setup.c b/setup.c
index 9a09bb41ab5..32ce023638a 100644
--- a/setup.c
+++ b/setup.c
@@ -923,6 +923,37 @@ static enum discovery_result 
setup_git_directory_gently_1(struct strbuf *dir,
        }
 }
 
+const char *discover_git_directory(struct strbuf *gitdir)
+{
+       struct strbuf dir = STRBUF_INIT;
+       size_t gitdir_offset = gitdir->len, cwd_len;
+
+       if (strbuf_getcwd(&dir))
+               return NULL;
+
+       cwd_len = dir.len;
+       if (setup_git_directory_gently_1(&dir, gitdir) < 0) {
+               strbuf_release(&dir);
+               return NULL;
+       }
+
+       /*
+        * The returned gitdir is relative to dir, and if dir does not reflect
+        * the current working directory, we simply make the gitdir absolute.
+        */
+       if (dir.len < cwd_len && !is_absolute_path(gitdir->buf + 
gitdir_offset)) {
+               /* Avoid a trailing "/." */
+               if (!strcmp(".", gitdir->buf + gitdir_offset))
+                       strbuf_setlen(gitdir, gitdir_offset);
+               else
+                       strbuf_addch(&dir, '/');
+               strbuf_insert(gitdir, gitdir_offset, dir.buf, dir.len);
+       }
+       strbuf_release(&dir);
+
+       return gitdir->buf;
+}
+
 const char *setup_git_directory_gently(int *nongit_ok)
 {
        struct strbuf cwd = STRBUF_INIT, dir = STRBUF_INIT, gitdir = 
STRBUF_INIT;
-- 
2.12.0.windows.1.7.g94dafc3b124


Reply via email to