doc hash-function-transition: clarify how older gits die on NewHash
[gitweb.git] / merge-recursive.c
index a4c280dfc78e943ec541f83ccb0b39921ccdf2b2..869092f7b9bc0ce1104a1c43c7201acdee2eb4f8 100644 (file)
@@ -513,6 +513,25 @@ static void record_df_conflict_files(struct merge_options *o,
 
 struct rename {
        struct diff_filepair *pair;
+       /*
+        * Purpose of src_entry and dst_entry:
+        *
+        * If 'before' is renamed to 'after' then src_entry will contain
+        * the versions of 'before' from the merge_base, HEAD, and MERGE in
+        * stages 1, 2, and 3; dst_entry will contain the respective
+        * versions of 'after' in corresponding locations.  Thus, we have a
+        * total of six modes and oids, though some will be null.  (Stage 0
+        * is ignored; we're interested in handling conflicts.)
+        *
+        * Since we don't turn on break-rewrites by default, neither
+        * src_entry nor dst_entry can have all three of their stages have
+        * non-null oids, meaning at most four of the six will be non-null.
+        * Also, since this is a rename, both src_entry and dst_entry will
+        * have at least one non-null oid, meaning at least two will be
+        * non-null.  Of the six oids, a typical rename will have three be
+        * non-null.  Only two implies a rename/delete, and four implies a
+        * rename/add.
+        */
        struct stage_data *src_entry;
        struct stage_data *dst_entry;
        unsigned processed:1;
@@ -646,7 +665,7 @@ static int remove_file(struct merge_options *o, int clean,
                if (ignore_case) {
                        struct cache_entry *ce;
                        ce = cache_file_exists(path, strlen(path), ignore_case);
-                       if (ce && ce_stage(ce) == 0)
+                       if (ce && ce_stage(ce) == 0 && strcmp(path, ce->name))
                                return 0;
                }
                if (remove_path(path))
@@ -1009,8 +1028,9 @@ static int merge_file_1(struct merge_options *o,
                        if ((merge_status < 0) || !result_buf.ptr)
                                ret = err(o, _("Failed to execute internal merge"));
 
-                       if (!ret && write_sha1_file(result_buf.ptr, result_buf.size,
-                                                   blob_type, result->oid.hash))
+                       if (!ret &&
+                           write_object_file(result_buf.ptr, result_buf.size,
+                                             blob_type, &result->oid))
                                ret = err(o, _("Unable to add %s to database"),
                                          a->path);
 
@@ -1026,10 +1046,19 @@ static int merge_file_1(struct merge_options *o,
                                                       &b->oid,
                                                       !o->call_depth);
                } else if (S_ISLNK(a->mode)) {
-                       oidcpy(&result->oid, &a->oid);
-
-                       if (!oid_eq(&a->oid, &b->oid))
-                               result->clean = 0;
+                       switch (o->recursive_variant) {
+                       case MERGE_RECURSIVE_NORMAL:
+                               oidcpy(&result->oid, &a->oid);
+                               if (!oid_eq(&a->oid, &b->oid))
+                                       result->clean = 0;
+                               break;
+                       case MERGE_RECURSIVE_OURS:
+                               oidcpy(&result->oid, &a->oid);
+                               break;
+                       case MERGE_RECURSIVE_THEIRS:
+                               oidcpy(&result->oid, &b->oid);
+                               break;
+                       }
                } else
                        die("BUG: unsupported object type in the tree");
        }
@@ -1952,6 +1981,13 @@ int merge_trees(struct merge_options *o,
        }
 
        if (oid_eq(&common->object.oid, &merge->object.oid)) {
+               struct strbuf sb = STRBUF_INIT;
+
+               if (!o->call_depth && index_has_changes(&sb)) {
+                       err(o, _("Dirty index: cannot merge (dirty: %s)"),
+                           sb.buf);
+                       return 0;
+               }
                output(o, 0, _("Already up to date!"));
                *result = head;
                return 1;
@@ -1982,10 +2018,10 @@ int merge_trees(struct merge_options *o,
                get_files_dirs(o, merge);
 
                entries = get_unmerged();
-               record_df_conflict_files(o, entries);
                re_head  = get_renames(o, head, common, head, merge, entries);
                re_merge = get_renames(o, merge, common, head, merge, entries);
                clean = process_renames(o, re_head, re_merge);
+               record_df_conflict_files(o, entries);
                if (clean < 0)
                        goto cleanup;
                for (i = entries->nr-1; 0 <= i; i--) {
@@ -2054,7 +2090,7 @@ int merge_recursive(struct merge_options *o,
 {
        struct commit_list *iter;
        struct commit *merged_common_ancestors;
-       struct tree *mrtree = mrtree;
+       struct tree *mrtree;
        int clean;
 
        if (show(o, 4)) {
@@ -2182,11 +2218,13 @@ int merge_recursive_generic(struct merge_options *o,
        hold_locked_index(&lock, LOCK_DIE_ON_ERROR);
        clean = merge_recursive(o, head_commit, next_commit, ca,
                        result);
-       if (clean < 0)
+       if (clean < 0) {
+               rollback_lock_file(&lock);
                return clean;
+       }
 
-       if (active_cache_changed &&
-           write_locked_index(&the_index, &lock, COMMIT_LOCK))
+       if (write_locked_index(&the_index, &lock,
+                              COMMIT_LOCK | SKIP_IF_UNCHANGED))
                return err(o, _("Unable to write index."));
 
        return clean ? 0 : 1;