@@ -169,6 +169,7 @@ enum atom_type {
169169 ATOM_ELSE ,
170170 ATOM_REST ,
171171 ATOM_AHEADBEHIND ,
172+ ATOM_ISBASE ,
172173};
173174
174175/*
@@ -890,6 +891,23 @@ static int ahead_behind_atom_parser(struct ref_format *format,
890891 return 0 ;
891892}
892893
894+ static int is_base_atom_parser (struct ref_format * format ,
895+ struct used_atom * atom UNUSED ,
896+ const char * arg , struct strbuf * err )
897+ {
898+ struct string_list_item * item ;
899+
900+ if (!arg )
901+ return strbuf_addf_ret (err , -1 , _ ("expected format: %%(is-base:<committish>)" ));
902+
903+ item = string_list_append (& format -> is_base_tips , arg );
904+ item -> util = lookup_commit_reference_by_name (arg );
905+ if (!item -> util )
906+ die ("failed to find '%s'" , arg );
907+
908+ return 0 ;
909+ }
910+
893911static int head_atom_parser (struct ref_format * format UNUSED ,
894912 struct used_atom * atom ,
895913 const char * arg , struct strbuf * err )
@@ -955,6 +973,7 @@ static struct {
955973 [ATOM_ELSE ] = { "else" , SOURCE_NONE },
956974 [ATOM_REST ] = { "rest" , SOURCE_NONE , FIELD_STR , rest_atom_parser },
957975 [ATOM_AHEADBEHIND ] = { "ahead-behind" , SOURCE_OTHER , FIELD_STR , ahead_behind_atom_parser },
976+ [ATOM_ISBASE ] = { "is-base" , SOURCE_OTHER , FIELD_STR , is_base_atom_parser },
958977 /*
959978 * Please update $__git_ref_fieldlist in git-completion.bash
960979 * when you add new atoms
@@ -2340,6 +2359,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
23402359 int i ;
23412360 struct object_info empty = OBJECT_INFO_INIT ;
23422361 int ahead_behind_atoms = 0 ;
2362+ int is_base_atoms = 0 ;
23432363
23442364 CALLOC_ARRAY (ref -> value , used_atom_cnt );
23452365
@@ -2489,6 +2509,15 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err)
24892509 v -> s = xstrdup ("" );
24902510 }
24912511 continue ;
2512+ } else if (atom_type == ATOM_ISBASE ) {
2513+ if (ref -> is_base && ref -> is_base [is_base_atoms ]) {
2514+ v -> s = xstrfmt ("(%s)" , ref -> is_base [is_base_atoms ]);
2515+ free (ref -> is_base [is_base_atoms ]);
2516+ } else {
2517+ v -> s = xstrdup ("" );
2518+ }
2519+ is_base_atoms ++ ;
2520+ continue ;
24922521 } else
24932522 continue ;
24942523
@@ -2895,6 +2924,7 @@ static void free_array_item(struct ref_array_item *item)
28952924 free (item -> value );
28962925 }
28972926 free (item -> counts );
2927+ free (item -> is_base );
28982928 free (item );
28992929}
29002930
@@ -3059,6 +3089,49 @@ void filter_ahead_behind(struct repository *r,
30593089 free (commits );
30603090}
30613091
3092+ void filter_is_base (struct repository * r ,
3093+ struct ref_format * format ,
3094+ struct ref_array * array )
3095+ {
3096+ struct commit * * bases ;
3097+ size_t bases_nr = 0 ;
3098+ struct ref_array_item * * back_index ;
3099+
3100+ if (!format -> is_base_tips .nr || !array -> nr )
3101+ return ;
3102+
3103+ CALLOC_ARRAY (back_index , array -> nr );
3104+ CALLOC_ARRAY (bases , array -> nr );
3105+
3106+ for (size_t i = 0 ; i < array -> nr ; i ++ ) {
3107+ const char * name = array -> items [i ]-> refname ;
3108+ struct commit * c = lookup_commit_reference_by_name_gently (name , 1 );
3109+
3110+ CALLOC_ARRAY (array -> items [i ]-> is_base , format -> is_base_tips .nr );
3111+
3112+ if (!c )
3113+ continue ;
3114+
3115+ back_index [bases_nr ] = array -> items [i ];
3116+ bases [bases_nr ] = c ;
3117+ bases_nr ++ ;
3118+ }
3119+
3120+ for (size_t i = 0 ; i < format -> is_base_tips .nr ; i ++ ) {
3121+ struct commit * tip = format -> is_base_tips .items [i ].util ;
3122+ int base_index = get_branch_base_for_tip (r , tip , bases , bases_nr );
3123+
3124+ if (base_index < 0 )
3125+ continue ;
3126+
3127+ /* Store the string for use in output later. */
3128+ back_index [base_index ]-> is_base [i ] = xstrdup (format -> is_base_tips .items [i ].string );
3129+ }
3130+
3131+ free (back_index );
3132+ free (bases );
3133+ }
3134+
30623135static int do_filter_refs (struct ref_filter * filter , unsigned int type , each_ref_fn fn , void * cb_data )
30633136{
30643137 int ret = 0 ;
@@ -3152,7 +3225,8 @@ static inline int can_do_iterative_format(struct ref_filter *filter,
31523225 return !(filter -> reachable_from ||
31533226 filter -> unreachable_from ||
31543227 sorting ||
3155- format -> bases .nr );
3228+ format -> bases .nr ||
3229+ format -> is_base_tips .nr );
31563230}
31573231
31583232void filter_and_format_refs (struct ref_filter * filter , unsigned int type ,
@@ -3176,6 +3250,7 @@ void filter_and_format_refs(struct ref_filter *filter, unsigned int type,
31763250 struct ref_array array = { 0 };
31773251 filter_refs (& array , filter , type );
31783252 filter_ahead_behind (the_repository , format , & array );
3253+ filter_is_base (the_repository , format , & array );
31793254 ref_array_sort (sorting , & array );
31803255 print_formatted_ref_array (& array , format );
31813256 ref_array_clear (& array );
0 commit comments