Merge branch 'tr/maint-apply-non-git-patch-parsefix'
authorJunio C Hamano <gitster@pobox.com>
Wed, 26 Jun 2013 22:08:09 +0000 (15:08 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 26 Jun 2013 22:08:09 +0000 (15:08 -0700)
Fix for the codepath to parse patches that add new files, generated
by programs other than Git. THis is an old breakage in v1.7.11 and
will need to be merged down to the maintanance tracks.

* tr/maint-apply-non-git-patch-parsefix:
apply: carefully strdup a possibly-NULL name

1  2 
builtin/apply.c
diff --combined builtin/apply.c
index faf8e3088340ab2787c45b0e105a600fd54e51d3,f69a864abe8073b60a0cef743e98d249e3005796..0e9b631db6db422b1e938d6168b608e0a2ae8618
@@@ -16,9 -16,6 +16,9 @@@
  #include "dir.h"
  #include "diff.h"
  #include "parse-options.h"
 +#include "xdiff-interface.h"
 +#include "ll-merge.h"
 +#include "rerere.h"
  
  /*
   *  --check turns on checking that the working tree matches the
@@@ -49,7 -46,6 +49,7 @@@ static int apply_with_reject
  static int apply_verbosely;
  static int allow_overlap;
  static int no_add;
 +static int threeway;
  static const char *fake_ancestor;
  static int line_termination = '\n';
  static unsigned int p_context = UINT_MAX;
@@@ -188,6 -184,7 +188,6 @@@ struct patch 
        int is_new, is_delete;  /* -1 = unknown, 0 = false, 1 = true */
        int rejected;
        unsigned ws_rule;
 -      unsigned long deflate_origlen;
        int lines_added, lines_deleted;
        int score;
        unsigned int is_toplevel_relative:1;
        unsigned int is_copy:1;
        unsigned int is_rename:1;
        unsigned int recount:1;
 +      unsigned int conflicted_threeway:1;
 +      unsigned int direct_to_threeway:1;
        struct fragment *fragments;
        char *result;
        size_t resultsize;
        char old_sha1_prefix[41];
        char new_sha1_prefix[41];
        struct patch *next;
 +
 +      /* three-way fallback result */
 +      unsigned char threeway_stage[3][20];
  };
  
  static void free_fragment_list(struct fragment *list)
@@@ -379,8 -371,8 +379,8 @@@ static void prepare_image(struct image 
  static void clear_image(struct image *image)
  {
        free(image->buf);
 -      image->buf = NULL;
 -      image->len = 0;
 +      free(image->line_allocated);
 +      memset(image, 0, sizeof(*image));
  }
  
  /* fmt must contain _one_ %s and no other substitution */
@@@ -906,7 -898,7 +906,7 @@@ static void parse_traditional_patch(con
                        patch->old_name = name;
                } else {
                        patch->old_name = name;
-                       patch->new_name = xstrdup(name);
+                       patch->new_name = null_strdup(name);
                }
        }
        if (!name)
