Reset possible helper before reusing remote structure
[gitweb.git] / merge-recursive.c
index d415c4188d181fbdc765fff90fbbc4897ced53ad..dd4fbd0e6bc22f2e5f5667205b47165f8aebbbd0 100644 (file)
@@ -3,6 +3,7 @@
  * Fredrik Kuivinen.
  * The thieves were Alex Riesen and Johannes Schindelin, in June/July 2006
  */
+#include "advice.h"
 #include "cache.h"
 #include "cache-tree.h"
 #include "commit.h"
@@ -86,6 +87,7 @@ static void flush_output(struct merge_options *o)
        }
 }
 
+__attribute__((format (printf, 3, 4)))
 static void output(struct merge_options *o, int v, const char *fmt, ...)
 {
        int len;
@@ -181,6 +183,7 @@ static int git_merge_trees(int index_only,
        opts.fn = threeway_merge;
        opts.src_index = &the_index;
        opts.dst_index = &the_index;
+       opts.msgs = get_porcelain_error_msgs();
 
        init_tree_desc_from_tree(t+0, common);
        init_tree_desc_from_tree(t+1, head);
@@ -201,7 +204,8 @@ struct tree *write_tree_from_memory(struct merge_options *o)
                for (i = 0; i < active_nr; i++) {
                        struct cache_entry *ce = active_cache[i];
                        if (ce_stage(ce))
-                               output(o, 0, "%d %.*s", ce_stage(ce), ce_namelen(ce), ce->name);
+                               output(o, 0, "%d %.*s", ce_stage(ce),
+                                      (int)ce_namelen(ce), ce->name);
                }
                return NULL;
        }
@@ -952,9 +956,31 @@ static int process_renames(struct merge_options *o,
                                       "%s added in %s",
                                       ren1_src, ren1_dst, branch1,
                                       ren1_dst, branch2);
-                               new_path = unique_path(o, ren1_dst, branch2);
-                               output(o, 1, "Adding as %s instead", new_path);
-                               update_file(o, 0, dst_other.sha1, dst_other.mode, new_path);
+                               if (o->call_depth) {
+                                       struct merge_file_info mfi;
+                                       struct diff_filespec one, a, b;
+
+                                       one.path = a.path = b.path =
+                                               (char *)ren1_dst;
+                                       hashcpy(one.sha1, null_sha1);
+                                       one.mode = 0;
+                                       hashcpy(a.sha1, ren1->pair->two->sha1);
+                                       a.mode = ren1->pair->two->mode;
+                                       hashcpy(b.sha1, dst_other.sha1);
+                                       b.mode = dst_other.mode;
+                                       mfi = merge_file(o, &one, &a, &b,
+                                                        branch1,
+                                                        branch2);
+                                       output(o, 1, "Adding merged %s", ren1_dst);
+                                       update_file(o, 0,
+                                                   mfi.sha,
+                                                   mfi.mode,
+                                                   ren1_dst);
+                               } else {
+                                       new_path = unique_path(o, ren1_dst, branch2);
+                                       output(o, 1, "Adding as %s instead", new_path);
+                                       update_file(o, 0, dst_other.sha1, dst_other.mode, new_path);
+                               }
                        } else if ((item = string_list_lookup(ren1_dst, renames2Dst))) {
                                ren2 = item->util;
                                clean_merge = 0;
@@ -1145,6 +1171,28 @@ static int process_entry(struct merge_options *o,
        return clean_merge;
 }
 
+struct unpack_trees_error_msgs get_porcelain_error_msgs(void)
+{
+       struct unpack_trees_error_msgs msgs = {
+               /* would_overwrite */
+               "Your local changes to '%s' would be overwritten by merge.  Aborting.",
+               /* not_uptodate_file */
+               "Your local changes to '%s' would be overwritten by merge.  Aborting.",
+               /* not_uptodate_dir */
+               "Updating '%s' would lose untracked files in it.  Aborting.",
+               /* would_lose_untracked */
+               "Untracked working tree file '%s' would be %s by merge.  Aborting",
+               /* bind_overlap -- will not happen here */
+               NULL,
+       };
+       if (advice_commit_before_merge) {
+               msgs.would_overwrite = msgs.not_uptodate_file =
+                       "Your local changes to '%s' would be overwritten by merge.  Aborting.\n"
+                       "Please, commit your changes or stash them before you can merge.";
+       }
+       return msgs;
+}
+
 int merge_trees(struct merge_options *o,
                struct tree *head,
                struct tree *merge,
@@ -1166,10 +1214,14 @@ int merge_trees(struct merge_options *o,
 
        code = git_merge_trees(o->call_depth, common, head, merge);
 
-       if (code != 0)
-               die("merging of trees %s and %s failed",
-                   sha1_to_hex(head->object.sha1),
-                   sha1_to_hex(merge->object.sha1));
+       if (code != 0) {
+               if (show(o, 4) || o->call_depth)
+                       die("merging of trees %s and %s failed",
+                           sha1_to_hex(head->object.sha1),
+                           sha1_to_hex(merge->object.sha1));
+               else
+                       exit(128);
+       }
 
        if (unmerged_cache()) {
                struct string_list *entries, *re_head, *re_merge;