Code

Merge branch 'maint-1.7.6' into maint-1.7.7
[git.git] / builtin / apply.c
index b719f41482ee3be39d91a30f93eeabaf9d96be55..082fe8f3e3e6088adcce4b54ae351c4ec1f03786 100644 (file)
@@ -43,6 +43,7 @@ static int apply = 1;
 static int apply_in_reverse;
 static int apply_with_reject;
 static int apply_verbosely;
+static int allow_overlap;
 static int no_add;
 static const char *fake_ancestor;
 static int line_termination = '\n';
@@ -204,6 +205,7 @@ struct line {
        unsigned hash : 24;
        unsigned flag : 8;
 #define LINE_COMMON     1
+#define LINE_PATCHED   2
 };
 
 /*
@@ -248,9 +250,6 @@ static int fuzzy_matchlines(const char *s1, size_t n1,
        const char *last2 = s2 + n2 - 1;
        int result = 0;
 
-       if (n1 < 0 || n2 < 0)
-               return 0;
-
        /* ignore line endings */
        while ((*last1 == '\r') || (*last1 == '\n'))
                last1--;
@@ -1405,6 +1404,9 @@ static int find_header(char *line, unsigned long size, int *hdrsize, struct patc
                                            "%d leading pathname components (line %d)" , p_value, linenr);
                                patch->old_name = patch->new_name = patch->def_name;
                        }
+                       if (!patch->is_delete && !patch->new_name)
+                               die("git diff header lacks filename information "
+                                   "(line %d)", linenr);
                        patch->is_toplevel_relative = 1;
                        *hdrsize = git_hdr_len;
                        return offset;
@@ -1632,7 +1634,7 @@ static inline int metadata_changes(struct patch *patch)
 static char *inflate_it(const void *data, unsigned long size,
                        unsigned long inflated_size)
 {
-       z_stream stream;
+       git_zstream stream;
        void *out;
        int st;
 
@@ -2085,7 +2087,8 @@ static int match_fragment(struct image *img,
 
        /* Quick hash check */
        for (i = 0; i < preimage_limit; i++)
-               if (preimage->line[i].hash != img->line[try_lno + i].hash)
+               if ((img->line[try_lno + i].flag & LINE_PATCHED) ||
+                   (preimage->line[i].hash != img->line[try_lno + i].hash))
                        return 0;
 
        if (preimage_limit == preimage->nr) {
@@ -2428,11 +2431,15 @@ static void update_image(struct image *img,
        memcpy(img->line + applied_pos,
               postimage->line,
               postimage->nr * sizeof(*img->line));
+       if (!allow_overlap)
+               for (i = 0; i < postimage->nr; i++)
+                       img->line[applied_pos + i].flag |= LINE_PATCHED;
        img->nr = nr;
 }
 
 static int apply_one_fragment(struct image *img, struct fragment *frag,
-                             int inaccurate_eof, unsigned ws_rule)
+                             int inaccurate_eof, unsigned ws_rule,
+                             int nth_fragment)
 {
        int match_beginning, match_end;
        const char *patch = frag->patch;
@@ -2440,6 +2447,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
        char *old, *oldlines;
        struct strbuf newlines;
        int new_blank_lines_at_end = 0;
+       int found_new_blank_lines_at_end = 0;
+       int hunk_linenr = frag->linenr;
        unsigned long leading, trailing;
        int pos, applied_pos;
        struct image preimage;
@@ -2533,14 +2542,18 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
                                error("invalid start of line: '%c'", first);
                        return -1;
                }
-               if (added_blank_line)
+               if (added_blank_line) {
+                       if (!new_blank_lines_at_end)
+                               found_new_blank_lines_at_end = hunk_linenr;
                        new_blank_lines_at_end++;
+               }
                else if (is_blank_context)
                        ;
                else
                        new_blank_lines_at_end = 0;
                patch += len;
                size -= len;
+               hunk_linenr++;
        }
        if (inaccurate_eof &&
            old > oldlines && old[-1] == '\n' &&
@@ -2622,7 +2635,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
                    preimage.nr + applied_pos >= img->nr &&
                    (ws_rule & WS_BLANK_AT_EOF) &&
                    ws_error_action != nowarn_ws_error) {
-                       record_ws_error(WS_BLANK_AT_EOF, "+", 1, frag->linenr);
+                       record_ws_error(WS_BLANK_AT_EOF, "+", 1,
+                                       found_new_blank_lines_at_end);
                        if (ws_error_action == correct_ws_error) {
                                while (new_blank_lines_at_end--)
                                        remove_last_line(&postimage);
@@ -2638,6 +2652,15 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
                                apply = 0;
                }
 
+               if (apply_verbosely && applied_pos != pos) {
+                       int offset = applied_pos - pos;
+                       if (apply_in_reverse)
+                               offset = 0 - offset;
+                       fprintf(stderr,
+                               "Hunk #%d succeeded at %d (offset %d lines).\n",
+                               nth_fragment, applied_pos + 1, offset);
+               }
+
                /*
                 * Warn if it was necessary to reduce the number
                 * of context lines.
@@ -2785,12 +2808,14 @@ static int apply_fragments(struct image *img, struct patch *patch)
        const char *name = patch->old_name ? patch->old_name : patch->new_name;
        unsigned ws_rule = patch->ws_rule;
        unsigned inaccurate_eof = patch->inaccurate_eof;
+       int nth = 0;
 
        if (patch->is_binary)
                return apply_binary(img, patch);
 
        while (frag) {
-               if (apply_one_fragment(img, frag, inaccurate_eof, ws_rule)) {
+               nth++;
+               if (apply_one_fragment(img, frag, inaccurate_eof, ws_rule, nth)) {
                        error("patch failed: %s:%ld", name, frag->oldpos);
                        if (!apply_with_reject)
                                return -1;
@@ -3872,7 +3897,9 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
                        "don't expect at least one line of context"),
                OPT_BOOLEAN(0, "reject", &apply_with_reject,
                        "leave the rejected hunks in corresponding *.rej files"),
-               OPT__VERBOSE(&apply_verbosely),
+               OPT_BOOLEAN(0, "allow-overlap", &allow_overlap,
+                       "allow overlapping hunks"),
+               OPT__VERBOSE(&apply_verbosely, "be verbose"),
                OPT_BIT(0, "inaccurate-eof", &options,
                        "tolerate incorrectly detected missing new-line at the end of file",
                        INACCURATE_EOF),