Skip to content

Commit 6c5db18

Browse files
committed
diff: teach --stat to ignore uninteresting modifications
Sometimes when diffing, files may show as being momdified even when there are no interesting diffs to show. This happens naturally when using options such as --ignore-space-change. We don't want to prevent the display of all files that have 0 effective diffs since they could be the result of a rename, permission change, or other similar operation that may still be of interest so we special case additions and deletions as they are always interesting. Signed-off-by: Matthew Rogers <mattr94@gmail.com>
1 parent 878e727 commit 6c5db18

File tree

2 files changed

+66
-9
lines changed

2 files changed

+66
-9
lines changed

diff.c

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3153,16 +3153,19 @@ static void show_dirstat_by_line(struct diffstat_t *data, struct diff_options *o
31533153
gather_dirstat(options, &dir, changed, "", 0);
31543154
}
31553155

3156+
static void free_diffstat_file(struct diffstat_file *f)
3157+
{
3158+
free(f->print_name);
3159+
free(f->name);
3160+
free(f->from_name);
3161+
free(f);
3162+
}
3163+
31563164
void free_diffstat_info(struct diffstat_t *diffstat)
31573165
{
31583166
int i;
3159-
for (i = 0; i < diffstat->nr; i++) {
3160-
struct diffstat_file *f = diffstat->files[i];
3161-
free(f->print_name);
3162-
free(f->name);
3163-
free(f->from_name);
3164-
free(f);
3165-
}
3167+
for (i = 0; i < diffstat->nr; i++)
3168+
free_diffstat_file(diffstat->files[i]);
31663169
free(diffstat->files);
31673170
}
31683171

@@ -3718,6 +3721,26 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
37183721
if (xdi_diff_outf(&mf1, &mf2, discard_hunk_line,
37193722
diffstat_consume, diffstat, &xpp, &xecfg))
37203723
die("unable to generate diffstat for %s", one->path);
3724+
3725+
if (DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two)) {
3726+
struct diffstat_file *file =
3727+
diffstat->files[diffstat->nr - 1];
3728+
/*
3729+
* Omit diffstats of modified files where nothing changed.
3730+
* Even if !same_contents, this might be the case due to
3731+
* ignoring whitespace changes, etc.
3732+
*
3733+
* But note that we special-case additions and deletions,
3734+
* as adding an empty file, for example is still of interest.
3735+
*/
3736+
if ((p->status == DIFF_STATUS_MODIFIED)
3737+
&& !file->added
3738+
&& !file->deleted
3739+
&& one->mode == two->mode) {
3740+
free_diffstat_file(file);
3741+
diffstat->nr--;
3742+
}
3743+
}
37213744
}
37223745

37233746
diff_free_filespec_data(one);

t/t4015-diff-whitespace.sh

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,7 @@ test_expect_success 'checkdiff allows new blank lines' '
789789
git diff --check
790790
'
791791

792-
test_expect_success 'whitespace-only changes not reported' '
792+
test_expect_success 'whitespace-only changes not reported (diff)' '
793793
git reset --hard &&
794794
echo >x "hello world" &&
795795
git add x &&
@@ -799,10 +799,44 @@ test_expect_success 'whitespace-only changes not reported' '
799799
test_must_be_empty actual
800800
'
801801

802-
test_expect_success 'whitespace-only changes reported across renames' '
802+
test_expect_success 'whitespace-only changes not reported (diffstat)' '
803+
# reuse state from previous test
804+
git diff --stat -b >actual &&
805+
test_must_be_empty actual
806+
'
807+
808+
test_expect_success 'whitespace changes with modification reported (diffstat)' '
809+
git reset --hard &&
810+
echo >x "hello world" &&
811+
git update-index --chmod=+x x &&
812+
git diff --stat --cached -b >actual &&
813+
cat <<-EOF >expect &&
814+
x | 0
815+
1 file changed, 0 insertions(+), 0 deletions(-)
816+
EOF
817+
test_cmp expect actual
818+
'
819+
820+
test_expect_success 'whitespace-only changes reported across renames (diffstat)' '
803821
git reset --hard &&
804822
for i in 1 2 3 4 5 6 7 8 9; do echo "$i$i$i$i$i$i"; done >x &&
805823
git add x &&
824+
git commit -m "base" &&
825+
sed -e "5s/^/ /" x >z &&
826+
git rm x &&
827+
git add z &&
828+
git diff -w -M --cached --stat >actual &&
829+
cat <<-EOF >expect &&
830+
x => z | 0
831+
1 file changed, 0 insertions(+), 0 deletions(-)
832+
EOF
833+
test_cmp expect actual
834+
'
835+
836+
test_expect_success 'whitespace-only changes reported across renames' '
837+
git reset --hard HEAD~1 &&
838+
for i in 1 2 3 4 5 6 7 8 9; do echo "$i$i$i$i$i$i"; done >x &&
839+
git add x &&
806840
hash_x=$(git hash-object x) &&
807841
before=$(git rev-parse --short "$hash_x") &&
808842
git commit -m "base" &&

0 commit comments

Comments
 (0)