]> git.ipfire.org Git - thirdparty/git.git/commitdiff
object: clear grafts when clearing parsed object pool
authorPatrick Steinhardt <ps@pks.im>
Thu, 5 Sep 2024 10:09:12 +0000 (12:09 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 5 Sep 2024 15:49:11 +0000 (08:49 -0700)
We do not clear grafts part of the parsed object pool when clearing the
pool itself, which can lead to memory leaks when a repository is being
cleared.

Fix this by moving `reset_commit_grafts()` into "object.c" and making it
part of the `struct parsed_object_pool` interface such that we can call
it from `parsed_object_pool_clear()`. Adapt `parsed_object_pool_new()`
to take and store a reference to its owning repository, which is needed
by `unparse_commit()`.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
commit.c
commit.h
object.c
object.h
repository.c
shallow.c

index ec9efc189d53421241a4385ffb0d0278ebdecfee..bbef0e81c65ca5761fb8de8a89a85fbddb220127 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -177,7 +177,7 @@ int commit_graft_pos(struct repository *r, const struct object_id *oid)
                       commit_graft_oid_access);
 }
 
-static void unparse_commit(struct repository *r, const struct object_id *oid)
+void unparse_commit(struct repository *r, const struct object_id *oid)
 {
        struct commit *c = lookup_commit(r, oid);
 
@@ -318,18 +318,6 @@ int for_each_commit_graft(each_commit_graft_fn fn, void *cb_data)
        return ret;
 }
 
-void reset_commit_grafts(struct repository *r)
-{
-       int i;
-
-       for (i = 0; i < r->parsed_objects->grafts_nr; i++) {
-               unparse_commit(r, &r->parsed_objects->grafts[i]->oid);
-               free(r->parsed_objects->grafts[i]);
-       }
-       r->parsed_objects->grafts_nr = 0;
-       r->parsed_objects->commit_graft_prepared = 0;
-}
-
 struct commit_buffer {
        void *buffer;
        unsigned long size;
index d62b1d93f9566250fa9b8cabe36a050bf3cc7b78..5ba0f77b1eb608099ff12115ea401c4a0eb4eb7b 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -108,6 +108,8 @@ static inline int repo_parse_commit_no_graph(struct repository *r,
 
 void parse_commit_or_die(struct commit *item);
 
+void unparse_commit(struct repository *r, const struct object_id *oid);
+
 struct buffer_slab;
 struct buffer_slab *allocate_commit_buffer_slab(void);
 void free_commit_buffer_slab(struct buffer_slab *bs);
@@ -240,7 +242,6 @@ int commit_graft_pos(struct repository *r, const struct object_id *oid);
 int register_commit_graft(struct repository *r, struct commit_graft *, int);
 void prepare_commit_graft(struct repository *r);
 struct commit_graft *lookup_commit_graft(struct repository *r, const struct object_id *oid);
-void reset_commit_grafts(struct repository *r);
 
 struct commit *get_fork_point(const char *refname, struct commit *commit);
 
index d756c7f2ea34f31f68e2cab93d9b53da87a42ea3..94ea8fb8d2c4f9877e0b89759e890c44d6392698 100644 (file)
--- a/object.c
+++ b/object.c
@@ -545,11 +545,12 @@ void repo_clear_commit_marks(struct repository *r, unsigned int flags)
        }
 }
 
-struct parsed_object_pool *parsed_object_pool_new(void)
+struct parsed_object_pool *parsed_object_pool_new(struct repository *repo)
 {
        struct parsed_object_pool *o = xmalloc(sizeof(*o));
        memset(o, 0, sizeof(*o));
 
+       o->repo = repo;
        o->blob_state = allocate_alloc_state();
        o->tree_state = allocate_alloc_state();
        o->commit_state = allocate_alloc_state();
@@ -628,6 +629,16 @@ void raw_object_store_clear(struct raw_object_store *o)
        hashmap_clear(&o->pack_map);
 }
 
+void parsed_object_pool_reset_commit_grafts(struct parsed_object_pool *o)
+{
+       for (int i = 0; i < o->grafts_nr; i++) {
+               unparse_commit(o->repo, &o->grafts[i]->oid);
+               free(o->grafts[i]);
+       }
+       o->grafts_nr = 0;
+       o->commit_graft_prepared = 0;
+}
+
 void parsed_object_pool_clear(struct parsed_object_pool *o)
 {
        /*
@@ -659,6 +670,7 @@ void parsed_object_pool_clear(struct parsed_object_pool *o)
        free_commit_buffer_slab(o->buffer_slab);
        o->buffer_slab = NULL;
 
+       parsed_object_pool_reset_commit_grafts(o);
        clear_alloc_state(o->blob_state);
        clear_alloc_state(o->tree_state);
        clear_alloc_state(o->commit_state);
index 05691486ebfcec575faeb7306b6e4298655116bb..17f32f1103e58a24500580efd1ad789fa610fb1c 100644 (file)
--- a/object.h
+++ b/object.h
@@ -7,6 +7,7 @@ struct buffer_slab;
 struct repository;
 
 struct parsed_object_pool {
+       struct repository *repo;
        struct object **obj_hash;
        int nr_objs, obj_hash_size;
 
@@ -31,8 +32,9 @@ struct parsed_object_pool {
        struct buffer_slab *buffer_slab;
 };
 
-struct parsed_object_pool *parsed_object_pool_new(void);
+struct parsed_object_pool *parsed_object_pool_new(struct repository *repo);
 void parsed_object_pool_clear(struct parsed_object_pool *o);
+void parsed_object_pool_reset_commit_grafts(struct parsed_object_pool *o);
 
 struct object_list {
        struct object *item;
index 9825a3089932ede3f5dc588874d618768988c283..e6fc2c6aa9d19d8b35be471483e6575b65ad82e9 100644 (file)
@@ -54,7 +54,7 @@ void initialize_repository(struct repository *repo)
 {
        repo->objects = raw_object_store_new();
        repo->remote_state = remote_state_new();
-       repo->parsed_objects = parsed_object_pool_new();
+       repo->parsed_objects = parsed_object_pool_new(repo);
        ALLOC_ARRAY(repo->index, 1);
        index_state_init(repo->index, repo);
 
index b8cd051e3b6a7023a8467fc6b1b290073a32c8e4..a10cf9e9d5d4b43073174b13a653e49b825c5398 100644 (file)
--- a/shallow.c
+++ b/shallow.c
@@ -97,7 +97,7 @@ static void reset_repository_shallow(struct repository *r)
 {
        r->parsed_objects->is_shallow = -1;
        stat_validity_clear(r->parsed_objects->shallow_stat);
-       reset_commit_grafts(r);
+       parsed_object_pool_reset_commit_grafts(r->parsed_objects);
 }
 
 int commit_shallow_file(struct repository *r, struct shallow_lock *lk)