--- builtin-apply.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 48 insertions(+), 7 deletions(-) diff --git a/builtin-apply.c b/builtin-apply.c index 01230f1..6c6ccbd 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -1639,10 +1639,17 @@ static int read_old_data(struct stat *st, const char *path, struct strbuf *buf) } } +/* + * Update the preimage, and the common lines in postimage, + * from buffer buf of length len. If postlen is 0 the postimage + * is updated in place, otherwise it's updated on a new buffer + * of length postlen + */ + static void update_pre_post_images(struct image *preimage, struct image *postimage, char *buf, - size_t len) + size_t len, size_t postlen) { int i, ctx; char *new, *old, *fixed; @@ -1661,11 +1668,19 @@ static void update_pre_post_images(struct image *preimage, *preimage = fixed_preimage; /* - * Adjust the common context lines in postimage, in place. - * This is possible because whitespace fixing does not make - * the string grow. + * Adjust the common context lines in postimage. This can be + * done in-place when we are just doing whitespace fixing, + * which does not make the string grow, but needs a new buffer + * when ignore_whitespace causes the update, since in this case + * we could have e.g. tabs converted to multiple spaces. + * We trust the caller to tell us if the update can be done + * in place (postlen==0) or not. */ - new = old = postimage->buf; + old = postimage->buf; + if (postlen) + new = postimage->buf = xmalloc(postlen); + else + new = old; fixed = preimage->buf; for (i = ctx = 0; i < postimage->nr; i++) { size_t len = postimage->line[i].len; @@ -1737,8 +1752,34 @@ static int match_fragment(struct image *img, if ((match_end ? (try + preimage->len == img->len) : (try + preimage->len <= img->len)) && - lines_match(img->buf + try, preimage->buf, preimage->len)) + lines_match(img->buf + try, preimage->buf, preimage->len)) { + /* + * When ignoring whitespace, we want to preserve the + * target image whitespace in lines that are not modified, + * so we update the preimage and the common lines in + * the postimage to the target whitespace. + */ + if (ignore_whitespace) { + /* + * New length for the updated pre and postimages + */ + size_t prelen = 0; + size_t postlen = postimage->len; + for (i = 0; i < preimage->nr; i++) { + size_t len = img->line[try_lno + i].len; + if (preimage->line[i].flag & LINE_COMMON) + postlen += len - preimage->line[i].len; + prelen += preimage->line[i].len = len; + } + fixed_buf = xmalloc(prelen); + memcpy(fixed_buf, img->buf + try, prelen); + + update_pre_post_images( + preimage, postimage, + fixed_buf, prelen, postlen); + } return 1; + } if (ws_error_action != correct_ws_error) return 0; @@ -1799,7 +1840,7 @@ static int match_fragment(struct image *img, * hunk match. Update the context lines in the postimage. */ update_pre_post_images(preimage, postimage, - fixed_buf, buf - fixed_buf); + fixed_buf, buf - fixed_buf, 0); return 1; unmatch_exit: -- 1.6.3.3.512.g4fff -- 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