{"thread":{"id":"64678","subject":"[PATCH 00/14] export and use commit_stack","startedAt":"2025-12-24T17:03:30Z","lastAt":"2025-12-24T17:03:31Z","messageCount":15,"participants":["René Scharfe"],"isPatch":true,"patchVersion":1,"patchTotal":14},"messages":[{"id":"532710","messageId":"20251224170327.68049-1-l.s.r@web.de","threadId":"64678","inReplyTo":null,"subject":"[PATCH 00/14] export and use commit_stack","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-24T17:03:13Z","receivedAt":"2025-12-24T17:03:30Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"There are more than ten different variants of dynamic arrays of commit\npointers.  Pick one implementation, export it, add _init() and _grow()\nfunctions and use it to reduce code duplication.\n\n  revision: export commit_stack\n  log: use commit_stack\n  midx: use commit_stack\n  name-rev: use commit_stack\n  remote: use commit_stack for local_commits\n  remote: use commit_stack for sent_tips\n  remote: use commit_stack for src_commits\n  test-reach: use commit_stack\n\n  commit: add commit_stack_init()\n  pack-bitmap-write: use commit_stack\n  shallow: use commit_stack\n\n  commit: add commit_stack_grow()\n  commit-graph: use commit_stack\n  commit-reach: use commit_stack\n\n builtin/log.c         | 31 ++++++++--------\n builtin/name-rev.c    | 17 +++------\n commit-graph.c        | 86 ++++++++++++++++++++-----------------------\n commit-reach.c        | 25 ++++++-------\n commit.c              | 28 ++++++++++++++\n commit.h              | 12 ++++++\n midx-write.c          | 35 ++++++------------\n pack-bitmap-write.c   | 18 ++++-----\n remote.c              | 74 ++++++++++---------------------------\n revision.c            | 23 ------------\n shallow.c             | 44 +++++++++-------------\n shallow.h             |  4 +-\n t/helper/test-reach.c | 34 +++++++----------\n 13 files changed, 184 insertions(+), 247 deletions(-)\n\n-- \n2.52.0\n\n"},{"id":"532711","messageId":"20251224170327.68049-2-l.s.r@web.de","threadId":"64678","inReplyTo":"20251224170327.68049-1-l.s.r@web.de","subject":"[PATCH 01/14] revision: export commit_stack","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-24T17:03:14Z","receivedAt":"2025-12-24T17:03:30Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Dynamic arrays of commit pointers are used in several places.  Some of\nthem use a custom struct to hold array, item count and capacity, others\nhave them as separate variables linked by a common name part.\n\nPick one succinct, clean implementation -- commit_stack -- and convert\nthe different variants to it to reduce code duplication.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n commit.c   | 17 +++++++++++++++++\n commit.h   | 10 ++++++++++\n revision.c | 23 -----------------------\n 3 files changed, 27 insertions(+), 23 deletions(-)\n\ndiff --git a/commit.c b/commit.c\nindex 709c9eed58..f2edafa49c 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1981,3 +1981,20 @@ int run_commit_hook(int editor_is_used, const char *index_file,\n \topt.invoked_hook = invoked_hook;\n \treturn run_hooks_opt(the_repository, name, &opt);\n }\n+\n+void commit_stack_push(struct commit_stack *stack, struct commit *commit)\n+{\n+\tALLOC_GROW(stack->items, stack->nr + 1, stack->alloc);\n+\tstack->items[stack->nr++] = commit;\n+}\n+\n+struct commit *commit_stack_pop(struct commit_stack *stack)\n+{\n+\treturn stack->nr ? stack->items[--stack->nr] : NULL;\n+}\n+\n+void commit_stack_clear(struct commit_stack *stack)\n+{\n+\tFREE_AND_NULL(stack->items);\n+\tstack->nr = stack->alloc = 0;\n+}\ndiff --git a/commit.h b/commit.h\nindex 5406dd2663..81e047f820 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -381,4 +381,14 @@ int parse_buffer_signed_by_header(const char *buffer,\n \t\t\t\t  const struct git_hash_algo *algop);\n int add_header_signature(struct strbuf *buf, struct strbuf *sig, const struct git_hash_algo *algo);\n \n+struct commit_stack {\n+\tstruct commit **items;\n+\tsize_t nr, alloc;\n+};\n+#define COMMIT_STACK_INIT { 0 }\n+\n+void commit_stack_push(struct commit_stack *, struct commit *);\n+struct commit *commit_stack_pop(struct commit_stack *);\n+void commit_stack_clear(struct commit_stack *);\n+\n #endif /* COMMIT_H */\ndiff --git a/revision.c b/revision.c\nindex 5f0850ae5c..1858e093ee 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -250,29 +250,6 @@ void mark_trees_uninteresting_sparse(struct repository *r,\n \tpaths_and_oids_clear(&map);\n }\n \n-struct commit_stack {\n-\tstruct commit **items;\n-\tsize_t nr, alloc;\n-};\n-#define COMMIT_STACK_INIT { 0 }\n-\n-static void commit_stack_push(struct commit_stack *stack, struct commit *commit)\n-{\n-\tALLOC_GROW(stack->items, stack->nr + 1, stack->alloc);\n-\tstack->items[stack->nr++] = commit;\n-}\n-\n-static struct commit *commit_stack_pop(struct commit_stack *stack)\n-{\n-\treturn stack->nr ? stack->items[--stack->nr] : NULL;\n-}\n-\n-static void commit_stack_clear(struct commit_stack *stack)\n-{\n-\tFREE_AND_NULL(stack->items);\n-\tstack->nr = stack->alloc = 0;\n-}\n-\n static void mark_one_parent_uninteresting(struct rev_info *revs, struct commit *commit,\n \t\t\t\t\t  struct commit_stack *pending)\n {\n-- \n2.52.0\n\n"},{"id":"532712","messageId":"20251224170327.68049-6-l.s.r@web.de","threadId":"64678","inReplyTo":"20251224170327.68049-1-l.s.r@web.de","subject":"[PATCH 05/14] remote: use commit_stack for local_commits","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-24T17:03:18Z","receivedAt":"2025-12-24T17:03:30Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Replace a commit array implementation with commit_stack.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n remote.c | 39 ++++++---------------------------------\n 1 file changed, 6 insertions(+), 33 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex 59b3715120..af888e3f20 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -2544,36 +2544,9 @@ static int remote_tracking(struct remote *remote, const char *refname,\n \treturn 0;\n }\n \n-/*\n- * The struct \"reflog_commit_array\" and related helper functions\n- * are used for collecting commits into an array during reflog\n- * traversals in \"check_and_collect_until()\".\n- */\n-struct reflog_commit_array {\n-\tstruct commit **item;\n-\tsize_t nr, alloc;\n-};\n-\n-#define REFLOG_COMMIT_ARRAY_INIT { 0 }\n-\n-/* Append a commit to the array. */\n-static void append_commit(struct reflog_commit_array *arr,\n-\t\t\t  struct commit *commit)\n-{\n-\tALLOC_GROW(arr->item, arr->nr + 1, arr->alloc);\n-\tarr->item[arr->nr++] = commit;\n-}\n-\n-/* Free and reset the array. */\n-static void free_commit_array(struct reflog_commit_array *arr)\n-{\n-\tFREE_AND_NULL(arr->item);\n-\tarr->nr = arr->alloc = 0;\n-}\n-\n struct check_and_collect_until_cb_data {\n \tstruct commit *remote_commit;\n-\tstruct reflog_commit_array *local_commits;\n+\tstruct commit_stack *local_commits;\n \ttimestamp_t remote_reflog_timestamp;\n };\n \n@@ -2605,7 +2578,7 @@ static int check_and_collect_until(const char *refname UNUSED,\n \t\treturn 1;\n \n \tif ((commit = lookup_commit_reference(the_repository, n_oid)))\n-\t\tappend_commit(cb->local_commits, commit);\n+\t\tcommit_stack_push(cb->local_commits, commit);\n \n \t/*\n \t * If the reflog entry timestamp is older than the remote ref's\n@@ -2633,7 +2606,7 @@ static int is_reachable_in_reflog(const char *local, const struct ref *remote)\n \tstruct commit *commit;\n \tstruct commit **chunk;\n \tstruct check_and_collect_until_cb_data cb;\n-\tstruct reflog_commit_array arr = REFLOG_COMMIT_ARRAY_INIT;\n+\tstruct commit_stack arr = COMMIT_STACK_INIT;\n \tsize_t size = 0;\n \tint ret = 0;\n \n@@ -2664,8 +2637,8 @@ static int is_reachable_in_reflog(const char *local, const struct ref *remote)\n \t * Check if the remote commit is reachable from any\n \t * of the commits in the collected array, in batches.\n \t */\n-\tfor (chunk = arr.item; chunk < arr.item + arr.nr; chunk += size) {\n-\t\tsize = arr.item + arr.nr - chunk;\n+\tfor (chunk = arr.items; chunk < arr.items + arr.nr; chunk += size) {\n+\t\tsize = arr.items + arr.nr - chunk;\n \t\tif (MERGE_BASES_BATCH_SIZE < size)\n \t\t\tsize = MERGE_BASES_BATCH_SIZE;\n \n@@ -2674,7 +2647,7 @@ static int is_reachable_in_reflog(const char *local, const struct ref *remote)\n \t}\n \n cleanup_return:\n-\tfree_commit_array(&arr);\n+\tcommit_stack_clear(&arr);\n \treturn ret;\n }\n \n-- \n2.52.0\n\n"},{"id":"532713","messageId":"20251224170327.68049-9-l.s.r@web.de","threadId":"64678","inReplyTo":"20251224170327.68049-1-l.s.r@web.de","subject":"[PATCH 08/14] test-reach: use commit_stack","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-24T17:03:21Z","receivedAt":"2025-12-24T17:03:30Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Use commit_stack instead of open-coding it.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n t/helper/test-reach.c | 34 ++++++++++++++--------------------\n 1 file changed, 14 insertions(+), 20 deletions(-)\n\ndiff --git a/t/helper/test-reach.c b/t/helper/test-reach.c\nindex c58c93800f..feabeb29c2 100644\n--- a/t/helper/test-reach.c\n+++ b/t/helper/test-reach.c\n@@ -34,8 +34,8 @@ int cmd__reach(int ac, const char **av)\n \tstruct commit *A, *B;\n \tstruct commit_list *X, *Y;\n \tstruct object_array X_obj = OBJECT_ARRAY_INIT;\n-\tstruct commit **X_array, **Y_array;\n-\tsize_t X_nr, X_alloc, Y_nr, Y_alloc;\n+\tstruct commit_stack X_stack = COMMIT_STACK_INIT;\n+\tstruct commit_stack Y_stack = COMMIT_STACK_INIT;\n \tstruct strbuf buf = STRBUF_INIT;\n \tstruct repository *r = the_repository;\n \n@@ -46,10 +46,6 @@ int cmd__reach(int ac, const char **av)\n \n \tA = B = NULL;\n \tX = Y = NULL;\n-\tX_nr = Y_nr = 0;\n-\tX_alloc = Y_alloc = 16;\n-\tALLOC_ARRAY(X_array, X_alloc);\n-\tALLOC_ARRAY(Y_array, Y_alloc);\n \n \twhile (strbuf_getline(&buf, stdin) != EOF) {\n \t\tstruct object_id oid;\n@@ -88,15 +84,13 @@ int cmd__reach(int ac, const char **av)\n \n \t\t\tcase 'X':\n \t\t\t\tcommit_list_insert(c, &X);\n-\t\t\t\tALLOC_GROW(X_array, X_nr + 1, X_alloc);\n-\t\t\t\tX_array[X_nr++] = c;\n+\t\t\t\tcommit_stack_push(&X_stack, c);\n \t\t\t\tadd_object_array(orig, NULL, &X_obj);\n \t\t\t\tbreak;\n \n \t\t\tcase 'Y':\n \t\t\t\tcommit_list_insert(c, &Y);\n-\t\t\t\tALLOC_GROW(Y_array, Y_nr + 1, Y_alloc);\n-\t\t\t\tY_array[Y_nr++] = c;\n+\t\t\t\tcommit_stack_push(&Y_stack, c);\n \t\t\t\tbreak;\n \n \t\t\tdefault:\n@@ -112,16 +106,16 @@ int cmd__reach(int ac, const char **av)\n \t\t       repo_in_merge_bases(the_repository, A, B));\n \telse if (!strcmp(av[1], \"in_merge_bases_many\"))\n \t\tprintf(\"%s(A,X):%d\\n\", av[1],\n-\t\t       repo_in_merge_bases_many(the_repository, A, X_nr, X_array, 0));\n+\t\t       repo_in_merge_bases_many(the_repository, A, X_stack.nr, X_stack.items, 0));\n \telse if (!strcmp(av[1], \"is_descendant_of\"))\n \t\tprintf(\"%s(A,X):%d\\n\", av[1], repo_is_descendant_of(r, A, X));\n \telse if (!strcmp(av[1], \"get_branch_base_for_tip\"))\n-\t\tprintf(\"%s(A,X):%d\\n\", av[1], get_branch_base_for_tip(r, A, X_array, X_nr));\n+\t\tprintf(\"%s(A,X):%d\\n\", av[1], get_branch_base_for_tip(r, A, X_stack.items, X_stack.nr));\n \telse if (!strcmp(av[1], \"get_merge_bases_many\")) {\n \t\tstruct commit_list *list = NULL;\n \t\tif (repo_get_merge_bases_many(the_repository,\n-\t\t\t\t\t      A, X_nr,\n-\t\t\t\t\t      X_array,\n+\t\t\t\t\t      A, X_stack.nr,\n+\t\t\t\t\t      X_stack.items,\n \t\t\t\t\t      &list) < 0)\n \t\t\texit(128);\n \t\tprintf(\"%s(A,X):\\n\", av[1]);\n@@ -159,8 +153,8 @@ int cmd__reach(int ac, const char **av)\n \t\tconst int reachable_flag = 1;\n \t\tint count = 0;\n \t\tstruct commit_list *current;\n-\t\tstruct commit_list *list = get_reachable_subset(X_array, X_nr,\n-\t\t\t\t\t\t\t\tY_array, Y_nr,\n+\t\tstruct commit_list *list = get_reachable_subset(X_stack.items, X_stack.nr,\n+\t\t\t\t\t\t\t\tY_stack.items, Y_stack.nr,\n \t\t\t\t\t\t\t\treachable_flag);\n \t\tprintf(\"get_reachable_subset(X,Y)\\n\");\n \t\tfor (current = list; current; current = current->next) {\n@@ -169,8 +163,8 @@ int cmd__reach(int ac, const char **av)\n \t\t\t\t    oid_to_hex(&list->item->object.oid));\n \t\t\tcount++;\n \t\t}\n-\t\tfor (size_t i = 0; i < Y_nr; i++) {\n-\t\t\tif (Y_array[i]->object.flags & reachable_flag)\n+\t\tfor (size_t i = 0; i < Y_stack.nr; i++) {\n+\t\t\tif (Y_stack.items[i]->object.flags & reachable_flag)\n \t\t\t\tcount--;\n \t\t}\n \n@@ -185,7 +179,7 @@ int cmd__reach(int ac, const char **av)\n \tstrbuf_release(&buf);\n \tfree_commit_list(X);\n \tfree_commit_list(Y);\n-\tfree(X_array);\n-\tfree(Y_array);\n+\tcommit_stack_clear(&X_stack);\n+\tcommit_stack_clear(&Y_stack);\n \treturn 0;\n }\n-- \n2.52.0\n\n"},{"id":"532714","messageId":"20251224170327.68049-5-l.s.r@web.de","threadId":"64678","inReplyTo":"20251224170327.68049-1-l.s.r@web.de","subject":"[PATCH 04/14] name-rev: use commit_stack","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-24T17:03:17Z","receivedAt":"2025-12-24T17:03:30Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Simplify the code by using commit_stack instead of open-coding it.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n builtin/name-rev.c | 17 ++++++-----------\n 1 file changed, 6 insertions(+), 11 deletions(-)\n\ndiff --git a/builtin/name-rev.c b/builtin/name-rev.c\nindex 615f7d1aae..6188cf98ce 100644\n--- a/builtin/name-rev.c\n+++ b/builtin/name-rev.c\n@@ -180,8 +180,7 @@ static void name_rev(struct commit *start_commit,\n {\n \tstruct prio_queue queue;\n \tstruct commit *commit;\n-\tstruct commit **parents_to_queue = NULL;\n-\tsize_t parents_to_queue_nr, parents_to_queue_alloc = 0;\n+\tstruct commit_stack parents_to_queue = COMMIT_STACK_INIT;\n \tstruct rev_name *start_name;\n \n \trepo_parse_commit(the_repository, start_commit);\n@@ -206,7 +205,7 @@ static void name_rev(struct commit *start_commit,\n \t\tstruct commit_list *parents;\n \t\tint parent_number = 1;\n \n-\t\tparents_to_queue_nr = 0;\n+\t\tparents_to_queue.nr = 0;\n \n \t\tfor (parents = commit->parents;\n \t\t\t\tparents;\n@@ -238,22 +237,18 @@ static void name_rev(struct commit *start_commit,\n \t\t\t\t\t\t\t\tstring_pool);\n \t\t\t\telse\n \t\t\t\t\tparent_name->tip_name = name->tip_name;\n-\t\t\t\tALLOC_GROW(parents_to_queue,\n-\t\t\t\t\t   parents_to_queue_nr + 1,\n-\t\t\t\t\t   parents_to_queue_alloc);\n-\t\t\t\tparents_to_queue[parents_to_queue_nr] = parent;\n-\t\t\t\tparents_to_queue_nr++;\n+\t\t\t\tcommit_stack_push(&parents_to_queue, parent);\n \t\t\t}\n \t\t}\n \n \t\t/* The first parent must come out first from the prio_queue */\n-\t\twhile (parents_to_queue_nr)\n+\t\twhile (parents_to_queue.nr)\n \t\t\tprio_queue_put(&queue,\n-\t\t\t\t       parents_to_queue[--parents_to_queue_nr]);\n+\t\t\t\t       commit_stack_pop(&parents_to_queue));\n \t}\n \n \tclear_prio_queue(&queue);\n-\tfree(parents_to_queue);\n+\tcommit_stack_clear(&parents_to_queue);\n }\n \n static int subpath_matches(const char *path, const char *filter)\n-- \n2.52.0\n\n"},{"id":"532716","messageId":"20251224170327.68049-3-l.s.r@web.de","threadId":"64678","inReplyTo":"20251224170327.68049-1-l.s.r@web.de","subject":"[PATCH 02/14] log: use commit_stack","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-24T17:03:15Z","receivedAt":"2025-12-24T17:03:30Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Calling commit_stack_push() to add commits is simpler and more efficient\nthan using REALLOC_ARRAY.  Calling commit_stack_pop() to consume them in\nLIFO order is also a tad simpler than calculating the array index from\nthe end.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n builtin/log.c | 31 +++++++++++++++----------------\n 1 file changed, 15 insertions(+), 16 deletions(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex d4cf9c59c8..5c9a8ef363 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -1896,11 +1896,11 @@ int cmd_format_patch(int argc,\n {\n \tstruct format_config cfg;\n \tstruct commit *commit;\n-\tstruct commit **list = NULL;\n+\tstruct commit_stack list = COMMIT_STACK_INIT;\n \tstruct rev_info rev;\n \tchar *to_free = NULL;\n \tstruct setup_revision_opt s_r_opt;\n-\tsize_t nr = 0, total, i;\n+\tsize_t total, i;\n \tint use_stdout = 0;\n \tint start_number = -1;\n \tint just_numbers = 0;\n@@ -2283,14 +2283,12 @@ int cmd_format_patch(int argc,\n \t\tif (ignore_if_in_upstream && has_commit_patch_id(commit, &ids))\n \t\t\tcontinue;\n \n-\t\tnr++;\n-\t\tREALLOC_ARRAY(list, nr);\n-\t\tlist[nr - 1] = commit;\n+\t\tcommit_stack_push(&list, commit);\n \t}\n-\tif (nr == 0)\n+\tif (!list.nr)\n \t\t/* nothing to do */\n \t\tgoto done;\n-\ttotal = nr;\n+\ttotal = list.nr;\n \tif (cover_letter == -1) {\n \t\tif (cfg.config_cover_letter == COVER_AUTO)\n \t\t\tcover_letter = (total > 1);\n@@ -2308,7 +2306,7 @@ int cmd_format_patch(int argc,\n \t\tif (!cover_letter && total != 1)\n \t\t\tdie(_(\"--interdiff requires --cover-letter or single patch\"));\n \t\trev.idiff_oid1 = &idiff_prev.oid[idiff_prev.nr - 1];\n-\t\trev.idiff_oid2 = get_commit_tree_oid(list[0]);\n+\t\trev.idiff_oid2 = get_commit_tree_oid(list.items[0]);\n \t\trev.idiff_title = diff_title(&idiff_title, reroll_count,\n \t\t\t\t\t     _(\"Interdiff:\"),\n \t\t\t\t\t     _(\"Interdiff against v%d:\"));\n@@ -2324,7 +2322,7 @@ int cmd_format_patch(int argc,\n \t\t\tdie(_(\"--range-diff requires --cover-letter or single patch\"));\n \n \t\tinfer_range_diff_ranges(&rdiff1, &rdiff2, rdiff_prev,\n-\t\t\t\t\torigin, list[0]);\n+\t\t\t\t\torigin, list.items[0]);\n \t\trev.rdiff1 = rdiff1.buf;\n \t\trev.rdiff2 = rdiff2.buf;\n \t\trev.creation_factor = creation_factor;\n@@ -2360,11 +2358,11 @@ int cmd_format_patch(int argc,\n \t}\n \n \tmemset(&bases, 0, sizeof(bases));\n-\tbase = get_base_commit(&cfg, list, nr);\n+\tbase = get_base_commit(&cfg, list.items, list.nr);\n \tif (base) {\n \t\treset_revision_walk();\n \t\tclear_object_flags(the_repository, UNINTERESTING);\n-\t\tprepare_bases(&bases, base, list, nr);\n+\t\tprepare_bases(&bases, base, list.items, list.nr);\n \t}\n \n \tif (in_reply_to || cfg.thread || cover_letter) {\n@@ -2381,7 +2379,8 @@ int cmd_format_patch(int argc,\n \t\tif (cfg.thread)\n \t\t\tgen_message_id(&rev, \"cover\");\n \t\tmake_cover_letter(&rev, !!output_directory,\n-\t\t\t\t  origin, nr, list, description_file, branch_name, quiet, &cfg);\n+\t\t\t\t  origin, list.nr, list.items,\n+\t\t\t\t  description_file, branch_name, quiet, &cfg);\n \t\tprint_bases(&bases, rev.diffopt.file);\n \t\tprint_signature(signature, rev.diffopt.file);\n \t\ttotal++;\n@@ -2395,12 +2394,12 @@ int cmd_format_patch(int argc,\n \tif (show_progress)\n \t\tprogress = start_delayed_progress(the_repository,\n \t\t\t\t\t\t  _(\"Generating patches\"), total);\n-\tfor (i = 0; i < nr; i++) {\n-\t\tsize_t idx = nr - i - 1;\n+\twhile (list.nr) {\n+\t\tsize_t idx = list.nr - 1;\n \t\tint shown;\n \n \t\tdisplay_progress(progress, total - idx);\n-\t\tcommit = list[idx];\n+\t\tcommit = commit_stack_pop(&list);\n \t\trev.nr = total - idx + (start_number - 1);\n \n \t\t/* Make the second and subsequent mails replies to the first */\n@@ -2469,7 +2468,7 @@ int cmd_format_patch(int argc,\n \t\t}\n \t}\n \tstop_progress(&progress);\n-\tfree(list);\n+\tcommit_stack_clear(&list);\n \tif (ignore_if_in_upstream)\n \t\tfree_patch_ids(&ids);\n \n-- \n2.52.0\n\n"},{"id":"532717","messageId":"20251224170327.68049-8-l.s.r@web.de","threadId":"64678","inReplyTo":"20251224170327.68049-1-l.s.r@web.de","subject":"[PATCH 07/14] remote: use commit_stack for src_commits","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-24T17:03:20Z","receivedAt":"2025-12-24T17:03:30Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Use commit_stack instead of open-coding it.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n remote.c | 15 +++++++--------\n 1 file changed, 7 insertions(+), 8 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex ffea887c70..b756ff6f15 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -1443,9 +1443,7 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds\n \tif (sent_tips.nr) {\n \t\tconst int reachable_flag = 1;\n \t\tstruct commit_list *found_commits;\n-\t\tstruct commit **src_commits;\n-\t\tsize_t nr_src_commits = 0, alloc_src_commits = 16;\n-\t\tALLOC_ARRAY(src_commits, alloc_src_commits);\n+\t\tstruct commit_stack src_commits = COMMIT_STACK_INIT;\n \n \t\tfor_each_string_list_item(item, &src_tag) {\n \t\t\tstruct ref *ref = item->util;\n@@ -1460,13 +1458,13 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds\n \t\t\t\t/* not pushing a commit, which is not an error */\n \t\t\t\tcontinue;\n \n-\t\t\tALLOC_GROW(src_commits, nr_src_commits + 1, alloc_src_commits);\n-\t\t\tsrc_commits[nr_src_commits++] = commit;\n+\t\t\tcommit_stack_push(&src_commits, commit);\n \t\t}\n \n \t\tfound_commits = get_reachable_subset(sent_tips.items,\n \t\t\t\t\t\t     sent_tips.nr,\n-\t\t\t\t\t\t     src_commits, nr_src_commits,\n+\t\t\t\t\t\t     src_commits.items,\n+\t\t\t\t\t\t     src_commits.nr,\n \t\t\t\t\t\t     reachable_flag);\n \n \t\tfor_each_string_list_item(item, &src_tag) {\n@@ -1496,8 +1494,9 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds\n \t\t\tdst_ref->peer_ref = copy_ref(ref);\n \t\t}\n \n-\t\tclear_commit_marks_many(nr_src_commits, src_commits, reachable_flag);\n-\t\tfree(src_commits);\n+\t\tclear_commit_marks_many(src_commits.nr, src_commits.items,\n+\t\t\t\t\treachable_flag);\n+\t\tcommit_stack_clear(&src_commits);\n \t\tfree_commit_list(found_commits);\n \t}\n \n-- \n2.52.0\n\n"},{"id":"532720","messageId":"20251224170327.68049-4-l.s.r@web.de","threadId":"64678","inReplyTo":"20251224170327.68049-1-l.s.r@web.de","subject":"[PATCH 03/14] midx: use commit_stack","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-24T17:03:16Z","receivedAt":"2025-12-24T17:03:30Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Simplify collection commits in a callback function by passing it a\ncommit_stack pointer all the way from the caller, instead of using\nseparate variables for array and item count and a bunch of intermediate\nmembers in struct bitmap_commit_cb.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n midx-write.c | 35 ++++++++++++-----------------------\n 1 file changed, 12 insertions(+), 23 deletions(-)\n\ndiff --git a/midx-write.c b/midx-write.c\nindex e3e9be6d03..b4a82d6ba5 100644\n--- a/midx-write.c\n+++ b/midx-write.c\n@@ -723,9 +723,7 @@ static int add_ref_to_pending(const struct reference *ref, void *cb_data)\n }\n \n struct bitmap_commit_cb {\n-\tstruct commit **commits;\n-\tsize_t commits_nr, commits_alloc;\n-\n+\tstruct commit_stack *commits;\n \tstruct write_midx_context *ctx;\n };\n \n@@ -745,8 +743,7 @@ static void bitmap_show_commit(struct commit *commit, void *_data)\n \tif (pos < 0)\n \t\treturn;\n \n-\tALLOC_GROW(data->commits, data->commits_nr + 1, data->commits_alloc);\n-\tdata->commits[data->commits_nr++] = commit;\n+\tcommit_stack_push(data->commits, commit);\n }\n \n static int read_refs_snapshot(const char *refs_snapshot,\n@@ -784,17 +781,15 @@ static int read_refs_snapshot(const char *refs_snapshot,\n \treturn 0;\n }\n \n-static struct commit **find_commits_for_midx_bitmap(uint32_t *indexed_commits_nr_p,\n-\t\t\t\t\t\t    const char *refs_snapshot,\n-\t\t\t\t\t\t    struct write_midx_context *ctx)\n+static void find_commits_for_midx_bitmap(struct commit_stack *commits,\n+\t\t\t\t\t const char *refs_snapshot,\n+\t\t\t\t\t struct write_midx_context *ctx)\n {\n \tstruct rev_info revs;\n-\tstruct bitmap_commit_cb cb = {0};\n+\tstruct bitmap_commit_cb cb = { .commits = commits, .ctx = ctx };\n \n \ttrace2_region_enter(\"midx\", \"find_commits_for_midx_bitmap\", ctx->repo);\n \n-\tcb.ctx = ctx;\n-\n \trepo_init_revisions(ctx->repo, &revs, NULL);\n \tif (refs_snapshot) {\n \t\tread_refs_snapshot(refs_snapshot, &revs);\n@@ -823,14 +818,10 @@ static struct commit **find_commits_for_midx_bitmap(uint32_t *indexed_commits_nr\n \t\tdie(_(\"revision walk setup failed\"));\n \n \ttraverse_commit_list(&revs, bitmap_show_commit, NULL, &cb);\n-\tif (indexed_commits_nr_p)\n-\t\t*indexed_commits_nr_p = cb.commits_nr;\n \n \trelease_revisions(&revs);\n \n \ttrace2_region_leave(\"midx\", \"find_commits_for_midx_bitmap\", ctx->repo);\n-\n-\treturn cb.commits;\n }\n \n static int write_midx_bitmap(struct write_midx_context *ctx,\n@@ -1375,15 +1366,14 @@ static int write_midx_internal(struct odb_source *source,\n \n \tif (flags & MIDX_WRITE_BITMAP) {\n \t\tstruct packing_data pdata;\n-\t\tstruct commit **commits;\n-\t\tuint32_t commits_nr;\n+\t\tstruct commit_stack commits = COMMIT_STACK_INIT;\n \n \t\tif (!ctx.entries_nr)\n \t\t\tBUG(\"cannot write a bitmap without any objects\");\n \n \t\tprepare_midx_packing_data(&pdata, &ctx);\n \n-\t\tcommits = find_commits_for_midx_bitmap(&commits_nr, refs_snapshot, &ctx);\n+\t\tfind_commits_for_midx_bitmap(&commits, refs_snapshot, &ctx);\n \n \t\t/*\n \t\t * The previous steps translated the information from\n@@ -1394,17 +1384,16 @@ static int write_midx_internal(struct odb_source *source,\n \t\tFREE_AND_NULL(ctx.entries);\n \t\tctx.entries_nr = 0;\n \n-\t\tif (write_midx_bitmap(&ctx,\n-\t\t\t\t      midx_hash, &pdata, commits, commits_nr,\n-\t\t\t\t      flags) < 0) {\n+\t\tif (write_midx_bitmap(&ctx, midx_hash, &pdata,\n+\t\t\t\t      commits.items, commits.nr, flags) < 0) {\n \t\t\terror(_(\"could not write multi-pack bitmap\"));\n \t\t\tclear_packing_data(&pdata);\n-\t\t\tfree(commits);\n+\t\t\tcommit_stack_clear(&commits);\n \t\t\tgoto cleanup;\n \t\t}\n \n \t\tclear_packing_data(&pdata);\n-\t\tfree(commits);\n+\t\tcommit_stack_clear(&commits);\n \t}\n \t/*\n \t * NOTE: Do not use ctx.entries beyond this point, since it might\n-- \n2.52.0\n\n"},{"id":"532724","messageId":"20251224170327.68049-7-l.s.r@web.de","threadId":"64678","inReplyTo":"20251224170327.68049-1-l.s.r@web.de","subject":"[PATCH 06/14] remote: use commit_stack for sent_tips","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-24T17:03:19Z","receivedAt":"2025-12-24T17:03:30Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Call commit_stack functions instead of effectively open-coding them.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n remote.c | 20 +++++++-------------\n 1 file changed, 7 insertions(+), 13 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex af888e3f20..ffea887c70 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -1381,12 +1381,7 @@ static struct ref **tail_ref(struct ref **head)\n \treturn tail;\n }\n \n-struct tips {\n-\tstruct commit **tip;\n-\tsize_t nr, alloc;\n-};\n-\n-static void add_to_tips(struct tips *tips, const struct object_id *oid)\n+static void add_to_tips(struct commit_stack *tips, const struct object_id *oid)\n {\n \tstruct commit *commit;\n \n@@ -1396,8 +1391,7 @@ static void add_to_tips(struct tips *tips, const struct object_id *oid)\n \tif (!commit || (commit->object.flags & TMP_MARK))\n \t\treturn;\n \tcommit->object.flags |= TMP_MARK;\n-\tALLOC_GROW(tips->tip, tips->nr + 1, tips->alloc);\n-\ttips->tip[tips->nr++] = commit;\n+\tcommit_stack_push(tips, commit);\n }\n \n static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***dst_tail)\n@@ -1406,13 +1400,12 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds\n \tstruct string_list src_tag = STRING_LIST_INIT_NODUP;\n \tstruct string_list_item *item;\n \tstruct ref *ref;\n-\tstruct tips sent_tips;\n+\tstruct commit_stack sent_tips = COMMIT_STACK_INIT;\n \n \t/*\n \t * Collect everything we know they would have at the end of\n \t * this push, and collect all tags they have.\n \t */\n-\tmemset(&sent_tips, 0, sizeof(sent_tips));\n \tfor (ref = *dst; ref; ref = ref->next) {\n \t\tif (ref->peer_ref &&\n \t\t    !is_null_oid(&ref->peer_ref->new_oid))\n@@ -1422,7 +1415,7 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds\n \t\tif (starts_with(ref->name, \"refs/tags/\"))\n \t\t\tstring_list_append(&dst_tag, ref->name);\n \t}\n-\tclear_commit_marks_many(sent_tips.nr, sent_tips.tip, TMP_MARK);\n+\tclear_commit_marks_many(sent_tips.nr, sent_tips.items, TMP_MARK);\n \n \tstring_list_sort(&dst_tag);\n \n@@ -1471,7 +1464,8 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds\n \t\t\tsrc_commits[nr_src_commits++] = commit;\n \t\t}\n \n-\t\tfound_commits = get_reachable_subset(sent_tips.tip, sent_tips.nr,\n+\t\tfound_commits = get_reachable_subset(sent_tips.items,\n+\t\t\t\t\t\t     sent_tips.nr,\n \t\t\t\t\t\t     src_commits, nr_src_commits,\n \t\t\t\t\t\t     reachable_flag);\n \n@@ -1508,7 +1502,7 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds\n \t}\n \n \tstring_list_clear(&src_tag, 0);\n-\tfree(sent_tips.tip);\n+\tcommit_stack_clear(&sent_tips);\n }\n \n struct ref *find_ref_by_name(const struct ref *list, const char *name)\n-- \n2.52.0\n\n"},{"id":"532715","messageId":"20251224170327.68049-12-l.s.r@web.de","threadId":"64678","inReplyTo":"20251224170327.68049-1-l.s.r@web.de","subject":"[PATCH 11/14] shallow: use commit_stack","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-24T17:03:24Z","receivedAt":"2025-12-24T17:03:31Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"From: Rene Scharfe <l.s.r@web.de>\n\nReplace a commit array implementation with commit_stack.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n shallow.c | 44 +++++++++++++++++---------------------------\n shallow.h |  4 ++--\n 2 files changed, 19 insertions(+), 29 deletions(-)\n\ndiff --git a/shallow.c b/shallow.c\nindex 186e9178f3..c870efcefc 100644\n--- a/shallow.c\n+++ b/shallow.c\n@@ -471,6 +471,7 @@ void prepare_shallow_info(struct shallow_info *info, struct oid_array *sa)\n {\n \ttrace_printf_key(&trace_shallow, \"shallow: prepare_shallow_info\\n\");\n \tmemset(info, 0, sizeof(*info));\n+\tcommit_stack_init(&info->commits);\n \tinfo->shallow = sa;\n \tif (!sa)\n \t\treturn;\n@@ -503,6 +504,7 @@ void clear_shallow_info(struct shallow_info *info)\n \tfree(info->shallow_ref);\n \tfree(info->ours);\n \tfree(info->theirs);\n+\tcommit_stack_clear(&info->commits);\n }\n \n /* Step 4, remove non-existent ones in \"theirs\" after getting the pack */\n@@ -733,19 +735,13 @@ void assign_shallow_commits_to_refs(struct shallow_info *info,\n \tfree(shallow);\n }\n \n-struct commit_array {\n-\tstruct commit **commits;\n-\tsize_t nr, alloc;\n-};\n-\n static int add_ref(const struct reference *ref, void *cb_data)\n {\n-\tstruct commit_array *ca = cb_data;\n-\tALLOC_GROW(ca->commits, ca->nr + 1, ca->alloc);\n-\tca->commits[ca->nr] = lookup_commit_reference_gently(the_repository,\n-\t\t\t\t\t\t\t     ref->oid, 1);\n-\tif (ca->commits[ca->nr])\n-\t\tca->nr++;\n+\tstruct commit_stack *cs = cb_data;\n+\tstruct commit *commit = lookup_commit_reference_gently(the_repository,\n+\t\t\t\t\t\t\t       ref->oid, 1);\n+\tif (commit)\n+\t\tcommit_stack_push(cs, commit);\n \treturn 0;\n }\n \n@@ -770,7 +766,7 @@ static void post_assign_shallow(struct shallow_info *info,\n \tuint32_t **bitmap;\n \tsize_t dst, i, j;\n \tsize_t bitmap_nr = DIV_ROUND_UP(info->ref->nr, 32);\n-\tstruct commit_array ca;\n+\tstruct commit_stack cs = COMMIT_STACK_INIT;\n \n \ttrace_printf_key(&trace_shallow, \"shallow: post_assign_shallow\\n\");\n \tif (ref_status)\n@@ -793,9 +789,8 @@ static void post_assign_shallow(struct shallow_info *info,\n \t}\n \tinfo->nr_theirs = dst;\n \n-\tmemset(&ca, 0, sizeof(ca));\n-\trefs_head_ref(get_main_ref_store(the_repository), add_ref, &ca);\n-\trefs_for_each_ref(get_main_ref_store(the_repository), add_ref, &ca);\n+\trefs_head_ref(get_main_ref_store(the_repository), add_ref, &cs);\n+\trefs_for_each_ref(get_main_ref_store(the_repository), add_ref, &cs);\n \n \t/* Remove unreachable shallow commits from \"ours\" */\n \tfor (i = dst = 0; i < info->nr_ours; i++) {\n@@ -808,7 +803,7 @@ static void post_assign_shallow(struct shallow_info *info,\n \t\tfor (j = 0; j < bitmap_nr; j++)\n \t\t\tif (bitmap[0][j]) {\n \t\t\t\t/* Step 7, reachability test at commit level */\n-\t\t\t\tint ret = repo_in_merge_bases_many(the_repository, c, ca.nr, ca.commits, 1);\n+\t\t\t\tint ret = repo_in_merge_bases_many(the_repository, c, cs.nr, cs.items, 1);\n \t\t\t\tif (ret < 0)\n \t\t\t\t\texit(128);\n \t\t\t\tif (!ret) {\n@@ -820,7 +815,7 @@ static void post_assign_shallow(struct shallow_info *info,\n \t}\n \tinfo->nr_ours = dst;\n \n-\tfree(ca.commits);\n+\tcommit_stack_clear(&cs);\n }\n \n /* (Delayed) step 7, reachability test at commit level */\n@@ -830,22 +825,17 @@ int delayed_reachability_test(struct shallow_info *si, int c)\n \t\tstruct commit *commit = lookup_commit(the_repository,\n \t\t\t\t\t\t      &si->shallow->oid[c]);\n \n-\t\tif (!si->commits) {\n-\t\t\tstruct commit_array ca;\n-\n-\t\t\tmemset(&ca, 0, sizeof(ca));\n+\t\tif (!si->commits.nr) {\n \t\t\trefs_head_ref(get_main_ref_store(the_repository),\n-\t\t\t\t      add_ref, &ca);\n+\t\t\t\t      add_ref, &si->commits);\n \t\t\trefs_for_each_ref(get_main_ref_store(the_repository),\n-\t\t\t\t\t  add_ref, &ca);\n-\t\t\tsi->commits = ca.commits;\n-\t\t\tsi->nr_commits = ca.nr;\n+\t\t\t\t\t  add_ref, &si->commits);\n \t\t}\n \n \t\tsi->reachable[c] = repo_in_merge_bases_many(the_repository,\n \t\t\t\t\t\t\t    commit,\n-\t\t\t\t\t\t\t    si->nr_commits,\n-\t\t\t\t\t\t\t    si->commits,\n+\t\t\t\t\t\t\t    si->commits.nr,\n+\t\t\t\t\t\t\t    si->commits.items,\n \t\t\t\t\t\t\t    1);\n \t\tif (si->reachable[c] < 0)\n \t\t\texit(128);\ndiff --git a/shallow.h b/shallow.h\nindex ad591bd139..1c0787de1d 100644\n--- a/shallow.h\n+++ b/shallow.h\n@@ -1,6 +1,7 @@\n #ifndef SHALLOW_H\n #define SHALLOW_H\n \n+#include \"commit.h\"\n #include \"lockfile.h\"\n #include \"object.h\"\n #include \"repository.h\"\n@@ -69,8 +70,7 @@ struct shallow_info {\n \tint *need_reachability_test;\n \tint *reachable;\n \tint *shallow_ref;\n-\tstruct commit **commits;\n-\tsize_t nr_commits;\n+\tstruct commit_stack commits;\n };\n \n void prepare_shallow_info(struct shallow_info *, struct oid_array *);\n-- \n2.52.0\n\n"},{"id":"532718","messageId":"20251224170327.68049-11-l.s.r@web.de","threadId":"64678","inReplyTo":"20251224170327.68049-1-l.s.r@web.de","subject":"[PATCH 10/14] pack-bitmap-write: use commit_stack","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-24T17:03:23Z","receivedAt":"2025-12-24T17:03:31Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Use commit_stack instead of open-coding it.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n pack-bitmap-write.c | 18 +++++++-----------\n 1 file changed, 7 insertions(+), 11 deletions(-)\n\ndiff --git a/pack-bitmap-write.c b/pack-bitmap-write.c\nindex 4404921521..bf73ce5710 100644\n--- a/pack-bitmap-write.c\n+++ b/pack-bitmap-write.c\n@@ -315,8 +315,7 @@ define_commit_slab(bb_data, struct bb_commit);\n \n struct bitmap_builder {\n \tstruct bb_data data;\n-\tstruct commit **commits;\n-\tsize_t commits_nr, commits_alloc;\n+\tstruct commit_stack commits;\n };\n \n static void bitmap_builder_init(struct bitmap_builder *bb,\n@@ -329,8 +328,8 @@ static void bitmap_builder_init(struct bitmap_builder *bb,\n \tstruct commit_list *r;\n \tunsigned int i, num_maximal = 0;\n \n-\tmemset(bb, 0, sizeof(*bb));\n \tinit_bb_data(&bb->data);\n+\tcommit_stack_init(&bb->commits);\n \n \treset_revision_walk();\n \trepo_init_revisions(writer->to_pack->repo, &revs, NULL);\n@@ -390,8 +389,7 @@ static void bitmap_builder_init(struct bitmap_builder *bb,\n \n \t\tif (c_ent->maximal) {\n \t\t\tnum_maximal++;\n-\t\t\tALLOC_GROW(bb->commits, bb->commits_nr + 1, bb->commits_alloc);\n-\t\t\tbb->commits[bb->commits_nr++] = commit;\n+\t\t\tcommit_stack_push(&bb->commits, commit);\n \t\t}\n \n \t\tif (p) {\n@@ -438,8 +436,7 @@ static void bitmap_builder_init(struct bitmap_builder *bb,\n \t}\n \n \tfor (r = reusable; r; r = r->next) {\n-\t\tALLOC_GROW(bb->commits, bb->commits_nr + 1, bb->commits_alloc);\n-\t\tbb->commits[bb->commits_nr++] = r->item;\n+\t\tcommit_stack_push(&bb->commits, r->item);\n \t}\n \n \ttrace2_data_intmax(\"pack-bitmap-write\", writer->repo,\n@@ -454,8 +451,7 @@ static void bitmap_builder_init(struct bitmap_builder *bb,\n static void bitmap_builder_clear(struct bitmap_builder *bb)\n {\n \tdeep_clear_bb_data(&bb->data, clear_bb_commit);\n-\tfree(bb->commits);\n-\tbb->commits_nr = bb->commits_alloc = 0;\n+\tcommit_stack_clear(&bb->commits);\n }\n \n static int fill_bitmap_tree(struct bitmap_writer *writer,\n@@ -630,8 +626,8 @@ int bitmap_writer_build(struct bitmap_writer *writer)\n \t\tmapping = NULL;\n \n \tbitmap_builder_init(&bb, writer, old_bitmap);\n-\tfor (i = bb.commits_nr; i > 0; i--) {\n-\t\tstruct commit *commit = bb.commits[i-1];\n+\tfor (i = bb.commits.nr; i > 0; i--) {\n+\t\tstruct commit *commit = bb.commits.items[i-1];\n \t\tstruct bb_commit *ent = bb_data_at(&bb.data, commit);\n \t\tstruct commit *child;\n \t\tint reused = 0;\n-- \n2.52.0\n\n"},{"id":"532719","messageId":"20251224170327.68049-10-l.s.r@web.de","threadId":"64678","inReplyTo":"20251224170327.68049-1-l.s.r@web.de","subject":"[PATCH 09/14] commit: add commit_stack_init()","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-24T17:03:22Z","receivedAt":"2025-12-24T17:03:31Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Add a function for initializing a struct commit_stack, for when static\ninitialization is not possible or impractical.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n commit.c | 10 ++++++++--\n commit.h |  1 +\n 2 files changed, 9 insertions(+), 2 deletions(-)\n\ndiff --git a/commit.c b/commit.c\nindex f2edafa49c..55b1c8d2f8 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1982,6 +1982,12 @@ int run_commit_hook(int editor_is_used, const char *index_file,\n \treturn run_hooks_opt(the_repository, name, &opt);\n }\n \n+void commit_stack_init(struct commit_stack *stack)\n+{\n+\tstack->items = NULL;\n+\tstack->nr = stack->alloc = 0;\n+}\n+\n void commit_stack_push(struct commit_stack *stack, struct commit *commit)\n {\n \tALLOC_GROW(stack->items, stack->nr + 1, stack->alloc);\n@@ -1995,6 +2001,6 @@ struct commit *commit_stack_pop(struct commit_stack *stack)\n \n void commit_stack_clear(struct commit_stack *stack)\n {\n-\tFREE_AND_NULL(stack->items);\n-\tstack->nr = stack->alloc = 0;\n+\tfree(stack->items);\n+\tcommit_stack_init(stack);\n }\ndiff --git a/commit.h b/commit.h\nindex 81e047f820..7c01a76425 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -387,6 +387,7 @@ struct commit_stack {\n };\n #define COMMIT_STACK_INIT { 0 }\n \n+void commit_stack_init(struct commit_stack *);\n void commit_stack_push(struct commit_stack *, struct commit *);\n struct commit *commit_stack_pop(struct commit_stack *);\n void commit_stack_clear(struct commit_stack *);\n-- \n2.52.0\n\n"},{"id":"532721","messageId":"20251224170327.68049-14-l.s.r@web.de","threadId":"64678","inReplyTo":"20251224170327.68049-1-l.s.r@web.de","subject":"[PATCH 13/14] commit-graph: use commit_stack","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-24T17:03:26Z","receivedAt":"2025-12-24T17:03:31Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Replace a commit array implementation with commit_stack.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n commit-graph.c | 86 +++++++++++++++++++++++---------------------------\n 1 file changed, 39 insertions(+), 47 deletions(-)\n\ndiff --git a/commit-graph.c b/commit-graph.c\nindex 80be2ff2c3..00e8193adc 100644\n--- a/commit-graph.c\n+++ b/commit-graph.c\n@@ -1127,18 +1127,12 @@ struct tree *get_commit_tree_in_graph(struct repository *r, const struct commit\n \treturn get_commit_tree_in_graph_one(r->objects->commit_graph, c);\n }\n \n-struct packed_commit_list {\n-\tstruct commit **list;\n-\tsize_t nr;\n-\tsize_t alloc;\n-};\n-\n struct write_commit_graph_context {\n \tstruct repository *r;\n \tstruct odb_source *odb_source;\n \tchar *graph_name;\n \tstruct oid_array oids;\n-\tstruct packed_commit_list commits;\n+\tstruct commit_stack commits;\n \tint num_extra_edges;\n \tint num_generation_data_overflows;\n \tunsigned long approx_nr_objects;\n@@ -1180,7 +1174,7 @@ static int write_graph_chunk_fanout(struct hashfile *f,\n {\n \tstruct write_commit_graph_context *ctx = data;\n \tint i, count = 0;\n-\tstruct commit **list = ctx->commits.list;\n+\tstruct commit **list = ctx->commits.items;\n \n \t/*\n \t * Write the first-level table (the list is sorted,\n@@ -1206,7 +1200,7 @@ static int write_graph_chunk_oids(struct hashfile *f,\n \t\t\t\t  void *data)\n {\n \tstruct write_commit_graph_context *ctx = data;\n-\tstruct commit **list = ctx->commits.list;\n+\tstruct commit **list = ctx->commits.items;\n \tint count;\n \tfor (count = 0; count < ctx->commits.nr; count++, list++) {\n \t\tdisplay_progress(ctx->progress, ++ctx->progress_cnt);\n@@ -1226,8 +1220,8 @@ static int write_graph_chunk_data(struct hashfile *f,\n \t\t\t\t  void *data)\n {\n \tstruct write_commit_graph_context *ctx = data;\n-\tstruct commit **list = ctx->commits.list;\n-\tstruct commit **last = ctx->commits.list + ctx->commits.nr;\n+\tstruct commit **list = ctx->commits.items;\n+\tstruct commit **last = ctx->commits.items + ctx->commits.nr;\n \tuint32_t num_extra_edges = 0;\n \n \twhile (list < last) {\n@@ -1249,7 +1243,7 @@ static int write_graph_chunk_data(struct hashfile *f,\n \t\t\tedge_value = GRAPH_PARENT_NONE;\n \t\telse {\n \t\t\tedge_value = oid_pos(&parent->item->object.oid,\n-\t\t\t\t\t     ctx->commits.list,\n+\t\t\t\t\t     ctx->commits.items,\n \t\t\t\t\t     ctx->commits.nr,\n \t\t\t\t\t     commit_to_oid);\n \n@@ -1280,7 +1274,7 @@ static int write_graph_chunk_data(struct hashfile *f,\n \t\t\tedge_value = GRAPH_EXTRA_EDGES_NEEDED | num_extra_edges;\n \t\telse {\n \t\t\tedge_value = oid_pos(&parent->item->object.oid,\n-\t\t\t\t\t     ctx->commits.list,\n+\t\t\t\t\t     ctx->commits.items,\n \t\t\t\t\t     ctx->commits.nr,\n \t\t\t\t\t     commit_to_oid);\n \n@@ -1332,7 +1326,7 @@ static int write_graph_chunk_generation_data(struct hashfile *f,\n \tint i, num_generation_data_overflows = 0;\n \n \tfor (i = 0; i < ctx->commits.nr; i++) {\n-\t\tstruct commit *c = ctx->commits.list[i];\n+\t\tstruct commit *c = ctx->commits.items[i];\n \t\ttimestamp_t offset;\n \t\trepo_parse_commit(ctx->r, c);\n \t\toffset = commit_graph_data_at(c)->generation - c->date;\n@@ -1355,7 +1349,7 @@ static int write_graph_chunk_generation_data_overflow(struct hashfile *f,\n \tstruct write_commit_graph_context *ctx = data;\n \tint i;\n \tfor (i = 0; i < ctx->commits.nr; i++) {\n-\t\tstruct commit *c = ctx->commits.list[i];\n+\t\tstruct commit *c = ctx->commits.items[i];\n \t\ttimestamp_t offset = commit_graph_data_at(c)->generation - c->date;\n \t\tdisplay_progress(ctx->progress, ++ctx->progress_cnt);\n \n@@ -1372,8 +1366,8 @@ static int write_graph_chunk_extra_edges(struct hashfile *f,\n \t\t\t\t\t void *data)\n {\n \tstruct write_commit_graph_context *ctx = data;\n-\tstruct commit **list = ctx->commits.list;\n-\tstruct commit **last = ctx->commits.list + ctx->commits.nr;\n+\tstruct commit **list = ctx->commits.items;\n+\tstruct commit **last = ctx->commits.items + ctx->commits.nr;\n \tstruct commit_list *parent;\n \n \twhile (list < last) {\n@@ -1393,7 +1387,7 @@ static int write_graph_chunk_extra_edges(struct hashfile *f,\n \t\t/* Since num_parents > 2, this initializer is safe. */\n \t\tfor (parent = (*list)->parents->next; parent; parent = parent->next) {\n \t\t\tint edge_value = oid_pos(&parent->item->object.oid,\n-\t\t\t\t\t\t ctx->commits.list,\n+\t\t\t\t\t\t ctx->commits.items,\n \t\t\t\t\t\t ctx->commits.nr,\n \t\t\t\t\t\t commit_to_oid);\n \n@@ -1427,8 +1421,8 @@ static int write_graph_chunk_bloom_indexes(struct hashfile *f,\n \t\t\t\t\t   void *data)\n {\n \tstruct write_commit_graph_context *ctx = data;\n-\tstruct commit **list = ctx->commits.list;\n-\tstruct commit **last = ctx->commits.list + ctx->commits.nr;\n+\tstruct commit **list = ctx->commits.items;\n+\tstruct commit **last = ctx->commits.items + ctx->commits.nr;\n \tuint32_t cur_pos = 0;\n \n \twhile (list < last) {\n@@ -1463,8 +1457,8 @@ static int write_graph_chunk_bloom_data(struct hashfile *f,\n \t\t\t\t\tvoid *data)\n {\n \tstruct write_commit_graph_context *ctx = data;\n-\tstruct commit **list = ctx->commits.list;\n-\tstruct commit **last = ctx->commits.list + ctx->commits.nr;\n+\tstruct commit **list = ctx->commits.items;\n+\tstruct commit **last = ctx->commits.items + ctx->commits.nr;\n \n \ttrace2_bloom_filter_settings(ctx);\n \n@@ -1585,7 +1579,7 @@ static void close_reachable(struct write_commit_graph_context *ctx)\n \n struct compute_generation_info {\n \tstruct repository *r;\n-\tstruct packed_commit_list *commits;\n+\tstruct commit_stack *commits;\n \tstruct progress *progress;\n \tint progress_cnt;\n \n@@ -1622,7 +1616,7 @@ static void compute_reachable_generation_numbers(\n \tstruct commit_list *list = NULL;\n \n \tfor (i = 0; i < info->commits->nr; i++) {\n-\t\tstruct commit *c = info->commits->list[i];\n+\t\tstruct commit *c = info->commits->items[i];\n \t\ttimestamp_t gen;\n \t\trepo_parse_commit(info->r, c);\n \t\tgen = info->get_generation(c, info->data);\n@@ -1729,7 +1723,7 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)\n \n \tif (!ctx->trust_generation_numbers) {\n \t\tfor (i = 0; i < ctx->commits.nr; i++) {\n-\t\t\tstruct commit *c = ctx->commits.list[i];\n+\t\t\tstruct commit *c = ctx->commits.items[i];\n \t\t\trepo_parse_commit(ctx->r, c);\n \t\t\tcommit_graph_data_at(c)->generation = GENERATION_NUMBER_ZERO;\n \t\t}\n@@ -1738,7 +1732,7 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)\n \tcompute_reachable_generation_numbers(&info, 2);\n \n \tfor (i = 0; i < ctx->commits.nr; i++) {\n-\t\tstruct commit *c = ctx->commits.list[i];\n+\t\tstruct commit *c = ctx->commits.items[i];\n \t\ttimestamp_t offset = commit_graph_data_at(c)->generation - c->date;\n \t\tif (offset > GENERATION_NUMBER_V2_OFFSET_MAX)\n \t\t\tctx->num_generation_data_overflows++;\n@@ -1760,8 +1754,8 @@ void ensure_generations_valid(struct repository *r,\n \t\t\t      struct commit **commits, size_t nr)\n {\n \tint generation_version = get_configured_generation_version(r);\n-\tstruct packed_commit_list list = {\n-\t\t.list = commits,\n+\tstruct commit_stack list = {\n+\t\t.items = commits,\n \t\t.alloc = nr,\n \t\t.nr = nr,\n \t};\n@@ -1804,7 +1798,7 @@ static void compute_bloom_filters(struct write_commit_graph_context *ctx)\n \t\t\t_(\"Computing commit changed paths Bloom filters\"),\n \t\t\tctx->commits.nr);\n \n-\tDUP_ARRAY(sorted_commits, ctx->commits.list, ctx->commits.nr);\n+\tDUP_ARRAY(sorted_commits, ctx->commits.items, ctx->commits.nr);\n \n \tif (ctx->order_by_pack)\n \t\tQSORT(sorted_commits, ctx->commits.nr, commit_pos_cmp);\n@@ -1992,26 +1986,26 @@ static void copy_oids_to_commits(struct write_commit_graph_context *ctx)\n \toid_array_sort(&ctx->oids);\n \tfor (i = 0; i < ctx->oids.nr; i = oid_array_next_unique(&ctx->oids, i)) {\n \t\tunsigned int num_parents;\n+\t\tstruct commit *commit;\n \n \t\tdisplay_progress(ctx->progress, i + 1);\n \n-\t\tALLOC_GROW(ctx->commits.list, ctx->commits.nr + 1, ctx->commits.alloc);\n-\t\tctx->commits.list[ctx->commits.nr] = lookup_commit(ctx->r, &ctx->oids.oid[i]);\n+\t\tcommit = lookup_commit(ctx->r, &ctx->oids.oid[i]);\n \n \t\tif (ctx->split && flags != COMMIT_GRAPH_SPLIT_REPLACE &&\n-\t\t    commit_graph_position(ctx->commits.list[ctx->commits.nr]) != COMMIT_NOT_FROM_GRAPH)\n+\t\t    commit_graph_position(commit) != COMMIT_NOT_FROM_GRAPH)\n \t\t\tcontinue;\n \n \t\tif (ctx->split && flags == COMMIT_GRAPH_SPLIT_REPLACE)\n-\t\t\trepo_parse_commit(ctx->r, ctx->commits.list[ctx->commits.nr]);\n+\t\t\trepo_parse_commit(ctx->r, commit);\n \t\telse\n-\t\t\trepo_parse_commit_no_graph(ctx->r, ctx->commits.list[ctx->commits.nr]);\n+\t\t\trepo_parse_commit_no_graph(ctx->r, commit);\n \n-\t\tnum_parents = commit_list_count(ctx->commits.list[ctx->commits.nr]->parents);\n+\t\tnum_parents = commit_list_count(commit->parents);\n \t\tif (num_parents > 2)\n \t\t\tctx->num_extra_edges += num_parents - 1;\n \n-\t\tctx->commits.nr++;\n+\t\tcommit_stack_push(&ctx->commits, commit);\n \t}\n \tstop_progress(&ctx->progress);\n }\n@@ -2330,7 +2324,7 @@ static void merge_commit_graph(struct write_commit_graph_context *ctx,\n \t\t    oid_to_hex(&g->oid),\n \t\t    (uintmax_t)st_add(ctx->commits.nr, g->num_commits));\n \n-\tALLOC_GROW(ctx->commits.list, ctx->commits.nr + g->num_commits, ctx->commits.alloc);\n+\tcommit_stack_grow(&ctx->commits, g->num_commits);\n \n \tfor (i = 0; i < g->num_commits; i++) {\n \t\tstruct object_id oid;\n@@ -2343,10 +2337,8 @@ static void merge_commit_graph(struct write_commit_graph_context *ctx,\n \t\t/* only add commits if they still exist in the repo */\n \t\tresult = lookup_commit_reference_gently(ctx->r, &oid, 1);\n \n-\t\tif (result) {\n-\t\t\tctx->commits.list[ctx->commits.nr] = result;\n-\t\t\tctx->commits.nr++;\n-\t\t}\n+\t\tif (result)\n+\t\t\tcommit_stack_push(&ctx->commits, result);\n \t}\n }\n \n@@ -2367,14 +2359,14 @@ static void sort_and_scan_merged_commits(struct write_commit_graph_context *ctx)\n \t\t\t\t\t_(\"Scanning merged commits\"),\n \t\t\t\t\tctx->commits.nr);\n \n-\tQSORT(ctx->commits.list, ctx->commits.nr, commit_compare);\n+\tQSORT(ctx->commits.items, ctx->commits.nr, commit_compare);\n \n \tctx->num_extra_edges = 0;\n \tfor (i = 0; i < ctx->commits.nr; i++) {\n \t\tdisplay_progress(ctx->progress, i + 1);\n \n-\t\tif (i && oideq(&ctx->commits.list[i - 1]->object.oid,\n-\t\t\t  &ctx->commits.list[i]->object.oid)) {\n+\t\tif (i && oideq(&ctx->commits.items[i - 1]->object.oid,\n+\t\t\t  &ctx->commits.items[i]->object.oid)) {\n \t\t\t/*\n \t\t\t * Silently ignore duplicates. These were likely\n \t\t\t * created due to a commit appearing in multiple\n@@ -2385,10 +2377,10 @@ static void sort_and_scan_merged_commits(struct write_commit_graph_context *ctx)\n \t\t} else {\n \t\t\tunsigned int num_parents;\n \n-\t\t\tctx->commits.list[dedup_i] = ctx->commits.list[i];\n+\t\t\tctx->commits.items[dedup_i] = ctx->commits.items[i];\n \t\t\tdedup_i++;\n \n-\t\t\tnum_parents = commit_list_count(ctx->commits.list[i]->parents);\n+\t\t\tnum_parents = commit_list_count(ctx->commits.items[i]->parents);\n \t\t\tif (num_parents > 2)\n \t\t\t\tctx->num_extra_edges += num_parents - 1;\n \t\t}\n@@ -2666,7 +2658,7 @@ int write_commit_graph(struct odb_source *source,\n cleanup:\n \tfree(ctx.graph_name);\n \tfree(ctx.base_graph_name);\n-\tfree(ctx.commits.list);\n+\tcommit_stack_clear(&ctx.commits);\n \toid_array_clear(&ctx.oids);\n \tclear_topo_level_slab(&topo_levels);\n \n-- \n2.52.0\n\n"},{"id":"532722","messageId":"20251224170327.68049-15-l.s.r@web.de","threadId":"64678","inReplyTo":"20251224170327.68049-1-l.s.r@web.de","subject":"[PATCH 14/14] commit-reach: use commit_stack","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-24T17:03:27Z","receivedAt":"2025-12-24T17:03:31Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Use commit_stack instead of open-coding it.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n commit-reach.c | 25 ++++++++++++-------------\n 1 file changed, 12 insertions(+), 13 deletions(-)\n\ndiff --git a/commit-reach.c b/commit-reach.c\nindex cc18c86d3b..e7d9b3208f 100644\n--- a/commit-reach.c\n+++ b/commit-reach.c\n@@ -283,8 +283,8 @@ static int remove_redundant_with_gen(struct repository *r,\n {\n \tsize_t i, count_non_stale = 0, count_still_independent = cnt;\n \ttimestamp_t min_generation = GENERATION_NUMBER_INFINITY;\n-\tstruct commit **walk_start, **sorted;\n-\tsize_t walk_start_nr = 0, walk_start_alloc = cnt;\n+\tstruct commit **sorted;\n+\tstruct commit_stack walk_start = COMMIT_STACK_INIT;\n \tsize_t min_gen_pos = 0;\n \n \t/*\n@@ -298,7 +298,7 @@ static int remove_redundant_with_gen(struct repository *r,\n \tQSORT(sorted, cnt, compare_commits_by_gen);\n \tmin_generation = commit_graph_generation(sorted[0]);\n \n-\tALLOC_ARRAY(walk_start, walk_start_alloc);\n+\tcommit_stack_grow(&walk_start, cnt);\n \n \t/* Mark all parents of the input as STALE */\n \tfor (i = 0; i < cnt; i++) {\n@@ -312,18 +312,17 @@ static int remove_redundant_with_gen(struct repository *r,\n \t\t\trepo_parse_commit(r, parents->item);\n \t\t\tif (!(parents->item->object.flags & STALE)) {\n \t\t\t\tparents->item->object.flags |= STALE;\n-\t\t\t\tALLOC_GROW(walk_start, walk_start_nr + 1, walk_start_alloc);\n-\t\t\t\twalk_start[walk_start_nr++] = parents->item;\n+\t\t\t\tcommit_stack_push(&walk_start, parents->item);\n \t\t\t}\n \t\t\tparents = parents->next;\n \t\t}\n \t}\n \n-\tQSORT(walk_start, walk_start_nr, compare_commits_by_gen);\n+\tQSORT(walk_start.items, walk_start.nr, compare_commits_by_gen);\n \n \t/* remove STALE bit for now to allow walking through parents */\n-\tfor (i = 0; i < walk_start_nr; i++)\n-\t\twalk_start[i]->object.flags &= ~STALE;\n+\tfor (i = 0; i < walk_start.nr; i++)\n+\t\twalk_start.items[i]->object.flags &= ~STALE;\n \n \t/*\n \t * Start walking from the highest generation. Hopefully, it will\n@@ -331,12 +330,12 @@ static int remove_redundant_with_gen(struct repository *r,\n \t * terminate early. Otherwise, we will do the same amount of work\n \t * as before.\n \t */\n-\tfor (i = walk_start_nr; i && count_still_independent > 1; i--) {\n+\tfor (i = walk_start.nr; i && count_still_independent > 1; i--) {\n \t\t/* push the STALE bits up to min generation */\n \t\tstruct commit_list *stack = NULL;\n \n-\t\tcommit_list_insert(walk_start[i - 1], &stack);\n-\t\twalk_start[i - 1]->object.flags |= STALE;\n+\t\tcommit_list_insert(walk_start.items[i - 1], &stack);\n+\t\twalk_start.items[i - 1]->object.flags |= STALE;\n \n \t\twhile (stack) {\n \t\t\tstruct commit_list *parents;\n@@ -390,8 +389,8 @@ static int remove_redundant_with_gen(struct repository *r,\n \t}\n \n \t/* clear marks */\n-\tclear_commit_marks_many(walk_start_nr, walk_start, STALE);\n-\tfree(walk_start);\n+\tclear_commit_marks_many(walk_start.nr, walk_start.items, STALE);\n+\tcommit_stack_clear(&walk_start);\n \n \t*dedup_cnt = count_non_stale;\n \treturn 0;\n-- \n2.52.0\n\n"},{"id":"532723","messageId":"20251224170327.68049-13-l.s.r@web.de","threadId":"64678","inReplyTo":"20251224170327.68049-1-l.s.r@web.de","subject":"[PATCH 12/14] commit: add commit_stack_grow()","fromName":"René Scharfe","fromEmail":"l.s.r@web.de","sentAt":"2025-12-24T17:03:25Z","receivedAt":"2025-12-24T17:03:31Z","isPatch":true,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Add a function for increasing the capacity of a commit_stack.  It is\nuseful for reducing reallocations when the target size is known in\nadvance.\n\nSigned-off-by: René Scharfe <l.s.r@web.de>\n---\n commit.c | 7 ++++++-\n commit.h | 1 +\n 2 files changed, 7 insertions(+), 1 deletion(-)\n\ndiff --git a/commit.c b/commit.c\nindex 55b1c8d2f8..28bb5ce029 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1988,9 +1988,14 @@ void commit_stack_init(struct commit_stack *stack)\n \tstack->nr = stack->alloc = 0;\n }\n \n+void commit_stack_grow(struct commit_stack *stack, size_t extra)\n+{\n+\tALLOC_GROW(stack->items, st_add(stack->nr, extra), stack->alloc);\n+}\n+\n void commit_stack_push(struct commit_stack *stack, struct commit *commit)\n {\n-\tALLOC_GROW(stack->items, stack->nr + 1, stack->alloc);\n+\tcommit_stack_grow(stack, 1);\n \tstack->items[stack->nr++] = commit;\n }\n \ndiff --git a/commit.h b/commit.h\nindex 7c01a76425..79a761c37d 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -388,6 +388,7 @@ struct commit_stack {\n #define COMMIT_STACK_INIT { 0 }\n \n void commit_stack_init(struct commit_stack *);\n+void commit_stack_grow(struct commit_stack *, size_t);\n void commit_stack_push(struct commit_stack *, struct commit *);\n struct commit *commit_stack_pop(struct commit_stack *);\n void commit_stack_clear(struct commit_stack *);\n-- \n2.52.0\n\n"}]}