From: Johannes Schindelin Date: Mon, 13 Mar 2017 20:10:45 +0000 (+0100) Subject: setup: introduce the discover_git_directory() function X-Git-Tag: v2.13.0-rc0~100^2~7 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/16ac8b8db6ec7400719db6b5c76edaab33c47606 setup: introduce the discover_git_directory() function We modified the setup_git_directory_gently_1() function earlier to make it possible to discover the GIT_DIR without changing global state. However, it is still 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 fix the early config. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- diff --git a/cache.h b/cache.h index 61fc86e6d7..3cba58e219 100644 --- a/cache.h +++ b/cache.h @@ -518,6 +518,13 @@ 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 of the repository that contains the current working directory, + * without changing the working directory or other global state. The result is + * appended to gitdir. The return value is either NULL if no repository was + * found, or pointing to the path inside gitdir's buffer. + */ +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 27a31de33f..d08730d94d 100644 --- a/setup.c +++ b/setup.c @@ -924,6 +924,49 @@ 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, err = STRBUF_INIT; + size_t gitdir_offset = gitdir->len, cwd_len; + struct repository_format candidate; + + 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_reset(&dir); + strbuf_addf(&dir, "%s/config", gitdir->buf + gitdir_offset); + read_repository_format(&candidate, dir.buf); + strbuf_release(&dir); + + if (verify_repository_format(&candidate, &err) < 0) { + warning("ignoring git dir '%s': %s", + gitdir->buf + gitdir_offset, err.buf); + strbuf_release(&err); + return NULL; + } + + return gitdir->buf + gitdir_offset; +} + const char *setup_git_directory_gently(int *nongit_ok) { static struct strbuf cwd = STRBUF_INIT;