public inbox for git@vger.kernel.org 
 help / color / mirror / Atom feed
* [PATCH 00/14] export and use commit_stack
@ 2025-12-24 17:03 René Scharfe
  2025-12-24 17:03 ` [PATCH 01/14] revision: export commit_stack René Scharfe
                   ` (13 more replies)
  0 siblings, 14 replies; 15+ messages in thread
From: René Scharfe @ 2025-12-24 17:03 UTC (permalink / raw)
  To: git

There are more than ten different variants of dynamic arrays of commit
pointers.  Pick one implementation, export it, add _init() and _grow()
functions and use it to reduce code duplication.

  revision: export commit_stack
  log: use commit_stack
  midx: use commit_stack
  name-rev: use commit_stack
  remote: use commit_stack for local_commits
  remote: use commit_stack for sent_tips
  remote: use commit_stack for src_commits
  test-reach: use commit_stack

  commit: add commit_stack_init()
  pack-bitmap-write: use commit_stack
  shallow: use commit_stack

  commit: add commit_stack_grow()
  commit-graph: use commit_stack
  commit-reach: use commit_stack

 builtin/log.c         | 31 ++++++++--------
 builtin/name-rev.c    | 17 +++------
 commit-graph.c        | 86 ++++++++++++++++++++-----------------------
 commit-reach.c        | 25 ++++++-------
 commit.c              | 28 ++++++++++++++
 commit.h              | 12 ++++++
 midx-write.c          | 35 ++++++------------
 pack-bitmap-write.c   | 18 ++++-----
 remote.c              | 74 ++++++++++---------------------------
 revision.c            | 23 ------------
 shallow.c             | 44 +++++++++-------------
 shallow.h             |  4 +-
 t/helper/test-reach.c | 34 +++++++----------
 13 files changed, 184 insertions(+), 247 deletions(-)

-- 
2.52.0


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 01/14] revision: export commit_stack
  2025-12-24 17:03 [PATCH 00/14] export and use commit_stack René Scharfe
@ 2025-12-24 17:03 ` René Scharfe
  2025-12-24 17:03 ` [PATCH 02/14] log: use commit_stack René Scharfe
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: René Scharfe @ 2025-12-24 17:03 UTC (permalink / raw)
  To: git

Dynamic arrays of commit pointers are used in several places.  Some of
them use a custom struct to hold array, item count and capacity, others
have them as separate variables linked by a common name part.

Pick one succinct, clean implementation -- commit_stack -- and convert
the different variants to it to reduce code duplication.

Signed-off-by: René Scharfe <l.s.r@web•de>
---
 commit.c   | 17 +++++++++++++++++
 commit.h   | 10 ++++++++++
 revision.c | 23 -----------------------
 3 files changed, 27 insertions(+), 23 deletions(-)

diff --git a/commit.c b/commit.c
index 709c9eed58..f2edafa49c 100644
--- a/commit.c
+++ b/commit.c
@@ -1981,3 +1981,20 @@ int run_commit_hook(int editor_is_used, const char *index_file,
 	opt.invoked_hook = invoked_hook;
 	return run_hooks_opt(the_repository, name, &opt);
 }
+
+void commit_stack_push(struct commit_stack *stack, struct commit *commit)
+{
+	ALLOC_GROW(stack->items, stack->nr + 1, stack->alloc);
+	stack->items[stack->nr++] = commit;
+}
+
+struct commit *commit_stack_pop(struct commit_stack *stack)
+{
+	return stack->nr ? stack->items[--stack->nr] : NULL;
+}
+
+void commit_stack_clear(struct commit_stack *stack)
+{
+	FREE_AND_NULL(stack->items);
+	stack->nr = stack->alloc = 0;
+}
diff --git a/commit.h b/commit.h
index 5406dd2663..81e047f820 100644
--- a/commit.h
+++ b/commit.h
@@ -381,4 +381,14 @@ int parse_buffer_signed_by_header(const char *buffer,
 				  const struct git_hash_algo *algop);
 int add_header_signature(struct strbuf *buf, struct strbuf *sig, const struct git_hash_algo *algo);
 
+struct commit_stack {
+	struct commit **items;
+	size_t nr, alloc;
+};
+#define COMMIT_STACK_INIT { 0 }
+
+void commit_stack_push(struct commit_stack *, struct commit *);
+struct commit *commit_stack_pop(struct commit_stack *);
+void commit_stack_clear(struct commit_stack *);
+
 #endif /* COMMIT_H */
diff --git a/revision.c b/revision.c
index 5f0850ae5c..1858e093ee 100644
--- a/revision.c
+++ b/revision.c
@@ -250,29 +250,6 @@ void mark_trees_uninteresting_sparse(struct repository *r,
 	paths_and_oids_clear(&map);
 }
 
