odb: handle initialization of sources in `odb_new()`

The logic to set up a new object database is currently distributed across two functions in "repository.c": - In `initialize_repository()` we initialize an empty object database. This object database is not fully initialized and doesn't have any sources attached to it. - The primary object database source is then created in `repo_set_gitdir()`. Ideally though, the logic should be entirely self-contained so that we can iterate more readily on how exactly the sources themselves get set up. Refactor `odb_new()` to handle both allocation and setup of the object database. This ensures that the object database is always initialized and ready for use, and it allows us to change how the sources get set up eventually. Note that `repo_set_gitdir()` still reaches into the sources when the function gets called with an already-initialized object database. This will be fixed in the next commit. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Nov 19, 2025 at 08:50 UTC 35d9fc65edc0a5df9f714d02afaa2c942fb28570
3 files changed +35 -14
odb.c
+13 -1
@@ -1034,15 +1034,27 @@ int odb_write_object_stream(struct object_database *odb,
1034 return odb_source_loose_write_stream(odb->sources, stream, len, oid);
1035 }
1036
1037 -struct object_database *odb_new(struct repository *repo)
1037 +struct object_database *odb_new(struct repository *repo,
1038 + const char *primary_source,
1039 + const char *secondary_sources)
1040 {
1041 struct object_database *o = xmalloc(sizeof(*o));
1042 + char *to_free = NULL;
1043
1044 memset(o, 0, sizeof(*o));
1045 o->repo = repo;
1046 o->packfiles = packfile_store_new(o);
1047 pthread_mutex_init(&o->replace_mutex, NULL);
1048 string_list_init_dup(&o->submodule_source_paths);
1049 +
1050 + if (!primary_source)
1051 + primary_source = to_free = xstrfmt("%s/objects", repo->commondir);
1052 + o->sources = odb_source_new(o, primary_source, true);
1053 + o->sources_tail = &o->sources->next;
1054 + o->alternate_db = xstrdup_or_null(secondary_sources);
1055 +
1056 + free(to_free);
1057 +
1058 return o;
1059 }
1060
odb.h
+14 -1
@@ -159,7 +159,20 @@ struct object_database {
159 struct string_list submodule_source_paths;
160 };
161
162 -struct object_database *odb_new(struct repository *repo);
162 +/*
163 + * Create a new object database for the given repository.
164 + *
165 + * If the primary source parameter is set it will override the usual primary
166 + * object directory derived from the repository's common directory. The
167 + * alternate sources are expected to be a PATH_SEP-separated list of secondary
168 + * sources. Note that these alternate sources will be added in addition to, not
169 + * instead of, the alternates identified by the primary source.
170 + *
171 + * Returns the newly created object database.
172 + */
173 +struct object_database *odb_new(struct repository *repo,
174 + const char *primary_source,
175 + const char *alternate_sources);
176
177 /* Free the object database and release all resources. */
178 void odb_free(struct object_database *o);
repository.c
+8 -12
@@ -52,7 +52,6 @@ static void set_default_hash_algo(struct repository *repo)
52
53 void initialize_repository(struct repository *repo)
54 {
55 - repo->objects = odb_new(repo);
55 repo->remote_state = remote_state_new();
56 repo->parsed_objects = parsed_object_pool_new(repo);
57 ALLOC_ARRAY(repo->index, 1);
@@ -160,29 +159,26 @@ void repo_set_gitdir(struct repository *repo,
159 * until after xstrdup(root). Then we can free it.
160 */
161 char *old_gitdir = repo->gitdir;
163 - char *objects_path = NULL;
162
163 repo->gitdir = xstrdup(gitfile ? gitfile : root);
164 free(old_gitdir);
165
166 repo_set_commondir(repo, o->commondir);
169 - expand_base_dir(&objects_path, o->object_dir,
170 - repo->commondir, "objects");
171 -
172 - if (!repo->objects->sources) {
173 - repo->objects->sources = odb_source_new(repo->objects,
174 - objects_path, true);
175 - repo->objects->sources_tail = &repo->objects->sources->next;
176 - free(objects_path);
167 +
168 + if (!repo->objects) {
169 + repo->objects = odb_new(repo, o->object_dir, o->alternate_db);
170 } else {
171 + char *objects_path = NULL;
172 + expand_base_dir(&objects_path, o->object_dir,
173 + repo->commondir, "objects");
174 free(repo->objects->sources->path);
175 repo->objects->sources->path = objects_path;
176 + free(repo->objects->alternate_db);
177 + repo->objects->alternate_db = xstrdup_or_null(o->alternate_db);
178 }
179
180 repo->disable_ref_updates = o->disable_ref_updates;
181
184 - free(repo->objects->alternate_db);
185 - repo->objects->alternate_db = xstrdup_or_null(o->alternate_db);
182 expand_base_dir(&repo->graft_file, o->graft_file,
183 repo->commondir, "info/grafts");
184 expand_base_dir(&repo->index_file, o->index_file,