@@@ -1041,17 -1033,15 +1041,17 @@@ static int gitdiff_renamedst(const cha
  
  static int gitdiff_similarity(const char *line, struct patch *patch)
  {
 -      if ((patch->score = strtoul(line, NULL, 10)) == ULONG_MAX)
 -              patch->score = 0;
 +      unsigned long val = strtoul(line, NULL, 10);
 +      if (val <= 100)
 +              patch->score = val;
        return 0;
  }
  
  static int gitdiff_dissimilarity(const char *line, struct patch *patch)
  {
 -      if ((patch->score = strtoul(line, NULL, 10)) == ULONG_MAX)
 -              patch->score = 0;
 +      unsigned long val = strtoul(line, NULL, 10);
 +      if (val <= 100)
 +              patch->score = val;
        return 0;
  }
  
@@@ -1097,23 -1087,15 +1097,23 @@@ static int gitdiff_unrecognized(const c
        return -1;
  }
  
 -static const char *stop_at_slash(const char *line, int llen)
 +/*
 + * Skip p_value leading components from "line"; as we do not accept
 + * absolute paths, return NULL in that case.
 + */
 +static const char *skip_tree_prefix(const char *line, int llen)
  {
 -      int nslash = p_value;
 +      int nslash;
        int i;
  
 +      if (!p_value)
 +              return (llen && line[0] == '/') ? NULL : line;
 +
 +      nslash = p_value;
        for (i = 0; i < llen; i++) {
                int ch = line[i];
                if (ch == '/' && --nslash <= 0)
 -                      return &line[i];
 +                      return (i == 0) ? NULL : &line[i + 1];
        }
        return NULL;
  }
@@@ -1143,11 -1125,12 +1143,11 @@@ static char *git_header_name(const cha
                if (unquote_c_style(&first, line, &second))
                        goto free_and_fail1;
  
 -              /* advance to the first slash */
 -              cp = stop_at_slash(first.buf, first.len);
 -              /* we do not accept absolute paths */
 -              if (!cp || cp == first.buf)
 +              /* strip the a/b prefix including trailing slash */
 +              cp = skip_tree_prefix(first.buf, first.len);
 +              if (!cp)
                        goto free_and_fail1;
 -              strbuf_remove(&first, 0, cp + 1 - first.buf);
 +              strbuf_remove(&first, 0, cp - first.buf);
  
                /*
                 * second points at one past closing dq of name.
                if (*second == '"') {
                        if (unquote_c_style(&sp, second, NULL))
                                goto free_and_fail1;
 -                      cp = stop_at_slash(sp.buf, sp.len);
 -                      if (!cp || cp == sp.buf)
 +                      cp = skip_tree_prefix(sp.buf, sp.len);
 +                      if (!cp)
                                goto free_and_fail1;
                        /* They must match, otherwise ignore */
 -                      if (strcmp(cp + 1, first.buf))
 +                      if (strcmp(cp, first.buf))
                                goto free_and_fail1;
                        strbuf_release(&sp);
                        return strbuf_detach(&first, NULL);
                }
  
                /* unquoted second */
 -              cp = stop_at_slash(second, line + llen - second);
 -              if (!cp || cp == second)
 +              cp = skip_tree_prefix(second, line + llen - second);
 +              if (!cp)
                        goto free_and_fail1;
 -              cp++;
 -              if (line + llen - cp != first.len + 1 ||
 +              if (line + llen - cp != first.len ||
                    memcmp(first.buf, cp, first.len))
                        goto free_and_fail1;
                return strbuf_detach(&first, NULL);
        }
  
        /* unquoted first name */
 -      name = stop_at_slash(line, llen);
 -      if (!name || name == line)
 +      name = skip_tree_prefix(line, llen);
 +      if (!name)
                return NULL;
 -      name++;
  
        /*
         * since the first name is unquoted, a dq if exists must be
                        if (unquote_c_style(&sp, second, NULL))
                                goto free_and_fail2;
  
 -                      np = stop_at_slash(sp.buf, sp.len);
 -                      if (!np || np == sp.buf)
 +                      np = skip_tree_prefix(sp.buf, sp.len);
 +                      if (!np)
                                goto free_and_fail2;
 -                      np++;
  
                        len = sp.buf + sp.len - np;
                        if (len < second - name &&
                case '\n':
                        return NULL;
                case '\t': case ' ':
 -                      second = stop_at_slash(name + len, line_len - len);
 +                      /*
 +                       * Is this the separator between the preimage
 +                       * and the postimage pathname?  Again, we are
 +                       * only interested in the case where there is
 +                       * no rename, as this is only to set def_name
 +                       * and a rename patch has the names elsewhere
 +                       * in an unambiguous form.
 +                       */
 +                      if (!name[len + 1])
 +                              return NULL; /* no postimage name */
 +                      second = skip_tree_prefix(name + len + 1,
 +                                                line_len - (len + 1));
                        if (!second)
                                return NULL;
 -                      second++;
 -                      if (second[len] == '\n' && !strncmp(name, second, len)) {
 +                      /*
 +                       * Does len bytes starting at "name" and "second"
 +                       * (that are separated by one HT or SP we just
 +                       * found) exactly match?
 +                       */
 +                      if (second[len] == '\n' && !strncmp(name, second, len))
                                return xmemdupz(name, len);
 -                      }
                }
        }
  }
