On 5/20/07, Junio C Hamano <junkio@xxxxxxx> wrote:
I was starting to suspect that I misunderstood what you were trying to do. I thought you were trying to avoid a patch that adds (one or more) blank line(s) at the end of the file, but is it that you do not want to have a hunk that adds more than one blank line anywhere? However, the comment "Only fragments that add lines at the bottom ends with '+' lines" suggests otherwise.
No, you understand right.
Because we had the same mistake in our earlier code as you made in this patch, which assumed that a hunk that ends with '+' only apply at the end (and we still assume that by default), if you apply this with patch git-apply without --unidiff-zero option, you get an error. If you use the option this patch can be applied correctly.
Ok. This is take 3. It works correctly on standard patches and also on u0 example that you gave above. This patch is on top of git 1.5.2 Please check it. builtin-apply.c | 34 ++++++++++++++++++++++++++++++++++ 1 files changed, 34 insertions(+), 0 deletions(-) diff --git a/builtin-apply.c b/builtin-apply.c index 0399743..6032f78 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -1671,6 +1671,7 @@ static int apply_one_fragment(struct buffer_desc *desc, char *new = xmalloc(size); const char *oldlines, *newlines; int oldsize = 0, newsize = 0; + int trailing_added_lines = 0; unsigned long leading, trailing; int pos, lines; @@ -1699,6 +1700,17 @@ static int apply_one_fragment(struct buffer_desc *desc, else if (first == '+') first = '-'; } + /* + * Count lines added at the end of the file. + * This is not enough to get things right in case of + * patches generated with --unified=0, but it's a + * useful upper bound. + */ + if (first == '+') + trailing_added_lines++; + else + trailing_added_lines = 0; + switch (first) { case '\n': /* Newer GNU diff, empty context line */ @@ -1738,6 +1750,24 @@ static int apply_one_fragment(struct buffer_desc *desc, newsize--; } + if (new_whitespace == strip_whitespace) { + /* Any added empty lines is already cleaned-up here + * becuase of 'strip_whitespace' flag, so just count '\n' + */ + int empty = 0; + while ( empty < trailing_added_lines + && newsize - empty > 0 + && new[newsize - empty - 1] == '\n') + empty++; + + if (empty < trailing_added_lines) + empty--; + + /* these are the empty lines added at + * the end of the file, modulo u0 patches. + */ + trailing_added_lines = empty; + } oldlines = old; newlines = new; leading = frag->leading; @@ -1770,6 +1800,10 @@ static int apply_one_fragment(struct buffer_desc *desc, if (match_beginning && offset) offset = -1; if (offset >= 0) { + + if (desc->size - oldsize - offset == 0) /* end of file? */ + newsize -= trailing_added_lines; + int diff = newsize - oldsize; unsigned long size = desc->size + diff; unsigned long alloc = desc->alloc; - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html