@@ -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
30863087void 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
31273136void 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
32543274static 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
32863308void 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- }
0 commit comments