2828#include "line-range.h"
2929#include "line-log.h"
3030#include "dir.h"
31+ #include "progress.h"
3132
3233static char blame_usage [] = N_ ("git blame [<options>] [<rev-opts>] [<rev>] [--] <file>" );
3334
@@ -50,6 +51,7 @@ static int incremental;
5051static int xdl_opts ;
5152static int abbrev = -1 ;
5253static int no_whole_file_rename ;
54+ static int show_progress ;
5355
5456static struct date_mode blame_date_mode = { DATE_ISO8601 };
5557static size_t blame_date_width ;
@@ -127,6 +129,11 @@ struct origin {
127129 char path [FLEX_ARRAY ];
128130};
129131
132+ struct progress_info {
133+ struct progress * progress ;
134+ int blamed_lines ;
135+ };
136+
130137static int diff_hunks (mmfile_t * file_a , mmfile_t * file_b , long ctxlen ,
131138 xdl_emit_hunk_consume_func_t hunk_func , void * cb_data )
132139{
@@ -1745,7 +1752,8 @@ static int emit_one_suspect_detail(struct origin *suspect, int repeat)
17451752 * The blame_entry is found to be guilty for the range.
17461753 * Show it in incremental output.
17471754 */
1748- static void found_guilty_entry (struct blame_entry * ent )
1755+ static void found_guilty_entry (struct blame_entry * ent ,
1756+ struct progress_info * pi )
17491757{
17501758 if (incremental ) {
17511759 struct origin * suspect = ent -> suspect ;
@@ -1757,6 +1765,8 @@ static void found_guilty_entry(struct blame_entry *ent)
17571765 write_filename_info (suspect -> path );
17581766 maybe_flush_or_die (stdout , "stdout" );
17591767 }
1768+ pi -> blamed_lines += ent -> num_lines ;
1769+ display_progress (pi -> progress , pi -> blamed_lines );
17601770}
17611771
17621772/*
@@ -1767,6 +1777,11 @@ static void assign_blame(struct scoreboard *sb, int opt)
17671777{
17681778 struct rev_info * revs = sb -> revs ;
17691779 struct commit * commit = prio_queue_get (& sb -> commits );
1780+ struct progress_info pi = { NULL , 0 };
1781+
1782+ if (show_progress )
1783+ pi .progress = start_progress_delay (_ ("Blaming lines" ),
1784+ sb -> num_lines , 50 , 1 );
17701785
17711786 while (commit ) {
17721787 struct blame_entry * ent ;
@@ -1808,7 +1823,7 @@ static void assign_blame(struct scoreboard *sb, int opt)
18081823 suspect -> guilty = 1 ;
18091824 for (;;) {
18101825 struct blame_entry * next = ent -> next ;
1811- found_guilty_entry (ent );
1826+ found_guilty_entry (ent , & pi );
18121827 if (next ) {
18131828 ent = next ;
18141829 continue ;
@@ -1824,6 +1839,8 @@ static void assign_blame(struct scoreboard *sb, int opt)
18241839 if (DEBUG ) /* sanity */
18251840 sanity_check_refcnt (sb );
18261841 }
1842+
1843+ stop_progress (& pi .progress );
18271844}
18281845
18291846static const char * format_time (unsigned long time , const char * tz_str ,
@@ -2513,6 +2530,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
25132530 OPT_BOOL ('b' , NULL , & blank_boundary , N_ ("Show blank SHA-1 for boundary commits (Default: off)" )),
25142531 OPT_BOOL (0 , "root" , & show_root , N_ ("Do not treat root commits as boundaries (Default: off)" )),
25152532 OPT_BOOL (0 , "show-stats" , & show_stats , N_ ("Show work cost statistics" )),
2533+ OPT_BOOL (0 , "progress" , & show_progress , N_ ("Force progress reporting" )),
25162534 OPT_BIT (0 , "score-debug" , & output_option , N_ ("Show output score for blame entries" ), OUTPUT_SHOW_SCORE ),
25172535 OPT_BIT ('f' , "show-name" , & output_option , N_ ("Show original filename (Default: auto)" ), OUTPUT_SHOW_NAME ),
25182536 OPT_BIT ('n' , "show-number" , & output_option , N_ ("Show original linenumber (Default: off)" ), OUTPUT_SHOW_NUMBER ),
@@ -2548,6 +2566,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
25482566
25492567 save_commit_buffer = 0 ;
25502568 dashdash_pos = 0 ;
2569+ show_progress = -1 ;
25512570
25522571 parse_options_start (& ctx , argc , argv , prefix , options ,
25532572 PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0 );
@@ -2572,6 +2591,13 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
25722591 DIFF_OPT_CLR (& revs .diffopt , FOLLOW_RENAMES );
25732592 argc = parse_options_end (& ctx );
25742593
2594+ if (incremental || (output_option & OUTPUT_PORCELAIN )) {
2595+ if (show_progress > 0 )
2596+ die ("--progress can't be used with --incremental or porcelain formats" );
2597+ show_progress = 0 ;
2598+ } else if (show_progress < 0 )
2599+ show_progress = isatty (2 );
2600+
25752601 if (0 < abbrev )
25762602 /* one more abbrev length is needed for the boundary commit */
25772603 abbrev ++ ;
@@ -2797,11 +2823,11 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
27972823
27982824 read_mailmap (& mailmap , NULL );
27992825
2826+ assign_blame (& sb , opt );
2827+
28002828 if (!incremental )
28012829 setup_pager ();
28022830
2803- assign_blame (& sb , opt );
2804-
28052831 free (final_commit_name );
28062832
28072833 if (incremental )
0 commit comments