From 1bf1a859ae980a73552c76fe20a5952a763ec81e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 23 May 2006 19:08:01 -0700 Subject: [PATCH 1/3] apply: treat EOF as proper context. Catalin noticed that we do not treat end-of-file condition shown in the patch text as the patch context. This causes a patch that appends at the end of the file to cleanly apply even if something else has been appended to the file. If this happened in the middle, we would refuse by saying that the file has conflicting modifications. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- apply.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/apply.c b/apply.c index 0ed9d132e8..768b572a81 100644 --- a/apply.c +++ b/apply.c @@ -1333,6 +1333,7 @@ static int apply_line(char *output, const char *patch, int plen) static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag) { + int match_end; char *buf = desc->buffer; const char *patch = frag->patch; int offset, size = frag->size; @@ -1395,10 +1396,19 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag) newlines = new; leading = frag->leading; trailing = frag->trailing; + + /* + * If we don't have any trailing data in the patch, + * we want it to match at the end of the file. + */ + match_end = !trailing; + lines = 0; pos = frag->newpos; for (;;) { offset = find_offset(buf, desc->size, oldlines, oldsize, pos, &lines); + if (match_end && offset + oldsize != desc->size) + offset = -1; if (offset >= 0) { int diff = newsize - oldsize; unsigned long size = desc->size + diff; @@ -1428,6 +1438,10 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag) /* Am I at my context limits? */ if ((leading <= p_context) && (trailing <= p_context)) break; + if (match_end) { + match_end = 0; + continue; + } /* Reduce the number of context lines * Reduce both leading and trailing if they are equal * otherwise just reduce the larger context. From cc189c2ca2c725c430f100f61e7c4a6849f93163 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Tue, 23 May 2006 22:48:36 +0100 Subject: [PATCH 2/3] Add a test-case for git-apply trying to add an ending line git-apply adding an ending line doesn't seem to fail if the ending line is already present in the patched file. Signed-off-by: Catalin Marinas Signed-off-by: Junio C Hamano --- t/t4113-apply-ending.sh | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100755 t/t4113-apply-ending.sh diff --git a/t/t4113-apply-ending.sh b/t/t4113-apply-ending.sh new file mode 100755 index 0000000000..d021ae84c3 --- /dev/null +++ b/t/t4113-apply-ending.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# +# Copyright (c) 2006 Catalin Marinas +# + +test_description='git-apply trying to add an ending line. + +' +. ./test-lib.sh + +# setup + +cat >test-patch <<\EOF +diff --git a/file b/file +--- a/file ++++ b/file +@@ -1,2 +1,3 @@ + a + b ++c +EOF + +echo 'a' >file +echo 'b' >>file +echo 'c' >>file + +test_expect_success setup \ + 'git-update-index --add file' + +# test + +test_expect_failure apply \ + 'git-apply --index test-patch' + +test_done From 65aadb92a1ce9605fa2f412b51de91781a3ef3d6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 24 May 2006 13:19:50 -0700 Subject: [PATCH 3/3] apply: force matching at the beginning. When there is no leading context, the patch must match at the beginning of preimage; otherwise there is a "patch adds these lines while the other lines were added to the original file" conflict. This is the opposite of match_end fix earlier in this series. Unlike matching at the end case, we can additionally check the preimage line number recorded in the patch, so the change is not symmetrical with the earlier one. Signed-off-by: Junio C Hamano --- apply.c | 13 ++++++++----- t/t4113-apply-ending.sh | 20 +++++++++++++++++++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/apply.c b/apply.c index 768b572a81..f11fb18b69 100644 --- a/apply.c +++ b/apply.c @@ -1333,7 +1333,7 @@ static int apply_line(char *output, const char *patch, int plen) static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag) { - int match_end; + int match_beginning, match_end; char *buf = desc->buffer; const char *patch = frag->patch; int offset, size = frag->size; @@ -1398,9 +1398,10 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag) trailing = frag->trailing; /* - * If we don't have any trailing data in the patch, - * we want it to match at the end of the file. + * If we don't have any leading/trailing data in the patch, + * we want it to match at the beginning/end of the file. */ + match_beginning = !leading && (frag->oldpos == 1); match_end = !trailing; lines = 0; @@ -1409,6 +1410,8 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag) offset = find_offset(buf, desc->size, oldlines, oldsize, pos, &lines); if (match_end && offset + oldsize != desc->size) offset = -1; + if (match_beginning && offset) + offset = -1; if (offset >= 0) { int diff = newsize - oldsize; unsigned long size = desc->size + diff; @@ -1438,8 +1441,8 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag) /* Am I at my context limits? */ if ((leading <= p_context) && (trailing <= p_context)) break; - if (match_end) { - match_end = 0; + if (match_beginning || match_end) { + match_beginning = match_end = 0; continue; } /* Reduce the number of context lines diff --git a/t/t4113-apply-ending.sh b/t/t4113-apply-ending.sh index d021ae84c3..7fd0cf62ec 100755 --- a/t/t4113-apply-ending.sh +++ b/t/t4113-apply-ending.sh @@ -29,7 +29,25 @@ test_expect_success setup \ # test -test_expect_failure apply \ +test_expect_failure 'apply at the end' \ 'git-apply --index test-patch' +cat >test-patch <<\EOF +diff a/file b/file +--- a/file ++++ b/file +@@ -1,2 +1,3 @@ ++a + b + c +EOF + +echo >file 'a +b +c' +git-update-index file + +test_expect_failure 'apply at the beginning' \ + 'git-apply --index test-patch' + test_done