@@ -1538,8 +1538,36 @@ static void show_dirstat(struct diff_options *options)
15381538 struct diff_filepair * p = q -> queue [i ];
15391539 const char * name ;
15401540 unsigned long copied , added , damage ;
1541+ int content_changed ;
15411542
1542- name = p -> one -> path ? p -> one -> path : p -> two -> path ;
1543+ name = p -> two -> path ? p -> two -> path : p -> one -> path ;
1544+
1545+ if (p -> one -> sha1_valid && p -> two -> sha1_valid )
1546+ content_changed = hashcmp (p -> one -> sha1 , p -> two -> sha1 );
1547+ else
1548+ content_changed = 1 ;
1549+
1550+ if (!content_changed ) {
1551+ /*
1552+ * The SHA1 has not changed, so pre-/post-content is
1553+ * identical. We can therefore skip looking at the
1554+ * file contents altogether.
1555+ */
1556+ damage = 0 ;
1557+ goto found_damage ;
1558+ }
1559+
1560+ if (DIFF_OPT_TST (options , DIRSTAT_BY_FILE )) {
1561+ /*
1562+ * In --dirstat-by-file mode, we don't really need to
1563+ * look at the actual file contents at all.
1564+ * The fact that the SHA1 changed is enough for us to
1565+ * add this file to the list of results
1566+ * (with each file contributing equal damage).
1567+ */
1568+ damage = 1 ;
1569+ goto found_damage ;
1570+ }
15431571
15441572 if (DIFF_FILE_VALID (p -> one ) && DIFF_FILE_VALID (p -> two )) {
15451573 diff_populate_filespec (p -> one , 0 );
@@ -1563,14 +1591,18 @@ static void show_dirstat(struct diff_options *options)
15631591 /*
15641592 * Original minus copied is the removed material,
15651593 * added is the new material. They are both damages
1566- * made to the preimage. In --dirstat-by-file mode, count
1567- * damaged files, not damaged lines. This is done by
1568- * counting only a single damaged line per file.
1594+ * made to the preimage.
1595+ * If the resulting damage is zero, we know that
1596+ * diffcore_count_changes() considers the two entries to
1597+ * be identical, but since content_changed is true, we
1598+ * know that there must have been _some_ kind of change,
1599+ * so we force all entries to have damage > 0.
15691600 */
15701601 damage = (p -> one -> size - copied ) + added ;
1571- if (DIFF_OPT_TST ( options , DIRSTAT_BY_FILE ) && damage > 0 )
1602+ if (! damage )
15721603 damage = 1 ;
15731604
1605+ found_damage :
15741606 ALLOC_GROW (dir .files , dir .nr + 1 , dir .alloc );
15751607 dir .files [dir .nr ].name = name ;
15761608 dir .files [dir .nr ].changed = damage ;
0 commit comments