path: root/diffcore-delta.c
diff options
authorLinus Torvalds <>2009-12-04 20:07:47 (GMT)
committerJunio C Hamano <>2009-12-05 18:54:17 (GMT)
commit77cd6ab62108c2d4ddd4343abd9bae17c406be4b (patch)
tree0c3e054326d70a5b75bd9b7e5c7bbaf525c1cb70 /diffcore-delta.c
parent952dfc6944b29582482ff50a85c04879406c06ba (diff)
Fix diff -B/--dirstat miscounting of newly added contents
What used to happen is that diffcore_count_changes() simply ignored any hashes in the destination that didn't match hashes in the source. EXCEPT if the source hash didn't exist at all, in which case it would count _one_ destination hash that happened to have the "next" hash value. As a consequence, newly added material was often undercounted, making output from --dirstat and "complete rewrite" detection used by -B unrelialble. This changes it so that: - whenever it bypasses a destination hash (because it doesn't match a source), it counts the bytes associated with that as "literal added" - at the end (once we have used up all the source hashes), we do the same thing with the remaining destination hashes. - when hashes do match, and we use the difference in counts as a value, we also use up that destination hash entry (the 'd++'). Signed-off-by: Linus Torvalds <> Signed-off-by: Junio C Hamano <>
Diffstat (limited to 'diffcore-delta.c')
1 files changed, 10 insertions, 1 deletions
diff --git a/diffcore-delta.c b/diffcore-delta.c
index e670f85..7cf431d 100644
--- a/diffcore-delta.c
+++ b/diffcore-delta.c
@@ -201,10 +201,15 @@ int diffcore_count_changes(struct diff_filespec *src,
while (d->cnt) {
if (d->hashval >= s->hashval)
+ la += d->cnt;
src_cnt = s->cnt;
- dst_cnt = d->hashval == s->hashval ? d->cnt : 0;
+ dst_cnt = 0;
+ if (d->cnt && d->hashval == s->hashval) {
+ dst_cnt = d->cnt;
+ d++;
+ }
if (src_cnt < dst_cnt) {
la += dst_cnt - src_cnt;
sc += src_cnt;
@@ -213,6 +218,10 @@ int diffcore_count_changes(struct diff_filespec *src,
sc += dst_cnt;
+ while (d->cnt) {
+ la += d->cnt;
+ d++;
+ }
if (!src_count_p)