Skip to content

Commit ee5a317

Browse files
committed
Fix "git apply" to correctly enforce "match at the beginning"
An earlier commit 4be6096 (apply --unidiff-zero: loosen sanity checks for --unidiff=0 patches, 2006-09-17) made match_beginning and match_end computed incorrectly. If a hunk inserts at the beginning, old position recorded at the hunk is line 0, and if a hunk changes at the beginning, it is line 1. The new test added to t4104 exposes that the old code did not insist on matching at the beginning for a patch to add a line to an empty file. An even older 65aadb9 (apply: force matching at the beginning., 2006-05-24) was equally wrong in that it tried to take hints from the number of leading context lines, to decide if the hunk must match at the beginning, but we can just look at the line number in the hunk to decide. Signed-off-by: Junio C Hamano <[email protected]>
1 parent f8dd64f commit ee5a317

File tree

2 files changed

+29
-13
lines changed

2 files changed

+29
-13
lines changed

builtin-apply.c

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1736,21 +1736,24 @@ static int apply_one_fragment(struct strbuf *buf, struct fragment *frag,
17361736
trailing = frag->trailing;
17371737

17381738
/*
1739-
* If we don't have any leading/trailing data in the patch,
1740-
* we want it to match at the beginning/end of the file.
1739+
* A hunk to change lines at the beginning would begin with
1740+
* @@ -1,L +N,M @@
17411741
*
1742-
* But that would break if the patch is generated with
1743-
* --unified=0; sane people wouldn't do that to cause us
1744-
* trouble, but we try to please not so sane ones as well.
1742+
* And a hunk to add to an empty file would begin with
1743+
* @@ -0,0 +N,M @@
1744+
*
1745+
* In other words, a hunk that is (frag->oldpos <= 1) with or
1746+
* without leading context must match at the beginning.
17451747
*/
1746-
if (unidiff_zero) {
1747-
match_beginning = (!leading && !frag->oldpos);
1748-
match_end = 0;
1749-
}
1750-
else {
1751-
match_beginning = !leading && (frag->oldpos == 1);
1752-
match_end = !trailing;
1753-
}
1748+
match_beginning = frag->oldpos <= 1;
1749+
1750+
/*
1751+
* A hunk without trailing lines must match at the end.
1752+
* However, we simply cannot tell if a hunk must match end
1753+
* from the lack of trailing lines if the patch was generated
1754+
* with unidiff without any context.
1755+
*/
1756+
match_end = !unidiff_zero && !trailing;
17541757

17551758
lines = 0;
17561759
pos = frag->newpos;

t/t4104-apply-boundary.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,17 @@ do
112112
'
113113
done
114114

115+
test_expect_success 'two lines' '
116+
117+
>file &&
118+
git add file &&
119+
echo aaa >file &&
120+
git diff >patch &&
121+
git add file &&
122+
echo bbb >file &&
123+
git add file &&
124+
test_must_fail git apply --check patch
125+
126+
'
127+
115128
test_done

0 commit comments

Comments
 (0)