cvsexportcommit -p : fix the usage of git-apply -C.
[gitweb.git] / merge-recursive.c
index fa320eb6b1a9e257167e7f843fe36cbdfd908726..e1aebd77274bb75e9fda95b2d64f69a9dda4276a 100644 (file)
@@ -278,8 +278,16 @@ static struct tree *git_write_tree(void)
 {
        struct tree *result = NULL;
 
-       if (unmerged_index())
+       if (unmerged_index()) {
+               int i;
+               output(0, "There are unmerged index entries:");
+               for (i = 0; i < active_nr; i++) {
+                       struct cache_entry *ce = active_cache[i];
+                       if (ce_stage(ce))
+                               output(0, "%d %.*s", ce_stage(ce), ce_namelen(ce), ce->name);
+               }
                return NULL;
+       }
 
        if (!active_cache_tree)
                active_cache_tree = cache_tree();
@@ -386,7 +394,7 @@ struct rename
 };
 
 /*
- * Get information of all renames which occured between 'o_tree' and
+ * Get information of all renames which occurred between 'o_tree' and
  * 'tree'. We need the three trees in the merge ('o_tree', 'a_tree' and
  * 'b_tree') to be able to associate the correct cache entries with
  * the rename information. 'tree' is always equal to either a_tree or b_tree.
@@ -560,17 +568,17 @@ static void update_file_flags(const unsigned char *sha,
                update_wd = 0;
 
        if (update_wd) {
-               char type[20];
+               enum object_type type;
                void *buf;
                unsigned long size;
 
-               buf = read_sha1_file(sha, type, &size);
+               buf = read_sha1_file(sha, &type, &size);
                if (!buf)
                        die("cannot read object %s '%s'", sha1_to_hex(sha), path);
-               if (strcmp(type, blob_type) != 0)
+               if (type != OBJ_BLOB)
                        die("blob expected for %s '%s'", sha1_to_hex(sha), path);
 
-               if (S_ISREG(mode)) {
+               if (S_ISREG(mode) || (!has_symlinks && S_ISLNK(mode))) {
                        int fd;
                        if (mkdir_p(path, 0777))
                                die("failed to create path %s: %s", path, strerror(errno));
@@ -589,8 +597,9 @@ static void update_file_flags(const unsigned char *sha,
                        memcpy(lnk, buf, size);
                        lnk[size] = '\0';
                        mkdir_p(path, 0777);
-                       unlink(lnk);
+                       unlink(path);
                        symlink(lnk, path);
+                       free(lnk);
                } else
                        die("do not know what to do with %06o %s '%s'",
                            mode, sha1_to_hex(sha), path);
@@ -620,7 +629,7 @@ struct merge_file_info
 static void fill_mm(const unsigned char *sha1, mmfile_t *mm)
 {
        unsigned long size;
-       char type[20];
+       enum object_type type;
 
        if (!hashcmp(sha1, null_sha1)) {
                mm->ptr = xstrdup("");
@@ -628,8 +637,8 @@ static void fill_mm(const unsigned char *sha1, mmfile_t *mm)
                return;
        }
 
-       mm->ptr = read_sha1_file(sha1, type, &size);
-       if (!mm->ptr || strcmp(type, blob_type))
+       mm->ptr = read_sha1_file(sha1, &type, &size);
+       if (!mm->ptr || type != OBJ_BLOB)
                die("unable to read blob object %s", sha1_to_hex(sha1));
        mm->size = size;
 }
@@ -734,8 +743,19 @@ static void conflict_rename_rename(struct rename *ren1,
                       ren2_dst, branch1, dst_name2);
                remove_file(0, ren2_dst, 0);
        }
-       update_stages(dst_name1, NULL, ren1->pair->two, NULL, 1);
-       update_stages(dst_name2, NULL, NULL, ren2->pair->two, 1);
+       if (index_only) {
+               remove_file_from_cache(dst_name1);
+               remove_file_from_cache(dst_name2);
+               /*
+                * Uncomment to leave the conflicting names in the resulting tree
+                *
+                * update_file(0, ren1->pair->two->sha1, ren1->pair->two->mode, dst_name1);
+                * update_file(0, ren2->pair->two->sha1, ren2->pair->two->mode, dst_name2);
+                */
+       } else {
+               update_stages(dst_name1, NULL, ren1->pair->two, NULL, 1);
+               update_stages(dst_name2, NULL, NULL, ren2->pair->two, 1);
+       }
        while (delp--)
                free(del[delp]);
 }
@@ -851,10 +871,16 @@ static int process_renames(struct path_list *a_renames,
                        if (strcmp(ren1_dst, ren2_dst) != 0) {
                                clean_merge = 0;
                                output(1, "CONFLICT (rename/rename): "
-                                      "Rename %s->%s in branch %s "
-                                      "rename %s->%s in %s",
+                                      "Rename \"%s\"->\"%s\" in branch \"%s\" "
+                                      "rename \"%s\"->\"%s\" in \"%s\"%s",
                                       src, ren1_dst, branch1,
-                                      src, ren2_dst, branch2);
+                                      src, ren2_dst, branch2,
+                                      index_only ? " (left unresolved)": "");
+                               if (index_only) {
+                                       remove_file_from_cache(src);
+                                       update_file(0, ren1->pair->one->sha1,
+                                                   ren1->pair->one->mode, src);
+                               }
                                conflict_rename_rename(ren1, branch1, ren2, branch2);
                        } else {
                                struct merge_file_info mfi;
@@ -891,7 +917,7 @@ static int process_renames(struct path_list *a_renames,
                        struct diff_filespec src_other, dst_other;
                        int try_merge, stage = a_renames == renames1 ? 3: 2;
 
-                       remove_file(1, ren1_src, index_only);
+                       remove_file(1, ren1_src, index_only || stage == 3);
 
                        hashcpy(src_other.sha1, ren1->src_entry->stages[stage].sha);
                        src_other.mode = ren1->src_entry->stages[stage].mode;
@@ -1175,7 +1201,7 @@ static struct commit_list *reverse_commit_list(struct commit_list *list)
 
 /*
  * Merge the commits h1 and h2, return the resulting virtual
- * commit object and a flag indicating the cleaness of the merge.
+ * commit object and a flag indicating the cleanness of the merge.
  */
 static int merge(struct commit *h1,
                 struct commit *h2,
@@ -1213,7 +1239,7 @@ static int merge(struct commit *h1,
 
                tree->object.parsed = 1;
                tree->object.type = OBJ_TREE;
-               write_sha1_file(NULL, 0, tree_type, tree->object.sha1);
+               pretend_sha1_file(NULL, 0, OBJ_TREE, tree->object.sha1);
                merged_common_ancestors = make_virtual_commit(tree, "ancestor");
        }
 
@@ -1222,8 +1248,8 @@ static int merge(struct commit *h1,
                /*
                 * When the merge fails, the result contains files
                 * with conflict markers. The cleanness flag is
-                * ignored, it was never acutally used, as result of
-                * merge_trees has always overwritten it: the commited
+                * ignored, it was never actually used, as result of
+                * merge_trees has always overwritten it: the committed
                 * "conflicts" were already resolved.
                 */
                discard_cache();