setup: handle ODB-related environment variables in odb_new()

When initializing a repository's object database we have to respect the
GIT_OBJECT_DIRECTORY and GIT_ALTERNATE_OBJECT_DIRECTORIES environment
variables, which can be set by the user to override the default location
of where we write objects to and read objects from.

This is handled in `apply_repository_format()`, which is fine. But in a
subsequent commit we'll have to defer constructing the object database
to a later point in some cases, and that will require a second site
where we call `odb_new()`. And of course, that second site would have to
handle those environment variables, as well.

It would be somewhat awkward to duplicate the logic though. But there's
a better alternative: instead of handling this logic in "setup.c", we
can easily handle environment variables in `odb_new()` itself. This
ensures that object database creation is neatly self-contained, and we
don't have to duplicate any of the logic.

Another benefit is that in a future patch series we plan to move
handling of alternates into the backends themselves [1], and that will
require us to also handle those environment variables in the "files"
backend itself. So moving the logic into the ODB level already gets us
one step closer to that goal.

Refactor the logic accordingly.

[1]: https://lore.kernel.org/git/amLgMqkqxR8mKIbT@pks.im/

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Patrick Steinhardt
2026-08-07 05:34:27 +02:00
committed by Junio C Hamano
parent 8a1ba94eb5
commit 30bc6f0e8c
4 changed files with 32 additions and 19 deletions

21
odb.c
View File

@@ -1004,26 +1004,29 @@ int odb_write_object_stream(struct object_database *odb,
}
struct object_database *odb_new(struct repository *repo,
const char *primary_source,
const char *secondary_sources)
enum odb_new_flags flags)
{
struct object_database *o = xmalloc(sizeof(*o));
char *to_free = NULL;
char *primary_source = NULL, *secondary_sources = NULL;
struct object_database *o;
memset(o, 0, sizeof(*o));
CALLOC_ARRAY(o, 1);
o->repo = repo;
pthread_mutex_init(&o->replace_mutex, NULL);
string_list_init_dup(&o->submodule_source_paths);
if (flags & ODB_NEW_HONOR_ENV) {
primary_source = xstrdup_or_null(getenv(DB_ENVIRONMENT));
secondary_sources = xstrdup_or_null(getenv(ALTERNATE_DB_ENVIRONMENT));
}
if (!primary_source)
primary_source = to_free = xstrfmt("%s/objects", repo->commondir);
primary_source = xstrfmt("%s/objects", repo->commondir);
o->sources = odb_source_new(o, primary_source, true);
o->sources_tail = &o->sources->next;
o->alternate_db = xstrdup_or_null(secondary_sources);
o->alternate_db = secondary_sources;
o->inmemory_objects = &odb_source_inmemory_new(o)->base;
free(to_free);
free(primary_source);
return o;
}

17
odb.h
View File

@@ -100,6 +100,20 @@ struct object_database {
struct string_list submodule_source_paths;
};
enum odb_new_flags {
/*
* Honor environment variables when constructing the object database
* sources. This makes us respect the following environment variables:
*
* - GIT_OBJECT_DIRECTORY to override the primary object directory.
*
* - GIT_ALTERNATE_OBJECT_DIRECTORIES to override alternates.
*
* Environment variables may be backend-specific.
*/
ODB_NEW_HONOR_ENV = (1 << 0),
};
/*
* Create a new object database for the given repository.
*
@@ -112,8 +126,7 @@ struct object_database {
* Returns the newly created object database.
*/
struct object_database *odb_new(struct repository *repo,
const char *primary_source,
const char *alternate_sources);
enum odb_new_flags flags);
/* Free the object database and release all resources. */
void odb_free(struct object_database *o);

11
setup.c
View File

@@ -1765,7 +1765,7 @@ int apply_repository_format(struct repository *repo,
enum apply_repository_format_flags flags,
struct strbuf *err)
{
char *object_directory = NULL, *alternate_object_directories = NULL;
enum odb_new_flags odb_new_flags = 0;
if (verify_repository_format(format, err) < 0)
return -1;
@@ -1779,8 +1779,6 @@ int apply_repository_format(struct repository *repo,
if (flags & APPLY_REPOSITORY_FORMAT_HONOR_ENV) {
const char *shallow_file;
object_directory = xstrdup_or_null(getenv(DB_ENVIRONMENT));
alternate_object_directories = xstrdup_or_null(getenv(ALTERNATE_DB_ENVIRONMENT));
shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);
if (shallow_file)
set_alternate_shallow_file(repo, shallow_file);
@@ -1803,11 +1801,10 @@ int apply_repository_format(struct repository *repo,
repo->repository_format_precious_objects =
format->precious_objects;
repo->objects = odb_new(repo, object_directory,
alternate_object_directories);
if (flags & APPLY_REPOSITORY_FORMAT_HONOR_ENV)
odb_new_flags |= ODB_NEW_HONOR_ENV;
repo->objects = odb_new(repo, odb_new_flags);
free(alternate_object_directories);
free(object_directory);
return 0;
}

View File

@@ -38,7 +38,7 @@ static void cl_assert_object_info(struct odb_source_inmemory *source,
void test_odb_inmemory__initialize(void)
{
odb = odb_new(&repo, "", "");
odb = odb_new(&repo, 0);
}
void test_odb_inmemory__cleanup(void)