-struct commit_stack {
-	struct commit **items;
-	size_t nr, alloc;
-};
-#define COMMIT_STACK_INIT { 0 }
-
-static void commit_stack_push(struct commit_stack *stack, struct commit *commit)
-{
-	ALLOC_GROW(stack->items, stack->nr + 1, stack->alloc);
-	stack->items[stack->nr++] = commit;
-}
-
-static struct commit *commit_stack_pop(struct commit_stack *stack)
-{
-	return stack->nr ? stack->items[--stack->nr] : NULL;
-}
-
-static void commit_stack_clear(struct commit_stack *stack)
-{
-	FREE_AND_NULL(stack->items);
-	stack->nr = stack->alloc = 0;
-}
-
 static void mark_one_parent_uninteresting(struct rev_info *revs, struct commit *commit,
 					  struct commit_stack *pending)
 {
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 02/14] log: use commit_stack
  2025-12-24 17:03 [PATCH 00/14] export and use commit_stack René Scharfe
  2025-12-24 17:03 ` [PATCH 01/14] revision: export commit_stack René Scharfe
@ 2025-12-24 17:03 ` René Scharfe
  2025-12-24 17:03 ` [PATCH 03/14] midx: " René Scharfe
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: René Scharfe @ 2025-12-24 17:03 UTC (permalink / raw)
  To: git

Calling commit_stack_push() to add commits is simpler and more efficient
than using REALLOC_ARRAY.  Calling commit_stack_pop() to consume them in
LIFO order is also a tad simpler than calculating the array index from
the end.

Signed-off-by: René Scharfe <l.s.r@web•de>
---
 builtin/log.c | 31 +++++++++++++++----------------
 1 file changed, 15 insertions(+), 16 deletions(-)

diff --git a/builtin/log.c b/builtin/log.c
index d4cf9c59c8..5c9a8ef363 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -1896,11 +1896,11 @@ int cmd_format_patch(int argc,
 {
 	struct format_config cfg;
 	struct commit *commit;
-	struct commit **list = NULL;
+	struct commit_stack list = COMMIT_STACK_INIT;
 	struct rev_info rev;
 	char *to_free = NULL;
 	struct setup_revision_opt s_r_opt;
-	size_t nr = 0, total, i;
+	size_t total, i;
 	int use_stdout = 0;
 	int start_number = -1;
 	int just_numbers = 0;
@@ -2283,14 +2283,12 @@ int cmd_format_patch(int argc,
 		if (ignore_if_in_upstream && has_commit_patch_id(commit, &ids))
 			continue;
 
-		nr++;
-		REALLOC_ARRAY(list, nr);
-		list[nr - 1] = commit;
+		commit_stack_push(&list, commit);
 	}
-	if (nr == 0)
+	if (!list.nr)
 		/* nothing to do */
 		goto done;
-	total = nr;
+	total = list.nr;
 	if (cover_letter == -1) {
 		if (cfg.config_cover_letter == COVER_AUTO)
 			cover_letter = (total > 1);
@@ -2308,7 +2306,7 @@ int cmd_format_patch(int argc,
 		if (!cover_letter && total != 1)
 			die(_("--interdiff requires --cover-letter or single patch"));
 		rev.idiff_oid1 = &idiff_prev.oid[idiff_prev.nr - 1];
-		rev.idiff_oid2 = get_commit_tree_oid(list[0]);
+		rev.idiff_oid2 = get_commit_tree_oid(list.items[0]);
 		rev.idiff_title = diff_title(&idiff_title, reroll_count,
 					     _("Interdiff:"),
 					     _("Interdiff against v%d:"));
@@ -2324,7 +2322,7 @@ int cmd_format_patch(int argc,
 			die(_("--range-diff requires --cover-letter or single patch"));
 
 		infer_range_diff_ranges(&rdiff1, &rdiff2, rdiff_prev,
-					origin, list[0]);
+					origin, list.items[0]);
 		rev.rdiff1 = rdiff1.buf;
 		rev.rdiff2 = rdiff2.buf;
 		rev.creation_factor = creation_factor;
@@ -2360,11 +2358,11 @@ int cmd_format_patch(int argc,
 	}
 
 	memset(&bases, 0, sizeof(bases));
-	base = get_base_commit(&cfg, list, nr);
+	base = get_base_commit(&cfg, list.items, list.nr);
 	if (base) {
 		reset_revision_walk();
 		clear_object_flags(the_repository, UNINTERESTING);
-		prepare_bases(&bases, base, list, nr);
+		prepare_bases(&bases, base, list.items, list.nr);
 	}
 
 	if (in_reply_to || cfg.thread || cover_letter) {
@@ -2381,7 +2379,8 @@ int cmd_format_patch(int argc,
 		if (cfg.thread)
 			gen_message_id(&rev, "cover");
 		make_cover_letter(&rev, !!output_directory,
-				  origin, nr, list, description_file, branch_name, quiet, &cfg);
+				  origin, list.nr, list.items,
+				  description_file, branch_name, quiet, &cfg);
 		print_bases(&bases, rev.diffopt.file);
 		print_signature(signature, rev.diffopt.file);
 		total++;
@@ -2395,12 +2394,12 @@ int cmd_format_patch(int argc,
 	if (show_progress)
 		progress = start_delayed_progress(the_repository,
 						  _("Generating patches"), total);
-	for (i = 0; i < nr; i++) {
-		size_t idx = nr - i - 1;
+	while (list.nr) {
+		size_t idx = list.nr - 1;
 		int shown;
 
 		display_progress(progress, total - idx);
-		commit = list[idx];
+		commit = commit_stack_pop(&list);
 		rev.nr = total - idx + (start_number - 1);
 
 		/* Make the second and subsequent mails replies to the first */
@@ -2469,7 +2468,7 @@ int cmd_format_patch(int argc,
 		}
 	}
 	stop_progress(&progress);
-	free(list);
+	commit_stack_clear(&list);
 	if (ignore_if_in_upstream)
 		free_patch_ids(&ids);
 
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 03/14] midx: use commit_stack
  2025-12-24 17:03 [PATCH 00/14] export and use commit_stack René Scharfe
  2025-12-24 17:03 ` [PATCH 01/14] revision: export commit_stack René Scharfe
  2025-12-24 17:03 ` [PATCH 02/14] log: use commit_stack René Scharfe
@ 2025-12-24 17:03 ` René Scharfe
  2025-12-24 17:03 ` [PATCH 04/14] name-rev: " René Scharfe
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: René Scharfe @ 2025-12-24 17:03 UTC (permalink / raw)
  To: git

Simplify collection commits in a callback function by passing it a
commit_stack pointer all the way from the caller, instead of using
separate variables for array and item count and a bunch of intermediate
members in struct bitmap_commit_cb.

Signed-off-by: René Scharfe <l.s.r@web•de>
---
 midx-write.c | 35 ++++++++++++-----------------------
 1 file changed, 12 insertions(+), 23 deletions(-)

diff --git a/midx-write.c b/midx-write.c
index e3e9be6d03..b4a82d6ba5 100644
--- a/midx-write.c
+++ b/midx-write.c
@@ -723,9 +723,7 @@ static int add_ref_to_pending(const struct reference *ref, void *cb_data)
 }
 
 struct bitmap_commit_cb {
-	struct commit **commits;
-	size_t commits_nr, commits_alloc;
-
+	struct commit_stack *commits;
 	struct write_midx_context *ctx;
 };
 
@@ -745,8 +743,7 @@ static void bitmap_show_commit(struct commit *commit, void *_data)
 	if (pos < 0)
 		return;
 
-	ALLOC_GROW(data->commits, data->commits_nr + 1, data->commits_alloc);
-	data->commits[data->commits_nr++] = commit;
+	commit_stack_push(data->commits, commit);
 }
 
 static int read_refs_snapshot(const char *refs_snapshot,
@@ -784,17 +781,15 @@ static int read_refs_snapshot(const char *refs_snapshot,
 	return 0;
 }
 
-static struct commit **find_commits_for_midx_bitmap(uint32_t *indexed_commits_nr_p,
-						    const char *refs_snapshot,
-						    struct write_midx_context *ctx)
+static void find_commits_for_midx_bitmap(struct commit_stack *commits,
+					 const char *refs_snapshot,
+					 struct write_midx_context *ctx)
 {
 	struct rev_info revs;
-	struct bitmap_commit_cb cb = {0};
+	struct bitmap_commit_cb cb = { .commits = commits, .ctx = ctx };
 
 	trace2_region_enter("midx", "find_commits_for_midx_bitmap", ctx->repo);
 
-	cb.ctx = ctx;
-
 	repo_init_revisions(ctx->repo, &revs, NULL);
 	if (refs_snapshot) {
 		read_refs_snapshot(refs_snapshot, &revs);
@@ -823,14 +818,10 @@ static struct commit **find_commits_for_midx_bitmap(uint32_t *indexed_commits_nr
 		die(_("revision walk setup failed"));
 
 	traverse_commit_list(&revs, bitmap_show_commit, NULL, &cb);
-	if (indexed_commits_nr_p)
-		*indexed_commits_nr_p = cb.commits_nr;
 
 	release_revisions(&revs);
 
 	trace2_region_leave("midx", "find_commits_for_midx_bitmap", ctx->repo);
-
-	return cb.commits;
 }
 
 static int write_midx_bitmap(struct write_midx_context *ctx,
@@ -1375,15 +1366,14 @@ static int write_midx_internal(struct odb_source *source,
 
 	if (flags & MIDX_WRITE_BITMAP) {
 		struct packing_data pdata;
-		struct commit **commits;
-		uint32_t commits_nr;
+		struct commit_stack commits = COMMIT_STACK_INIT;
 
 		if (!ctx.entries_nr)
 			BUG("cannot write a bitmap without any objects");
 
 		prepare_midx_packing_data(&pdata, &ctx);
 
-		commits = find_commits_for_midx_bitmap(&commits_nr, refs_snapshot, &ctx);
+		find_commits_for_midx_bitmap(&commits, refs_snapshot, &ctx);
 
 		/*
 		 * The previous steps translated the information from
@@ -1394,17 +1384,16 @@ static int write_midx_internal(struct odb_source *source,
 		FREE_AND_NULL(ctx.entries);
 		ctx.entries_nr = 0;
 
-		if (write_midx_bitmap(&ctx,
-				      midx_hash, &pdata, commits, commits_nr,
-				      flags) < 0) {
+		if (write_midx_bitmap(&ctx, midx_hash, &pdata,
+				      commits.items, commits.nr, flags) < 0) {
 			error(_("could not write multi-pack bitmap"));
 			clear_packing_data(&pdata);
-			free(commits);
+			commit_stack_clear(&commits);
 			goto cleanup;
 		}
 
 		clear_packing_data(&pdata);
-		free(commits);
+		commit_stack_clear(&commits);
 	}
 	/*
 	 * NOTE: Do not use ctx.entries beyond this point, since it might
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 04/14] name-rev: use commit_stack
  2025-12-24 17:03 [PATCH 00/14] export and use commit_stack René Scharfe
                   ` (2 preceding siblings ...)
  2025-12-24 17:03 ` [PATCH 03/14] midx: " René Scharfe
@ 2025-12-24 17:03 ` René Scharfe
  2025-12-24 17:03 ` [PATCH 05/14] remote: use commit_stack for local_commits René Scharfe
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: René Scharfe @ 2025-12-24 17:03 UTC (permalink / raw)
  To: git

Simplify the code by using commit_stack instead of open-coding it.

Signed-off-by: René Scharfe <l.s.r@web•de>
---
 builtin/name-rev.c | 17 ++++++-----------
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 615f7d1aae..6188cf98ce 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -180,8 +180,7 @@ static void name_rev(struct commit *start_commit,
 {
 	struct prio_queue queue;
 	struct commit *commit;
-	struct commit **parents_to_queue = NULL;
-	size_t parents_to_queue_nr, parents_to_queue_alloc = 0;
+	struct commit_stack parents_to_queue = COMMIT_STACK_INIT;
 	struct rev_name *start_name;
 
 	repo_parse_commit(the_repository, start_commit);
@@ -206,7 +205,7 @@ static void name_rev(struct commit *start_commit,
 		struct commit_list *parents;
 		int parent_number = 1;
 
-		parents_to_queue_nr = 0;
+		parents_to_queue.nr = 0;
 
 		for (parents = commit->parents;
 				parents;
@@ -238,22 +237,18 @@ static void name_rev(struct commit *start_commit,
 								string_pool);
 				else
 					parent_name->tip_name = name->tip_name;
-				ALLOC_GROW(parents_to_queue,
-					   parents_to_queue_nr + 1,
-					   parents_to_queue_alloc);
-				parents_to_queue[parents_to_queue_nr] = parent;
-				parents_to_queue_nr++;
+				commit_stack_push(&parents_to_queue, parent);
 			}
 		}
 
 		/* The first parent must come out first from the prio_queue */
-		while (parents_to_queue_nr)
+		while (parents_to_queue.nr)
 			prio_queue_put(&queue,
-				       parents_to_queue[--parents_to_queue_nr]);
+				       commit_stack_pop(&parents_to_queue));
 	}
 
 	clear_prio_queue(&queue);
-	free(parents_to_queue);
+	commit_stack_clear(&parents_to_queue);
 }
 
 static int subpath_matches(const char *path, const char *filter)
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 05/14] remote: use commit_stack for local_commits
  2025-12-24 17:03 [PATCH 00/14] export and use commit_stack René Scharfe
                   ` (3 preceding siblings ...)
  2025-12-24 17:03 ` [PATCH 04/14] name-rev: " René Scharfe
@ 2025-12-24 17:03 ` René Scharfe
  2025-12-24 17:03 ` [PATCH 06/14] remote: use commit_stack for sent_tips René Scharfe
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: René Scharfe @ 2025-12-24 17:03 UTC (permalink / raw)
  To: git

Replace a commit array implementation with commit_stack.

Signed-off-by: René Scharfe <l.s.r@web•de>
---
 remote.c | 39 ++++++---------------------------------
 1 file changed, 6 insertions(+), 33 deletions(-)

diff --git a/remote.c b/remote.c
index 59b3715120..af888e3f20 100644
--- a/remote.c
+++ b/remote.c
@@ -2544,36 +2544,9 @@ static int remote_tracking(struct remote *remote, const char *refname,
 	return 0;
 }
 
-/*
- * The struct "reflog_commit_array" and related helper functions
- * are used for collecting commits into an array during reflog
- * traversals in "check_and_collect_until()".
- */
-struct reflog_commit_array {
-	struct commit **item;
-	size_t nr, alloc;
-};
-
-#define REFLOG_COMMIT_ARRAY_INIT { 0 }
-
-/* Append a commit to the array. */
-static void append_commit(struct reflog_commit_array *arr,
-			  struct commit *commit)
-{
-	ALLOC_GROW(arr->item, arr->nr + 1, arr->alloc);
-	arr->item[arr->nr++] = commit;
-}
-
-/* Free and reset the array. */
-static void free_commit_array(struct reflog_commit_array *arr)
-{
-	FREE_AND_NULL(arr->item);
-	arr->nr = arr->alloc = 0;
-}
-
 struct check_and_collect_until_cb_data {
 	struct commit *remote_commit;
-	struct reflog_commit_array *local_commits;
+	struct commit_stack *local_commits;
 	timestamp_t remote_reflog_timestamp;
 };
 
@@ -2605,7 +2578,7 @@ static int check_and_collect_until(const char *refname UNUSED,
 		return 1;
 
 	if ((commit = lookup_commit_reference(the_repository, n_oid)))
-		append_commit(cb->local_commits, commit);
+		commit_stack_push(cb->local_commits, commit);
 
 	/*
 	 * If the reflog entry timestamp is older than the remote ref's
@@ -2633,7 +2606,7 @@ static int is_reachable_in_reflog(const char *local, const struct ref *remote)
 	struct commit *commit;
 	struct commit **chunk;
 	struct check_and_collect_until_cb_data cb;
-	struct reflog_commit_array arr = REFLOG_COMMIT_ARRAY_INIT;
+	struct commit_stack arr = COMMIT_STACK_INIT;
 	size_t size = 0;
 	int ret = 0;
 
@@ -2664,8 +2637,8 @@ static int is_reachable_in_reflog(const char *local, const struct ref *remote)
 	 * Check if the remote commit is reachable from any
 	 * of the commits in the collected array, in batches.
 	 */
-	for (chunk = arr.item; chunk < arr.item + arr.nr; chunk += size) {
-		size = arr.item + arr.nr - chunk;
+	for (chunk = arr.items; chunk < arr.items + arr.nr; chunk += size) {
+		size = arr.items + arr.nr - chunk;
 		if (MERGE_BASES_BATCH_SIZE < size)
 			size = MERGE_BASES_BATCH_SIZE;
 
@@ -2674,7 +2647,7 @@ static int is_reachable_in_reflog(const char *local, const struct ref *remote)
 	}
 
 cleanup_return:
-	free_commit_array(&arr);
+	commit_stack_clear(&arr);
 	return ret;
 }
 
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 06/14] remote: use commit_stack for sent_tips
  2025-12-24 17:03 [PATCH 00/14] export and use commit_stack René Scharfe
                   ` (4 preceding siblings ...)
  2025-12-24 17:03 ` [PATCH 05/14] remote: use commit_stack for local_commits René Scharfe
@ 2025-12-24 17:03 ` René Scharfe
  2025-12-24 17:03 ` [PATCH 07/14] remote: use commit_stack for src_commits René Scharfe
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: René Scharfe @ 2025-12-24 17:03 UTC (permalink / raw)
  To: git

Call commit_stack functions instead of effectively open-coding them.

Signed-off-by: René Scharfe <l.s.r@web•de>
---
 remote.c | 20 +++++++-------------
 1 file changed, 7 insertions(+), 13 deletions(-)

diff --git a/remote.c b/remote.c
index af888e3f20..ffea887c70 100644
--- a/remote.c
+++ b/remote.c
@@ -1381,12 +1381,7 @@ static struct ref **tail_ref(struct ref **head)
 	return tail;
 }
 
-struct tips {
-	struct commit **tip;
-	size_t nr, alloc;
-};
-
-static void add_to_tips(struct tips *tips, const struct object_id *oid)
+static void add_to_tips(struct commit_stack *tips, const struct object_id *oid)
 {
 	struct commit *commit;
 
@@ -1396,8 +1391,7 @@ static void add_to_tips(struct tips *tips, const struct object_id *oid)
 	if (!commit || (commit->object.flags & TMP_MARK))
 		return;
 	commit->object.flags |= TMP_MARK;
-	ALLOC_GROW(tips->tip, tips->nr + 1, tips->alloc);
-	tips->tip[tips->nr++] = commit;
+	commit_stack_push(tips, commit);
 }
 
 static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***dst_tail)
@@ -1406,13 +1400,12 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds
 	struct string_list src_tag = STRING_LIST_INIT_NODUP;
 	struct string_list_item *item;
 	struct ref *ref;
-	struct tips sent_tips;
+	struct commit_stack sent_tips = COMMIT_STACK_INIT;
 
 	/*
 	 * Collect everything we know they would have at the end of
 	 * this push, and collect all tags they have.
 	 */
-	memset(&sent_tips, 0, sizeof(sent_tips));
 	for (ref = *dst; ref; ref = ref->next) {
 		if (ref->peer_ref &&
 		    !is_null_oid(&ref->peer_ref->new_oid))
@@ -1422,7 +1415,7 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds
 		if (starts_with(ref->name, "refs/tags/"))
 			string_list_append(&dst_tag, ref->name);
 	}
-	clear_commit_marks_many(sent_tips.nr, sent_tips.tip, TMP_MARK);
+	clear_commit_marks_many(sent_tips.nr, sent_tips.items, TMP_MARK);
 
 	string_list_sort(&dst_tag);
 
@@ -1471,7 +1464,8 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds
 			src_commits[nr_src_commits++] = commit;
 		}
 
-		found_commits = get_reachable_subset(sent_tips.tip, sent_tips.nr,
+		found_commits = get_reachable_subset(sent_tips.items,
+						     sent_tips.nr,
 						     src_commits, nr_src_commits,
 						     reachable_flag);
 
@@ -1508,7 +1502,7 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds
 	}
 
 	string_list_clear(&src_tag, 0);
-	free(sent_tips.tip);
+	commit_stack_clear(&sent_tips);
 }
 
 struct ref *find_ref_by_name(const struct ref *list, const char *name)
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 07/14] remote: use commit_stack for src_commits
  2025-12-24 17:03 [PATCH 00/14] export and use commit_stack René Scharfe
                   ` (5 preceding siblings ...)
  2025-12-24 17:03 ` [PATCH 06/14] remote: use commit_stack for sent_tips René Scharfe
@ 2025-12-24 17:03 ` René Scharfe
  2025-12-24 17:03 ` [PATCH 08/14] test-reach: use commit_stack René Scharfe
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: René Scharfe @ 2025-12-24 17:03 UTC (permalink / raw)
  To: git

Use commit_stack instead of open-coding it.

Signed-off-by: René Scharfe <l.s.r@web•de>
---
 remote.c | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/remote.c b/remote.c
index ffea887c70..b756ff6f15 100644
--- a/remote.c
+++ b/remote.c
@@ -1443,9 +1443,7 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds
 	if (sent_tips.nr) {
 		const int reachable_flag = 1;
 		struct commit_list *found_commits;
-		struct commit **src_commits;
-		size_t nr_src_commits = 0, alloc_src_commits = 16;
-		ALLOC_ARRAY(src_commits, alloc_src_commits);
+		struct commit_stack src_commits = COMMIT_STACK_INIT;
 
 		for_each_string_list_item(item, &src_tag) {
 			struct ref *ref = item->util;
@@ -1460,13 +1458,13 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds
 				/* not pushing a commit, which is not an error */
 				continue;
 
-			ALLOC_GROW(src_commits, nr_src_commits + 1, alloc_src_commits);
-			src_commits[nr_src_commits++] = commit;
+			commit_stack_push(&src_commits, commit);
 		}
 
 		found_commits = get_reachable_subset(sent_tips.items,
 						     sent_tips.nr,
-						     src_commits, nr_src_commits,
+						     src_commits.items,
+						     src_commits.nr,
 						     reachable_flag);
 
 		for_each_string_list_item(item, &src_tag) {
@@ -1496,8 +1494,9 @@ static void add_missing_tags(struct ref *src, struct ref **dst, struct ref ***ds
 			dst_ref->peer_ref = copy_ref(ref);
 		}
 
-		clear_commit_marks_many(nr_src_commits, src_commits, reachable_flag);
-		free(src_commits);
+		clear_commit_marks_many(src_commits.nr, src_commits.items,
+					reachable_flag);
+		commit_stack_clear(&src_commits);
 		free_commit_list(found_commits);
 	}
 
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 08/14] test-reach: use commit_stack
  2025-12-24 17:03 [PATCH 00/14] export and use commit_stack René Scharfe
                   ` (6 preceding siblings ...)
  2025-12-24 17:03 ` [PATCH 07/14] remote: use commit_stack for src_commits René Scharfe
@ 2025-12-24 17:03 ` René Scharfe
  2025-12-24 17:03 ` [PATCH 09/14] commit: add commit_stack_init() René Scharfe
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: René Scharfe @ 2025-12-24 17:03 UTC (permalink / raw)
  To: git

Use commit_stack instead of open-coding it.

Signed-off-by: René Scharfe <l.s.r@web•de>
---
 t/helper/test-reach.c | 34 ++++++++++++++--------------------
 1 file changed, 14 insertions(+), 20 deletions(-)

diff --git a/t/helper/test-reach.c b/t/helper/test-reach.c
index c58c93800f..feabeb29c2 100644
--- a/t/helper/test-reach.c
+++ b/t/helper/test-reach.c
@@ -34,8 +34,8 @@ int cmd__reach(int ac, const char **av)
 	struct commit *A, *B;
 	struct commit_list *X, *Y;
 	struct object_array X_obj = OBJECT_ARRAY_INIT;
-	struct commit **X_array, **Y_array;
-	size_t X_nr, X_alloc, Y_nr, Y_alloc;
+	struct commit_stack X_stack = COMMIT_STACK_INIT;
+	struct commit_stack Y_stack = COMMIT_STACK_INIT;
 	struct strbuf buf = STRBUF_INIT;
 	struct repository *r = the_repository;
 
@@ -46,10 +46,6 @@ int cmd__reach(int ac, const char **av)
 
 	A = B = NULL;
 	X = Y = NULL;
-	X_nr = Y_nr = 0;
-	X_alloc = Y_alloc = 16;
-	ALLOC_ARRAY(X_array, X_alloc);
-	ALLOC_ARRAY(Y_array, Y_alloc);
 
 	while (strbuf_getline(&buf, stdin) != EOF) {
 		struct object_id oid;
@@ -88,15 +84,13 @@ int cmd__reach(int ac, const char **av)
 
 			case 'X':
 				commit_list_insert(c, &X);
-				ALLOC_GROW(X_array, X_nr + 1, X_alloc);
-				X_array[X_nr++] = c;
+				commit_stack_push(&X_stack, c);
 				add_object_array(orig, NULL, &X_obj);
 				break;
 
 			case 'Y':
 				commit_list_insert(c, &Y);
-				ALLOC_GROW(Y_array, Y_nr + 1, Y_alloc);
-				Y_array[Y_nr++] = c;
+				commit_stack_push(&Y_stack, c);
 				break;
 
 			default:
@@ -112,16 +106,16 @@ int cmd__reach(int ac, const char **av)
 		       repo_in_merge_bases(the_repository, A, B));
 	else if (!strcmp(av[1], "in_merge_bases_many"))
 		printf("%s(A,X):%d\n", av[1],
-		       repo_in_merge_bases_many(the_repository, A, X_nr, X_array, 0));
+		       repo_in_merge_bases_many(the_repository, A, X_stack.nr, X_stack.items, 0));
 	else if (!strcmp(av[1], "is_descendant_of"))
 		printf("%s(A,X):%d\n", av[1], repo_is_descendant_of(r, A, X));
 	else if (!strcmp(av[1], "get_branch_base_for_tip"))
-		printf("%s(A,X):%d\n", av[1], get_branch_base_for_tip(r, A, X_array, X_nr));
+		printf("%s(A,X):%d\n", av[1], get_branch_base_for_tip(r, A, X_stack.items, X_stack.nr));
 	else if (!strcmp(av[1], "get_merge_bases_many")) {
 		struct commit_list *list = NULL;
 		if (repo_get_merge_bases_many(the_repository,
-					      A, X_nr,
-					      X_array,
+					      A, X_stack.nr,
+					      X_stack.items,
 					      &list) < 0)
 			exit(128);
 		printf("%s(A,X):\n", av[1]);
@@ -159,8 +153,8 @@ int cmd__reach(int ac, const char **av)
 		const int reachable_flag = 1;
 		int count = 0;
 		struct commit_list *current;
-		struct commit_list *list = get_reachable_subset(X_array, X_nr,
-								Y_array, Y_nr,
+		struct commit_list *list = get_reachable_subset(X_stack.items, X_stack.nr,
+								Y_stack.items, Y_stack.nr,
 								reachable_flag);
 		printf("get_reachable_subset(X,Y)\n");
 		for (current = list; current; current = current->next) {
@@ -169,8 +163,8 @@ int cmd__reach(int ac, const char **av)
 				    oid_to_hex(&list->item->object.oid));
 			count++;
 		}
-		for (size_t i = 0; i < Y_nr; i++) {
-			if (Y_array[i]->object.flags & reachable_flag)
+		for (size_t i = 0; i < Y_stack.nr; i++) {
+			if (Y_stack.items[i]->object.flags & reachable_flag)
 				count--;
 		}
 
@@ -185,7 +179,7 @@ int cmd__reach(int ac, const char **av)
 	strbuf_release(&buf);
 	free_commit_list(X);
 	free_commit_list(Y);
-	free(X_array);
-	free(Y_array);
+	commit_stack_clear(&X_stack);
+	commit_stack_clear(&Y_stack);
 	return 0;
 }
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 09/14] commit: add commit_stack_init()
  2025-12-24 17:03 [PATCH 00/14] export and use commit_stack René Scharfe
                   ` (7 preceding siblings ...)
  2025-12-24 17:03 ` [PATCH 08/14] test-reach: use commit_stack René Scharfe
@ 2025-12-24 17:03 ` René Scharfe
  2025-12-24 17:03 ` [PATCH 10/14] pack-bitmap-write: use commit_stack René Scharfe
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: René Scharfe @ 2025-12-24 17:03 UTC (permalink / raw)
  To: git

Add a function for initializing a struct commit_stack, for when static
initialization is not possible or impractical.

Signed-off-by: René Scharfe <l.s.r@web•de>
---
 commit.c | 10 ++++++++--
 commit.h |  1 +
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/commit.c b/commit.c
index f2edafa49c..55b1c8d2f8 100644
--- a/commit.c
+++ b/commit.c
@@ -1982,6 +1982,12 @@ int run_commit_hook(int editor_is_used, const char *index_file,
 	return run_hooks_opt(the_repository, name, &opt);
 }
 
+void commit_stack_init(struct commit_stack *stack)
+{
+	stack->items = NULL;
+	stack->nr = stack->alloc = 0;
+}
+
 void commit_stack_push(struct commit_stack *stack, struct commit *commit)
 {
 	ALLOC_GROW(stack->items, stack->nr + 1, stack->alloc);
@@ -1995,6 +2001,6 @@ struct commit *commit_stack_pop(struct commit_stack *stack)
 
 void commit_stack_clear(struct commit_stack *stack)
 {
-	FREE_AND_NULL(stack->items);
-	stack->nr = stack->alloc = 0;
+	free(stack->items);
+	commit_stack_init(stack);
 }
diff --git a/commit.h b/commit.h
index 81e047f820..7c01a76425 100644
--- a/commit.h
+++ b/commit.h
@@ -387,6 +387,7 @@ struct commit_stack {
 };
 #define COMMIT_STACK_INIT { 0 }
 
+void commit_stack_init(struct commit_stack *);
 void commit_stack_push(struct commit_stack *, struct commit *);
 struct commit *commit_stack_pop(struct commit_stack *);
 void commit_stack_clear(struct commit_stack *);
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 10/14] pack-bitmap-write: use commit_stack
  2025-12-24 17:03 [PATCH 00/14] export and use commit_stack René Scharfe
                   ` (8 preceding siblings ...)
  2025-12-24 17:03 ` [PATCH 09/14] commit: add commit_stack_init() René Scharfe
@ 2025-12-24 17:03 ` René Scharfe
  2025-12-24 17:03 ` [PATCH 11/14] shallow: " René Scharfe
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: René Scharfe @ 2025-12-24 17:03 UTC (permalink / raw)
  To: git

Use commit_stack instead of open-coding it.

Signed-off-by: René Scharfe <l.s.r@web•de>
---
 pack-bitmap-write.c | 18 +++++++-----------
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c
index 4404921521..bf73ce5710 100644
--- a/pack-bitmap-write.c
+++ b/pack-bitmap-write.c
@@ -315,8 +315,7 @@ define_commit_slab(bb_data, struct bb_commit);
 
 struct bitmap_builder {
 	struct bb_data data;
-	struct commit **commits;
-	size_t commits_nr, commits_alloc;
+	struct commit_stack commits;
 };
 
 static void bitmap_builder_init(struct bitmap_builder *bb,
@@ -329,8 +328,8 @@ static void bitmap_builder_init(struct bitmap_builder *bb,
 	struct commit_list *r;
 	unsigned int i, num_maximal = 0;
 
-	memset(bb, 0, sizeof(*bb));
 	init_bb_data(&bb->data);
+	commit_stack_init(&bb->commits);
 
 	reset_revision_walk();
 	repo_init_revisions(writer->to_pack->repo, &revs, NULL);
@@ -390,8 +389,7 @@ static void bitmap_builder_init(struct bitmap_builder *bb,
 
 		if (c_ent->maximal) {
 			num_maximal++;
-			ALLOC_GROW(bb->commits, bb->commits_nr + 1, bb->commits_alloc);
-			bb->commits[bb->commits_nr++] = commit;
+			commit_stack_push(&bb->commits, commit);
 		}
 
 		if (p) {
@@ -438,8 +436,7 @@ static void bitmap_builder_init(struct bitmap_builder *bb,
 	}
 
 	for (r = reusable; r; r = r->next) {
-		ALLOC_GROW(bb->commits, bb->commits_nr + 1, bb->commits_alloc);
-		bb->commits[bb->commits_nr++] = r->item;
+		commit_stack_push(&bb->commits, r->item);
 	}
 
 	trace2_data_intmax("pack-bitmap-write", writer->repo,
@@ -454,8 +451,7 @@ static void bitmap_builder_init(struct bitmap_builder *bb,
 static void bitmap_builder_clear(struct bitmap_builder *bb)
 {
 	deep_clear_bb_data(&bb->data, clear_bb_commit);
-	free(bb->commits);
-	bb->commits_nr = bb->commits_alloc = 0;
+	commit_stack_clear(&bb->commits);
 }
 
 static int fill_bitmap_tree(struct bitmap_writer *writer,
@@ -630,8 +626,8 @@ int bitmap_writer_build(struct bitmap_writer *writer)
 		mapping = NULL;
 
 	bitmap_builder_init(&bb, writer, old_bitmap);
-	for (i = bb.commits_nr; i > 0; i--) {
-		struct commit *commit = bb.commits[i-1];
+	for (i = bb.commits.nr; i > 0; i--) {
+		struct commit *commit = bb.commits.items[i-1];
 		struct bb_commit *ent = bb_data_at(&bb.data, commit);
 		struct commit *child;
 		int reused = 0;
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 11/14] shallow: use commit_stack
  2025-12-24 17:03 [PATCH 00/14] export and use commit_stack René Scharfe
                   ` (9 preceding siblings ...)
  2025-12-24 17:03 ` [PATCH 10/14] pack-bitmap-write: use commit_stack René Scharfe
@ 2025-12-24 17:03 ` René Scharfe
  2025-12-24 17:03 ` [PATCH 12/14] commit: add commit_stack_grow() René Scharfe
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: René Scharfe @ 2025-12-24 17:03 UTC (permalink / raw)
  To: git; +Cc: Rene Scharfe

From: Rene Scharfe <l.s.r@web•de>

Replace a commit array implementation with commit_stack.

Signed-off-by: René Scharfe <l.s.r@web•de>
---
 shallow.c | 44 +++++++++++++++++---------------------------
 shallow.h |  4 ++--
 2 files changed, 19 insertions(+), 29 deletions(-)

diff --git a/shallow.c b/shallow.c
index 186e9178f3..c870efcefc 100644
--- a/shallow.c
+++ b/shallow.c
@@ -471,6 +471,7 @@ void prepare_shallow_info(struct shallow_info *info, struct oid_array *sa)
 {
 	trace_printf_key(&trace_shallow, "shallow: prepare_shallow_info\n");
 	memset(info, 0, sizeof(*info));
+	commit_stack_init(&info->commits);
 	info->shallow = sa;
 	if (!sa)
 		return;
@@ -503,6 +504,7 @@ void clear_shallow_info(struct shallow_info *info)
 	free(info->shallow_ref);
 	free(info->ours);
 	free(info->theirs);
+	commit_stack_clear(&info->commits);
 }
 
 /* Step 4, remove non-existent ones in "theirs" after getting the pack */
@@ -733,19 +735,13 @@ void assign_shallow_commits_to_refs(struct shallow_info *info,
 	free(shallow);
 }
 
-struct commit_array {
-	struct commit **commits;
-	size_t nr, alloc;
-};
-
 static int add_ref(const struct reference *ref, void *cb_data)
 {
-	struct commit_array *ca = cb_data;
-	ALLOC_GROW(ca->commits, ca->nr + 1, ca->alloc);
-	ca->commits[ca->nr] = lookup_commit_reference_gently(the_repository,
-							     ref->oid, 1);
-	if (ca->commits[ca->nr])
-		ca->nr++;
+	struct commit_stack *cs = cb_data;
+	struct commit *commit = lookup_commit_reference_gently(the_repository,
+							       ref->oid, 1);
+	if (commit)
+		commit_stack_push(cs, commit);
 	return 0;
 }
 
@@ -770,7 +766,7 @@ static void post_assign_shallow(struct shallow_info *info,
 	uint32_t **bitmap;
 	size_t dst, i, j;
 	size_t bitmap_nr = DIV_ROUND_UP(info->ref->nr, 32);
-	struct commit_array ca;
+	struct commit_stack cs = COMMIT_STACK_INIT;
 
 	trace_printf_key(&trace_shallow, "shallow: post_assign_shallow\n");
 	if (ref_status)
@@ -793,9 +789,8 @@ static void post_assign_shallow(struct shallow_info *info,
 	}
 	info->nr_theirs = dst;
 
-	memset(&ca, 0, sizeof(ca));
-	refs_head_ref(get_main_ref_store(the_repository), add_ref, &ca);
-	refs_for_each_ref(get_main_ref_store(the_repository), add_ref, &ca);
+	refs_head_ref(get_main_ref_store(the_repository), add_ref, &cs);
+	refs_for_each_ref(get_main_ref_store(the_repository), add_ref, &cs);
 
 	/* Remove unreachable shallow commits from "ours" */
 	for (i = dst = 0; i < info->nr_ours; i++) {
@@ -808,7 +803,7 @@ static void post_assign_shallow(struct shallow_info *info,
 		for (j = 0; j < bitmap_nr; j++)
 			if (bitmap[0][j]) {
 				/* Step 7, reachability test at commit level */
-				int ret = repo_in_merge_bases_many(the_repository, c, ca.nr, ca.commits, 1);
+				int ret = repo_in_merge_bases_many(the_repository, c, cs.nr, cs.items, 1);
 				if (ret < 0)
 					exit(128);
 				if (!ret) {
@@ -820,7 +815,7 @@ static void post_assign_shallow(struct shallow_info *info,
 	}
 	info->nr_ours = dst;
 
-	free(ca.commits);
+	commit_stack_clear(&cs);
 }
 
 /* (Delayed) step 7, reachability test at commit level */
@@ -830,22 +825,17 @@ int delayed_reachability_test(struct shallow_info *si, int c)
 		struct commit *commit = lookup_commit(the_repository,
 						      &si->shallow->oid[c]);
 
-		if (!si->commits) {
-			struct commit_array ca;
-
-			memset(&ca, 0, sizeof(ca));
+		if (!si->commits.nr) {
 			refs_head_ref(get_main_ref_store(the_repository),
-				      add_ref, &ca);
+				      add_ref, &si->commits);
 			refs_for_each_ref(get_main_ref_store(the_repository),
-					  add_ref, &ca);
-			si->commits = ca.commits;
-			si->nr_commits = ca.nr;
+					  add_ref, &si->commits);
 		}
 
 		si->reachable[c] = repo_in_merge_bases_many(the_repository,
 							    commit,
-							    si->nr_commits,
-							    si->commits,
+							    si->commits.nr,
+							    si->commits.items,
 							    1);
 		if (si->reachable[c] < 0)
 			exit(128);
diff --git a/shallow.h b/shallow.h
index ad591bd139..1c0787de1d 100644
--- a/shallow.h
+++ b/shallow.h
@@ -1,6 +1,7 @@
 #ifndef SHALLOW_H
 #define SHALLOW_H
 
+#include "commit.h"
 #include "lockfile.h"
 #include "object.h"
 #include "repository.h"
@@ -69,8 +70,7 @@ struct shallow_info {
 	int *need_reachability_test;
 	int *reachable;
 	int *shallow_ref;
-	struct commit **commits;
-	size_t nr_commits;
+	struct commit_stack commits;
 };
 
 void prepare_shallow_info(struct shallow_info *, struct oid_array *);
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 12/14] commit: add commit_stack_grow()
  2025-12-24 17:03 [PATCH 00/14] export and use commit_stack René Scharfe
                   ` (10 preceding siblings ...)
  2025-12-24 17:03 ` [PATCH 11/14] shallow: " René Scharfe
@ 2025-12-24 17:03 ` René Scharfe
  2025-12-24 17:03 ` [PATCH 13/14] commit-graph: use commit_stack René Scharfe
  2025-12-24 17:03 ` [PATCH 14/14] commit-reach: " René Scharfe
  13 siblings, 0 replies; 15+ messages in thread
