Merge branch 'bp/merge-rename-config'
authorJunio C Hamano <gitster@pobox.com>
Wed, 30 May 2018 05:04:04 +0000 (14:04 +0900)
committerJunio C Hamano <gitster@pobox.com>
Wed, 30 May 2018 05:04:04 +0000 (14:04 +0900)
With merge.renames configuration set to false, the recursive merge
strategy can be told not to spend cycles trying to find renamed
paths and merge them accordingly.

* bp/merge-rename-config:
merge: pass aggressive when rename detection is turned off
merge: add merge.renames config setting
merge: update documentation for {merge,diff}.renameLimit

1  2 
diff.c
merge-recursive.c
diff --combined diff.c
index 4753170fe1296c87579db3376aa5a625b0042f19,5dfc24aa6dfd1222e350069eb7da862f86aac0bc..b2840231f36e8425bf06438ac4bd236a5ed7dc86
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -177,7 -177,7 +177,7 @@@ static int parse_submodule_params(struc
        return 0;
  }
  
static int git_config_rename(const char *var, const char *value)
+ int git_config_rename(const char *var, const char *value)
  {
        if (!value)
                return DIFF_DETECT_RENAME;
@@@ -3638,8 -3638,7 +3638,8 @@@ int diff_populate_filespec(struct diff_
        else {
                enum object_type type;
                if (size_only || (flags & CHECK_BINARY)) {
 -                      type = oid_object_info(&s->oid, &s->size);
 +                      type = oid_object_info(the_repository, &s->oid,
 +                                             &s->size);
                        if (type < 0)
                                die("unable to read %s",
                                    oid_to_hex(&s->oid));
diff --combined merge-recursive.c
index 35df695fa420073d04997a3792f1c3a45d278b5d,680e01226b2ecb68d2b8199378a055ce622f0cb7..8d96e94bd5911376bec5df3fecb1ab502691060a
@@@ -162,7 -162,7 +162,7 @@@ static struct commit *make_virtual_comm
        struct commit *commit = alloc_commit_node();
  
        set_merge_remote_desc(commit, comment, (struct object *)commit);
 -      commit->tree = tree;
 +      commit->maybe_tree = tree;
        commit->object.parsed = 1;
        return commit;
  }
@@@ -356,6 -356,7 +356,7 @@@ static int git_merge_trees(struct merge
        o->unpack_opts.fn = threeway_merge;
        o->unpack_opts.src_index = &the_index;
        o->unpack_opts.dst_index = &tmp_index;
+       o->unpack_opts.aggressive = !merge_detect_rename(o);
        setup_unpack_trees_porcelain(&o->unpack_opts, "merge");
  
        init_tree_desc_from_tree(t+0, common);
@@@ -1603,7 -1604,15 +1604,15 @@@ static struct diff_queue_struct *get_di
        diff_setup(&opts);
        opts.flags.recursive = 1;
        opts.flags.rename_empty = 0;
-       opts.detect_rename = DIFF_DETECT_RENAME;
+       opts.detect_rename = merge_detect_rename(o);
+       /*
+        * We do not have logic to handle the detection of copies.  In
+        * fact, it may not even make sense to add such logic: would we
+        * really want a change to a base file to be propagated through
+        * multiple other files by a merge?
+        */
+       if (opts.detect_rename > DIFF_DETECT_RENAME)
+               opts.detect_rename = DIFF_DETECT_RENAME;
        opts.rename_limit = o->merge_rename_limit >= 0 ? o->merge_rename_limit :
                            o->diff_rename_limit >= 0 ? o->diff_rename_limit :
                            1000;
@@@ -2643,7 -2652,7 +2652,7 @@@ static int handle_renames(struct merge_
        ri->head_renames = NULL;
        ri->merge_renames = NULL;
  
-       if (!o->detect_rename)
+       if (!merge_detect_rename(o))
                return 1;
  
        head_pairs = get_diffpairs(o, common, head);
@@@ -3246,8 -3255,7 +3255,8 @@@ int merge_recursive(struct merge_option
                read_cache();
  
        o->ancestor = "merged common ancestors";
 -      clean = merge_trees(o, h1->tree, h2->tree, merged_common_ancestors->tree,
 +      clean = merge_trees(o, get_commit_tree(h1), get_commit_tree(h2),
 +                          get_commit_tree(merged_common_ancestors),
                            &mrtree);
        if (clean < 0) {
                flush_output(o);
@@@ -3325,9 -3333,18 +3334,18 @@@ int merge_recursive_generic(struct merg
  
  static void merge_recursive_config(struct merge_options *o)
  {
+       char *value = NULL;
        git_config_get_int("merge.verbosity", &o->verbosity);
        git_config_get_int("diff.renamelimit", &o->diff_rename_limit);
        git_config_get_int("merge.renamelimit", &o->merge_rename_limit);
+       if (!git_config_get_string("diff.renames", &value)) {
+               o->diff_detect_rename = git_config_rename("diff.renames", value);
+               free(value);
+       }
+       if (!git_config_get_string("merge.renames", &value)) {
+               o->merge_detect_rename = git_config_rename("merge.renames", value);
+               free(value);
+       }
        git_config(git_xmerge_config, NULL);
  }
  
@@@ -3340,7 -3357,8 +3358,8 @@@ void init_merge_options(struct merge_op
        o->diff_rename_limit = -1;
        o->merge_rename_limit = -1;
        o->renormalize = 0;
-       o->detect_rename = 1;
+       o->diff_detect_rename = -1;
+       o->merge_detect_rename = -1;
        merge_recursive_config(o);
        merge_verbosity = getenv("GIT_MERGE_VERBOSITY");
        if (merge_verbosity)
@@@ -3391,16 -3409,16 +3410,16 @@@ int parse_merge_opt(struct merge_option
        else if (!strcmp(s, "no-renormalize"))
                o->renormalize = 0;
        else if (!strcmp(s, "no-renames"))
-               o->detect_rename = 0;
+               o->merge_detect_rename = 0;
        else if (!strcmp(s, "find-renames")) {
-               o->detect_rename = 1;
+               o->merge_detect_rename = 1;
                o->rename_score = 0;
        }
        else if (skip_prefix(s, "find-renames=", &arg) ||
                 skip_prefix(s, "rename-threshold=", &arg)) {
                if ((o->rename_score = parse_rename_score(&arg)) == -1 || *arg != 0)
                        return -1;
-               o->detect_rename = 1;
+               o->merge_detect_rename = 1;
        }
        else
                return -1;