Merge branch 'rs/commit-stack' into jch

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
This commit is contained in:
Junio C Hamano 2026-01-09 18:37:06 -08:00
commit 99a511be73
13 changed files with 184 additions and 247 deletions

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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 */

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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);

View File

@ -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 *);

View File

@ -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;
}