grep.c: remove implicit dependency on the_index
[gitweb.git] / merge-recursive.c
index 3d6b34b4f7438d2408780d73095e9a1bd0cd4338..e5243dbc542d786a645a9c038c855a6ca30acaba 100644 (file)
@@ -320,7 +320,7 @@ static int add_cacheinfo(struct merge_options *o,
        struct cache_entry *ce;
        int ret;
 
-       ce = make_cache_entry(mode, oid ? oid->hash : null_sha1, path, stage, 0);
+       ce = make_cache_entry(&the_index, mode, oid ? oid : &null_oid, path, stage, 0);
        if (!ce)
                return err(o, _("add_cacheinfo failed for path '%s'; merge aborting."), path);
 
@@ -328,7 +328,7 @@ static int add_cacheinfo(struct merge_options *o,
        if (refresh) {
                struct cache_entry *nce;
 
-               nce = refresh_cache_entry(ce, CE_MATCH_REFRESH | CE_MATCH_IGNORE_MISSING);
+               nce = refresh_cache_entry(&the_index, ce, CE_MATCH_REFRESH | CE_MATCH_IGNORE_MISSING);
                if (!nce)
                        return err(o, _("add_cacheinfo failed to refresh for path '%s'; merge aborting."), path);
                if (nce != ce)
@@ -966,7 +966,7 @@ static int update_file_flags(struct merge_options *o,
                }
                if (S_ISREG(mode)) {
                        struct strbuf strbuf = STRBUF_INIT;
-                       if (convert_to_working_tree(path, buf, size, &strbuf)) {
+                       if (convert_to_working_tree(&the_index, path, buf, size, &strbuf)) {
                                free(buf);
                                size = strbuf.len;
                                buf = strbuf_detach(&strbuf, NULL);
@@ -2869,12 +2869,19 @@ static int detect_and_process_renames(struct merge_options *o,
        head_pairs = get_diffpairs(o, common, head);
        merge_pairs = get_diffpairs(o, common, merge);
 
-       dir_re_head = get_directory_renames(head_pairs, head);
-       dir_re_merge = get_directory_renames(merge_pairs, merge);
+       if (o->detect_directory_renames) {
+               dir_re_head = get_directory_renames(head_pairs, head);
+               dir_re_merge = get_directory_renames(merge_pairs, merge);
 
-       handle_directory_level_conflicts(o,
-                                        dir_re_head, head,
-                                        dir_re_merge, merge);
+               handle_directory_level_conflicts(o,
+                                                dir_re_head, head,
+                                                dir_re_merge, merge);
+       } else {
+               dir_re_head  = xmalloc(sizeof(*dir_re_head));
+               dir_re_merge = xmalloc(sizeof(*dir_re_merge));
+               dir_rename_init(dir_re_head);
+               dir_rename_init(dir_re_merge);
+       }
 
        ri->head_renames  = get_renames(o, head_pairs,
                                        dir_re_merge, dir_re_head, head,
@@ -3070,10 +3077,26 @@ static int merge_content(struct merge_options *o,
        if (mfi.clean &&
            was_tracked_and_matches(o, path, &mfi.oid, mfi.mode) &&
            !df_conflict_remains) {
+               int pos;
+               struct cache_entry *ce;
+
                output(o, 3, _("Skipped %s (merged same as existing)"), path);
                if (add_cacheinfo(o, mfi.mode, &mfi.oid, path,
                                  0, (!o->call_depth && !is_dirty), 0))
                        return -1;
+               /*
+                * However, add_cacheinfo() will delete the old cache entry
+                * and add a new one.  We need to copy over any skip_worktree
+                * flag to avoid making the file appear as if it were
+                * deleted by the user.
+                */
+               pos = index_name_pos(&o->orig_index, path, strlen(path));
+               ce = o->orig_index.cache[pos];
+               if (ce_skip_worktree(ce)) {
+                       pos = index_name_pos(&the_index, path, strlen(path));
+                       ce = the_index.cache[pos];
+                       ce->ce_flags |= CE_SKIP_WORKTREE;
+               }
                return mfi.clean;
        }
 
@@ -3281,6 +3304,13 @@ int merge_trees(struct merge_options *o,
                struct tree **result)
 {
        int code, clean;
+       struct strbuf sb = STRBUF_INIT;
+
+       if (!o->call_depth && index_has_changes(&the_index, head, &sb)) {
+               err(o, _("Your local changes to the following files would be overwritten by merge:\n  %s"),
+                   sb.buf);
+               return -1;
+       }
 
        if (o->subtree_shift) {
                merge = shift_tree_object(head, merge, o->subtree_shift);
@@ -3288,13 +3318,6 @@ 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;
@@ -3570,6 +3593,7 @@ void init_merge_options(struct merge_options *o)
        o->renormalize = 0;
        o->diff_detect_rename = -1;
        o->merge_detect_rename = -1;
+       o->detect_directory_renames = 1;
        merge_recursive_config(o);
        merge_verbosity = getenv("GIT_MERGE_VERBOSITY");
        if (merge_verbosity)