From efe7f3586156bff4d29c347a1c41f93627c9f3e3 Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Sun, 20 May 2007 14:45:59 +0200 Subject: [PATCH 1/2] Teach 'git-apply --whitespace=strip' to remove empty lines at the end of file [jc: with an obvious microfix to avoid doing this unless --whitespace=strip] Signed-off-by: Marco Costalba Signed-off-by: Junio C Hamano --- builtin-apply.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/builtin-apply.c b/builtin-apply.c index 0399743c4e..ac7c82437e 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -1671,6 +1671,7 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, i 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, struct fragment *frag, i 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, struct fragment *frag, i 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,9 +1800,16 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, i if (match_beginning && offset) offset = -1; if (offset >= 0) { - int diff = newsize - oldsize; - unsigned long size = desc->size + diff; - unsigned long alloc = desc->alloc; + int diff; + unsigned long size, alloc; + + if (new_whitespace == strip_whitespace && + (desc->size - oldsize - offset == 0)) /* end of file? */ + newsize -= trailing_added_lines; + + diff = newsize - oldsize; + size = desc->size + diff; + alloc = desc->alloc; /* Warn if it was necessary to reduce the number * of context lines. From 077e1af5983000266bc7c1423a87b7768ca03754 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 20 May 2007 23:51:06 -0700 Subject: [PATCH 2/2] git-apply: Fix removal of new trailing blank lines. The earlier code removed one newline too many from the hunk that adds new lines at the end of the file. Also the way the code counted the added blank lines was somewhat roundabout; I think the way updated code does it is more direct and easier to follow: * We keep track of the number of blank lines added; * While processing each line, we notice if it adds a blank line, and increment the counter, or reset it to zero otherwise; * When actually we apply the data, we remove the empty lines we counted earlier if we are applying it at the end of the file. Signed-off-by: Junio C Hamano --- builtin-apply.c | 48 +++++++++++++++--------------------------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/builtin-apply.c b/builtin-apply.c index ac7c82437e..e717898037 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -1671,7 +1671,7 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, i char *new = xmalloc(size); const char *oldlines, *newlines; int oldsize = 0, newsize = 0; - int trailing_added_lines = 0; + int new_blank_lines_at_end = 0; unsigned long leading, trailing; int pos, lines; @@ -1679,6 +1679,7 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, i char first; int len = linelen(patch, size); int plen; + int added_blank_line = 0; if (!len) break; @@ -1700,16 +1701,6 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, i 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': @@ -1728,9 +1719,14 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, i break; /* Fall-through for ' ' */ case '+': - if (first != '+' || !no_add) - newsize += apply_line(new + newsize, patch, - plen); + if (first != '+' || !no_add) { + int added = apply_line(new + newsize, patch, + plen); + newsize += added; + if (first == '+' && + added == 1 && new[newsize-1] == '\n') + added_blank_line = 1; + } break; case '@': case '\\': /* Ignore it, we already handled it */ @@ -1740,6 +1736,10 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, i error("invalid start of line: '%c'", first); return -1; } + if (added_blank_line) + new_blank_lines_at_end++; + else + new_blank_lines_at_end = 0; patch += len; size -= len; } @@ -1750,24 +1750,6 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, i 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; @@ -1805,7 +1787,7 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, i if (new_whitespace == strip_whitespace && (desc->size - oldsize - offset == 0)) /* end of file? */ - newsize -= trailing_added_lines; + newsize -= new_blank_lines_at_end; diff = newsize - oldsize; size = desc->size + diff;