diff --git a/cache.h b/cache.h index 752031e84a..274137ae16 100644 --- a/cache.h +++ b/cache.h @@ -443,6 +443,7 @@ extern char *get_object_directory(void); extern char *get_index_file(void); extern char *get_graft_file(void); extern int set_git_dir(const char *path); +extern int get_common_dir_noenv(struct strbuf *sb, const char *gitdir); extern int get_common_dir(struct strbuf *sb, const char *gitdir); extern const char *get_git_namespace(void); extern const char *strip_namespace(const char *namespaced_ref); diff --git a/path.c b/path.c index 65beb2dca3..5ec34905a3 100644 --- a/path.c +++ b/path.c @@ -335,12 +335,15 @@ static int check_common(const char *unmatched, void *value, void *baton) return 0; } -static void update_common_dir(struct strbuf *buf, int git_dir_len) +static void update_common_dir(struct strbuf *buf, int git_dir_len, + const char *common_dir) { char *base = buf->buf + git_dir_len; init_common_trie(); + if (!common_dir) + common_dir = get_git_common_dir(); if (trie_find(&common_trie, base, check_common, NULL) > 0) - replace_dir(buf, git_dir_len, get_git_common_dir()); + replace_dir(buf, git_dir_len, common_dir); } void report_linked_checkout_garbage(void) @@ -377,7 +380,7 @@ static void adjust_git_path(struct strbuf *buf, int git_dir_len) else if (git_db_env && dir_prefix(base, "objects")) replace_dir(buf, git_dir_len + 7, get_object_directory()); else if (git_common_dir_env) - update_common_dir(buf, git_dir_len); + update_common_dir(buf, git_dir_len, NULL); } static void do_git_path(struct strbuf *buf, const char *fmt, va_list args) @@ -445,6 +448,8 @@ static void do_submodule_path(struct strbuf *buf, const char *path, const char *fmt, va_list args) { const char *git_dir; + struct strbuf git_submodule_common_dir = STRBUF_INIT; + struct strbuf git_submodule_dir = STRBUF_INIT; strbuf_addstr(buf, path); if (buf->len && buf->buf[buf->len - 1] != '/') @@ -457,9 +462,17 @@ static void do_submodule_path(struct strbuf *buf, const char *path, strbuf_addstr(buf, git_dir); } strbuf_addch(buf, '/'); + strbuf_addstr(&git_submodule_dir, buf->buf); strbuf_vaddf(buf, fmt, args); + + if (get_common_dir_noenv(&git_submodule_common_dir, git_submodule_dir.buf)) + update_common_dir(buf, git_submodule_dir.len, git_submodule_common_dir.buf); + strbuf_cleanup_path(buf); + + strbuf_release(&git_submodule_dir); + strbuf_release(&git_submodule_common_dir); } char *git_pathdup_submodule(const char *path, const char *fmt, ...) @@ -648,7 +661,7 @@ const char *enter_repo(const char *path, int strict) } if (!suffix[i]) return NULL; - gitfile = read_gitfile(used_path) ; + gitfile = read_gitfile(used_path); if (gitfile) strcpy(used_path, gitfile); if (chdir(used_path)) diff --git a/setup.c b/setup.c index a17c51e61d..e41e5e1a82 100644 --- a/setup.c +++ b/setup.c @@ -228,15 +228,22 @@ void verify_non_filename(const char *prefix, const char *arg) } int get_common_dir(struct strbuf *sb, const char *gitdir) +{ + const char *git_env_common_dir = getenv(GIT_COMMON_DIR_ENVIRONMENT); + if (git_env_common_dir) { + strbuf_addstr(sb, git_env_common_dir); + return 1; + } else { + return get_common_dir_noenv(sb, gitdir); + } +} + +int get_common_dir_noenv(struct strbuf *sb, const char *gitdir) { struct strbuf data = STRBUF_INIT; struct strbuf path = STRBUF_INIT; - const char *git_common_dir = getenv(GIT_COMMON_DIR_ENVIRONMENT); int ret = 0; - if (git_common_dir) { - strbuf_addstr(sb, git_common_dir); - return 1; - } + strbuf_addf(&path, "%s/commondir", gitdir); if (file_exists(path.buf)) { if (strbuf_read_file(&data, path.buf, 0) <= 0) diff --git a/submodule.c b/submodule.c index 245ed4dfbb..5e5a46fe2a 100644 --- a/submodule.c +++ b/submodule.c @@ -122,15 +122,8 @@ static int add_submodule_odb(const char *path) struct strbuf objects_directory = STRBUF_INIT; struct alternate_object_database *alt_odb; int ret = 0; - const char *git_dir; - strbuf_addf(&objects_directory, "%s/.git", path); - git_dir = read_gitfile(objects_directory.buf); - if (git_dir) { - strbuf_reset(&objects_directory); - strbuf_addstr(&objects_directory, git_dir); - } - strbuf_addstr(&objects_directory, "/objects/"); + strbuf_git_path_submodule(&objects_directory, path, "objects/"); if (!is_directory(objects_directory.buf)) { ret = -1; goto done; diff --git a/t/t7410-submodule-checkout-to.sh b/t/t7410-submodule-checkout-to.sh index 3f609e8909..1acef32647 100755 --- a/t/t7410-submodule-checkout-to.sh +++ b/t/t7410-submodule-checkout-to.sh @@ -47,4 +47,14 @@ test_expect_success 'checkout main and initialize independed clones' \ test_expect_success 'can see submodule diffs after independed cloning' \ '(cd fully_cloned_submodule/main && git diff --submodule master"^!" | grep "file1 updated")' +test_expect_success 'checkout sub manually' \ + 'mkdir linked_submodule && + (cd clone/main && + git worktree add "$base_path/linked_submodule/main" "$rev1_hash_main") && + (cd clone/main/sub && + git worktree add "$base_path/linked_submodule/main/sub" "$rev1_hash_sub")' + +test_expect_success 'can see submodule diffs after manual checkout of linked submodule' \ + '(cd linked_submodule/main && git diff --submodule master"^!" | grep "file1 updated")' + test_done