aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2026-01-12 05:19:52 -0800
committerJunio C Hamano <gitster@pobox.com>2026-01-12 05:19:52 -0800
commit3235ef374ea9808002b3304036c1b31965033ea0 (patch)
tree2f82cb718b5447a6021308b4d905c2e8e8c4de22
parent0320bcd743ccf9e707b45c84761e94e9ca72f710 (diff)
parent0e445956f4c9b6d079feb5ed831f018c857b955b (diff)
downloadgit-3235ef374ea9808002b3304036c1b31965033ea0.tar.xz
Merge branch 'rs/commit-stack'
Code clean-up, unifying various hand-rolled "list of commit objects" and use the commit_stack API. * rs/commit-stack: commit-reach: use commit_stack commit-graph: use commit_stack commit: add commit_stack_grow() shallow: use commit_stack pack-bitmap-write: use commit_stack commit: add commit_stack_init() test-reach: use commit_stack remote: use commit_stack for src_commits remote: use commit_stack for sent_tips remote: use commit_stack for local_commits name-rev: use commit_stack midx: use commit_stack log: use commit_stack revision: export commit_stack
-rw-r--r--builtin/log.c31
-rw-r--r--builtin/name-rev.c17
-rw-r--r--commit-graph.c86
-rw-r--r--commit-reach.c25
-rw-r--r--commit.c28
-rw-r--r--commit.h12
-rw-r--r--midx-write.c35
-rw-r--r--pack-bitmap-write.c18
-rw-r--r--remote.c74
-rw-r--r--revision.c23
-rw-r--r--shallow.c44
-rw-r--r--shallow.h4
-rw-r--r--t/helper/test-reach.c34
13 files changed, 184 insertions, 247 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);
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)
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);
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;
diff --git a/commit.c b/commit.c
index 2527f15d9d..efd0c02683 100644
--- a/commit.c
+++ b/commit.c
@@ -1984,3 +1984,31 @@ 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_init(struct commit_stack *stack)
+{
+ stack->items = NULL;
+ 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)
+{
+ commit_stack_grow(stack, 1);
+ 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(stack->items);
+ commit_stack_init(stack);
+}
diff --git a/commit.h b/commit.h
index 5406dd2663..79a761c37d 100644
--- a/commit.h
+++ b/commit.h
@@ -381,4 +381,16 @@ 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_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 *);
+
#endif /* COMMIT_H */
diff --git a/midx-write.c b/midx-write.c
index ce459b02c3..87b97c7087 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,
@@ -1447,15 +1438,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
@@ -1466,17 +1456,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
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 @@ next:
}
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 @@ next:
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;
diff --git a/remote.c b/remote.c
index 59b3715120..b756ff6f15 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);
@@ -1450,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;
@@ -1467,12 +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.tip, sent_tips.nr,
- src_commits, nr_src_commits,
+ found_commits = get_reachable_subset(sent_tips.items,
+ sent_tips.nr,
+ src_commits.items,
+ src_commits.nr,
reachable_flag);
for_each_string_list_item(item, &src_tag) {
@@ -1502,13 +1494,14 @@ 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);
}
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)
@@ -2544,36 +2537,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 +2571,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 +2599,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 +2630,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 +2640,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;
}
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)
{
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 *);
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;
}