Code

Merge branch 'jc/maint-apply-match-beginning'
authorJunio C Hamano <gitster@pobox.com>
Mon, 7 Apr 2008 03:04:29 +0000 (20:04 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 7 Apr 2008 03:04:29 +0000 (20:04 -0700)
* jc/maint-apply-match-beginning:
  Fix "git apply" to correctly enforce "match at the beginning"

1  2 
builtin-apply.c

diff --cc builtin-apply.c
index b5f78ac3a78679fdb747380305fb6772c39874e0,03f2e950ba55bce81a846514926512af6746f41b..abe73a0f8194e95c2a10a27c2007560e6d57f3d5
@@@ -1937,37 -1736,52 +1937,40 @@@ static int apply_one_fragment(struct im
        trailing = frag->trailing;
  
        /*
-        * If we don't have any leading/trailing data in the patch,
-        * we want it to match at the beginning/end of the file.
+        * A hunk to change lines at the beginning would begin with
+        * @@ -1,L +N,M @@
         *
-        * But that would break if the patch is generated with
-        * --unified=0; sane people wouldn't do that to cause us
-        * trouble, but we try to please not so sane ones as well.
+        * And a hunk to add to an empty file would begin with
+        * @@ -0,0 +N,M @@
+        *
+        * In other words, a hunk that is (frag->oldpos <= 1) with or
+        * without leading context must match at the beginning.
         */
-       if (unidiff_zero) {
-               match_beginning = (!leading && !frag->oldpos);
-               match_end = 0;
-       }
-       else {
-               match_beginning = !leading && (frag->oldpos == 1);
-               match_end = !trailing;
-       }
+       match_beginning = frag->oldpos <= 1;
+       /*
+        * A hunk without trailing lines must match at the end.
+        * However, we simply cannot tell if a hunk must match end
+        * from the lack of trailing lines if the patch was generated
+        * with unidiff without any context.
+        */
+       match_end = !unidiff_zero && !trailing;
  
 -      lines = 0;
 -      pos = frag->newpos;
 +      pos = frag->newpos ? (frag->newpos - 1) : 0;
 +      preimage.buf = oldlines;
 +      preimage.len = old - oldlines;
 +      postimage.buf = newlines;
 +      postimage.len = new - newlines;
 +      preimage.line = preimage.line_allocated;
 +      postimage.line = postimage.line_allocated;
 +
        for (;;) {
 -              offset = find_offset(buf->buf, buf->len,
 -                                   oldlines, oldsize, pos, &lines);
 -              if (match_end && offset + oldsize != buf->len)
 -                      offset = -1;
 -              if (match_beginning && offset)
 -                      offset = -1;
 -              if (offset >= 0) {
 -                      if (ws_error_action == correct_ws_error &&
 -                          (buf->len - oldsize - offset == 0)) /* end of file? */
 -                              newsize -= new_blank_lines_at_end;
 -
 -                      /* Warn if it was necessary to reduce the number
 -                       * of context lines.
 -                       */
 -                      if ((leading != frag->leading) ||
 -                          (trailing != frag->trailing))
 -                              fprintf(stderr, "Context reduced to (%ld/%ld)"
 -                                      " to apply fragment at %d\n",
 -                                      leading, trailing, pos + lines);
 -
 -                      strbuf_splice(buf, offset, oldsize, newlines, newsize);
 -                      offset = 0;
 +
 +              applied_pos = find_pos(img, &preimage, &postimage, pos,
 +                                     ws_rule, match_beginning, match_end);
 +
 +              if (applied_pos >= 0)
                        break;
 -              }
  
                /* Am I at my context limits? */
                if ((leading <= p_context) && (trailing <= p_context))