提交 74faaa16 编写于 作者: L Linus Torvalds 提交者: Junio C Hamano

Fix "git diff --stat" for interesting - but empty - file changes

The behavior of "git diff --stat" is rather odd for files that have
zero lines of changes: it will discount them entirely unless they were
renames.

Which means that the stat output will simply not show files that only
had "other" changes: they were created or deleted, or their mode was
changed.

Now, those changes do show up in the summary, but so do renames, so
the diffstat logic is inconsistent. Why does it show renames with zero
lines changed, but not mode changes or added files with zero lines
changed?

So change the logic to not check for "is_renamed", but for
"is_interesting" instead, where "interesting" is judged to be any
action but a pure data change (because a pure data change with zero
data changed really isn't worth showing, if we ever get one in our
diffpairs).

So if you did

   chmod +x Makefile
   git diff --stat

before, it would show empty (" 0 files changed"), with this it shows

 Makefile | 0
 1 file changed, 0 insertions(+), 0 deletions(-)

which I think is a more correct diffstat (and then with "--summary" it
shows *what* the metadata change to Makefile was - this is completely
consistent with our handling of renamed files).

Side note: the old behavior was *really* odd. With no changes at all,
"git diff --stat" output was empty. With just a chmod, it said "0
files changed". No way is our legacy behavior sane.
Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: NJunio C Hamano <gitster@pobox.com>
上级 87a5461f
......@@ -1300,6 +1300,7 @@ struct diffstat_t {
unsigned is_unmerged:1;
unsigned is_binary:1;
unsigned is_renamed:1;
unsigned is_interesting:1;
uintmax_t added, deleted;
} **files;
};
......@@ -1469,7 +1470,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
for (i = 0; (i < count) && (i < data->nr); i++) {
struct diffstat_file *file = data->files[i];
uintmax_t change = file->added + file->deleted;
if (!data->files[i]->is_renamed &&
if (!data->files[i]->is_interesting &&
(change == 0)) {
count++; /* not shown == room for one more */
continue;
......@@ -1590,7 +1591,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
uintmax_t deleted = data->files[i]->deleted;
int name_len;
if (!data->files[i]->is_renamed &&
if (!data->files[i]->is_interesting &&
(added + deleted == 0)) {
total_files--;
continue;
......@@ -1669,7 +1670,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
for (i = count; i < data->nr; i++) {
uintmax_t added = data->files[i]->added;
uintmax_t deleted = data->files[i]->deleted;
if (!data->files[i]->is_renamed &&
if (!data->files[i]->is_interesting &&
(added + deleted == 0)) {
total_files--;
continue;
......@@ -1697,7 +1698,7 @@ static void show_shortstats(struct diffstat_t *data, struct diff_options *option
if (data->files[i]->is_unmerged)
continue;
if (!data->files[i]->is_renamed && (added + deleted == 0)) {
if (!data->files[i]->is_interesting && (added + deleted == 0)) {
total_files--;
} else if (!data->files[i]->is_binary) { /* don't count bytes */
adds += added;
......@@ -2397,13 +2398,20 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
struct diff_filespec *two,
struct diffstat_t *diffstat,
struct diff_options *o,
int complete_rewrite)
struct diff_filepair *p)
{
mmfile_t mf1, mf2;
struct diffstat_file *data;
int same_contents;
int complete_rewrite = 0;
if (!DIFF_PAIR_UNMERGED(p)) {
if (p->status == DIFF_STATUS_MODIFIED && p->score)
complete_rewrite = 1;
}
data = diffstat_add(diffstat, name_a, name_b);
data->is_interesting = p->status != 0;
if (!one || !two) {
data->is_unmerged = 1;
......@@ -3114,11 +3122,10 @@ static void run_diffstat(struct diff_filepair *p, struct diff_options *o,
{
const char *name;
const char *other;
int complete_rewrite = 0;
if (DIFF_PAIR_UNMERGED(p)) {
/* unmerged */
builtin_diffstat(p->one->path, NULL, NULL, NULL, diffstat, o, 0);
builtin_diffstat(p->one->path, NULL, NULL, NULL, diffstat, o, p);
return;
}
......@@ -3131,9 +3138,7 @@ static void run_diffstat(struct diff_filepair *p, struct diff_options *o,
diff_fill_sha1_info(p->one);
diff_fill_sha1_info(p->two);
if (p->status == DIFF_STATUS_MODIFIED && p->score)
complete_rewrite = 1;
builtin_diffstat(name, other, p->one, p->two, diffstat, o, complete_rewrite);
builtin_diffstat(name, other, p->one, p->two, diffstat, o, p);
}
static void run_checkdiff(struct diff_filepair *p, struct diff_options *o)
......
......@@ -32,28 +32,28 @@ test_expect_success 'prepare binary file' '
git commit -m binbin
'
test_expect_success '--stat output after text chmod' '
test_chmod -x rezrov &&
echo " 0 files changed" >expect &&
git diff HEAD --stat >actual &&
test_i18ncmp expect actual
'
test_expect_success '--shortstat output after text chmod' '
git diff HEAD --shortstat >actual &&
test_i18ncmp expect actual
'
test_expect_success '--stat output after binary chmod' '
test_chmod +x binbin &&
echo " 0 files changed" >expect &&
git diff HEAD --stat >actual &&
test_i18ncmp expect actual
'
test_expect_success '--shortstat output after binary chmod' '
git diff HEAD --shortstat >actual &&
test_i18ncmp expect actual
'
# test_expect_success '--stat output after text chmod' '
# test_chmod -x rezrov &&
# echo " 0 files changed" >expect &&
# git diff HEAD --stat >actual &&
# test_i18ncmp expect actual
# '
#
# test_expect_success '--shortstat output after text chmod' '
# git diff HEAD --shortstat >actual &&
# test_i18ncmp expect actual
# '
#
# test_expect_success '--stat output after binary chmod' '
# test_chmod +x binbin &&
# echo " 0 files changed" >expect &&
# git diff HEAD --stat >actual &&
# test_i18ncmp expect actual
# '
#
# test_expect_success '--shortstat output after binary chmod' '
# git diff HEAD --shortstat >actual &&
# test_i18ncmp expect actual
# '
test_done
......@@ -16,7 +16,8 @@ test_expect_success setup '
cat >expect <<-\EOF
a | 1 +
b | 1 +
2 files changed, 2 insertions(+)
...
4 files changed, 2 insertions(+)
EOF
git diff --stat --stat-count=2 >actual &&
test_i18ncmp expect actual
......
......@@ -85,7 +85,7 @@ test_expect_success 'NUL termination' '
test_expect_success 'NUL separation with --stat' '
stat0_part=$(git diff --stat HEAD^ HEAD) &&
stat1_part=$(git diff --stat --root HEAD^) &&
stat1_part=$(git diff-tree --no-commit-id --stat --root HEAD^) &&
printf "add bar\n$stat0_part\n\0initial\n$stat1_part\n" >expected &&
git log -z --stat --pretty="format:%s" >actual &&
test_i18ncmp expected actual
......@@ -93,7 +93,7 @@ test_expect_success 'NUL separation with --stat' '
test_expect_failure 'NUL termination with --stat' '
stat0_part=$(git diff --stat HEAD^ HEAD) &&
stat1_part=$(git diff --stat --root HEAD^) &&
stat1_part=$(git diff-tree --no-commit-id --stat --root HEAD^) &&
printf "add bar\n$stat0_part\n\0initial\n$stat1_part\n\0" >expected &&
git log -z --stat --pretty="tformat:%s" >actual &&
test_i18ncmp expected actual
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册