Skip to content

Commit 6fc158f

Browse files
gitsterGit for Windows Build Agent
authored andcommitted
Merge branch 'rs/ref-filter-used-atoms-value-fix'
"git branch --sort=..." and "git for-each-ref --format=... --sort=..." did not work as expected with some atoms, which has been corrected. * rs/ref-fitler-used-atoms-value-fix: ref-filter: remove ref_format_clear() ref-filter: move is-base tip to used_atom ref-filter: move ahead-behind bases into used_atom Signed-off-by: Johannes Schindelin <[email protected]>
2 parents b9c5f49 + 2c98971 commit 6fc158f

File tree

8 files changed

+121
-72
lines changed

8 files changed

+121
-72
lines changed

builtin/branch.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
473473
if (verify_ref_format(format))
474474
die(_("unable to parse format string"));
475475

476-
filter_ahead_behind(the_repository, format, &array);
476+
filter_ahead_behind(the_repository, &array);
477477
ref_array_sort(sorting, &array);
478478

479479
if (column_active(colopts)) {
@@ -884,7 +884,6 @@ int cmd_branch(int argc,
884884
string_list_clear(&output, 0);
885885
ref_sorting_release(sorting);
886886
ref_filter_clear(&filter);
887-
ref_format_clear(&format);
888887

889888
ret = 0;
890889
goto out;

builtin/for-each-ref.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@ int cmd_for_each_ref(int argc,
108108
filter_and_format_refs(&filter, flags, sorting, &format);
109109

110110
ref_filter_clear(&filter);
111-
ref_format_clear(&format);
112111
ref_sorting_release(sorting);
113112
strvec_clear(&vec);
114113
return 0;

builtin/tag.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,6 @@ int cmd_tag(int argc,
698698
cleanup:
699699
ref_sorting_release(sorting);
700700
ref_filter_clear(&filter);
701-
ref_format_clear(&format);
702701
strbuf_release(&buf);
703702
strbuf_release(&ref);
704703
strbuf_release(&reflog_msg);

builtin/verify-tag.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,5 @@ int cmd_verify_tag(int argc,
6969
if (format.format)
7070
pretty_print_ref(name, &oid, &format);
7171
}
72-
ref_format_clear(&format);
7372
return had_error;
7473
}

ref-filter.c

Lines changed: 63 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,10 @@ static struct used_atom {
235235
enum { S_BARE, S_GRADE, S_SIGNER, S_KEY,
236236
S_FINGERPRINT, S_PRI_KEY_FP, S_TRUST_LEVEL } option;
237237
} signature;
238+
struct {
239+
char *name;
240+
struct commit *commit;
241+
} base;
238242
struct strvec describe_args;
239243
struct refname_atom refname;
240244
char *head;
@@ -891,35 +895,30 @@ static int rest_atom_parser(struct ref_format *format UNUSED,
891895
return 0;
892896
}
893897

894-
static int ahead_behind_atom_parser(struct ref_format *format,
895-
struct used_atom *atom UNUSED,
898+
static int ahead_behind_atom_parser(struct ref_format *format UNUSED,
899+
struct used_atom *atom,
896900
const char *arg, struct strbuf *err)
897901
{
898-
struct string_list_item *item;
899-
900902
if (!arg)
901903
return strbuf_addf_ret(err, -1, _("expected format: %%(ahead-behind:<committish>)"));
902904

903-
item = string_list_append(&format->bases, arg);
904-
item->util = lookup_commit_reference_by_name(arg);
905-
if (!item->util)
905+
atom->u.base.commit = lookup_commit_reference_by_name(arg);
906+
if (!atom->u.base.commit)
906907
die("failed to find '%s'", arg);
907908

908909
return 0;
909910
}
910911

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,
913914
const char *arg, struct strbuf *err)
914915
{
915-
struct string_list_item *item;
916-
917916
if (!arg)
918917
return strbuf_addf_ret(err, -1, _("expected format: %%(is-base:<committish>)"));
919918

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)
923922
die("failed to find '%s'", arg);
924923

925924
return 0;
@@ -3009,6 +3008,8 @@ void ref_array_clear(struct ref_array *array)
30093008
free(atom->u.head);
30103009
else if (atom->atom_type == ATOM_DESCRIBE)
30113010
strvec_clear(&atom->u.describe_args);
3011+
else if (atom->atom_type == ATOM_ISBASE)
3012+
free(atom->u.base.name);
30123013
else if (atom->atom_type == ATOM_TRAILERS ||
30133014
(atom->atom_type == ATOM_CONTENTS &&
30143015
atom->u.contents.option == C_TRAILERS)) {
@@ -3084,22 +3085,30 @@ static void reach_filter(struct ref_array *array,
30843085
}
30853086

30863087
void filter_ahead_behind(struct repository *r,
3087-
struct ref_format *format,
30883088
struct ref_array *array)
30893089
{
30903090
struct commit **commits;
3091-
size_t commits_nr = format->bases.nr + array->nr;
3091+
size_t bases_nr, commits_nr;
3092+
3093+
if (!array->nr)
3094+
return;
30923095

3093-
if (!format->bases.nr || !array->nr)
3096+
for (size_t i = bases_nr = 0; i < used_atom_cnt; i++) {
3097+
if (used_atom[i].atom_type == ATOM_AHEADBEHIND)
3098+
bases_nr++;
3099+
}
3100+
if (!bases_nr)
30943101
return;
30953102

3096-
ALLOC_ARRAY(commits, commits_nr);
3097-
for (size_t i = 0; i < format->bases.nr; i++)
3098-
commits[i] = format->bases.items[i].util;
3103+
ALLOC_ARRAY(commits, st_add(bases_nr, array->nr));
3104+
for (size_t i = 0, j = 0; i < used_atom_cnt; i++) {
3105+
if (used_atom[i].atom_type == ATOM_AHEADBEHIND)
3106+
commits[j++] = used_atom[i].u.base.commit;
3107+
}
30993108

3100-
ALLOC_ARRAY(array->counts, st_mult(format->bases.nr, array->nr));
3109+
ALLOC_ARRAY(array->counts, st_mult(bases_nr, array->nr));
31013110

3102-
commits_nr = format->bases.nr;
3111+
commits_nr = bases_nr;
31033112
array->counts_nr = 0;
31043113
for (size_t i = 0; i < array->nr; i++) {
31053114
const char *name = array->items[i]->refname;
@@ -3108,8 +3117,8 @@ void filter_ahead_behind(struct repository *r,
31083117
if (!commits[commits_nr])
31093118
continue;
31103119

3111-
CALLOC_ARRAY(array->items[i]->counts, format->bases.nr);
3112-
for (size_t j = 0; j < format->bases.nr; j++) {
3120+
CALLOC_ARRAY(array->items[i]->counts, bases_nr);
3121+
for (size_t j = 0; j < bases_nr; j++) {
31133122
struct ahead_behind_count *count;
31143123
count = &array->counts[array->counts_nr++];
31153124
count->tip_index = commits_nr;
@@ -3125,14 +3134,20 @@ void filter_ahead_behind(struct repository *r,
31253134
}
31263135

31273136
void filter_is_base(struct repository *r,
3128-
struct ref_format *format,
31293137
struct ref_array *array)
31303138
{
31313139
struct commit **bases;
3132-
size_t bases_nr = 0;
3140+
size_t bases_nr = 0, is_base_nr;
31333141
struct ref_array_item **back_index;
31343142

3135-
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)
31363151
return;
31373152

31383153
CALLOC_ARRAY(back_index, array->nr);
@@ -3142,7 +3157,7 @@ void filter_is_base(struct repository *r,
31423157
const char *name = array->items[i]->refname;
31433158
struct commit *c = lookup_commit_reference_by_name_gently(name, 1);
31443159

3145-
CALLOC_ARRAY(array->items[i]->is_base, format->is_base_tips.nr);
3160+
CALLOC_ARRAY(array->items[i]->is_base, is_base_nr);
31463161

31473162
if (!c)
31483163
continue;
@@ -3152,15 +3167,20 @@ void filter_is_base(struct repository *r,
31523167
bases_nr++;
31533168
}
31543169

3155-
for (size_t i = 0; i < format->is_base_tips.nr; i++) {
3156-
struct commit *tip = format->is_base_tips.items[i].util;
3157-
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;
31583176

3177+
tip = used_atom[i].u.base.commit;
3178+
base_index = get_branch_base_for_tip(r, tip, bases, bases_nr);
31593179
if (base_index < 0)
31603180
continue;
31613181

31623182
/* Store the string for use in output later. */
3163-
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);
31643184
}
31653185

31663186
free(back_index);
@@ -3252,8 +3272,7 @@ struct ref_sorting {
32523272
};
32533273

32543274
static inline int can_do_iterative_format(struct ref_filter *filter,
3255-
struct ref_sorting *sorting,
3256-
struct ref_format *format)
3275+
struct ref_sorting *sorting)
32573276
{
32583277
/*
32593278
* Reference backends sort patterns lexicographically by refname, so if
@@ -3277,17 +3296,20 @@ static inline int can_do_iterative_format(struct ref_filter *filter,
32773296
* - filtering on reachability
32783297
* - including ahead-behind information in the formatted output
32793298
*/
3280-
return !(filter->reachable_from ||
3281-
filter->unreachable_from ||
3282-
format->bases.nr ||
3283-
format->is_base_tips.nr);
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+
}
3305+
return !(filter->reachable_from || filter->unreachable_from);
32843306
}
32853307

32863308
void filter_and_format_refs(struct ref_filter *filter, unsigned int type,
32873309
struct ref_sorting *sorting,
32883310
struct ref_format *format)
32893311
{
3290-
if (can_do_iterative_format(filter, sorting, format)) {
3312+
if (can_do_iterative_format(filter, sorting)) {
32913313
int save_commit_buffer_orig;
32923314
struct ref_filter_and_format_cbdata ref_cbdata = {
32933315
.filter = filter,
@@ -3303,8 +3325,8 @@ void filter_and_format_refs(struct ref_filter *filter, unsigned int type,
33033325
} else {
33043326
struct ref_array array = { 0 };
33053327
filter_refs(&array, filter, type);
3306-
filter_ahead_behind(the_repository, format, &array);
3307-
filter_is_base(the_repository, format, &array);
3328+
filter_ahead_behind(the_repository, &array);
3329+
filter_is_base(the_repository, &array);
33083330
ref_array_sort(sorting, &array);
33093331
print_formatted_ref_array(&array, format);
33103332
ref_array_clear(&array);
@@ -3638,16 +3660,3 @@ void ref_filter_clear(struct ref_filter *filter)
36383660
free_commit_list(filter->unreachable_from);
36393661
ref_filter_init(filter);
36403662
}
3641-
3642-
void ref_format_init(struct ref_format *format)
3643-
{
3644-
struct ref_format blank = REF_FORMAT_INIT;
3645-
memcpy(format, &blank, sizeof(blank));
3646-
}
3647-
3648-
void ref_format_clear(struct ref_format *format)
3649-
{
3650-
string_list_clear(&format->bases, 0);
3651-
string_list_clear(&format->is_base_tips, 0);
3652-
ref_format_init(format);
3653-
}

ref-filter.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,6 @@ struct ref_format {
9999
/* Internal state to ref-filter */
100100
int need_color_reset_at_eol;
101101

102-
/* List of bases for ahead-behind counts. */
103-
struct string_list bases;
104-
105-
/* List of bases for is-base indicators. */
106-
struct string_list is_base_tips;
107-
108102
struct {
109103
int max_count;
110104
int omit_empty;
@@ -117,8 +111,6 @@ struct ref_format {
117111
}
118112
#define REF_FORMAT_INIT { \
119113
.use_color = -1, \
120-
.bases = STRING_LIST_INIT_DUP, \
121-
.is_base_tips = STRING_LIST_INIT_DUP, \
122114
}
123115

124116
/* Macros for checking --merged and --no-merged options */
@@ -205,7 +197,6 @@ struct ref_array_item *ref_array_push(struct ref_array *array,
205197
* If this is not called, then any ahead-behind atoms will be blank.
206198
*/
207199
void filter_ahead_behind(struct repository *r,
208-
struct ref_format *format,
209200
struct ref_array *array);
210201

211202
/*
@@ -215,13 +206,9 @@ void filter_ahead_behind(struct repository *r,
215206
* If this is not called, then any is-base atoms will be blank.
216207
*/
217208
void filter_is_base(struct repository *r,
218-
struct ref_format *format,
219209
struct ref_array *array);
220210

221211
void ref_filter_init(struct ref_filter *filter);
222212
void ref_filter_clear(struct ref_filter *filter);
223213

224-
void ref_format_init(struct ref_format *format);
225-
void ref_format_clear(struct ref_format *format);
226-
227214
#endif /* REF_FILTER_H */

t/t3203-branch-output.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,34 @@ test_expect_success 'git branch --format with ahead-behind' '
368368
test_cmp expect actual
369369
'
370370

371+
test_expect_success 'git branch `--sort=[-]ahead-behind` option' '
372+
cat >expect <<-\EOF &&
373+
(HEAD detached from fromtag) 0 0
374+
refs/heads/ambiguous 0 0
375+
refs/heads/branch-two 0 0
376+
refs/heads/branch-one 1 0
377+
refs/heads/main 1 0
378+
refs/heads/ref-to-branch 1 0
379+
refs/heads/ref-to-remote 1 0
380+
EOF
381+
git branch --format="%(refname) %(ahead-behind:HEAD)" \
382+
--sort=refname --sort=ahead-behind:HEAD >actual &&
383+
test_cmp expect actual &&
384+
385+
cat >expect <<-\EOF &&
386+
(HEAD detached from fromtag) 0 0
387+
refs/heads/branch-one 1 0
388+
refs/heads/main 1 0
389+
refs/heads/ref-to-branch 1 0
390+
refs/heads/ref-to-remote 1 0
391+
refs/heads/ambiguous 0 0
392+
refs/heads/branch-two 0 0
393+
EOF
394+
git branch --format="%(refname) %(ahead-behind:HEAD)" \
395+
--sort=refname --sort=-ahead-behind:HEAD >actual &&
396+
test_cmp expect actual
397+
'
398+
371399
test_expect_success 'git branch with --format=%(rest) must fail' '
372400
test_must_fail git branch --format="%(rest)" >actual
373401
'

t/t6600-test-reach.sh

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,4 +733,33 @@ test_expect_success 'for-each-ref is-base:multiple' '
733733
--format="%(refname)[%(is-base:commit-2-3)-%(is-base:commit-6-5)]" --stdin
734734
'
735735

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+
736765
test_done

0 commit comments

Comments
 (0)