Skip to content

Commit a4eab8f

Browse files
committed
Merge branch 'lt/diff-stat-show-0-lines'
"git diff --stat" miscounted the total number of changed lines when binary files were involved and hidden beyond --stat-count. It also miscounted the total number of changed files when there were unmerged paths. * lt/diff-stat-show-0-lines: t4049: refocus tests diff --shortstat: do not count "unmerged" entries diff --stat: do not count "unmerged" entries diff --stat: move the "total count" logic to the last loop diff --stat: use "file" temporary variable to refer to data->files[i] diff --stat: status of unmodified pair in diff-q is not zero test: add failing tests for "diff --stat" to t4049
2 parents 545492f + de90959 commit a4eab8f

File tree

2 files changed

+74
-28
lines changed

2 files changed

+74
-28
lines changed

diff.c

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,8 +1497,8 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
14971497
for (i = 0; (i < count) && (i < data->nr); i++) {
14981498
struct diffstat_file *file = data->files[i];
14991499
uintmax_t change = file->added + file->deleted;
1500-
if (!data->files[i]->is_interesting &&
1501-
(change == 0)) {
1500+
1501+
if (!file->is_interesting && (change == 0)) {
15021502
count++; /* not shown == room for one more */
15031503
continue;
15041504
}
@@ -1525,7 +1525,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
15251525
if (max_change < change)
15261526
max_change = change;
15271527
}
1528-
count = i; /* min(count, data->nr) */
1528+
count = i; /* where we can stop scanning in data->files[] */
15291529

15301530
/*
15311531
* We have width = stat_width or term_columns() columns total.
@@ -1613,16 +1613,15 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
16131613
*/
16141614
for (i = 0; i < count; i++) {
16151615
const char *prefix = "";
1616-
char *name = data->files[i]->print_name;
1617-
uintmax_t added = data->files[i]->added;
1618-
uintmax_t deleted = data->files[i]->deleted;
1616+
struct diffstat_file *file = data->files[i];
1617+
char *name = file->print_name;
1618+
uintmax_t added = file->added;
1619+
uintmax_t deleted = file->deleted;
16191620
int name_len;
16201621

1621-
if (!data->files[i]->is_interesting &&
1622-
(added + deleted == 0)) {
1623-
total_files--;
1622+
if (!file->is_interesting && (added + deleted == 0))
16241623
continue;
1625-
}
1624+
16261625
/*
16271626
* "scale" the filename
16281627
*/
@@ -1638,7 +1637,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
16381637
name = slash;
16391638
}
16401639

1641-
if (data->files[i]->is_binary) {
1640+
if (file->is_binary) {
16421641
fprintf(options->file, "%s", line_prefix);
16431642
show_name(options->file, prefix, name, len);
16441643
fprintf(options->file, " %*s", number_width, "Bin");
@@ -1655,7 +1654,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
16551654
fprintf(options->file, "\n");
16561655
continue;
16571656
}
1658-
else if (data->files[i]->is_unmerged) {
1657+
else if (file->is_unmerged) {
16591658
fprintf(options->file, "%s", line_prefix);
16601659
show_name(options->file, prefix, name, len);
16611660
fprintf(options->file, " Unmerged\n");
@@ -1667,8 +1666,6 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
16671666
*/
16681667
add = added;
16691668
del = deleted;
1670-
adds += add;
1671-
dels += del;
16721669

16731670
if (graph_width <= max_change) {
16741671
int total = add + del;
@@ -1694,16 +1691,24 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
16941691
show_graph(options->file, '-', del, del_c, reset);
16951692
fprintf(options->file, "\n");
16961693
}
1697-
for (i = count; i < data->nr; i++) {
1698-
uintmax_t added = data->files[i]->added;
1699-
uintmax_t deleted = data->files[i]->deleted;
1700-
if (!data->files[i]->is_interesting &&
1701-
(added + deleted == 0)) {
1694+
1695+
for (i = 0; i < data->nr; i++) {
1696+
struct diffstat_file *file = data->files[i];
1697+
uintmax_t added = file->added;
1698+
uintmax_t deleted = file->deleted;
1699+
1700+
if (file->is_unmerged ||
1701+
(!file->is_interesting && (added + deleted == 0))) {
17021702
total_files--;
17031703
continue;
17041704
}
1705-
adds += added;
1706-
dels += deleted;
1705+
1706+
if (!file->is_binary) {
1707+
adds += added;
1708+
dels += deleted;
1709+
}
1710+
if (i < count)
1711+
continue;
17071712
if (!extra_shown)
17081713
fprintf(options->file, "%s ...\n", line_prefix);
17091714
extra_shown = 1;
@@ -1723,9 +1728,8 @@ static void show_shortstats(struct diffstat_t *data, struct diff_options *option
17231728
int added = data->files[i]->added;
17241729
int deleted= data->files[i]->deleted;
17251730

1726-
if (data->files[i]->is_unmerged)
1727-
continue;
1728-
if (!data->files[i]->is_interesting && (added + deleted == 0)) {
1731+
if (data->files[i]->is_unmerged ||
1732+
(!data->files[i]->is_interesting && (added + deleted == 0))) {
17291733
total_files--;
17301734
} else if (!data->files[i]->is_binary) { /* don't count bytes */
17311735
adds += added;
@@ -2438,7 +2442,7 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
24382442
}
24392443

24402444
data = diffstat_add(diffstat, name_a, name_b);
2441-
data->is_interesting = p->status != 0;
2445+
data->is_interesting = p->status != DIFF_STATUS_UNKNOWN;
24422446

24432447
if (!one || !two) {
24442448
data->is_unmerged = 1;

t/t4049-diff-stat-count.sh

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,62 @@
44
test_description='diff --stat-count'
55
. ./test-lib.sh
66

7-
test_expect_success setup '
7+
test_expect_success 'setup' '
88
>a &&
99
>b &&
1010
>c &&
1111
>d &&
1212
git add a b c d &&
13-
chmod +x c d &&
13+
git commit -m initial
14+
'
15+
16+
test_expect_success 'mode-only change show as a 0-line change' '
17+
git reset --hard &&
18+
test_chmod +x b d &&
19+
echo a >a &&
20+
echo c >c &&
21+
cat >expect <<-\EOF
22+
a | 1 +
23+
b | 0
24+
...
25+
4 files changed, 2 insertions(+)
26+
EOF
27+
git diff --stat --stat-count=2 HEAD >actual &&
28+
test_i18ncmp expect actual
29+
'
30+
31+
test_expect_success 'binary changes do not count in lines' '
32+
git reset --hard &&
33+
echo a >a &&
34+
echo c >c &&
35+
cat "$TEST_DIRECTORY"/test-binary-1.png >d &&
36+
cat >expect <<-\EOF
37+
a | 1 +
38+
c | 1 +
39+
...
40+
3 files changed, 2 insertions(+)
41+
EOF
42+
git diff --stat --stat-count=2 >actual &&
43+
test_i18ncmp expect actual
44+
'
45+
46+
test_expect_success 'exclude unmerged entries from total file count' '
47+
git reset --hard &&
1448
echo a >a &&
1549
echo b >b &&
50+
git ls-files -s a >x &&
51+
git rm -f d &&
52+
for stage in 1 2 3
53+
do
54+
sed -e "s/ 0 a/ $stage d/" x
55+
done |
56+
git update-index --index-info &&
57+
echo d >d &&
1658
cat >expect <<-\EOF
1759
a | 1 +
1860
b | 1 +
1961
...
20-
4 files changed, 2 insertions(+)
62+
3 files changed, 3 insertions(+)
2163
EOF
2264
git diff --stat --stat-count=2 >actual &&
2365
test_i18ncmp expect actual

0 commit comments

Comments
 (0)