apply: convert threeway_stage to object_id
[gitweb.git] / builtin / apply.c
index 6696ea4c3ffd4f7af04f3f56609a78a74a0a0b55..9ffdce7e4bcd0cc1b63e7d79c1fc69266bed5ad6 100644 (file)
@@ -207,7 +207,7 @@ struct patch {
        struct patch *next;
 
        /* three-way fallback result */
-       unsigned char threeway_stage[3][20];
+       struct object_id threeway_stage[3];
 };
 
 static void free_fragment_list(struct fragment *list)
@@ -657,11 +657,6 @@ static size_t diff_timestamp_len(const char *line, size_t len)
        return line + len - end;
 }
 
-static char *null_strdup(const char *s)
-{
-       return s ? xstrdup(s) : NULL;
-}
-
 static char *find_name_common(const char *line, const char *def,
                              int p_value, const char *end, int terminate)
 {
@@ -684,10 +679,10 @@ static char *find_name_common(const char *line, const char *def,
                        start = line;
        }
        if (!start)
-               return squash_slash(null_strdup(def));
+               return squash_slash(xstrdup_or_null(def));
        len = line - start;
        if (!len)
-               return squash_slash(null_strdup(def));
+               return squash_slash(xstrdup_or_null(def));
 
        /*
         * Generally we prefer the shorter name, especially
@@ -909,7 +904,7 @@ static void parse_traditional_patch(const char *first, const char *second, struc
                        patch->old_name = name;
                } else {
                        patch->old_name = name;
-                       patch->new_name = null_strdup(name);
+                       patch->new_name = xstrdup_or_null(name);
                }
        }
        if (!name)
@@ -998,7 +993,7 @@ static int gitdiff_delete(const char *line, struct patch *patch)
 {
        patch->is_delete = 1;
        free(patch->old_name);
-       patch->old_name = null_strdup(patch->def_name);
+       patch->old_name = xstrdup_or_null(patch->def_name);
        return gitdiff_oldmode(line, patch);
 }
 
@@ -1006,7 +1001,7 @@ static int gitdiff_newfile(const char *line, struct patch *patch)
 {
        patch->is_new = 1;
        free(patch->new_name);
-       patch->new_name = null_strdup(patch->def_name);
+       patch->new_name = xstrdup_or_null(patch->def_name);
        return gitdiff_newmode(line, patch);
 }
 
@@ -2235,6 +2230,12 @@ static void update_pre_post_images(struct image *preimage,
                ctx++;
        }
 
+       if (postlen
+           ? postlen < new - postimage->buf
+           : postimage->len < new - postimage->buf)
+               die("BUG: caller miscounted postlen: asked %d, orig = %d, used = %d",
+                   (int)postlen, (int) postimage->len, (int)(new - postimage->buf));
+
        /* Fix the length of the whole thing */
        postimage->len = new - postimage->buf;
        postimage->nr -= reduced;
@@ -2390,10 +2391,27 @@ static int match_fragment(struct image *img,
 
        /*
         * The hunk does not apply byte-by-byte, but the hash says
-        * it might with whitespace fuzz. We haven't been asked to
+        * it might with whitespace fuzz. We weren't asked to
         * ignore whitespace, we were asked to correct whitespace
         * errors, so let's try matching after whitespace correction.
         *
+        * While checking the preimage against the target, whitespace
+        * errors in both fixed, we count how large the corresponding
+        * postimage needs to be.  The postimage prepared by
+        * apply_one_fragment() has whitespace errors fixed on added
+        * lines already, but the common lines were propagated as-is,
+        * which may become longer when their whitespace errors are
+        * fixed.
+        */
+
+       /* First count added lines in postimage */
+       postlen = 0;
+       for (i = 0; i < postimage->nr; i++) {
+               if (!(postimage->line[i].flag & LINE_COMMON))
+                       postlen += postimage->line[i].len;
+       }
+
+       /*
         * The preimage may extend beyond the end of the file,
         * but in this loop we will only handle the part of the
         * preimage that falls within the file.
@@ -2401,7 +2419,6 @@ static int match_fragment(struct image *img,
        strbuf_init(&fixed, preimage->len + 1);
        orig = preimage->buf;
        target = img->buf + try;
-       postlen = 0;
        for (i = 0; i < preimage_limit; i++) {
                size_t oldlen = preimage->line[i].len;
                size_t tgtlen = img->line[try_lno + i].len;
@@ -2429,7 +2446,10 @@ static int match_fragment(struct image *img,
                match = (tgtfix.len == fixed.len - fixstart &&
                         !memcmp(tgtfix.buf, fixed.buf + fixstart,
                                             fixed.len - fixstart));
-               postlen += tgtfix.len;
+
+               /* Add the length if this is common with the postimage */
+               if (preimage->line[i].flag & LINE_COMMON)
+                       postlen += tgtfix.len;
 
                strbuf_release(&tgtfix);
                if (!match)
@@ -3398,11 +3418,11 @@ static int try_threeway(struct image *image, struct patch *patch,
        if (status) {
                patch->conflicted_threeway = 1;
                if (patch->is_new)
-                       hashclr(patch->threeway_stage[0]);
+                       oidclr(&patch->threeway_stage[0]);
                else
-                       hashcpy(patch->threeway_stage[0], pre_sha1);
-               hashcpy(patch->threeway_stage[1], our_sha1);
-               hashcpy(patch->threeway_stage[2], post_sha1);
+                       hashcpy(patch->threeway_stage[0].hash, pre_sha1);
+               hashcpy(patch->threeway_stage[1].hash, our_sha1);
+               hashcpy(patch->threeway_stage[2].hash, post_sha1);
                fprintf(stderr, "Applied patch to '%s' with conflicts.\n", patch->new_name);
        } else {
                fprintf(stderr, "Applied patch to '%s' cleanly.\n", patch->new_name);
@@ -3728,7 +3748,7 @@ static void build_fake_ancestor(struct patch *list, const char *filename)
                        if (!preimage_sha1_in_gitlink_patch(patch, sha1))
                                ; /* ok, the textual part looks sane */
                        else
-                               die("sha1 information is lacking or useless for submoule %s",
+                               die("sha1 information is lacking or useless for submodule %s",
                                    name);
                } else if (!get_sha1_blob(patch->old_sha1_prefix, sha1)) {
                        ; /* ok */
@@ -4026,14 +4046,14 @@ static void add_conflicted_stages_file(struct patch *patch)
 
        remove_file_from_cache(patch->new_name);
        for (stage = 1; stage < 4; stage++) {
-               if (is_null_sha1(patch->threeway_stage[stage - 1]))
+               if (is_null_oid(&patch->threeway_stage[stage - 1]))
                        continue;
                ce = xcalloc(1, ce_size);
                memcpy(ce->name, patch->new_name, namelen);
                ce->ce_mode = create_ce_mode(mode);
                ce->ce_flags = create_ce_flags(stage);
                ce->ce_namelen = namelen;
-               hashcpy(ce->sha1, patch->threeway_stage[stage - 1]);
+               hashcpy(ce->sha1, patch->threeway_stage[stage - 1].hash);
                if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD) < 0)
                        die(_("unable to add cache entry for %s"), patch->new_name);
        }
@@ -4180,7 +4200,7 @@ static int write_out_results(struct patch *list)
        if (cpath.nr) {
                struct string_list_item *item;
 
-               sort_string_list(&cpath);
+               string_list_sort(&cpath);
                for_each_string_list_item(item, &cpath)
                        fprintf(stderr, "U %s\n", item->string);
                string_list_clear(&cpath, 0);