@@ -37,11 +37,11 @@ static unsigned char head_sha1[20];
3737static int branch_use_color = -1 ;
3838static char branch_colors [][COLOR_MAXLEN ] = {
3939 GIT_COLOR_RESET ,
40- GIT_COLOR_NORMAL , /* PLAIN */
41- GIT_COLOR_RED , /* REMOTE */
42- GIT_COLOR_NORMAL , /* LOCAL */
43- GIT_COLOR_GREEN , /* CURRENT */
44- GIT_COLOR_BLUE , /* UPSTREAM */
40+ GIT_COLOR_NORMAL , /* PLAIN */
41+ GIT_COLOR_RED , /* REMOTE */
42+ GIT_COLOR_NORMAL , /* LOCAL */
43+ GIT_COLOR_GREEN , /* CURRENT */
44+ GIT_COLOR_BLUE , /* UPSTREAM */
4545};
4646enum color_branch {
4747 BRANCH_COLOR_RESET = 0 ,
@@ -280,180 +280,88 @@ static int delete_branches(int argc, const char **argv, int force, int kinds,
280280 return (ret );
281281}
282282
283- static void fill_tracking_info (struct strbuf * stat , const char * branch_name ,
284- int show_upstream_ref )
283+ static int calc_maxwidth (struct ref_array * refs , int remote_bonus )
285284{
286- int ours , theirs ;
287- char * ref = NULL ;
288- struct branch * branch = branch_get (branch_name );
289- const char * upstream ;
290- struct strbuf fancy = STRBUF_INIT ;
291- int upstream_is_gone = 0 ;
292- int added_decoration = 1 ;
293-
294- if (stat_tracking_info (branch , & ours , & theirs , & upstream ) < 0 ) {
295- if (!upstream )
296- return ;
297- upstream_is_gone = 1 ;
298- }
299-
300- if (show_upstream_ref ) {
301- ref = shorten_unambiguous_ref (upstream , 0 );
302- if (want_color (branch_use_color ))
303- strbuf_addf (& fancy , "%s%s%s" ,
304- branch_get_color (BRANCH_COLOR_UPSTREAM ),
305- ref , branch_get_color (BRANCH_COLOR_RESET ));
306- else
307- strbuf_addstr (& fancy , ref );
308- }
285+ int i , max = 0 ;
286+ for (i = 0 ; i < refs -> nr ; i ++ ) {
287+ struct ref_array_item * it = refs -> items [i ];
288+ const char * desc = it -> refname ;
289+ int w ;
309290
310- if (upstream_is_gone ) {
311- if (show_upstream_ref )
312- strbuf_addf (stat , _ ("[%s: gone]" ), fancy .buf );
313- else
314- added_decoration = 0 ;
315- } else if (!ours && !theirs ) {
316- if (show_upstream_ref )
317- strbuf_addf (stat , _ ("[%s]" ), fancy .buf );
318- else
319- added_decoration = 0 ;
320- } else if (!ours ) {
321- if (show_upstream_ref )
322- strbuf_addf (stat , _ ("[%s: behind %d]" ), fancy .buf , theirs );
323- else
324- strbuf_addf (stat , _ ("[behind %d]" ), theirs );
291+ skip_prefix (it -> refname , "refs/heads/" , & desc );
292+ skip_prefix (it -> refname , "refs/remotes/" , & desc );
293+ if (it -> kind == FILTER_REFS_DETACHED_HEAD ) {
294+ char * head_desc = get_head_description ();
295+ w = utf8_strwidth (head_desc );
296+ free (head_desc );
297+ } else
298+ w = utf8_strwidth (desc );
325299
326- } else if (!theirs ) {
327- if (show_upstream_ref )
328- strbuf_addf (stat , _ ("[%s: ahead %d]" ), fancy .buf , ours );
329- else
330- strbuf_addf (stat , _ ("[ahead %d]" ), ours );
331- } else {
332- if (show_upstream_ref )
333- strbuf_addf (stat , _ ("[%s: ahead %d, behind %d]" ),
334- fancy .buf , ours , theirs );
335- else
336- strbuf_addf (stat , _ ("[ahead %d, behind %d]" ),
337- ours , theirs );
300+ if (it -> kind == FILTER_REFS_REMOTES )
301+ w += remote_bonus ;
302+ if (w > max )
303+ max = w ;
338304 }
339- strbuf_release (& fancy );
340- if (added_decoration )
341- strbuf_addch (stat , ' ' );
342- free (ref );
305+ return max ;
343306}
344307
345- static void add_verbose_info (struct strbuf * out , struct ref_array_item * item ,
346- struct ref_filter * filter , const char * refname )
308+ static const char * quote_literal_for_format (const char * s )
347309{
348- struct strbuf subject = STRBUF_INIT , stat = STRBUF_INIT ;
349- const char * sub = _ (" **** invalid ref ****" );
350- struct commit * commit = item -> commit ;
310+ static struct strbuf buf = STRBUF_INIT ;
351311
352- if (!parse_commit (commit )) {
353- pp_commit_easy (CMIT_FMT_ONELINE , commit , & subject );
354- sub = subject .buf ;
312+ strbuf_reset (& buf );
313+ while (* s ) {
314+ const char * ep = strchrnul (s , '%' );
315+ if (s < ep )
316+ strbuf_add (& buf , s , ep - s );
317+ if (* ep == '%' ) {
318+ strbuf_addstr (& buf , "%%" );
319+ s = ep + 1 ;
320+ } else {
321+ s = ep ;
322+ }
355323 }
356-
357- if (item -> kind == FILTER_REFS_BRANCHES )
358- fill_tracking_info (& stat , refname , filter -> verbose > 1 );
359-
360- strbuf_addf (out , " %s %s%s" ,
361- find_unique_abbrev (item -> commit -> object .oid .hash , filter -> abbrev ),
362- stat .buf , sub );
363- strbuf_release (& stat );
364- strbuf_release (& subject );
324+ return buf .buf ;
365325}
366326
367- static void format_and_print_ref_item (struct ref_array_item * item , int maxwidth ,
368- struct ref_filter * filter , const char * remote_prefix )
327+ static char * build_format (struct ref_filter * filter , int maxwidth , const char * remote_prefix )
369328{
370- char c ;
371- int current = 0 ;
372- int color ;
373- struct strbuf out = STRBUF_INIT , name = STRBUF_INIT ;
374- const char * prefix_to_show = "" ;
375- const char * prefix_to_skip = NULL ;
376- const char * desc = item -> refname ;
377- char * to_free = NULL ;
378-
379- switch (item -> kind ) {
380- case FILTER_REFS_BRANCHES :
381- prefix_to_skip = "refs/heads/" ;
382- skip_prefix (desc , prefix_to_skip , & desc );
383- if (!filter -> detached && !strcmp (desc , head ))
384- current = 1 ;
385- else
386- color = BRANCH_COLOR_LOCAL ;
387- break ;
388- case FILTER_REFS_REMOTES :
389- prefix_to_skip = "refs/remotes/" ;
390- skip_prefix (desc , prefix_to_skip , & desc );
391- color = BRANCH_COLOR_REMOTE ;
392- prefix_to_show = remote_prefix ;
393- break ;
394- case FILTER_REFS_DETACHED_HEAD :
395- desc = to_free = get_head_description ();
396- current = 1 ;
397- break ;
398- default :
399- color = BRANCH_COLOR_PLAIN ;
400- break ;
401- }
329+ struct strbuf fmt = STRBUF_INIT ;
330+ struct strbuf local = STRBUF_INIT ;
331+ struct strbuf remote = STRBUF_INIT ;
402332
403- c = ' ' ;
404- if (current ) {
405- c = '*' ;
406- color = BRANCH_COLOR_CURRENT ;
407- }
333+ strbuf_addf (& fmt , "%%(if)%%(HEAD)%%(then)* %s%%(else) %%(end)" ,
334+ branch_get_color (BRANCH_COLOR_CURRENT ));
408335
409- strbuf_addf (& name , "%s%s" , prefix_to_show , desc );
410336 if (filter -> verbose ) {
411- int utf8_compensation = strlen (name .buf ) - utf8_strwidth (name .buf );
412- strbuf_addf (& out , "%c %s%-*s%s" , c , branch_get_color (color ),
413- maxwidth + utf8_compensation , name .buf ,
337+ strbuf_addf (& local , "%%(align:%d,left)%%(refname:lstrip=2)%%(end)" , maxwidth );
338+ strbuf_addf (& local , "%s" , branch_get_color (BRANCH_COLOR_RESET ));
339+ strbuf_addf (& local , " %%(objectname:short=7) " );
340+
341+ if (filter -> verbose > 1 )
342+ strbuf_addf (& local , "%%(if)%%(upstream)%%(then)[%s%%(upstream:short)%s%%(if)%%(upstream:track)"
343+ "%%(then): %%(upstream:track,nobracket)%%(end)] %%(end)%%(contents:subject)" ,
344+ branch_get_color (BRANCH_COLOR_UPSTREAM ), branch_get_color (BRANCH_COLOR_RESET ));
345+ else
346+ strbuf_addf (& local , "%%(if)%%(upstream:track)%%(then)%%(upstream:track) %%(end)%%(contents:subject)" );
347+
348+ strbuf_addf (& remote , "%s%%(align:%d,left)%s%%(refname:lstrip=2)%%(end)%s%%(if)%%(symref)%%(then) -> %%(symref:short)"
349+ "%%(else) %%(objectname:short=7) %%(contents:subject)%%(end)" ,
350+ branch_get_color (BRANCH_COLOR_REMOTE ), maxwidth , quote_literal_for_format (remote_prefix ),
414351 branch_get_color (BRANCH_COLOR_RESET ));
415- } else
416- strbuf_addf (& out , "%c %s%s%s" , c , branch_get_color (color ),
417- name .buf , branch_get_color (BRANCH_COLOR_RESET ));
418-
419- if (item -> symref ) {
420- const char * symref = item -> symref ;
421- if (prefix_to_skip )
422- skip_prefix (symref , prefix_to_skip , & symref );
423- strbuf_addf (& out , " -> %s" , symref );
424- }
425- else if (filter -> verbose )
426- /* " f7c0c00 [ahead 58, behind 197] vcs-svn: drop obj_pool.h" */
427- add_verbose_info (& out , item , filter , desc );
428- if (column_active (colopts )) {
429- assert (!filter -> verbose && "--column and --verbose are incompatible" );
430- string_list_append (& output , out .buf );
431352 } else {
432- printf ("%s\n" , out .buf );
353+ strbuf_addf (& local , "%%(refname:lstrip=2)%s%%(if)%%(symref)%%(then) -> %%(symref:short)%%(end)" ,
354+ branch_get_color (BRANCH_COLOR_RESET ));
355+ strbuf_addf (& remote , "%s%s%%(refname:lstrip=2)%s%%(if)%%(symref)%%(then) -> %%(symref:short)%%(end)" ,
356+ branch_get_color (BRANCH_COLOR_REMOTE ), quote_literal_for_format (remote_prefix ),
357+ branch_get_color (BRANCH_COLOR_RESET ));
433358 }
434- strbuf_release (& name );
435- strbuf_release (& out );
436- free (to_free );
437- }
438-
439- static int calc_maxwidth (struct ref_array * refs , int remote_bonus )
440- {
441- int i , max = 0 ;
442- for (i = 0 ; i < refs -> nr ; i ++ ) {
443- struct ref_array_item * it = refs -> items [i ];
444- const char * desc = it -> refname ;
445- int w ;
446359
447- skip_prefix (it -> refname , "refs/heads/" , & desc );
448- skip_prefix (it -> refname , "refs/remotes/" , & desc );
449- w = utf8_strwidth (desc );
360+ strbuf_addf (& fmt , "%%(if:notequals=refs/remotes)%%(refname:rstrip=-2)%%(then)%s%%(else)%s%%(end)" , local .buf , remote .buf );
450361
451- if (it -> kind == FILTER_REFS_REMOTES )
452- w += remote_bonus ;
453- if (w > max )
454- max = w ;
455- }
456- return max ;
362+ strbuf_release (& local );
363+ strbuf_release (& remote );
364+ return strbuf_detach (& fmt , NULL );
457365}
458366
459367static void print_ref_list (struct ref_filter * filter , struct ref_sorting * sorting )
@@ -462,6 +370,8 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
462370 struct ref_array array ;
463371 int maxwidth = 0 ;
464372 const char * remote_prefix = "" ;
373+ struct strbuf out = STRBUF_INIT ;
374+ char * format ;
465375
466376 /*
467377 * If we are listing more than just remote branches,
@@ -473,18 +383,31 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
473383
474384 memset (& array , 0 , sizeof (array ));
475385
476- verify_ref_format ("%(refname)%(symref)" );
477386 filter_refs (& array , filter , filter -> kind | FILTER_REFS_INCLUDE_BROKEN );
478387
479388 if (filter -> verbose )
480389 maxwidth = calc_maxwidth (& array , strlen (remote_prefix ));
481390
391+ format = build_format (filter , maxwidth , remote_prefix );
392+ verify_ref_format (format );
393+
482394 ref_array_sort (sorting , & array );
483395
484- for (i = 0 ; i < array .nr ; i ++ )
485- format_and_print_ref_item (array .items [i ], maxwidth , filter , remote_prefix );
396+ for (i = 0 ; i < array .nr ; i ++ ) {
397+ format_ref_array_item (array .items [i ], format , 0 , & out );
398+ if (column_active (colopts )) {
399+ assert (!filter -> verbose && "--column and --verbose are incompatible" );
400+ /* format to a string_list to let print_columns() do its job */
401+ string_list_append (& output , out .buf );
402+ } else {
403+ fwrite (out .buf , 1 , out .len , stdout );
404+ putchar ('\n' );
405+ }
406+ strbuf_release (& out );
407+ }
486408
487409 ref_array_clear (& array );
410+ free (format );
488411}
489412
490413static void reject_rebase_or_bisect_branch (const char * target )
0 commit comments