refs: pass repo when retrieving submodule ref store

Looking up submodule ref stores has two deficiencies: - The initialized subrepo will be attributed to `the_repository`. - The submodule ref store will be tracked in a global map. This makes it impossible to have submodule ref stores for a repository other than `the_repository`. Modify the function to accept the parent repository as parameter and move the global map into `struct repository`. Like this it becomes possible to look up submodule ref stores for arbitrary repositories. Note that this also adds a new reference to `the_repository` in `resolve_gitlink_ref()`, which is part of the refs interfaces. This will get adjusted in the next patch. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed May 17, 2024 at 10:18 UTC 965f8991e59d84ba1b86e528f9c27852e746fa90
8 files changed +33 -21
builtin/submodule--helper.c
+4 -2
@@ -679,7 +679,8 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,
679 displaypath);
680 } else if (!(flags & OPT_CACHED)) {
681 struct object_id oid;
682 - struct ref_store *refs = get_submodule_ref_store(path);
682 + struct ref_store *refs = repo_get_submodule_ref_store(the_repository,
683 + path);
684
685 if (!refs) {
686 print_status(flags, '-', path, ce_oid, displaypath);
@@ -903,7 +904,8 @@ static void generate_submodule_summary(struct summary_cb *info,
904
905 if (!info->cached && oideq(&p->oid_dst, null_oid())) {
906 if (S_ISGITLINK(p->mod_dst)) {
906 - struct ref_store *refs = get_submodule_ref_store(p->sm_path);
907 + struct ref_store *refs = repo_get_submodule_ref_store(the_repository,
908 + p->sm_path);
909
910 if (refs)
911 refs_head_ref(refs, handle_submodule_head_ref, &p->oid_dst);
refs.c
+7 -15
@@ -1949,8 +1949,7 @@ int resolve_gitlink_ref(const char *submodule, const char *refname,
1949 struct ref_store *refs;
1950 int flags;
1951
1952 - refs = get_submodule_ref_store(submodule);
1953 -
1952 + refs = repo_get_submodule_ref_store(the_repository, submodule);
1953 if (!refs)
1954 return -1;
1955
@@ -1960,9 +1959,6 @@ int resolve_gitlink_ref(const char *submodule, const char *refname,
1959 return 0;
1960 }
1961
1963 -/* A strmap of ref_stores, stored by submodule name: */
1964 -static struct strmap submodule_ref_stores;
1965 -
1962 /* A strmap of ref_stores, stored by worktree id: */
1963 static struct strmap worktree_ref_stores;
1964
@@ -2036,7 +2032,8 @@ static void register_ref_store_map(struct strmap *map,
2032 BUG("%s ref_store '%s' initialized twice", type, name);
2033 }
2034
2039 -struct ref_store *get_submodule_ref_store(const char *submodule)
2035 +struct ref_store *repo_get_submodule_ref_store(struct repository *repo,
2036 + const char *submodule)
2037 {
2038 struct strbuf submodule_sb = STRBUF_INIT;
2039 struct ref_store *refs;
@@ -2057,7 +2054,7 @@ struct ref_store *get_submodule_ref_store(const char *submodule)
2054 /* We need to strip off one or more trailing slashes */
2055 submodule = to_free = xmemdupz(submodule, len);
2056
2060 - refs = lookup_ref_store_map(&submodule_ref_stores, submodule);
2057 + refs = lookup_ref_store_map(&repo->submodule_ref_stores, submodule);
2058 if (refs)
2059 goto done;
2060
@@ -2069,20 +2066,15 @@ struct ref_store *get_submodule_ref_store(const char *submodule)
2066 goto done;
2067
2068 subrepo = xmalloc(sizeof(*subrepo));
2072 - /*
2073 - * NEEDSWORK: Make get_submodule_ref_store() work with arbitrary
2074 - * superprojects other than the_repository. This probably should be
2075 - * done by making it take a struct repository * parameter instead of a
2076 - * submodule path.
2077 - */
2078 - if (repo_submodule_init(subrepo, the_repository, submodule,
2069 +
2070 + if (repo_submodule_init(subrepo, repo, submodule,
2071 null_oid())) {
2072 free(subrepo);
2073 goto done;
2074 }
2075 refs = ref_store_init(subrepo, submodule_sb.buf,
2076 REF_STORE_READ | REF_STORE_ODB);
2085 - register_ref_store_map(&submodule_ref_stores, "submodule",
2077 + register_ref_store_map(&repo->submodule_ref_stores, "submodule",
2078 refs, submodule);
2079
2080 done:
refs.h
+2 -1
@@ -954,7 +954,8 @@ struct ref_store *get_main_ref_store(struct repository *r);
954 * For backwards compatibility, submodule=="" is treated the same as
955 * submodule==NULL.
956 */
957 -struct ref_store *get_submodule_ref_store(const char *submodule);
957 +struct ref_store *repo_get_submodule_ref_store(struct repository *repo,
958 + const char *submodule);
959 struct ref_store *get_worktree_ref_store(const struct worktree *wt);
960
961 /*
refs/refs-internal.h
+1 -1
@@ -705,7 +705,7 @@ extern struct ref_storage_be refs_be_packed;
705 /*
706 * A representation of the reference store for the main repository or
707 * a submodule. The ref_store instances for submodules are kept in a
708 - * hash map; see get_submodule_ref_store() for more info.
708 + * hash map; see repo_get_submodule_ref_store() for more info.
709 */
710 struct ref_store {
711 /* The backend describing this ref_store's storage scheme: */
repository.c
+8
@@ -14,6 +14,7 @@
14 #include "sparse-index.h"
15 #include "trace2.h"
16 #include "promisor-remote.h"
17 +#include "refs.h"
18
19 /* The main repository */
20 static struct repository the_repo;
@@ -289,6 +290,9 @@ static void repo_clear_path_cache(struct repo_path_cache *cache)
290
291 void repo_clear(struct repository *repo)
292 {
293 + struct hashmap_iter iter;
294 + struct strmap_entry *e;
295 +
296 FREE_AND_NULL(repo->gitdir);
297 FREE_AND_NULL(repo->commondir);
298 FREE_AND_NULL(repo->graft_file);
@@ -329,6 +333,10 @@ void repo_clear(struct repository *repo)
333 FREE_AND_NULL(repo->remote_state);
334 }
335
336 + strmap_for_each_entry(&repo->submodule_ref_stores, &iter, e)
337 + ref_store_release(e->value);
338 + strmap_clear(&repo->submodule_ref_stores, 1);
339 +
340 repo_clear_path_cache(&repo->cached_paths);
341 }
342
repository.h
+8
@@ -1,6 +1,8 @@
1 #ifndef REPOSITORY_H
2 #define REPOSITORY_H
3
4 +#include "strmap.h"
5 +
6 struct config_set;
7 struct fsmonitor_settings;
8 struct git_hash_algo;
@@ -108,6 +110,12 @@ struct repository {
110 */
111 struct ref_store *refs_private;
112
113 + /*
114 + * A strmap of ref_stores, stored by submodule name, accessible via
115 + * `repo_get_submodule_ref_store()`.
116 + */
117 + struct strmap submodule_ref_stores;
118 +
119 /*
120 * Contains path to often used file names.
121 */
submodule.c
+2 -1
@@ -99,7 +99,8 @@ int is_staging_gitmodules_ok(struct index_state *istate)
99 static int for_each_remote_ref_submodule(const char *submodule,
100 each_ref_fn fn, void *cb_data)
101 {
102 - return refs_for_each_remote_ref(get_submodule_ref_store(submodule),
102 + return refs_for_each_remote_ref(repo_get_submodule_ref_store(the_repository,
103 + submodule),
104 fn, cb_data);
105 }
106
t/helper/test-ref-store.c
+1 -1
@@ -82,7 +82,7 @@ static const char **get_store(const char **argv, struct ref_store **refs)
82 add_to_alternates_memory(sb.buf);
83 strbuf_release(&sb);
84
85 - *refs = get_submodule_ref_store(gitdir);
85 + *refs = repo_get_submodule_ref_store(the_repository, gitdir);
86 } else if (skip_prefix(argv[0], "worktree:", &gitdir)) {
87 struct worktree **p, **worktrees = get_worktrees();
88