@@@ -1921,7 -1893,7 +1921,7 @@@ static int parse_binary(char *buffer, u
  }
  
  /*
 - * Read the patch text in "buffer" taht extends for "size" bytes; stop
 + * Read the patch text in "buffer" that extends for "size" bytes; stop
   * reading after seeing a single patch (i.e. changes to a single file).
   * Create fragments (i.e. patch hunks) and hang them to the given patch.
   * Return the number of bytes consumed, so that the caller can call us
@@@ -2097,7 -2069,7 +2097,7 @@@ static void update_pre_post_images(stru
                                   char *buf,
                                   size_t len, size_t postlen)
  {
 -      int i, ctx;
 +      int i, ctx, reduced;
        char *new, *old, *fixed;
        struct image fixed_preimage;
  
         * free "oldlines".
         */
        prepare_image(&fixed_preimage, buf, len, 1);
 -      assert(fixed_preimage.nr == preimage->nr);
 -      for (i = 0; i < preimage->nr; i++)
 +      assert(postlen
 +             ? fixed_preimage.nr == preimage->nr
 +             : fixed_preimage.nr <= preimage->nr);
 +      for (i = 0; i < fixed_preimage.nr; i++)
                fixed_preimage.line[i].flag = preimage->line[i].flag;
        free(preimage->line_allocated);
        *preimage = fixed_preimage;
  
        /*
         * 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 ignoring whitespace causes the update, since in this case
 -       * we could have e.g. tabs converted to multiple spaces.
 +       * done in-place when we are shrinking it with whitespace
 +       * fixing, but needs a new buffer when ignoring whitespace or
 +       * expanding leading tabs to spaces.
 +       *
         * We trust the caller to tell us if the update can be done
         * in place (postlen==0) or not.
         */
        else
                new = old;
        fixed = preimage->buf;
 -      for (i = ctx = 0; i < postimage->nr; i++) {
 +
 +      for (i = reduced = ctx = 0; i < postimage->nr; i++) {
                size_t len = postimage->line[i].len;
                if (!(postimage->line[i].flag & LINE_COMMON)) {
                        /* an added line -- no counterparts in preimage */
                        fixed += preimage->line[ctx].len;
                        ctx++;
                }
 -              if (preimage->nr <= ctx)
 -                      die(_("oops"));
 +
 +              /*
 +               * preimage is expected to run out, if the caller
 +               * fixed addition of trailing blank lines.
 +               */
 +              if (preimage->nr <= ctx) {
 +                      reduced++;
 +                      continue;
 +              }
  
                /* and copy it in, while fixing the line length */
                len = preimage->line[ctx].len;
  
        /* Fix the length of the whole thing */
        postimage->len = new - postimage->buf;
 +      postimage->nr -= reduced;
  }
  
  static int match_fragment(struct image *img,
        int i;
        char *fixed_buf, *buf, *orig, *target;
        struct strbuf fixed;
 -      size_t fixed_len;
 +      size_t fixed_len, postlen;
        int preimage_limit;
  
        if (preimage->nr + try_lno <= img->nr) {
        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;
                match = (tgtfix.len == fixed.len - fixstart &&
                         !memcmp(tgtfix.buf, fixed.buf + fixstart,
                                             fixed.len - fixstart));
 +              postlen += tgtfix.len;
  
                strbuf_release(&tgtfix);
                if (!match)
         * hunk match.  Update the context lines in the postimage.
         */
        fixed_buf = strbuf_detach(&fixed, &fixed_len);
 +      if (postlen < postimage->len)
 +              postlen = 0;
        update_pre_post_images(preimage, postimage,
 -                             fixed_buf, fixed_len, 0);
 +                             fixed_buf, fixed_len, postlen);
        return 1;
  
   unmatch_exit:
@@@ -2980,17 -2937,20 +2980,17 @@@ static int apply_fragments(struct imag
        return 0;
  }
  
 -static int read_file_or_gitlink(struct cache_entry *ce, struct strbuf *buf)
 +static int read_blob_object(struct strbuf *buf, const unsigned char *sha1, unsigned mode)
  {
 -      if (!ce)
 -              return 0;
 -
 -      if (S_ISGITLINK(ce->ce_mode)) {
 +      if (S_ISGITLINK(mode)) {
                strbuf_grow(buf, 100);
 -              strbuf_addf(buf, "Subproject commit %s\n", sha1_to_hex(ce->sha1));
 +              strbuf_addf(buf, "Subproject commit %s\n", sha1_to_hex(sha1));
        } else {
                enum object_type type;
                unsigned long sz;
                char *result;
  
 -              result = read_sha1_file(ce->sha1, &type, &sz);
 +              result = read_sha1_file(sha1, &type, &sz);
                if (!result)
                        return -1;
                /* XXX read_sha1_file NUL-terminates */
        return 0;
  }
  
 +static int read_file_or_gitlink(struct cache_entry *ce, struct strbuf *buf)
 +{
 +      if (!ce)
 +              return 0;
 +      return read_blob_object(buf, ce->sha1, ce->ce_mode);
 +}
 +
  static struct patch *in_fn_table(const char *name)
  {
        struct string_list_item *item;
   * item->util in the filename table records the status of the path.
   * Usually it points at a patch (whose result records the contents
   * of it after applying it), but it could be PATH_WAS_DELETED for a
 - * path that a previously applied patch has already removed.
 + * path that a previously applied patch has already removed, or
 + * PATH_TO_BE_DELETED for a path that a later patch would remove.
 + *
 + * The latter is needed to deal with a case where two paths A and B
 + * are swapped by first renaming A to B and then renaming B to A;
 + * moving A to B should not be prevented due to presence of B as we
 + * will remove it in a later patch.
   */
 - #define PATH_TO_BE_DELETED ((struct patch *) -2)
 +#define PATH_TO_BE_DELETED ((struct patch *) -2)
  #define PATH_WAS_DELETED ((struct patch *) -1)
  
  static int to_be_deleted(struct patch *patch)
@@@ -3084,324 -3031,127 +3084,324 @@@ static void prepare_fn_table(struct pat
        }
  }
  
 -static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *ce)
 +static int checkout_target(struct cache_entry *ce, struct stat *st)
 +{
 +      struct checkout costate;
 +
 +      memset(&costate, 0, sizeof(costate));
 +      costate.base_dir = "";
 +      costate.refresh_cache = 1;
 +      if (checkout_entry(ce, &costate, NULL) || lstat(ce->name, st))
 +              return error(_("cannot checkout %s"), ce->name);
 +      return 0;
 +}
 +
 +static struct patch *previous_patch(struct patch *patch, int *gone)
 +{
 +      struct patch *previous;
 +
 +      *gone = 0;
 +      if (patch->is_copy || patch->is_rename)
 +              return NULL; /* "git" patches do not depend on the order */
 +
 +      previous = in_fn_table(patch->old_name);
 +      if (!previous)
 +              return NULL;
 +
 +      if (to_be_deleted(previous))
 +              return NULL; /* the deletion hasn't happened yet */
 +
 +      if (was_deleted(previous))
 +              *gone = 1;
 +
 +      return previous;
 +}
 +
 +static int verify_index_match(struct cache_entry *ce, struct stat *st)
 +{
 +      if (S_ISGITLINK(ce->ce_mode)) {
 +              if (!S_ISDIR(st->st_mode))
 +                      return -1;
 +              return 0;
 +      }
 +      return ce_match_stat(ce, st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE);
 +}
 +
 +#define SUBMODULE_PATCH_WITHOUT_INDEX 1
 +
 +static int load_patch_target(struct strbuf *buf,
 +                           struct cache_entry *ce,
 +                           struct stat *st,
 +                           const char *name,
 +                           unsigned expected_mode)
 +{
 +      if (cached) {
 +              if (read_file_or_gitlink(ce, buf))
 +                      return error(_("read of %s failed"), name);
 +      } else if (name) {
 +              if (S_ISGITLINK(expected_mode)) {
 +                      if (ce)
 +                              return read_file_or_gitlink(ce, buf);
 +                      else
 +                              return SUBMODULE_PATCH_WITHOUT_INDEX;
 +              } else {
 +                      if (read_old_data(st, name, buf))
 +                              return error(_("read of %s failed"), name);
 +              }
 +      }
 +      return 0;
 +}
 +
 +/*
 + * We are about to apply "patch"; populate the "image" with the
 + * current version we have, from the working tree or from the index,
 + * depending on the situation e.g. --cached/--index.  If we are
 + * applying a non-git patch that incrementally updates the tree,
 + * we read from the result of a previous diff.
 + */
 +static int load_preimage(struct image *image,
 +                       struct patch *patch, struct stat *st, struct cache_entry *ce)
  {
        struct strbuf buf = STRBUF_INIT;
 -      struct image image;
        size_t len;
        char *img;
 -      struct patch *tpatch;
 +      struct patch *previous;
 +      int status;
  
 -      if (!(patch->is_copy || patch->is_rename) &&
 -          (tpatch = in_fn_table(patch->old_name)) != NULL && !to_be_deleted(tpatch)) {
 -              if (was_deleted(tpatch)) {
 -                      return error(_("patch %s has been renamed/deleted"),
 -                              patch->old_name);
 -              }
 +      previous = previous_patch(patch, &status);
 +      if (status)
 +              return error(_("path %s has been renamed/deleted"),
 +                           patch->old_name);
 +      if (previous) {
                /* We have a patched copy in memory; use that. */
 -              strbuf_add(&buf, tpatch->result, tpatch->resultsize);
 -      } else if (cached) {
 -              if (read_file_or_gitlink(ce, &buf))
 +              strbuf_add(&buf, previous->result, previous->resultsize);
 +      } else {
 +              status = load_patch_target(&buf, ce, st,
 +                                         patch->old_name, patch->old_mode);
 +              if (status < 0)
 +                      return status;
 +              else if (status == SUBMODULE_PATCH_WITHOUT_INDEX) {
 +                      /*
 +                       * There is no way to apply subproject
 +                       * patch without looking at the index.
 +                       * NEEDSWORK: shouldn't this be flagged
 +                       * as an error???
 +                       */
 +                      free_fragment_list(patch->fragments);
 +                      patch->fragments = NULL;
 +              } else if (status) {
                        return error(_("read of %s failed"), patch->old_name);
 -      } else if (patch->old_name) {
 -              if (S_ISGITLINK(patch->old_mode)) {
 -                      if (ce) {
 -                              read_file_or_gitlink(ce, &buf);
 -                      } else {
 -                              /*
 -                               * There is no way to apply subproject
 -                               * patch without looking at the index.
 -                               * NEEDSWORK: shouldn't this be flagged
 -                               * as an error???
 -                               */
 -                              free_fragment_list(patch->fragments);
 -                              patch->fragments = NULL;
 -                      }
 -              } else {
 -                      if (read_old_data(st, patch->old_name, &buf))
 -                              return error(_("read of %s failed"), patch->old_name);
                }
        }
  
        img = strbuf_detach(&buf, &len);
 -      prepare_image(&image, img, len, !patch->is_binary);
 +      prepare_image(image, img, len, !patch->is_binary);
 +      return 0;
 +}
  
 -      if (apply_fragments(&image, patch) < 0)
 -              return -1; /* note with --reject this succeeds. */
 -      patch->result = image.buf;
 -      patch->resultsize = image.len;
 -      add_to_fn_table(patch);
 -      free(image.line_allocated);
 +static int three_way_merge(struct image *image,
 +                         char *path,
 +                         const unsigned char *base,
 +                         const unsigned char *ours,
 +                         const unsigned char *theirs)
 +{
 +      mmfile_t base_file, our_file, their_file;
 +      mmbuffer_t result = { NULL };
 +      int status;
  
 -      if (0 < patch->is_delete && patch->resultsize)
 -              return error(_("removal patch leaves file contents"));
 +      read_mmblob(&base_file, base);
 +      read_mmblob(&our_file, ours);
 +      read_mmblob(&their_file, theirs);
 +      status = ll_merge(&result, path,
 +                        &base_file, "base",
 +                        &our_file, "ours",
 +                        &their_file, "theirs", NULL);
 +      free(base_file.ptr);
 +      free(our_file.ptr);
 +      free(their_file.ptr);
 +      if (status < 0 || !result.ptr) {
 +              free(result.ptr);
 +              return -1;
 +      }
 +      clear_image(image);
 +      image->buf = result.ptr;
 +      image->len = result.size;
 +
 +      return status;
 +}
 +
 +/*
 + * When directly falling back to add/add three-way merge, we read from
 + * the current contents of the new_name.  In no cases other than that
 + * this function will be called.
 + */
 +static int load_current(struct image *image, struct patch *patch)
 +{
 +      struct strbuf buf = STRBUF_INIT;
 +      int status, pos;
 +      size_t len;
 +      char *img;
 +      struct stat st;
 +      struct cache_entry *ce;
 +      char *name = patch->new_name;
 +      unsigned mode = patch->new_mode;
 +
 +      if (!patch->is_new)
 +              die("BUG: patch to %s is not a creation", patch->old_name);
 +
 +      pos = cache_name_pos(name, strlen(name));
 +      if (pos < 0)
 +              return error(_("%s: does not exist in index"), name);
 +      ce = active_cache[pos];
 +      if (lstat(name, &st)) {
 +              if (errno != ENOENT)
 +                      return error(_("%s: %s"), name, strerror(errno));
 +              if (checkout_target(ce, &st))
 +                      return -1;
 +      }
 +      if (verify_index_match(ce, &st))
 +              return error(_("%s: does not match index"), name);
  
 +      status = load_patch_target(&buf, ce, &st, name, mode);
 +      if (status < 0)
 +              return status;
 +      else if (status)
 +              return -1;
 +      img = strbuf_detach(&buf, &len);
 +      prepare_image(image, img, len, !patch->is_binary);
        return 0;
  }
  
 -static int check_to_create_blob(const char *new_name, int ok_if_exists)
 +static int try_threeway(struct image *image, struct patch *patch,
 +                      struct stat *st, struct cache_entry *ce)
  {
 -      struct stat nst;
 -      if (!lstat(new_name, &nst)) {
 -              if (S_ISDIR(nst.st_mode) || ok_if_exists)
 -                      return 0;
 -              /*
 -               * A leading component of new_name might be a symlink
 -               * that is going to be removed with this patch, but
 -               * still pointing at somewhere that has the path.
 -               * In such a case, path "new_name" does not exist as
 -               * far as git is concerned.
 -               */
 -              if (has_symlink_leading_path(new_name, strlen(new_name)))
 -                      return 0;
 +      unsigned char pre_sha1[20], post_sha1[20], our_sha1[20];
 +      struct strbuf buf = STRBUF_INIT;
 +      size_t len;
 +      int status;
 +      char *img;
 +      struct image tmp_image;
 +
 +      /* No point falling back to 3-way merge in these cases */
 +      if (patch->is_delete ||
 +          S_ISGITLINK(patch->old_mode) || S_ISGITLINK(patch->new_mode))
 +              return -1;
 +
 +      /* Preimage the patch was prepared for */
 +      if (patch->is_new)
 +              write_sha1_file("", 0, blob_type, pre_sha1);
 +      else if (get_sha1(patch->old_sha1_prefix, pre_sha1) ||
 +               read_blob_object(&buf, pre_sha1, patch->old_mode))
 +              return error("repository lacks the necessary blob to fall back on 3-way merge.");
 +
 +      fprintf(stderr, "Falling back to three-way merge...\n");
  
 -              return error(_("%s: already exists in working directory"), new_name);
 +      img = strbuf_detach(&buf, &len);
 +      prepare_image(&tmp_image, img, len, 1);
 +      /* Apply the patch to get the post image */
 +      if (apply_fragments(&tmp_image, patch) < 0) {
 +              clear_image(&tmp_image);
 +              return -1;
 +      }
 +      /* post_sha1[] is theirs */
 +      write_sha1_file(tmp_image.buf, tmp_image.len, blob_type, post_sha1);
 +      clear_image(&tmp_image);
 +
 +      /* our_sha1[] is ours */
 +      if (patch->is_new) {
 +              if (load_current(&tmp_image, patch))
 +                      return error("cannot read the current contents of '%s'",
 +                                   patch->new_name);
 +      } else {
 +              if (load_preimage(&tmp_image, patch, st, ce))
 +                      return error("cannot read the current contents of '%s'",
 +                                   patch->old_name);
 +      }
 +      write_sha1_file(tmp_image.buf, tmp_image.len, blob_type, our_sha1);
 +      clear_image(&tmp_image);
 +
 +      /* in-core three-way merge between post and our using pre as base */
 +      status = three_way_merge(image, patch->new_name,
 +                               pre_sha1, our_sha1, post_sha1);
 +      if (status < 0) {
 +              fprintf(stderr, "Failed to fall back on three-way merge...\n");
 +              return status;
 +      }
 +
 +      if (status) {
 +              patch->conflicted_threeway = 1;
 +              if (patch->is_new)
 +                      hashclr(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);
 +              fprintf(stderr, "Applied patch to '%s' with conflicts.\n", patch->new_name);
 +      } else {
 +              fprintf(stderr, "Applied patch to '%s' cleanly.\n", patch->new_name);
        }
 -      else if ((errno != ENOENT) && (errno != ENOTDIR))
 -              return error("%s: %s", new_name, strerror(errno));
        return 0;
  }
  
 -static int verify_index_match(struct cache_entry *ce, struct stat *st)
 +static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *ce)
  {
 -      if (S_ISGITLINK(ce->ce_mode)) {
 -              if (!S_ISDIR(st->st_mode))
 +      struct image image;
 +
 +      if (load_preimage(&image, patch, st, ce) < 0)
 +              return -1;
 +
 +      if (patch->direct_to_threeway ||
 +          apply_fragments(&image, patch) < 0) {
 +              /* Note: with --reject, apply_fragments() returns 0 */
 +              if (!threeway || try_threeway(&image, patch, st, ce) < 0)
                        return -1;
 -              return 0;
        }
 -      return ce_match_stat(ce, st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE);
 +      patch->result = image.buf;
 +      patch->resultsize = image.len;
 +      add_to_fn_table(patch);
 +      free(image.line_allocated);
 +
 +      if (0 < patch->is_delete && patch->resultsize)
 +              return error(_("removal patch leaves file contents"));
 +
 +      return 0;
  }
  
 +/*
 + * If "patch" that we are looking at modifies or deletes what we have,
 + * we would want it not to lose any local modification we have, either
 + * in the working tree or in the index.
 + *
 + * This also decides if a non-git patch is a creation patch or a
 + * modification to an existing empty file.  We do not check the state
 + * of the current tree for a creation patch in this function; the caller
 + * check_patch() separately makes sure (and errors out otherwise) that
 + * the path the patch creates does not exist in the current tree.
 + */
  static int check_preimage(struct patch *patch, struct cache_entry **ce, struct stat *st)
  {
        const char *old_name = patch->old_name;
 -      struct patch *tpatch = NULL;
 -      int stat_ret = 0;
 +      struct patch *previous = NULL;
 +      int stat_ret = 0, status;
        unsigned st_mode = 0;
  
 -      /*
 -       * Make sure that we do not have local modifications from the
 -       * index when we are looking at the index.  Also make sure
 -       * we have the preimage file to be patched in the work tree,
 -       * unless --cached, which tells git to apply only in the index.
 -       */
        if (!old_name)
                return 0;
  
        assert(patch->is_new <= 0);
 +      previous = previous_patch(patch, &status);
  
 -      if (!(patch->is_copy || patch->is_rename) &&
 -          (tpatch = in_fn_table(old_name)) != NULL && !to_be_deleted(tpatch)) {
 -              if (was_deleted(tpatch))
 -                      return error(_("%s: has been deleted/renamed"), old_name);
 -              st_mode = tpatch->new_mode;
 +      if (status)
 +              return error(_("path %s has been renamed/deleted"), old_name);
 +      if (previous) {
 +              st_mode = previous->new_mode;
        } else if (!cached) {
                stat_ret = lstat(old_name, st);
                if (stat_ret && errno != ENOENT)
                        return error(_("%s: %s"), old_name, strerror(errno));
        }
  
 -      if (to_be_deleted(tpatch))
 -              tpatch = NULL;
 -
 -      if (check_index && !tpatch) {
 +      if (check_index && !previous) {
                int pos = cache_name_pos(old_name, strlen(old_name));
                if (pos < 0) {
                        if (patch->is_new < 0)
                }
                *ce = active_cache[pos];
                if (stat_ret < 0) {
 -                      struct checkout costate;
 -                      /* checkout */
 -                      memset(&costate, 0, sizeof(costate));
 -                      costate.base_dir = "";
 -                      costate.refresh_cache = 1;
 -                      if (checkout_entry(*ce, &costate, NULL) ||
 -                          lstat(old_name, st))
 +                      if (checkout_target(*ce, st))
                                return -1;
                }
                if (!cached && verify_index_match(*ce, st))
                return error(_("%s: %s"), old_name, strerror(errno));
        }
  
 -      if (!cached && !tpatch)
 +      if (!cached && !previous)
                st_mode = ce_mode_from_stat(*ce, st->st_mode);
  
        if (patch->is_new < 0)
        return 0;
  }
  
 +
 +#define EXISTS_IN_INDEX 1
 +#define EXISTS_IN_WORKTREE 2
 +
 +static int check_to_create(const char *new_name, int ok_if_exists)
 +{
 +      struct stat nst;
 +
 +      if (check_index &&
 +          cache_name_pos(new_name, strlen(new_name)) >= 0 &&
 +          !ok_if_exists)
 +              return EXISTS_IN_INDEX;
 +      if (cached)
 +              return 0;
 +
 +      if (!lstat(new_name, &nst)) {
 +              if (S_ISDIR(nst.st_mode) || ok_if_exists)
 +                      return 0;
 +              /*
 +               * A leading component of new_name might be a symlink
 +               * that is going to be removed with this patch, but
 +               * still pointing at somewhere that has the path.
 +               * In such a case, path "new_name" does not exist as
 +               * far as git is concerned.
 +               */
 +              if (has_symlink_leading_path(new_name, strlen(new_name)))
 +                      return 0;
 +
 +              return EXISTS_IN_WORKTREE;
 +      } else if ((errno != ENOENT) && (errno != ENOTDIR)) {
 +              return error("%s: %s", new_name, strerror(errno));
 +      }
 +      return 0;
 +}
 +
  /*
   * Check and apply the patch in-core; leave the result in patch->result
   * for the caller to write it out to the final destination.
@@@ -3504,45 -3225,31 +3504,45 @@@ static int check_patch(struct patch *pa
                return status;
        old_name = patch->old_name;
  
 +      /*
 +       * A type-change diff is always split into a patch to delete
 +       * old, immediately followed by a patch to create new (see
 +       * diff.c::run_diff()); in such a case it is Ok that the entry
 +       * to be deleted by the previous patch is still in the working
 +       * tree and in the index.
 +       *
 +       * A patch to swap-rename between A and B would first rename A
 +       * to B and then rename B to A.  While applying the first one,
 +       * the presence of B should not stop A from getting renamed to
 +       * B; ask to_be_deleted() about the later rename.  Removal of
 +       * B and rename from A to B is handled the same way by asking
 +       * was_deleted().
 +       */
        if ((tpatch = in_fn_table(new_name)) &&
 -                      (was_deleted(tpatch) || to_be_deleted(tpatch)))
 -              /*
 -               * A type-change diff is always split into a patch to
 -               * delete old, immediately followed by a patch to
 -               * create new (see diff.c::run_diff()); in such a case
 -               * it is Ok that the entry to be deleted by the
 -               * previous patch is still in the working tree and in
 -               * the index.
 -               */
 +          (was_deleted(tpatch) || to_be_deleted(tpatch)))
                ok_if_exists = 1;
        else
                ok_if_exists = 0;
  
        if (new_name &&
 -          ((0 < patch->is_new) | (0 < patch->is_rename) | patch->is_copy)) {
 -              if (check_index &&
 -                  cache_name_pos(new_name, strlen(new_name)) >= 0 &&
 -                  !ok_if_exists)
 +          ((0 < patch->is_new) || patch->is_rename || patch->is_copy)) {
 +              int err = check_to_create(new_name, ok_if_exists);
 +
 +              if (err && threeway) {
 +                      patch->direct_to_threeway = 1;
 +              } else switch (err) {
 +              case 0:
 +                      break; /* happy */
 +              case EXISTS_IN_INDEX:
                        return error(_("%s: already exists in index"), new_name);
 -              if (!cached) {
 -                      int err = check_to_create_blob(new_name, ok_if_exists);
 -                      if (err)
 -                              return err;
 +                      break;
 +              case EXISTS_IN_WORKTREE:
 +                      return error(_("%s: already exists in working directory"),
 +                                   new_name);
 +              default:
 +                      return err;
                }
 +
                if (!patch->new_mode) {
                        if (0 < patch->is_new)
                                patch->new_mode = S_IFREG | 0644;
@@@ -3604,40 -3311,6 +3604,40 @@@ static int get_current_sha1(const char 
        return 0;
  }
  
 +static int preimage_sha1_in_gitlink_patch(struct patch *p, unsigned char sha1[20])
 +{
 +      /*
 +       * A usable gitlink patch has only one fragment (hunk) that looks like:
 +       * @@ -1 +1 @@
 +       * -Subproject commit <old sha1>
 +       * +Subproject commit <new sha1>
 +       * or
 +       * @@ -1 +0,0 @@
 +       * -Subproject commit <old sha1>
 +       * for a removal patch.
 +       */
 +      struct fragment *hunk = p->fragments;
 +      static const char heading[] = "-Subproject commit ";
 +      char *preimage;
 +
 +      if (/* does the patch have only one hunk? */
 +          hunk && !hunk->next &&
 +          /* is its preimage one line? */
 +          hunk->oldpos == 1 && hunk->oldlines == 1 &&
 +          /* does preimage begin with the heading? */
 +          (preimage = memchr(hunk->patch, '\n', hunk->size)) != NULL &&
 +          !prefixcmp(++preimage, heading) &&
 +          /* does it record full SHA-1? */
 +          !get_sha1_hex(preimage + sizeof(heading) - 1, sha1) &&
 +          preimage[sizeof(heading) + 40 - 1] == '\n' &&
 +          /* does the abbreviated name on the index line agree with it? */
 +          !prefixcmp(preimage + sizeof(heading) - 1, p->old_sha1_prefix))
 +              return 0; /* it all looks fine */
 +
 +      /* we may have full object name on the index line */
 +      return get_sha1_hex(p->old_sha1_prefix, sha1);
 +}
 +
  /* Build an index that contains the just the files needed for a 3way merge */
  static void build_fake_ancestor(struct patch *list, const char *filename)
  {
         * worth showing the new sha1 prefix, but until then...
         */
        for (patch = list; patch; patch = patch->next) {
 -              const unsigned char *sha1_ptr;
                unsigned char sha1[20];
                struct cache_entry *ce;
                const char *name;
                name = patch->old_name ? patch->old_name : patch->new_name;
                if (0 < patch->is_new)
                        continue;
 -              else if (get_sha1(patch->old_sha1_prefix, sha1))
 -                      /* git diff has no index line for mode/type changes */
 -                      if (!patch->lines_added && !patch->lines_deleted) {
 -                              if (get_current_sha1(patch->old_name, sha1))
 -                                      die("mode change for %s, which is not "
 -                                              "in current HEAD", name);
 -                              sha1_ptr = sha1;
 -                      } else
 -                              die("sha1 information is lacking or useless "
 -                                      "(%s).", name);
 -              else
 -                      sha1_ptr = sha1;
  
 -              ce = make_cache_entry(patch->old_mode, sha1_ptr, name, 0, 0);
 +              if (S_ISGITLINK(patch->old_mode)) {
 +                      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",
 +                                  name);
 +              } else if (!get_sha1_blob(patch->old_sha1_prefix, sha1)) {
 +                      ; /* ok */
 +              } else if (!patch->lines_added && !patch->lines_deleted) {
 +                      /* mode-only change: update the current */
 +                      if (get_current_sha1(patch->old_name, sha1))
 +                              die("mode change for %s, which is not "
 +                                  "in current HEAD", name);
 +              } else
 +                      die("sha1 information is lacking or useless "
 +                          "(%s).", name);
 +
 +              ce = make_cache_entry(patch->old_mode, sha1, name, 0, 0);
                if (!ce)
                        die(_("make_cache_entry failed for path '%s'"), name);
                if (add_index_entry(&result, ce, ADD_CACHE_OK_TO_ADD))
@@@ -3841,8 -3510,7 +3841,8 @@@ static void add_index_file(const char *
        ce = xcalloc(1, ce_size);
        memcpy(ce->name, path, namelen);
        ce->ce_mode = create_ce_mode(mode);
 -      ce->ce_flags = namelen;
 +      ce->ce_flags = create_ce_flags(0);
 +      ce->ce_namelen = namelen;
        if (S_ISGITLINK(mode)) {
                const char *s = buf;
  
@@@ -3944,33 -3612,6 +3944,33 @@@ static void create_one_file(char *path
        die_errno(_("unable to write file '%s' mode %o"), path, mode);
  }
  
 +static void add_conflicted_stages_file(struct patch *patch)
 +{
 +      int stage, namelen;
 +      unsigned ce_size, mode;
 +      struct cache_entry *ce;
 +
 +      if (!update_index)
 +              return;
 +      namelen = strlen(patch->new_name);
 +      ce_size = cache_entry_size(namelen);
 +      mode = patch->new_mode ? patch->new_mode : (S_IFREG | 0644);
 +
 +      remove_file_from_cache(patch->new_name);
 +      for (stage = 1; stage < 4; stage++) {
 +              if (is_null_sha1(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]);
 +              if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD) < 0)
 +                      die(_("unable to add cache entry for %s"), patch->new_name);
 +      }
 +}
 +
  static void create_file(struct patch *patch)
  {
        char *path = patch->new_name;
        if (!mode)
                mode = S_IFREG | 0644;
        create_one_file(path, mode, buf, size);
 -      add_index_file(path, mode, buf, size);
 +
 +      if (patch->conflicted_threeway)
 +              add_conflicted_stages_file(patch);
 +      else
 +              add_index_file(path, mode, buf, size);
  }
  
  /* phase zero is to remove, phase one is to create */
@@@ -4087,7 -3724,6 +4087,7 @@@ static int write_out_results(struct pat
        int phase;
        int errs = 0;
        struct patch *l;
 +      struct string_list cpath = STRING_LIST_INIT_DUP;
  
        for (phase = 0; phase < 2; phase++) {
                l = list;
                                errs = 1;
                        else {
                                write_out_one_result(l, phase);
 -                              if (phase == 1 && write_out_one_reject(l))
 -                                      errs = 1;
 +                              if (phase == 1) {
 +                                      if (write_out_one_reject(l))
 +                                              errs = 1;
 +                                      if (l->conflicted_threeway) {
 +                                              string_list_append(&cpath, l->new_name);
 +                                              errs = 1;
 +                                      }
 +                              }
                        }
                        l = l->next;
                }
        }
 +
 +      if (cpath.nr) {
 +              struct string_list_item *item;
 +
 +              sort_string_list(&cpath);
 +              for_each_string_list_item(item, &cpath)
 +                      fprintf(stderr, "U %s\n", item->string);
 +              string_list_clear(&cpath, 0);
 +
 +              rerere(0);
 +      }
 +
        return errs;
  }
  
@@@ -4242,12 -3860,8 +4242,12 @@@ static int apply_patch(int fd, const ch
            !apply_with_reject)
                exit(1);
  
 -      if (apply && write_out_results(list))
 -              exit(1);
 +      if (apply && write_out_results(list)) {
 +              if (apply_with_reject)
 +                      exit(1);
 +              /* with --3way, we still need to write the index out */
 +              return 1;
 +      }
  
        if (fake_ancestor)
                build_fake_ancestor(list, fake_ancestor);
@@@ -4369,7 -3983,7 +4369,7 @@@ int cmd_apply(int argc, const char **ar
                OPT_NOOP_NOARG(0, "allow-binary-replacement"),
                OPT_NOOP_NOARG(0, "binary"),
                OPT_BOOLEAN(0, "numstat", &numstat,
 -                      N_("shows number of added and deleted lines in decimal notation")),
 +                      N_("show number of added and deleted lines in decimal notation")),
                OPT_BOOLEAN(0, "summary", &summary,
                        N_("instead of applying the patch, output a summary for the input")),
                OPT_BOOLEAN(0, "check", &check,
                        N_("apply a patch without touching the working tree")),
                OPT_BOOLEAN(0, "apply", &force_apply,
                        N_("also apply the patch (use with --stat/--summary/--check)")),
 +              OPT_BOOL('3', "3way", &threeway,
 +                       N_( "attempt three-way merge if a patch does not apply")),
                OPT_FILENAME(0, "build-fake-ancestor", &fake_ancestor,
                        N_("build a temporary index based on embedded index information")),
                { OPTION_CALLBACK, 'z', NULL, NULL, NULL,
        argc = parse_options(argc, argv, prefix, builtin_apply_options,
                        apply_usage, 0);
  
 +      if (apply_with_reject && threeway)
 +              die("--reject and --3way cannot be used together.");
 +      if (cached && threeway)
 +              die("--cached and --3way cannot be used together.");
 +      if (threeway) {
 +              if (is_not_gitdir)
 +                      die(_("--3way outside a repository"));
 +              check_index = 1;
 +      }
        if (apply_with_reject)
                apply = apply_verbosely = 1;
        if (!force_apply && (diffstat || numstat || summary || check || fake_ancestor))