@matheusbsbs / matheus-bagliano / commits / 2ff3a80334
Fork 0

Teach --dirstat not to completely ignore rearranged lines within a file

Currently, the --dirstat analysis ignores when lines within a file are rearranged, because the "damage" calculated by show_dirstat() is 0. However, if the object name has changed, we already know that there is some damage, and it is unintuitive to claim there is _no_ damage. Teach show_dirstat() to assign a minimum amount of damage (== 1) to entries for which the analysis otherwise yields zero damage, to still represent that these files are changed, instead of saying that there is no change. Also, skip --dirstat analysis when the object names are the same (e.g. for a pure file rename). Signed-off-by: Johan Herland <johan@herland.net> Acked-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johan Herland committed Apr 11, 2011 at 00:48 UTC 2ff3a80334115797b8446909655e536f43900bc5
4 files changed +21 -5
Documentation/diff-options.txt
+2 -2
@@ -74,8 +74,8 @@ endif::git-format-patch[]
74 counted for the parent directory, unless `--cumulative` is used.
75 +
76 Note that the `--dirstat` option computes the changes while ignoring
77 -pure code movements within a file. In other words, rearranging lines
78 -in a file is not counted as a change.
77 +the amount of pure code movements within a file. In other words,
78 +rearranging lines in a file is not counted as much as other changes.
79
80 --dirstat-by-file[=<limit>]::
81 Same as `--dirstat`, but counts changed files instead of lines.
diff.c
+18 -1
@@ -1548,6 +1548,16 @@ static void show_dirstat(struct diff_options *options)
1548 else
1549 content_changed = 1;
1550
1551 + if (!content_changed) {
1552 + /*
1553 + * The SHA1 has not changed, so pre-/post-content is
1554 + * identical. We can therefore skip looking at the
1555 + * file contents altogether.
1556 + */
1557 + damage = 0;
1558 + goto found_damage;
1559 + }
1560 +
1561 if (DIFF_OPT_TST(options, DIRSTAT_BY_FILE)) {
1562 /*
1563 * In --dirstat-by-file mode, we don't really need to
@@ -1556,7 +1566,7 @@ static void show_dirstat(struct diff_options *options)
1566 * add this file to the list of results
1567 * (with each file contributing equal damage).
1568 */
1559 - damage = content_changed ? 1 : 0;
1569 + damage = 1;
1570 goto found_damage;
1571 }
1572
@@ -1583,8 +1593,15 @@ static void show_dirstat(struct diff_options *options)
1593 * Original minus copied is the removed material,
1594 * added is the new material. They are both damages
1595 * made to the preimage.
1596 + * If the resulting damage is zero, we know that
1597 + * diffcore_count_changes() considers the two entries to
1598 + * be identical, but since content_changed is true, we
1599 + * know that there must have been _some_ kind of change,
1600 + * so we force all entries to have damage > 0.
1601 */
1602 damage = (p->one->size - copied) + added;
1603 + if (!damage)
1604 + damage = 1;
1605
1606 found_damage:
1607 ALLOC_GROW(dir.files, dir.nr + 1, dir.alloc);
t/t4013-diff-various.sh
-2
@@ -300,9 +300,7 @@ diff --no-index --name-status -- dir2 dir
300 diff --no-index dir dir3
301 diff master master^ side
302 diff --dirstat master~1 master~2
303 -# --dirstat doesn't notice changes that simply rearrange existing lines
303 diff --dirstat initial rearrange
305 -# ...but --dirstat-by-file does notice changes that only rearrange lines
304 diff --dirstat-by-file initial rearrange
305 EOF
306
t/t4013/diff.diff_--dirstat_initial_rearrange
+1
@@ -1,2 +1,3 @@
1 $ git diff --dirstat initial rearrange
2 + 100.0% dir/
3 $