ref-filter: move is-base tip to used_atom
The string_list "is_base_tips" in struct ref_format stores the committish part of "is-base:<committish>". It has the same problems that its sibling string_list "bases" had. Fix them the same way as the previous commit did for the latter, by replacing the string_list with fields in "used_atom". Helped-by: Jeff King <peff@peff.net> Signed-off-by: René Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
René Scharfe committed
Jan 18, 2025 at 18:11 UTC
7ee4fd18ace71d187ee3ea5ba745a6a3493e0e0a
3 files changed
+62
-28
ref-filter.c
+33
-23
@@ -236,6 +236,7 @@ static struct used_atom {
236
S_FINGERPRINT, S_PRI_KEY_FP, S_TRUST_LEVEL } option;
237
} signature;
238
struct {
239
+ char *name;
240
struct commit *commit;
241
} base;
242
struct strvec describe_args;
@@ -908,18 +909,16 @@ static int ahead_behind_atom_parser(struct ref_format *format UNUSED,
909
return 0;
910
}
911
911
-static int is_base_atom_parser(struct ref_format *format,
912
- struct used_atom *atom UNUSED,
912
+static int is_base_atom_parser(struct ref_format *format UNUSED,
913
+ struct used_atom *atom,
914
const char *arg, struct strbuf *err)
915
{
915
- struct string_list_item *item;
916
-
916
if (!arg)
917
return strbuf_addf_ret(err, -1, _("expected format: %%(is-base:<committish>)"));
918
920
- item = string_list_append(&format->is_base_tips, arg);
921
- item->util = lookup_commit_reference_by_name(arg);
922
- if (!item->util)
919
+ atom->u.base.name = xstrdup(arg);
920
+ atom->u.base.commit = lookup_commit_reference_by_name(arg);
921
+ if (!atom->u.base.commit)
922
die("failed to find '%s'", arg);
923
924
return 0;
@@ -3009,6 +3008,8 @@ void ref_array_clear(struct ref_array *array)
3008
free(atom->u.head);
3009
else if (atom->atom_type == ATOM_DESCRIBE)
3010
strvec_clear(&atom->u.describe_args);
3011
+ else if (atom->atom_type == ATOM_ISBASE)
3012
+ free(atom->u.base.name);
3013
else if (atom->atom_type == ATOM_TRAILERS ||
3014
(atom->atom_type == ATOM_CONTENTS &&
3015
atom->u.contents.option == C_TRAILERS)) {
@@ -3133,14 +3134,20 @@ void filter_ahead_behind(struct repository *r,
3134
}
3135
3136
void filter_is_base(struct repository *r,
3136
- struct ref_format *format,
3137
struct ref_array *array)
3138
{
3139
struct commit **bases;
3140
- size_t bases_nr = 0;
3140
+ size_t bases_nr = 0, is_base_nr;
3141
struct ref_array_item **back_index;
3142
3143
- if (!format->is_base_tips.nr || !array->nr)
3143
+ if (!array->nr)
3144
+ return;
3145
+
3146
+ for (size_t i = is_base_nr = 0; i < used_atom_cnt; i++) {
3147
+ if (used_atom[i].atom_type == ATOM_ISBASE)
3148
+ is_base_nr++;
3149
+ }
3150
+ if (!is_base_nr)
3151
return;
3152
3153
CALLOC_ARRAY(back_index, array->nr);
@@ -3150,7 +3157,7 @@ void filter_is_base(struct repository *r,
3157
const char *name = array->items[i]->refname;
3158
struct commit *c = lookup_commit_reference_by_name_gently(name, 1);
3159
3153
- CALLOC_ARRAY(array->items[i]->is_base, format->is_base_tips.nr);
3160
+ CALLOC_ARRAY(array->items[i]->is_base, is_base_nr);
3161
3162
if (!c)
3163
continue;
@@ -3160,15 +3167,20 @@ void filter_is_base(struct repository *r,
3167
bases_nr++;
3168
}
3169
3163
- for (size_t i = 0; i < format->is_base_tips.nr; i++) {
3164
- struct commit *tip = format->is_base_tips.items[i].util;
3165
- int base_index = get_branch_base_for_tip(r, tip, bases, bases_nr);
3170
+ for (size_t i = 0, j = 0; i < used_atom_cnt; i++) {
3171
+ struct commit *tip;
3172
+ int base_index;
3173
+
3174
+ if (used_atom[i].atom_type != ATOM_ISBASE)
3175
+ continue;
3176
3177
+ tip = used_atom[i].u.base.commit;
3178
+ base_index = get_branch_base_for_tip(r, tip, bases, bases_nr);
3179
if (base_index < 0)
3180
continue;
3181
3182
/* Store the string for use in output later. */
3171
- back_index[base_index]->is_base[i] = xstrdup(format->is_base_tips.items[i].string);
3183
+ back_index[base_index]->is_base[j++] = xstrdup(used_atom[i].u.base.name);
3184
}
3185
3186
free(back_index);
@@ -3260,8 +3272,7 @@ struct ref_sorting {
3272
};
3273
3274
static inline int can_do_iterative_format(struct ref_filter *filter,
3263
- struct ref_sorting *sorting,
3264
- struct ref_format *format)
3275
+ struct ref_sorting *sorting)
3276
{
3277
/*
3278
* Reference backends sort patterns lexicographically by refname, so if
@@ -3288,17 +3299,17 @@ static inline int can_do_iterative_format(struct ref_filter *filter,
3299
for (size_t i = 0; i < used_atom_cnt; i++) {
3300
if (used_atom[i].atom_type == ATOM_AHEADBEHIND)
3301
return 0;
3302
+ if (used_atom[i].atom_type == ATOM_ISBASE)
3303
+ return 0;
3304
}
3292
- return !(filter->reachable_from ||
3293
- filter->unreachable_from ||
3294
- format->is_base_tips.nr);
3305
+ return !(filter->reachable_from || filter->unreachable_from);
3306
}
3307
3308
void filter_and_format_refs(struct ref_filter *filter, unsigned int type,
3309
struct ref_sorting *sorting,
3310
struct ref_format *format)
3311
{
3301
- if (can_do_iterative_format(filter, sorting, format)) {
3312
+ if (can_do_iterative_format(filter, sorting)) {
3313
int save_commit_buffer_orig;
3314
struct ref_filter_and_format_cbdata ref_cbdata = {
3315
.filter = filter,
@@ -3315,7 +3326,7 @@ void filter_and_format_refs(struct ref_filter *filter, unsigned int type,
3326
struct ref_array array = { 0 };
3327
filter_refs(&array, filter, type);
3328
filter_ahead_behind(the_repository, &array);
3318
- filter_is_base(the_repository, format, &array);
3329
+ filter_is_base(the_repository, &array);
3330
ref_array_sort(sorting, &array);
3331
print_formatted_ref_array(&array, format);
3332
ref_array_clear(&array);
@@ -3658,6 +3669,5 @@ void ref_format_init(struct ref_format *format)
3669
3670
void ref_format_clear(struct ref_format *format)
3671
{
3661
- string_list_clear(&format->is_base_tips, 0);
3672
ref_format_init(format);
3673
}
ref-filter.h
-5
@@ -99,9 +99,6 @@ struct ref_format {
99
/* Internal state to ref-filter */
100
int need_color_reset_at_eol;
101
102
- /* List of bases for is-base indicators. */
103
- struct string_list is_base_tips;
104
-
102
struct {
103
int max_count;
104
int omit_empty;
@@ -114,7 +111,6 @@ struct ref_format {
111
}
112
#define REF_FORMAT_INIT { \
113
.use_color = -1, \
117
- .is_base_tips = STRING_LIST_INIT_DUP, \
114
}
115
116
/* Macros for checking --merged and --no-merged options */
@@ -210,7 +206,6 @@ void filter_ahead_behind(struct repository *r,
206
* If this is not called, then any is-base atoms will be blank.
207
*/
208
void filter_is_base(struct repository *r,
213
- struct ref_format *format,
209
struct ref_array *array);
210
211
void ref_filter_init(struct ref_filter *filter);
t/t6600-test-reach.sh
+29
@@ -733,4 +733,33 @@ test_expect_success 'for-each-ref is-base:multiple' '
733
--format="%(refname)[%(is-base:commit-2-3)-%(is-base:commit-6-5)]" --stdin
734
'
735
736
+test_expect_success 'for-each-ref is-base: --sort' '
737
+ cat >input <<-\EOF &&
738
+ refs/heads/commit-1-1
739
+ refs/heads/commit-4-2
740
+ refs/heads/commit-4-4
741
+ refs/heads/commit-8-4
742
+ EOF
743
+
744
+ cat >expect <<-\EOF &&
745
+ refs/heads/commit-1-1
746
+ refs/heads/commit-4-4
747
+ refs/heads/commit-8-4
748
+ refs/heads/commit-4-2
749
+ EOF
750
+ run_all_modes git for-each-ref \
751
+ --format="%(refname)" --stdin \
752
+ --sort=refname --sort=is-base:commit-2-3 &&
753
+
754
+ cat >expect <<-\EOF &&
755
+ refs/heads/commit-4-2
756
+ refs/heads/commit-1-1
757
+ refs/heads/commit-4-4
758
+ refs/heads/commit-8-4
759
+ EOF
760
+ run_all_modes git for-each-ref \
761
+ --format="%(refname)" --stdin \
762
+ --sort=refname --sort=-is-base:commit-2-3
763
+'
764
+
765
test_done