Am 18.01.25 um 18:11 schrieb René Scharfe: > I think moving to the right place in one step requires less churn. Let's > compare; v2 coming up. The version building on top of v1 would look like this: --- ref-filter.c | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/ref-filter.c b/ref-filter.c index 89f44936f9..caf28466ab 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -235,6 +235,9 @@ static struct used_atom { enum { S_BARE, S_GRADE, S_SIGNER, S_KEY, S_FINGERPRINT, S_PRI_KEY_FP, S_TRUST_LEVEL } option; } signature; + struct { + struct commit *commit; + } base; struct strvec describe_args; struct refname_atom refname; char *head; @@ -242,9 +245,6 @@ static struct used_atom { } *used_atom; static int used_atom_cnt, need_tagged, need_symref; -/* List of bases for ahead-behind counts. */ -static struct string_list bases = STRING_LIST_INIT_DUP; - /* List of bases for is-base indicators. */ static struct string_list is_base_tips = STRING_LIST_INIT_DUP; @@ -898,17 +898,14 @@ static int rest_atom_parser(struct ref_format *format UNUSED, } static int ahead_behind_atom_parser(struct ref_format *format UNUSED, - struct used_atom *atom UNUSED, + struct used_atom *atom, const char *arg, struct strbuf *err) { - struct string_list_item *item; - if (!arg) return strbuf_addf_ret(err, -1, _("expected format: %%(ahead-behind:<committish>)")); - item = string_list_append(&bases, arg); - item->util = lookup_commit_reference_by_name(arg); - if (!item->util) + atom->u.base.commit = lookup_commit_reference_by_name(arg); + if (!atom->u.base.commit) die("failed to find '%s'", arg); return 0; @@ -3030,7 +3027,6 @@ void ref_array_clear(struct ref_array *array) } FREE_AND_NULL(used_atom); used_atom_cnt = 0; - string_list_clear(&bases, 0); string_list_clear(&is_base_tips, 0); if (ref_to_worktree_map.worktrees) { @@ -3095,18 +3091,27 @@ void filter_ahead_behind(struct repository *r, struct ref_array *array) { struct commit **commits; - size_t commits_nr = bases.nr + array->nr; + size_t bases_nr, commits_nr; + + if (!array->nr) + return; - if (!bases.nr || !array->nr) + for (size_t i = bases_nr = 0; i < used_atom_cnt; i++) { + if (used_atom[i].atom_type == ATOM_AHEADBEHIND) + bases_nr++; + } + if (!bases_nr) return; - ALLOC_ARRAY(commits, commits_nr); - for (size_t i = 0; i < bases.nr; i++) - commits[i] = bases.items[i].util; + ALLOC_ARRAY(commits, st_add(bases_nr, array->nr)); + for (size_t i = 0, j = 0; i < used_atom_cnt; i++) { + if (used_atom[i].atom_type == ATOM_AHEADBEHIND) + commits[j++] = used_atom[i].u.base.commit; + } - ALLOC_ARRAY(array->counts, st_mult(bases.nr, array->nr)); + ALLOC_ARRAY(array->counts, st_mult(bases_nr, array->nr)); - commits_nr = bases.nr; + commits_nr = bases_nr; array->counts_nr = 0; for (size_t i = 0; i < array->nr; i++) { const char *name = array->items[i]->refname; @@ -3115,8 +3120,8 @@ void filter_ahead_behind(struct repository *r, if (!commits[commits_nr]) continue; - CALLOC_ARRAY(array->items[i]->counts, bases.nr); - for (size_t j = 0; j < bases.nr; j++) { + CALLOC_ARRAY(array->items[i]->counts, bases_nr); + for (size_t j = 0; j < bases_nr; j++) { struct ahead_behind_count *count; count = &array->counts[array->counts_nr++]; count->tip_index = commits_nr; @@ -3282,9 +3287,12 @@ static inline int can_do_iterative_format(struct ref_filter *filter, * - filtering on reachability * - including ahead-behind information in the formatted output */ + for (size_t i = 0; i < used_atom_cnt; i++) { + if (used_atom[i].atom_type == ATOM_AHEADBEHIND) + return 0; + } return !(filter->reachable_from || filter->unreachable_from || - bases.nr || is_base_tips.nr); } -- 2.48.1