setup: teach discover_git_directory to respect the commondir

Currently 'discover_git_directory' only looks at the gitdir to determine if a git directory was discovered. This causes a problem in the event that the gitdir which was discovered was in fact a per-worktree git directory and not the common git directory. This is because the repository config, which is checked to verify the repository's format, is stored in the commondir and not in the per-worktree gitdir. Correct this behavior by checking the config stored in the commondir. It will also be of use for callers to have access to the commondir, so lets also return that upon successfully discovering a git directory. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Brandon Williams committed Jun 14, 2017 at 11:07 UTC d3fb71b3cb36971608a46744261e6b5f8802e784
3 files changed +26 -16
cache.h
+9 -6
@@ -525,12 +525,15 @@ extern void set_git_work_tree(const char *tree);
525
526 extern void setup_work_tree(void);
527 /*
528 - * Find GIT_DIR of the repository that contains the current working directory,
529 - * without changing the working directory or other global state. The result is
530 - * appended to gitdir. The return value is either NULL if no repository was
531 - * found, or pointing to the path inside gitdir's buffer.
532 - */
533 -extern const char *discover_git_directory(struct strbuf *gitdir);
528 + * Find the commondir and gitdir of the repository that contains the current
529 + * working directory, without changing the working directory or other global
530 + * state. The result is appended to commondir and gitdir. If the discovered
531 + * gitdir does not correspond to a worktree, then 'commondir' and 'gitdir' will
532 + * both have the same result appended to the buffer. The return value is
533 + * either 0 upon success and non-zero if no repository was found.
534 + */
535 +extern int discover_git_directory(struct strbuf *commondir,
536 + struct strbuf *gitdir);
537 extern const char *setup_git_directory_gently(int *);
538 extern const char *setup_git_directory(void);
539 extern char *prefix_path(const char *prefix, int len, const char *path);
config.c
+6 -4
@@ -1639,7 +1639,8 @@ static void configset_iter(struct config_set *cs, config_fn_t fn, void *data)
1639 void read_early_config(config_fn_t cb, void *data)
1640 {
1641 struct config_options opts = {0};
1642 - struct strbuf buf = STRBUF_INIT;
1642 + struct strbuf commondir = STRBUF_INIT;
1643 + struct strbuf gitdir = STRBUF_INIT;
1644
1645 opts.respect_includes = 1;
1646
@@ -1653,12 +1654,13 @@ void read_early_config(config_fn_t cb, void *data)
1654 * notably, the current working directory is still the same after the
1655 * call).
1656 */
1656 - else if (discover_git_directory(&buf))
1657 - opts.git_dir = buf.buf;
1657 + else if (!discover_git_directory(&commondir, &gitdir))
1658 + opts.git_dir = gitdir.buf;
1659
1660 git_config_with_options(cb, data, NULL, &opts);
1661
1661 - strbuf_release(&buf);
1662 + strbuf_release(&commondir);
1663 + strbuf_release(&gitdir);
1664 }
1665
1666 static void git_config_check_init(void);
setup.c
+11 -6
@@ -941,19 +941,21 @@ static enum discovery_result setup_git_directory_gently_1(struct strbuf *dir,
941 }
942 }
943
944 -const char *discover_git_directory(struct strbuf *gitdir)
944 +int discover_git_directory(struct strbuf *commondir,
945 + struct strbuf *gitdir)
946 {
947 struct strbuf dir = STRBUF_INIT, err = STRBUF_INIT;
948 size_t gitdir_offset = gitdir->len, cwd_len;
949 + size_t commondir_offset = commondir->len;
950 struct repository_format candidate;
951
952 if (strbuf_getcwd(&dir))
951 - return NULL;
953 + return -1;
954
955 cwd_len = dir.len;
956 if (setup_git_directory_gently_1(&dir, gitdir, 0) <= 0) {
957 strbuf_release(&dir);
956 - return NULL;
958 + return -1;
959 }
960
961 /*
@@ -969,8 +971,10 @@ const char *discover_git_directory(struct strbuf *gitdir)
971 strbuf_insert(gitdir, gitdir_offset, dir.buf, dir.len);
972 }
973
974 + get_common_dir(commondir, gitdir->buf + gitdir_offset);
975 +
976 strbuf_reset(&dir);
973 - strbuf_addf(&dir, "%s/config", gitdir->buf + gitdir_offset);
977 + strbuf_addf(&dir, "%s/config", commondir->buf + commondir_offset);
978 read_repository_format(&candidate, dir.buf);
979 strbuf_release(&dir);
980
@@ -978,11 +982,12 @@ const char *discover_git_directory(struct strbuf *gitdir)
982 warning("ignoring git dir '%s': %s",
983 gitdir->buf + gitdir_offset, err.buf);
984 strbuf_release(&err);
985 + strbuf_setlen(commondir, commondir_offset);
986 strbuf_setlen(gitdir, gitdir_offset);
982 - return NULL;
987 + return -1;
988 }
989
985 - return gitdir->buf + gitdir_offset;
990 + return 0;
991 }
992
993 const char *setup_git_directory_gently(int *nongit_ok)