From: René Scharfe @ 2025-12-24 17:03 UTC (permalink / raw)
  To: git

Add a function for increasing the capacity of a commit_stack.  It is
useful for reducing reallocations when the target size is known in
advance.

Signed-off-by: René Scharfe <l.s.r@web•de>
---
 commit.c | 7 ++++++-
 commit.h | 1 +
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/commit.c b/commit.c
index 55b1c8d2f8..28bb5ce029 100644
--- a/commit.c
+++ b/commit.c
@@ -1988,9 +1988,14 @@ void commit_stack_init(struct commit_stack *stack)
 	stack->nr = stack->alloc = 0;
 }
 
+void commit_stack_grow(struct commit_stack *stack, size_t extra)
+{
+	ALLOC_GROW(stack->items, st_add(stack->nr, extra), stack->alloc);
+}
+
 void commit_stack_push(struct commit_stack *stack, struct commit *commit)
 {
-	ALLOC_GROW(stack->items, stack->nr + 1, stack->alloc);
+	commit_stack_grow(stack, 1);
 	stack->items[stack->nr++] = commit;
 }
 
diff --git a/commit.h b/commit.h
index 7c01a76425..79a761c37d 100644
--- a/commit.h
+++ b/commit.h
@@ -388,6 +388,7 @@ struct commit_stack {
 #define COMMIT_STACK_INIT { 0 }
 
 void commit_stack_init(struct commit_stack *);
+void commit_stack_grow(struct commit_stack *, size_t);
 void commit_stack_push(struct commit_stack *, struct commit *);
 struct commit *commit_stack_pop(struct commit_stack *);
 void commit_stack_clear(struct commit_stack *);
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 13/14] commit-graph: use commit_stack
  2025-12-24 17:03 [PATCH 00/14] export and use commit_stack René Scharfe
                   ` (11 preceding siblings ...)
  2025-12-24 17:03 ` [PATCH 12/14] commit: add commit_stack_grow() René Scharfe
