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{
@@ -1746,7 +1753,8 @@ static int emit_one_suspect_detail(struct origin *suspect, int repeat)
17461753 * The blame_entry is found to be guilty for the range.
17471754 * Show it in incremental output.
17481755 */
1749- static void found_guilty_entry (struct blame_entry * ent )
1756+ static void found_guilty_entry (struct blame_entry * ent ,
1757+ struct progress_info * pi )
17501758{
17511759 if (incremental ) {
17521760 struct origin * suspect = ent -> suspect ;
@@ -1758,6 +1766,8 @@ static void found_guilty_entry(struct blame_entry *ent)
17581766 write_filename_info (suspect -> path );
17591767 maybe_flush_or_die (stdout , "stdout" );
17601768 }
1769+ pi -> blamed_lines += ent -> num_lines ;
1770+ display_progress (pi -> progress , pi -> blamed_lines );
17611771}
17621772
17631773/*
@@ -1768,6 +1778,11 @@ static void assign_blame(struct scoreboard *sb, int opt)
17681778{
17691779 struct rev_info * revs = sb -> revs ;
17701780 struct commit * commit = prio_queue_get (& sb -> commits );
1781+ struct progress_info pi = { NULL , 0 };
1782+
1783+ if (show_progress )
1784+ pi .progress = start_progress_delay (_ ("Blaming lines" ),
1785+ sb -> num_lines , 50 , 1 );
17711786
17721787 while (commit ) {
17731788 struct blame_entry * ent ;
@@ -1809,7 +1824,7 @@ static void assign_blame(struct scoreboard *sb, int opt)
18091824 suspect -> guilty = 1 ;
18101825 for (;;) {
18111826 struct blame_entry * next = ent -> next ;
1812- found_guilty_entry (ent );
1827+ found_guilty_entry (ent , & pi );
18131828 if (next ) {
18141829 ent = next ;
18151830 continue ;
@@ -1825,6 +1840,8 @@ static void assign_blame(struct scoreboard *sb, int opt)
18251840 if (DEBUG ) /* sanity */
18261841 sanity_check_refcnt (sb );
18271842 }
1843+
1844+ stop_progress (& pi .progress );
18281845}
18291846
18301847static const char * format_time (unsigned long time , const char * tz_str ,
@@ -2520,6 +2537,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
25202537 OPT_BOOL ('b' , NULL , & blank_boundary , N_ ("Show blank SHA-1 for boundary commits (Default: off)" )),
25212538 OPT_BOOL (0 , "root" , & show_root , N_ ("Do not treat root commits as boundaries (Default: off)" )),
25222539 OPT_BOOL (0 , "show-stats" , & show_stats , N_ ("Show work cost statistics" )),
2540+ OPT_BOOL (0 , "progress" , & show_progress , N_ ("Force progress reporting" )),
25232541 OPT_BIT (0 , "score-debug" , & output_option , N_ ("Show output score for blame entries" ), OUTPUT_SHOW_SCORE ),
25242542 OPT_BIT ('f' , "show-name" , & output_option , N_ ("Show original filename (Default: auto)" ), OUTPUT_SHOW_NAME ),
25252543 OPT_BIT ('n' , "show-number" , & output_option , N_ ("Show original linenumber (Default: off)" ), OUTPUT_SHOW_NUMBER ),
@@ -2555,6 +2573,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
25552573
25562574 save_commit_buffer = 0 ;
25572575 dashdash_pos = 0 ;
2576+ show_progress = -1 ;
25582577
25592578 parse_options_start (& ctx , argc , argv , prefix , options ,
25602579 PARSE_OPT_KEEP_DASHDASH | PARSE_OPT_KEEP_ARGV0 );
@@ -2579,6 +2598,13 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
25792598 DIFF_OPT_CLR (& revs .diffopt , FOLLOW_RENAMES );
25802599 argc = parse_options_end (& ctx );
25812600
2601+ if (incremental || (output_option & OUTPUT_PORCELAIN )) {
2602+ if (show_progress > 0 )
2603+ die ("--progress can't be used with --incremental or porcelain formats" );
2604+ show_progress = 0 ;
2605+ } else if (show_progress < 0 )
2606+ show_progress = isatty (2 );
2607+
25822608 if (0 < abbrev )
25832609 /* one more abbrev length is needed for the boundary commit */
25842610 abbrev ++ ;
@@ -2828,11 +2854,11 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
28282854
28292855 read_mailmap (& mailmap , NULL );
28302856
2857+ assign_blame (& sb , opt );
2858+
28312859 if (!incremental )
28322860 setup_pager ();
28332861
2834- assign_blame (& sb , opt );
2835-
28362862 free (final_commit_name );
28372863
28382864 if (incremental )
0 commit comments