Skip to content

Commit c9a3e72

Browse files
committed
diff: mode-only change should be noticed by "--patch -w --exit-code"
The codepath to notice the content-level changes, taking certain no-op changes like "ignore whitespace" into account, forgot that a mode-only change is still a change. This resulted in $ git diff --patch --exit-code -w to exit with status 0 even when there is such a mode-only change, breaking both "--patch" and "--quiet" output formats. Teach the builtin_diff() codepath that creation and deletion as well as mode changes are all interesting changes. Note that the test specifically checks removal of an empty file, because if there is anything in the preimage (i.e. the removed file is not empty), the removal would still trigger textual patch output and the codepath for that does update .found_changes bit to report that it found an interesting change. We need to make sure that the .found_changes bit is set even without triggering textual patch output. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 5f107ca commit c9a3e72

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

diff.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3497,18 +3497,21 @@ static void builtin_diff(const char *name_a,
34973497
strbuf_addf(&header, "%s%snew file mode %06o%s\n", line_prefix, meta, two->mode, reset);
34983498
if (xfrm_msg)
34993499
strbuf_addstr(&header, xfrm_msg);
3500+
o->found_changes = 1;
35003501
must_show_header = 1;
35013502
}
35023503
else if (lbl[1][0] == '/') {
35033504
strbuf_addf(&header, "%s%sdeleted file mode %06o%s\n", line_prefix, meta, one->mode, reset);
35043505
if (xfrm_msg)
35053506
strbuf_addstr(&header, xfrm_msg);
3507+
o->found_changes = 1;
35063508
must_show_header = 1;
35073509
}
35083510
else {
35093511
if (one->mode != two->mode) {
35103512
strbuf_addf(&header, "%s%sold mode %06o%s\n", line_prefix, meta, one->mode, reset);
35113513
strbuf_addf(&header, "%s%snew mode %06o%s\n", line_prefix, meta, two->mode, reset);
3514+
o->found_changes = 1;
35123515
must_show_header = 1;
35133516
}
35143517
if (xfrm_msg)

t/t4015-diff-whitespace.sh

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/bin/sh
22
#
33
# Copyright (c) 2006 Johannes E. Schindelin
4-
#
4+
# Copyright (c) 2023 Google LLC
55

66
test_description='Test special whitespace in diff engine.
77
@@ -11,6 +11,39 @@ TEST_PASSES_SANITIZE_LEAK=true
1111
. ./test-lib.sh
1212
. "$TEST_DIRECTORY"/lib-diff.sh
1313

14+
for opts in --patch --quiet -s
15+
do
16+
17+
test_expect_success "status with $opts (different)" '
18+
echo foo >x &&
19+
git add x &&
20+
echo bar >x &&
21+
test_expect_code 1 git diff -w $opts --exit-code x
22+
'
23+
24+
test_expect_success POSIXPERM "status with $opts (mode differs)" '
25+
test_when_finished "git update-index --chmod=-x x" &&
26+
echo foo >x &&
27+
git add x &&
28+
git update-index --chmod=+x x &&
29+
test_expect_code 1 git diff -w $opts --exit-code x
30+
'
31+
32+
test_expect_success "status with $opts (removing an empty file)" '
33+
: >x &&
34+
git add x &&
35+
rm x &&
36+
test_expect_code 1 git diff -w $opts --exit-code -- x
37+
'
38+
39+
test_expect_success "status with $opts (different but equivalent)" '
40+
echo foo >x &&
41+
git add x &&
42+
echo " foo" >x &&
43+
git diff -w $opts --exit-code x
44+
'
45+
done
46+
1447
test_expect_success "Ray Lehtiniemi's example" '
1548
cat <<-\EOF >x &&
1649
do {

0 commit comments

Comments
 (0)