Skip to content

diff: teach --stat to ignore uninteresting modifications #689

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 31 additions & 7 deletions diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -3153,16 +3153,19 @@ static void show_dirstat_by_line(struct diffstat_t *data, struct diff_options *o
gather_dirstat(options, &dir, changed, "", 0);
}

static void free_diffstat_file(struct diffstat_file *f)
{
free(f->print_name);
free(f->name);
free(f->from_name);
free(f);
}

void free_diffstat_info(struct diffstat_t *diffstat)
{
int i;
for (i = 0; i < diffstat->nr; i++) {
struct diffstat_file *f = diffstat->files[i];
free(f->print_name);
free(f->name);
free(f->from_name);
free(f);
}
for (i = 0; i < diffstat->nr; i++)
free_diffstat_file(diffstat->files[i]);
free(diffstat->files);
}

Expand Down Expand Up @@ -3718,6 +3721,27 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
if (xdi_diff_outf(&mf1, &mf2, discard_hunk_line,
diffstat_consume, diffstat, &xpp, &xecfg))
die("unable to generate diffstat for %s", one->path);

if (DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two)) {
struct diffstat_file *file =
diffstat->files[diffstat->nr - 1];
/*
* Omit diffstats of modified files where nothing changed.
* Even if !same_contents, this might be the case due to
* ignoring whitespace changes, etc.
*
* But note that we special-case additions, deletions,
* renames, and mode changes as adding an empty file,
* for example is still of interest.
*/
if ((p->status == DIFF_STATUS_MODIFIED)
&& !file->added
&& !file->deleted
&& one->mode == two->mode) {
free_diffstat_file(file);
diffstat->nr--;
}
}
}

diff_free_filespec_data(one);
Expand Down
38 changes: 36 additions & 2 deletions t/t4015-diff-whitespace.sh
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,7 @@ test_expect_success 'checkdiff allows new blank lines' '
git diff --check
'

test_expect_success 'whitespace-only changes not reported' '
test_expect_success 'whitespace-only changes not reported (diff)' '
git reset --hard &&
echo >x "hello world" &&
git add x &&
Expand All @@ -799,10 +799,44 @@ test_expect_success 'whitespace-only changes not reported' '
test_must_be_empty actual
'

test_expect_success 'whitespace-only changes reported across renames' '
test_expect_success 'whitespace-only changes not reported (diffstat)' '
# reuse state from previous test
git diff --stat -b >actual &&
test_must_be_empty actual
'

test_expect_success 'whitespace changes with modification reported (diffstat)' '
git reset --hard &&
echo >x "hello world" &&
git update-index --chmod=+x x &&
git diff --stat --cached -b >actual &&
cat <<-EOF >expect &&
x | 0
1 file changed, 0 insertions(+), 0 deletions(-)
EOF
test_cmp expect actual
'

test_expect_success 'whitespace-only changes reported across renames (diffstat)' '
git reset --hard &&
for i in 1 2 3 4 5 6 7 8 9; do echo "$i$i$i$i$i$i"; done >x &&
git add x &&
git commit -m "base" &&
sed -e "5s/^/ /" x >z &&
git rm x &&
git add z &&
git diff -w -M --cached --stat >actual &&
cat <<-EOF >expect &&
x => z | 0
1 file changed, 0 insertions(+), 0 deletions(-)
EOF
test_cmp expect actual
'

test_expect_success 'whitespace-only changes reported across renames' '
git reset --hard HEAD~1 &&
for i in 1 2 3 4 5 6 7 8 9; do echo "$i$i$i$i$i$i"; done >x &&
git add x &&
hash_x=$(git hash-object x) &&
before=$(git rev-parse --short "$hash_x") &&
git commit -m "base" &&
Expand Down