@@ -195,6 +195,56 @@ static int fn_out(void *priv, mmbuffer_t *mb, int nbuf)
195195 return 0 ;
196196}
197197
198+ static char * pprint_rename (const char * a , const char * b )
199+ {
200+ const char * old = a ;
201+ const char * new = b ;
202+ char * name = NULL ;
203+ int pfx_length , sfx_length ;
204+ int len_a = strlen (a );
205+ int len_b = strlen (b );
206+
207+ /* Find common prefix */
208+ pfx_length = 0 ;
209+ while (* old && * new && * old == * new ) {
210+ if (* old == '/' )
211+ pfx_length = old - a + 1 ;
212+ old ++ ;
213+ new ++ ;
214+ }
215+
216+ /* Find common suffix */
217+ old = a + len_a ;
218+ new = b + len_b ;
219+ sfx_length = 0 ;
220+ while (a <= old && b <= new && * old == * new ) {
221+ if (* old == '/' )
222+ sfx_length = len_a - (old - a );
223+ old -- ;
224+ new -- ;
225+ }
226+
227+ /*
228+ * pfx{mid-a => mid-b}sfx
229+ * {pfx-a => pfx-b}sfx
230+ * pfx{sfx-a => sfx-b}
231+ * name-a => name-b
232+ */
233+ if (pfx_length + sfx_length ) {
234+ name = xmalloc (len_a + len_b - pfx_length - sfx_length + 7 );
235+ sprintf (name , "%.*s{%.*s => %.*s}%s" ,
236+ pfx_length , a ,
237+ len_a - pfx_length - sfx_length , a + pfx_length ,
238+ len_b - pfx_length - sfx_length , b + pfx_length ,
239+ a + len_a - sfx_length );
240+ }
241+ else {
242+ name = xmalloc (len_a + len_b + 5 );
243+ sprintf (name , "%s => %s" , a , b );
244+ }
245+ return name ;
246+ }
247+
198248struct diffstat_t {
199249 struct xdiff_emit_state xm ;
200250
@@ -204,12 +254,14 @@ struct diffstat_t {
204254 char * name ;
205255 unsigned is_unmerged :1 ;
206256 unsigned is_binary :1 ;
257+ unsigned is_renamed :1 ;
207258 unsigned int added , deleted ;
208259 } * * files ;
209260};
210261
211262static struct diffstat_file * diffstat_add (struct diffstat_t * diffstat ,
212- const char * name )
263+ const char * name_a ,
264+ const char * name_b )
213265{
214266 struct diffstat_file * x ;
215267 x = xcalloc (sizeof (* x ), 1 );
@@ -219,7 +271,12 @@ static struct diffstat_file *diffstat_add(struct diffstat_t *diffstat,
219271 diffstat -> alloc * sizeof (x ));
220272 }
221273 diffstat -> files [diffstat -> nr ++ ] = x ;
222- x -> name = strdup (name );
274+ if (name_b ) {
275+ x -> name = pprint_rename (name_a , name_b );
276+ x -> is_renamed = 1 ;
277+ }
278+ else
279+ x -> name = strdup (name_a );
223280 return x ;
224281}
225282
@@ -305,7 +362,8 @@ static void show_stats(struct diffstat_t* data)
305362 printf (" %s%-*s | Unmerged\n" , prefix , len , name );
306363 goto free_diffstat_file ;
307364 }
308- else if (added + deleted == 0 ) {
365+ else if (!data -> files [i ]-> is_renamed &&
366+ (added + deleted == 0 )) {
309367 total_files -- ;
310368 goto free_diffstat_file ;
311369 }
@@ -425,13 +483,14 @@ static void builtin_diff(const char *name_a,
425483}
426484
427485static void builtin_diffstat (const char * name_a , const char * name_b ,
428- struct diff_filespec * one , struct diff_filespec * two ,
429- struct diffstat_t * diffstat )
486+ struct diff_filespec * one ,
487+ struct diff_filespec * two ,
488+ struct diffstat_t * diffstat )
430489{
431490 mmfile_t mf1 , mf2 ;
432491 struct diffstat_file * data ;
433492
434- data = diffstat_add (diffstat , name_a ? name_a : name_b );
493+ data = diffstat_add (diffstat , name_a , name_b );
435494
436495 if (!one || !two ) {
437496 data -> is_unmerged = 1 ;
@@ -992,7 +1051,7 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
9921051}
9931052
9941053static void run_diffstat (struct diff_filepair * p , struct diff_options * o ,
995- struct diffstat_t * diffstat )
1054+ struct diffstat_t * diffstat )
9961055{
9971056 const char * name ;
9981057 const char * other ;
@@ -1374,7 +1433,7 @@ static void diff_flush_patch(struct diff_filepair *p, struct diff_options *o)
13741433}
13751434
13761435static void diff_flush_stat (struct diff_filepair * p , struct diff_options * o ,
1377- struct diffstat_t * diffstat )
1436+ struct diffstat_t * diffstat )
13781437{
13791438 if (diff_unmodified_pair (p ))
13801439 return ;
@@ -1559,7 +1618,7 @@ void diff_flush(struct diff_options *options)
15591618 for (i = 0 ; i < q -> nr ; i ++ ) {
15601619 struct diff_filepair * p = q -> queue [i ];
15611620 flush_one_pair (p , DIFF_FORMAT_DIFFSTAT , options ,
1562- diffstat );
1621+ diffstat );
15631622 }
15641623 show_stats (diffstat );
15651624 free (diffstat );
0 commit comments