@ 2025-12-24 17:03 ` René Scharfe
  2025-12-24 17:03 ` [PATCH 14/14] commit-reach: " René Scharfe
  13 siblings, 0 replies; 15+ messages in thread
From: René Scharfe @ 2025-12-24 17:03 UTC (permalink / raw)
  To: git

Replace a commit array implementation with commit_stack.

Signed-off-by: René Scharfe <l.s.r@web•de>
---
 commit-graph.c | 86 +++++++++++++++++++++++---------------------------
 1 file changed, 39 insertions(+), 47 deletions(-)

diff --git a/commit-graph.c b/commit-graph.c
index 80be2ff2c3..00e8193adc 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -1127,18 +1127,12 @@ struct tree *get_commit_tree_in_graph(struct repository *r, const struct commit
 	return get_commit_tree_in_graph_one(r->objects->commit_graph, c);
 }
 
-struct packed_commit_list {
-	struct commit **list;
-	size_t nr;
-	size_t alloc;
-};
-
 struct write_commit_graph_context {
 	struct repository *r;
 	struct odb_source *odb_source;
 	char *graph_name;
 	struct oid_array oids;
-	struct packed_commit_list commits;
+	struct commit_stack commits;
 	int num_extra_edges;
 	int num_generation_data_overflows;
 	unsigned long approx_nr_objects;
@@ -1180,7 +1174,7 @@ static int write_graph_chunk_fanout(struct hashfile *f,
 {
 	struct write_commit_graph_context *ctx = data;
 	int i, count = 0;
-	struct commit **list = ctx->commits.list;
+	struct commit **list = ctx->commits.items;
 
 	/*
 	 * Write the first-level table (the list is sorted,
@@ -1206,7 +1200,7 @@ static int write_graph_chunk_oids(struct hashfile *f,
 				  void *data)
 {
 	struct write_commit_graph_context *ctx = data;
-	struct commit **list = ctx->commits.list;
+	struct commit **list = ctx->commits.items;
 	int count;
 	for (count = 0; count < ctx->commits.nr; count++, list++) {
 		display_progress(ctx->progress, ++ctx->progress_cnt);
@@ -1226,8 +1220,8 @@ static int write_graph_chunk_data(struct hashfile *f,
 				  void *data)
 {
 	struct write_commit_graph_context *ctx = data;
-	struct commit **list = ctx->commits.list;
-	struct commit **last = ctx->commits.list + ctx->commits.nr;
+	struct commit **list = ctx->commits.items;
+	struct commit **last = ctx->commits.items + ctx->commits.nr;
 	uint32_t num_extra_edges = 0;
 
 	while (list < last) {
@@ -1249,7 +1243,7 @@ static int write_graph_chunk_data(struct hashfile *f,
 			edge_value = GRAPH_PARENT_NONE;
 		else {
 			edge_value = oid_pos(&parent->item->object.oid,
-					     ctx->commits.list,
+					     ctx->commits.items,
 					     ctx->commits.nr,
 					     commit_to_oid);
 
@@ -1280,7 +1274,7 @@ static int write_graph_chunk_data(struct hashfile *f,
 			edge_value = GRAPH_EXTRA_EDGES_NEEDED | num_extra_edges;
 		else {
 			edge_value = oid_pos(&parent->item->object.oid,
-					     ctx->commits.list,
+					     ctx->commits.items,
 					     ctx->commits.nr,
 					     commit_to_oid);
 
@@ -1332,7 +1326,7 @@ static int write_graph_chunk_generation_data(struct hashfile *f,
 	int i, num_generation_data_overflows = 0;
 
 	for (i = 0; i < ctx->commits.nr; i++) {
-		struct commit *c = ctx->commits.list[i];
+		struct commit *c = ctx->commits.items[i];
 		timestamp_t offset;
 		repo_parse_commit(ctx->r, c);
 		offset = commit_graph_data_at(c)->generation - c->date;
@@ -1355,7 +1349,7 @@ static int write_graph_chunk_generation_data_overflow(struct hashfile *f,
 	struct write_commit_graph_context *ctx = data;
 	int i;
 	for (i = 0; i < ctx->commits.nr; i++) {
-		struct commit *c = ctx->commits.list[i];
+		struct commit *c = ctx->commits.items[i];
 		timestamp_t offset = commit_graph_data_at(c)->generation - c->date;
 		display_progress(ctx->progress, ++ctx->progress_cnt);
 
@@ -1372,8 +1366,8 @@ static int write_graph_chunk_extra_edges(struct hashfile *f,
 					 void *data)
 {
 	struct write_commit_graph_context *ctx = data;
-	struct commit **list = ctx->commits.list;
-	struct commit **last = ctx->commits.list + ctx->commits.nr;
+	struct commit **list = ctx->commits.items;
+	struct commit **last = ctx->commits.items + ctx->commits.nr;
 	struct commit_list *parent;
 
 	while (list < last) {
@@ -1393,7 +1387,7 @@ static int write_graph_chunk_extra_edges(struct hashfile *f,
 		/* Since num_parents > 2, this initializer is safe. */
 		for (parent = (*list)->parents->next; parent; parent = parent->next) {
 			int edge_value = oid_pos(&parent->item->object.oid,
-						 ctx->commits.list,
+						 ctx->commits.items,
 						 ctx->commits.nr,
 						 commit_to_oid);
 
@@ -1427,8 +1421,8 @@ static int write_graph_chunk_bloom_indexes(struct hashfile *f,
 					   void *data)
 {
 	struct write_commit_graph_context *ctx = data;
-	struct commit **list = ctx->commits.list;
-	struct commit **last = ctx->commits.list + ctx->commits.nr;
+	struct commit **list = ctx->commits.items;
+	struct commit **last = ctx->commits.items + ctx->commits.nr;
 	uint32_t cur_pos = 0;
 
 	while (list < last) {
@@ -1463,8 +1457,8 @@ static int write_graph_chunk_bloom_data(struct hashfile *f,
 					void *data)
 {
 	struct write_commit_graph_context *ctx = data;
-	struct commit **list = ctx->commits.list;
-	struct commit **last = ctx->commits.list + ctx->commits.nr;
+	struct commit **list = ctx->commits.items;
+	struct commit **last = ctx->commits.items + ctx->commits.nr;
 
 	trace2_bloom_filter_settings(ctx);
 
@@ -1585,7 +1579,7 @@ static void close_reachable(struct write_commit_graph_context *ctx)
 
 struct compute_generation_info {
 	struct repository *r;
-	struct packed_commit_list *commits;
+	struct commit_stack *commits;
 	struct progress *progress;
 	int progress_cnt;
 
@@ -1622,7 +1616,7 @@ static void compute_reachable_generation_numbers(
 	struct commit_list *list = NULL;
 
 	for (i = 0; i < info->commits->nr; i++) {
-		struct commit *c = info->commits->list[i];
+		struct commit *c = info->commits->items[i];
 		timestamp_t gen;
 		repo_parse_commit(info->r, c);
 		gen = info->get_generation(c, info->data);
@@ -1729,7 +1723,7 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
 
 	if (!ctx->trust_generation_numbers) {
 		for (i = 0; i < ctx->commits.nr; i++) {
-			struct commit *c = ctx->commits.list[i];
+			struct commit *c = ctx->commits.items[i];
 			repo_parse_commit(ctx->r, c);
 			commit_graph_data_at(c)->generation = GENERATION_NUMBER_ZERO;
 		}
@@ -1738,7 +1732,7 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
 	compute_reachable_generation_numbers(&info, 2);
 
 	for (i = 0; i < ctx->commits.nr; i++) {
-		struct commit *c = ctx->commits.list[i];
+		struct commit *c = ctx->commits.items[i];
 		timestamp_t offset = commit_graph_data_at(c)->generation - c->date;
 		if (offset > GENERATION_NUMBER_V2_OFFSET_MAX)
 			ctx->num_generation_data_overflows++;
@@ -1760,8 +1754,8 @@ void ensure_generations_valid(struct repository *r,
 			      struct commit **commits, size_t nr)
 {
 	int generation_version = get_configured_generation_version(r);
-	struct packed_commit_list list = {
-		.list = commits,
+	struct commit_stack list = {
+		.items = commits,
 		.alloc = nr,
 		.nr = nr,
 	};
@@ -1804,7 +1798,7 @@ static void compute_bloom_filters(struct write_commit_graph_context *ctx)
 			_("Computing commit changed paths Bloom filters"),
 			ctx->commits.nr);
 
-	DUP_ARRAY(sorted_commits, ctx->commits.list, ctx->commits.nr);
+	DUP_ARRAY(sorted_commits, ctx->commits.items, ctx->commits.nr);
 
 	if (ctx->order_by_pack)
 		QSORT(sorted_commits, ctx->commits.nr, commit_pos_cmp);
@@ -1992,26 +1986,26 @@ static void copy_oids_to_commits(struct write_commit_graph_context *ctx)
 	oid_array_sort(&ctx->oids);
 	for (i = 0; i < ctx->oids.nr; i = oid_array_next_unique(&ctx->oids, i)) {
 		unsigned int num_parents;
+		struct commit *commit;
 
 		display_progress(ctx->progress, i + 1);
 
-		ALLOC_GROW(ctx->commits.list, ctx->commits.nr + 1, ctx->commits.alloc);
-		ctx->commits.list[ctx->commits.nr] = lookup_commit(ctx->r, &ctx->oids.oid[i]);
+		commit = lookup_commit(ctx->r, &ctx->oids.oid[i]);
 
 		if (ctx->split && flags != COMMIT_GRAPH_SPLIT_REPLACE &&
-		    commit_graph_position(ctx->commits.list[ctx->commits.nr]) != COMMIT_NOT_FROM_GRAPH)
+		    commit_graph_position(commit) != COMMIT_NOT_FROM_GRAPH)
 			continue;
 
 		if (ctx->split && flags == COMMIT_GRAPH_SPLIT_REPLACE)
-			repo_parse_commit(ctx->r, ctx->commits.list[ctx->commits.nr]);
+			repo_parse_commit(ctx->r, commit);
 		else
-			repo_parse_commit_no_graph(ctx->r, ctx->commits.list[ctx->commits.nr]);
+			repo_parse_commit_no_graph(ctx->r, commit);
 
-		num_parents = commit_list_count(ctx->commits.list[ctx->commits.nr]->parents);
+		num_parents = commit_list_count(commit->parents);
 		if (num_parents > 2)
 			ctx->num_extra_edges += num_parents - 1;
 
-		ctx->commits.nr++;
+		commit_stack_push(&ctx->commits, commit);
 	}
 	stop_progress(&ctx->progress);
 }
@@ -2330,7 +2324,7 @@ static void merge_commit_graph(struct write_commit_graph_context *ctx,
 		    oid_to_hex(&g->oid),
 		    (uintmax_t)st_add(ctx->commits.nr, g->num_commits));
 
-	ALLOC_GROW(ctx->commits.list, ctx->commits.nr + g->num_commits, ctx->commits.alloc);
+	commit_stack_grow(&ctx->commits, g->num_commits);
 
 	for (i = 0; i < g->num_commits; i++) {
 		struct object_id oid;
@@ -2343,10 +2337,8 @@ static void merge_commit_graph(struct write_commit_graph_context *ctx,
 		/* only add commits if they still exist in the repo */
 		result = lookup_commit_reference_gently(ctx->r, &oid, 1);
 
-		if (result) {
-			ctx->commits.list[ctx->commits.nr] = result;
-			ctx->commits.nr++;
-		}
+		if (result)
+			commit_stack_push(&ctx->commits, result);
 	}
 }
 
@@ -2367,14 +2359,14 @@ static void sort_and_scan_merged_commits(struct write_commit_graph_context *ctx)
 					_("Scanning merged commits"),
 					ctx->commits.nr);
 
-	QSORT(ctx->commits.list, ctx->commits.nr, commit_compare);
+	QSORT(ctx->commits.items, ctx->commits.nr, commit_compare);
 
 	ctx->num_extra_edges = 0;
 	for (i = 0; i < ctx->commits.nr; i++) {
 		display_progress(ctx->progress, i + 1);
 
-		if (i && oideq(&ctx->commits.list[i - 1]->object.oid,
-			  &ctx->commits.list[i]->object.oid)) {
+		if (i && oideq(&ctx->commits.items[i - 1]->object.oid,
+			  &ctx->commits.items[i]->object.oid)) {
 			/*
 			 * Silently ignore duplicates. These were likely
 			 * created due to a commit appearing in multiple
@@ -2385,10 +2377,10 @@ static void sort_and_scan_merged_commits(struct write_commit_graph_context *ctx)
 		} else {
 			unsigned int num_parents;
 
-			ctx->commits.list[dedup_i] = ctx->commits.list[i];
+			ctx->commits.items[dedup_i] = ctx->commits.items[i];
 			dedup_i++;
 
-			num_parents = commit_list_count(ctx->commits.list[i]->parents);
+			num_parents = commit_list_count(ctx->commits.items[i]->parents);
 			if (num_parents > 2)
 				ctx->num_extra_edges += num_parents - 1;
 		}
@@ -2666,7 +2658,7 @@ int write_commit_graph(struct odb_source *source,
 cleanup:
 	free(ctx.graph_name);
 	free(ctx.base_graph_name);
-	free(ctx.commits.list);
+	commit_stack_clear(&ctx.commits);
 	oid_array_clear(&ctx.oids);
 	clear_topo_level_slab(&topo_levels);
 
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 14/14] commit-reach: use commit_stack
  2025-12-24 17:03 [PATCH 00/14] export and use commit_stack René Scharfe
                   ` (12 preceding siblings ...)
  2025-12-24 17:03 ` [PATCH 13/14] commit-graph: use commit_stack René Scharfe
@ 2025-12-24 17:03 ` René Scharfe
  13 siblings, 0 replies; 15+ messages in thread
From: René Scharfe @ 2025-12-24 17:03 UTC (permalink / raw)
  To: git

Use commit_stack instead of open-coding it.

Signed-off-by: René Scharfe <l.s.r@web•de>
---
 commit-reach.c | 25 ++++++++++++-------------
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/commit-reach.c b/commit-reach.c
index cc18c86d3b..e7d9b3208f 100644
--- a/commit-reach.c
+++ b/commit-reach.c
@@ -283,8 +283,8 @@ static int remove_redundant_with_gen(struct repository *r,
 {
 	size_t i, count_non_stale = 0, count_still_independent = cnt;
 	timestamp_t min_generation = GENERATION_NUMBER_INFINITY;
-	struct commit **walk_start, **sorted;
-	size_t walk_start_nr = 0, walk_start_alloc = cnt;
+	struct commit **sorted;
+	struct commit_stack walk_start = COMMIT_STACK_INIT;
 	size_t min_gen_pos = 0;
 
 	/*
@@ -298,7 +298,7 @@ static int remove_redundant_with_gen(struct repository *r,
 	QSORT(sorted, cnt, compare_commits_by_gen);
 	min_generation = commit_graph_generation(sorted[0]);
 
-	ALLOC_ARRAY(walk_start, walk_start_alloc);
+	commit_stack_grow(&walk_start, cnt);
 
 	/* Mark all parents of the input as STALE */
 	for (i = 0; i < cnt; i++) {
@@ -312,18 +312,17 @@ static int remove_redundant_with_gen(struct repository *r,
 			repo_parse_commit(r, parents->item);
 			if (!(parents->item->object.flags & STALE)) {
 				parents->item->object.flags |= STALE;
-				ALLOC_GROW(walk_start, walk_start_nr + 1, walk_start_alloc);
-				walk_start[walk_start_nr++] = parents->item;
+				commit_stack_push(&walk_start, parents->item);
 			}
 			parents = parents->next;
 		}
 	}
 
-	QSORT(walk_start, walk_start_nr, compare_commits_by_gen);
+	QSORT(walk_start.items, walk_start.nr, compare_commits_by_gen);
 
 	/* remove STALE bit for now to allow walking through parents */
-	for (i = 0; i < walk_start_nr; i++)
-		walk_start[i]->object.flags &= ~STALE;
+	for (i = 0; i < walk_start.nr; i++)
+		walk_start.items[i]->object.flags &= ~STALE;
 
 	/*
 	 * Start walking from the highest generation. Hopefully, it will
@@ -331,12 +330,12 @@ static int remove_redundant_with_gen(struct repository *r,
 	 * terminate early. Otherwise, we will do the same amount of work
 	 * as before.
 	 */
-	for (i = walk_start_nr; i && count_still_independent > 1; i--) {
+	for (i = walk_start.nr; i && count_still_independent > 1; i--) {
 		/* push the STALE bits up to min generation */
 		struct commit_list *stack = NULL;
 
-		commit_list_insert(walk_start[i - 1], &stack);
-		walk_start[i - 1]->object.flags |= STALE;
+		commit_list_insert(walk_start.items[i - 1], &stack);
+		walk_start.items[i - 1]->object.flags |= STALE;
 
 		while (stack) {
 			struct commit_list *parents;
@@ -390,8 +389,8 @@ static int remove_redundant_with_gen(struct repository *r,
 	}
 
 	/* clear marks */
-	clear_commit_marks_many(walk_start_nr, walk_start, STALE);
-	free(walk_start);
+	clear_commit_marks_many(walk_start.nr, walk_start.items, STALE);
+	commit_stack_clear(&walk_start);
 
 	*dedup_cnt = count_non_stale;
 	return 0;
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2025-12-24 17:03 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-24 17:03 [PATCH 00/14] export and use commit_stack René Scharfe
2025-12-24 17:03 ` [PATCH 01/14] revision: export commit_stack René Scharfe
2025-12-24 17:03 ` [PATCH 02/14] log: use commit_stack René Scharfe
2025-12-24 17:03 ` [PATCH 03/14] midx: " René Scharfe
2025-12-24 17:03 ` [PATCH 04/14] name-rev: " René Scharfe
2025-12-24 17:03 ` [PATCH 05/14] remote: use commit_stack for local_commits René Scharfe
2025-12-24 17:03 ` [PATCH 06/14] remote: use commit_stack for sent_tips René Scharfe
2025-12-24 17:03 ` [PATCH 07/14] remote: use commit_stack for src_commits René Scharfe
2025-12-24 17:03 ` [PATCH 08/14] test-reach: use commit_stack René Scharfe
2025-12-24 17:03 ` [PATCH 09/14] commit: add commit_stack_init() René Scharfe
2025-12-24 17:03 ` [PATCH 10/14] pack-bitmap-write: use commit_stack René Scharfe
2025-12-24 17:03 ` [PATCH 11/14] shallow: " René Scharfe
2025-12-24 17:03 ` [PATCH 12/14] commit: add commit_stack_grow() René Scharfe
2025-12-24 17:03 ` [PATCH 13/14] commit-graph: use commit_stack René Scharfe
2025-12-24 17:03 ` [PATCH 14/14] commit-reach: " René Scharfe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox