[PATCH v4 0/6] odb: make creation of object database pluggable
Patrick Steinhardt <[email protected]> Thu, 06 Aug 2026 09:50:58 +0200
| Newsgroups | org.kernel.vger.git |
|---|---|
| Message-ID | <[email protected]> |
Hi,
when creating a new repository we create a couple of on-disk data
structures for the object database. This includes the "objects/"
directory hierarchy with "objects/info" and "objects/pack", which are
specific to the backend.
This patch series makes the creation of the on-disk data structures
pluggable. While we continue to always create "objects/" regardless of
the backend (it's required for a repository to be recognized as such),
the other subdirectories are now created by the backend. This will allow
other backends to plug in their own logic.
The series starts with a small detour into the loose-object map. This
detour is required so that we can defer initialization of the object
database itself to a later point in time.
The series is based on 9a0c4701dc (The 7th batch, 2026-07-22).
Changes in v4:
- Drop `APPLY_REPOSITOY_FORMAT_SKIP_ODB_CREATION` in favor of explicit
calls to `odb_new()`.
- Remove a useless call to `xstrdup()`.
- Mark a string as translatable.
- Link to v3: https://patch.msgid.link/[email protected]
Changes in v3:
- Move handling of GIT_OBJECT_DIRECTORY and
GIT_ALTERNATE_OBJECT_DIRECTORIES into `odb_new()` itself. This
deduplicates some of the logic and also preps us for a future where
alternates are handled in the "files" backend itself.
- Link to v2: https://patch.msgid.link/[email protected]
Changes in v2:
- Add a testcase that demonstrates the bug fixed with alternate loose
object maps.
- Rename the "inmemory" bakcend to "in-memory".
- Clarify some commit messages.
- Link to v1: https://patch.msgid.link/[email protected]
Thanks!
Patrick
---
Patrick Steinhardt (6):
loose: load loose object map for the correct source
setup: detangle loading of loose object maps
setup: handle ODB-related environment variables in `odb_new()`
setup: defer object database creation
odb/source: introduce function to map source type to name
odb: make creation of on-disk structures pluggable
loose.c | 25 ++++++++++----------
loose.h | 1 +
odb.c | 21 +++++++++--------
odb.h | 17 ++++++++++++--
odb/source-files.c | 19 +++++++++++++++
odb/source-files.h | 4 +++-
odb/source-inmemory.h | 4 +++-
odb/source-loose.c | 2 ++
odb/source-loose.h | 4 +++-
odb/source-packed.h | 4 +++-
odb/source.c | 19 +++++++++++++++
odb/source.h | 29 +++++++++++++++++++++++
repository.c | 3 +--
setup.c | 54 +++++++++++++++++++++----------------------
t/t1016-compatObjectFormat.sh | 18 +++++++++++++++
t/unit-tests/u-odb-inmemory.c | 2 +-
16 files changed, 169 insertions(+), 57 deletions(-)
Range-diff versus v3:
1: e1a585a3f7 = 1: 6dd8d575c6 loose: load loose object map for the correct source
2: 1f1200f7ba = 2: 1e7adada64 setup: detangle loading of loose object maps
3: af02e520a2 ! 3: 2265f38695 setup: handle ODB-related environment variables in `odb_new()`
@@ odb.c: int odb_write_object_stream(struct object_database *odb,
+
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 = xstrdup_or_null(secondary_sources);
++ o->alternate_db = secondary_sources;
o->inmemory_objects = &odb_source_inmemory_new(o)->base;
- free(to_free);
-
-+ free(secondary_sources);
+ free(primary_source);
return o;
}
4: 2c794be101 ! 4: 5274ee6bab setup: defer object database creation
@@ Commit message
object database, but it's not usable yet until we eventually call
`create_object_directory()`.
- Defer the object database creation so that we handle both steps in the
- same function.
+ Lift the call to `odb_new()` out of `apply_repository_format()` so that
+ callers have more wiggle room with when exactly they call it, and adapt
+ them accordingly. The only exception is `init_db()`, where we now defer
+ creating the object database until we call `create_object_database()`.
+
+ With this change, initializing and creating the object database on disk
+ is now neatly encapsulated in a single function, which will make it
+ easier for a subsequent commit to move creation of the on-disk data
+ structures into the `struct odb_source` backends.
Signed-off-by: Patrick Steinhardt <[email protected]>
+ ## repository.c ##
+@@ repository.c: int repo_init(struct repository *repo,
+ warning("%s", err.buf);
+ goto error;
+ }
++ repo->objects = odb_new(repo, 0);
+
+ if (worktree)
+ repo_set_worktree(repo, worktree);
+
## setup.c ##
@@ setup.c: int apply_repository_format(struct repository *repo,
enum apply_repository_format_flags flags,
@@ setup.c: int apply_repository_format(struct repository *repo,
- if (flags & APPLY_REPOSITORY_FORMAT_HONOR_ENV)
- odb_new_flags |= ODB_NEW_HONOR_ENV;
- repo->objects = odb_new(repo, odb_new_flags);
-+ if (!(flags & APPLY_REPOSITORY_FORMAT_SKIP_ODB_CREATION)) {
-+ enum odb_new_flags odb_new_flags = 0;
-+ if (flags & APPLY_REPOSITORY_FORMAT_HONOR_ENV)
-+ odb_new_flags |= ODB_NEW_HONOR_ENV;
-+ repo->objects = odb_new(repo, odb_new_flags);
-+ }
-
+-
return 0;
}
+
+@@ setup.c: const char *enter_repo(struct repository *repo, const char *path, unsigned flags
+ read_and_verify_repository_format(&fmt, ".", NULL);
+ if (apply_repository_format(repo, &fmt, APPLY_REPOSITORY_FORMAT_HONOR_ENV, &err) < 0)
+ die("%s", err.buf);
++ repo->objects = odb_new(repo, ODB_NEW_HONOR_ENV);
+ startup_info->have_repository = 1;
+
+ clear_repository_format(&fmt);
+@@ setup.c: const char *setup_git_directory_gently(struct repository *repo, int *nongit_ok)
+ if (apply_repository_format(repo, &discovery.format,
+ APPLY_REPOSITORY_FORMAT_HONOR_ENV, &err) < 0)
+ die("%s", err.buf);
++ repo->objects = odb_new(repo, ODB_NEW_HONOR_ENV);
+
+ clear_repository_format(&discovery.format);
+ strbuf_release(&err);
@@ setup.c: static int create_default_files(struct repository *repo,
return reinit;
}
@@ setup.c: int init_db(struct repository *repo,
repository_format_configure(&repo_fmt, hash, ref_storage_format);
- if (apply_repository_format(repo, &repo_fmt, APPLY_REPOSITORY_FORMAT_HONOR_ENV, &err) < 0)
+ if (apply_repository_format(repo, &repo_fmt,
-+ APPLY_REPOSITORY_FORMAT_HONOR_ENV |
-+ APPLY_REPOSITORY_FORMAT_SKIP_ODB_CREATION, &err) < 0)
++ APPLY_REPOSITORY_FORMAT_HONOR_ENV, &err) < 0)
die("%s", err.buf);
- startup_info->have_repository = 1;
@@ setup.c: int init_db(struct repository *repo,
if (repo_settings_get_shared_repository(repo)) {
char buf[10];
-
- ## setup.h ##
-@@ setup.h: enum apply_repository_format_flags {
- * relate to the object database.
- */
- APPLY_REPOSITORY_FORMAT_HONOR_ENV = (1 << 0),
-+
-+ /*
-+ * Usually, the object database is created after the repository format
-+ * was applied. This step is skipped if this flag is set, which leaves
-+ * us with a partially-working repository.
-+ *
-+ * This is useful when initializing a new repository.
-+ */
-+ APPLY_REPOSITORY_FORMAT_SKIP_ODB_CREATION = (1 << 1),
- };
-
- /*
5: 7397c760df = 5: b444a314a6 odb/source: introduce function to map source type to name
6: 7049e41a73 ! 6: acb48f1072 odb: make creation of on-disk structures pluggable
@@ setup.c: static int create_default_files(struct repository *repo,
-
- strbuf_release(&path);
+ if (odb_source_create_on_disk(repo->objects->sources) < 0)
-+ die("failed creating object database");
++ die(_("failed creating object database"));
}
static void separate_git_dir(const char *git_dir, const char *git_link)
---
base-commit: 9a0c4701dcd5725c4184599322b52933ff5005ca
change-id: 20260710-pks-odb-create-on-disk-ae8757861c69