@matheusbsbs / matheus-bagliano / commits / 1cf3d5db9b
Fork 0

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" &&