Skip to content

Commit ed0f47a

Browse files
committed
git-apply: Loosen "match_beginning" logic
Even after a handfle attempts, match_beginning logic still has corner cases: 1bf1a85 (apply: treat EOF as proper context., 2006-05-23) 65aadb9 (apply: force matching at the beginning., 2006-05-24) 4be6096 (apply --unidiff-zero: loosen sanity checks ..., 2006-09-17) ee5a317 (Fix "git apply" to correctly enforce "match ..., 2008-04-06) This is a tricky piece of code. We still incorrectly enforce "match_beginning" for -U0 matches. I noticed this while trying out an example sequence from Clemens Buchacher: $ echo a >victim $ git add victim $ echo b >>victim $ git diff -U0 >patch $ cat patch diff --git i/victim w/victim index 7898192..422c2b7 100644 --- i/victim +++ w/victim @@ -1,0 +2 @@ a +b $ git apply --cached --unidiff-zero <patch $ git show :victim b a The change inserts a new line before the second line, but we insist it to be applied at the beginning. As the result, the code refuses to apply it at the original offset, and we end up adding the line at the beginning. Updates to the test script are by Clemens Buchacher. Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent ee83724 commit ed0f47a

File tree

2 files changed

+16
-4
lines changed

2 files changed

+16
-4
lines changed

builtin-apply.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1996,14 +1996,17 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
19961996
/*
19971997
* A hunk to change lines at the beginning would begin with
19981998
* @@ -1,L +N,M @@
1999+
* but we need to be careful. -U0 that inserts before the second
2000+
* line also has this pattern.
19992001
*
20002002
* And a hunk to add to an empty file would begin with
20012003
* @@ -0,0 +N,M @@
20022004
*
20032005
* In other words, a hunk that is (frag->oldpos <= 1) with or
20042006
* without leading context must match at the beginning.
20052007
*/
2006-
match_beginning = frag->oldpos <= 1;
2008+
match_beginning = (!frag->oldpos ||
2009+
(frag->oldpos == 1 && !unidiff_zero));
20072010

20082011
/*
20092012
* A hunk without trailing lines must match at the end.

t/t4104-apply-boundary.sh

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@ test_expect_success setup '
2727
git diff victim >add-a-patch.with &&
2828
git diff --unified=0 >add-a-patch.without &&
2929
30+
: insert at line two
31+
for i in b a '"$L"' y
32+
do
33+
echo $i
34+
done >victim &&
35+
cat victim >insert-a-expect &&
36+
git diff victim >insert-a-patch.with &&
37+
git diff --unified=0 >insert-a-patch.without &&
38+
3039
: modify at the head
3140
for i in a '"$L"' y
3241
do
@@ -55,7 +64,7 @@ test_expect_success setup '
5564
git diff --unified=0 >add-z-patch.without &&
5665
5766
: modify at the tail
58-
for i in a '"$L"' y
67+
for i in b '"$L"' z
5968
do
6069
echo $i
6170
done >victim &&
@@ -81,7 +90,7 @@ do
8190
with) u= ;;
8291
without) u='--unidiff-zero ' ;;
8392
esac
84-
for kind in add-a add-z mod-a mod-z del-a del-z
93+
for kind in add-a add-z insert-a mod-a mod-z del-a del-z
8594
do
8695
test_expect_success "apply $kind-patch $with context" '
8796
cat original >victim &&
@@ -95,7 +104,7 @@ do
95104
done
96105
done
97106

98-
for kind in add-a add-z mod-a mod-z del-a del-z
107+
for kind in add-a add-z insert-a mod-a mod-z del-a del-z
99108
do
100109
rm -f $kind-ng.without
101110
sed -e "s/^diff --git /diff /" \

0 commit comments

Comments
 (0)