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