From 0de2467e6c35930cf2530a213082829c8b86970d Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Wed, 17 Jun 2026 08:39:48 +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. Further note that we're also registering a `chdir_notify` callback to reparent our path. This wasn't previously necessary (and still isn't at this point in time) because all paths are taken from the owning "files" source, and that source already handles the reparenting for us. But a subsequent commit will change that so that we're using the path of the "packed" source, and once that happens we'll need it to be updated when changing the working directory. 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.