diff: teach --stat to ignore uninteresting modifications
When options such as --ignore-space-change are in use, files with modifications can have no interesting textual changes worth showing. In such cases, "git diff --stat" shows 0 lines of additions and deletions. Teach "git diff --stat" not to show such a path in its output, which would be more natural. However, 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> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Matthew Rogers committed
Aug 20, 2020 at 00:41 UTC
1cf3d5db9bd11514465d3692216211315f0dc82c
2 files changed
+67
-9
diff.c
+31
-7
@@ -3153,16 +3153,19 @@ static void show_dirstat_by_line(struct diffstat_t *data, struct diff_options *o
3153
gather_dirstat(options, &dir, changed, "", 0);
3154
}
3155
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
+
3164
void free_diffstat_info(struct diffstat_t *diffstat)
3165
{
3166
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]);
3169
free(diffstat->files);
3170
}
3171
@@ -3718,6 +3721,27 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
3721
if (xdi_diff_outf(&mf1, &mf2, discard_hunk_line,
3722
diffstat_consume, diffstat, &xpp, &xecfg))
3723
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, deletions,
3734
+ * renames, and mode changes as adding an empty file,
3735
+ * for example is still of interest.
3736
+ */
3737
+ if ((p->status == DIFF_STATUS_MODIFIED)
3738
+ && !file->added
3739
+ && !file->deleted
3740
+ && one->mode == two->mode) {
3741
+ free_diffstat_file(file);
3742
+ diffstat->nr--;
3743
+ }
3744
+ }
3745
}
3746
3747
diff_free_filespec_data(one);
t/t4015-diff-whitespace.sh
+36
-2
@@ -789,7 +789,7 @@ test_expect_success 'checkdiff allows new blank lines' '
789
git diff --check
790
'
791
792
-test_expect_success 'whitespace-only changes not reported' '
792
+test_expect_success 'whitespace-only changes not reported (diff)' '
793
git reset --hard &&
794
echo >x "hello world" &&
795
git add x &&
@@ -799,10 +799,44 @@ test_expect_success 'whitespace-only changes not reported' '
799
test_must_be_empty actual
800
'
801
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)' '
821
git reset --hard &&
822
for i in 1 2 3 4 5 6 7 8 9; do echo "$i$i$i$i$i$i"; done >x &&
823
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 &&
840
hash_x=$(git hash-object x) &&
841
before=$(git rev-parse --short "$hash_x") &&
842
git commit -m "base" &&