Skip to content

Commit 2ff3a80

Browse files
jherlandgitster
authored andcommitted
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 <[email protected]> Acked-by: Linus Torvalds <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 0133dab commit 2ff3a80

File tree

4 files changed

+21
-5
lines changed

4 files changed

+21
-5
lines changed

Documentation/diff-options.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ endif::git-format-patch[]
7474
counted for the parent directory, unless `--cumulative` is used.
7575
+
7676
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.
7979

8080
--dirstat-by-file[=<limit>]::
8181
Same as `--dirstat`, but counts changed files instead of lines.

diff.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1548,6 +1548,16 @@ static void show_dirstat(struct diff_options *options)
15481548
else
15491549
content_changed = 1;
15501550

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+
15511561
if (DIFF_OPT_TST(options, DIRSTAT_BY_FILE)) {
15521562
/*
15531563
* In --dirstat-by-file mode, we don't really need to
@@ -1556,7 +1566,7 @@ static void show_dirstat(struct diff_options *options)
15561566
* add this file to the list of results
15571567
* (with each file contributing equal damage).
15581568
*/
1559-
damage = content_changed ? 1 : 0;
1569+
damage = 1;
15601570
goto found_damage;
15611571
}
15621572

@@ -1583,8 +1593,15 @@ static void show_dirstat(struct diff_options *options)
15831593
* Original minus copied is the removed material,
15841594
* added is the new material. They are both damages
15851595
* 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.
15861601
*/
15871602
damage = (p->one->size - copied) + added;
1603+
if (!damage)
1604+
damage = 1;
15881605

15891606
found_damage:
15901607
ALLOC_GROW(dir.files, dir.nr + 1, dir.alloc);

t/t4013-diff-various.sh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,9 +300,7 @@ diff --no-index --name-status -- dir2 dir
300300
diff --no-index dir dir3
301301
diff master master^ side
302302
diff --dirstat master~1 master~2
303-
# --dirstat doesn't notice changes that simply rearrange existing lines
304303
diff --dirstat initial rearrange
305-
# ...but --dirstat-by-file does notice changes that only rearrange lines
306304
diff --dirstat-by-file initial rearrange
307305
EOF
308306

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
$ git diff --dirstat initial rearrange
2+
100.0% dir/
23
$

0 commit comments

Comments
 (0)