From 1eb77914ab336d187409714bbacdcd1b06af035b Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 9 Jun 2026 10:50:58 +0200 Subject: [PATCH] odb/source-packed: start converting to a proper `struct odb_source` Start converting `struct odb_source_packed` into a proper pluggable `struct odb_source` by embedding the base struct and assigning it the new `ODB_SOURCE_PACKED` type. Furthermore, wire up lifecycle management of this source by implementing the `free` callback and taking ownership of the chdir notifications. Note that the packed source is not yet functional as a standalone `struct odb_source`, as it's missing all of the callback implementations. These will be wired up in subsequent commits. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- odb/source-files.c | 2 +- odb/source-packed.c | 49 ++++++++++++++++++++++++++++++++++++++++----- odb/source-packed.h | 12 +++++++++++ odb/source.h | 3 +++ packfile.c | 10 --------- packfile.h | 6 ------ 6 files changed, 60 insertions(+), 22 deletions(-) diff --git a/odb/source-files.c b/odb/source-files.c index e04525fb08..3608808e7c 100644 --- a/odb/source-files.c +++ b/odb/source-files.c @@ -29,7 +29,7 @@ static void odb_source_files_free(struct odb_source *source) struct odb_source_files *files = odb_source_files_downcast(source); chdir_notify_unregister(NULL, odb_source_files_reparent, files); odb_source_free(&files->loose->base); - packfile_store_free(files->packed); + odb_source_free(&files->packed->base); odb_source_release(&files->base); free(files); } diff --git a/odb/source-packed.c b/odb/source-packed.c index 12e785be48..f81a990cbd 100644 --- a/odb/source-packed.c +++ b/odb/source-packed.c @@ -1,11 +1,50 @@ #include "git-compat-util.h" +#include "abspath.h" +#include "chdir-notify.h" #include "odb/source-packed.h" +#include "packfile.h" + +static void odb_source_packed_reparent(const char *name UNUSED, + const char *old_cwd, + const char *new_cwd, + void *cb_data) +{ + struct odb_source_packed *packed = cb_data; + char *path = reparent_relative_path(old_cwd, new_cwd, + packed->base.path); + free(packed->base.path); + packed->base.path = path; +} + +static void odb_source_packed_free(struct odb_source *source) +{ + struct odb_source_packed *packed = odb_source_packed_downcast(source); + + chdir_notify_unregister(NULL, odb_source_packed_reparent, packed); + + for (struct packfile_list_entry *e = packed->packs.head; e; e = e->next) + free(e->pack); + packfile_list_clear(&packed->packs); + + strmap_clear(&packed->packs_by_path, 0); + odb_source_release(&packed->base); + free(packed); +} struct odb_source_packed *odb_source_packed_new(struct odb_source_files *parent) { - struct odb_source_packed *store; - CALLOC_ARRAY(store, 1); - store->files = parent; - strmap_init(&store->packs_by_path); - return store; + struct odb_source_packed *packed; + + CALLOC_ARRAY(packed, 1); + odb_source_init(&packed->base, parent->base.odb, ODB_SOURCE_PACKED, + parent->base.path, parent->base.local); + packed->files = parent; + strmap_init(&packed->packs_by_path); + + packed->base.free = odb_source_packed_free; + + if (!is_absolute_path(parent->base.path)) + chdir_notify_register(NULL, odb_source_packed_reparent, packed); + + return packed; } diff --git a/odb/source-packed.h b/odb/source-packed.h index 3c2d229a17..68e64cabab 100644 --- a/odb/source-packed.h +++ b/odb/source-packed.h @@ -9,6 +9,7 @@ * A store that manages packfiles for a given object database. */ struct odb_source_packed { + struct odb_source base; struct odb_source_files *files; /* @@ -69,4 +70,15 @@ struct odb_source_packed { */ struct odb_source_packed *odb_source_packed_new(struct odb_source_files *parent); +/* + * Cast the given object database source to the packed backend. This will cause + * a BUG in case the source doesn't use this backend. + */ +static inline struct odb_source_packed *odb_source_packed_downcast(struct odb_source *source) +{ + if (source->type != ODB_SOURCE_PACKED) + BUG("trying to downcast source of type '%d' to packed", source->type); + return container_of(source, struct odb_source_packed, base); +} + #endif diff --git a/odb/source.h b/odb/source.h index 8bcb67787e..6865e1f71a 100644 --- a/odb/source.h +++ b/odb/source.h @@ -17,6 +17,9 @@ enum odb_source_type { /* The "loose" backend that uses loose objects, only. */ ODB_SOURCE_LOOSE, + /* The "packed" backend that uses packfiles. */ + ODB_SOURCE_PACKED, + /* The "in-memory" backend that stores objects in memory. */ ODB_SOURCE_INMEMORY, }; diff --git a/packfile.c b/packfile.c index 862a24ad49..6d492216de 100644 --- a/packfile.c +++ b/packfile.c @@ -2749,16 +2749,6 @@ int parse_pack_header_option(const char *in, unsigned char *out, unsigned int *l return 0; } -void packfile_store_free(struct odb_source_packed *store) -{ - for (struct packfile_list_entry *e = store->packs.head; e; e = e->next) - free(e->pack); - packfile_list_clear(&store->packs); - - strmap_clear(&store->packs_by_path, 0); - free(store); -} - void packfile_store_close(struct odb_source_packed *store) { for (struct packfile_list_entry *e = store->packs.head; e; e = e->next) { diff --git a/packfile.h b/packfile.h index 2d0bb7adbe..e8bc9349f8 100644 --- a/packfile.h +++ b/packfile.h @@ -55,12 +55,6 @@ struct packed_git { char pack_name[FLEX_ARRAY]; /* more */ }; -/* - * Free the packfile store and all its associated state. All packfiles - * tracked by the store will be closed. - */ -void packfile_store_free(struct odb_source_packed *store); - /* * Close all packfiles associated with this store. The packfiles won't be * free'd, so they can be re-opened at a later point in time.