http: respect protocol.*.allow=user for http-alternates
[gitweb.git] / merge-recursive.c
index b446df9c1da0db2e21918f188b85536960d306f2..a52139eadad264296de781a542c474aa7cd62bb6 100644 (file)
 static struct tree *shift_tree_object(struct tree *one, struct tree *two,
                                      const char *subtree_shift)
 {
-       unsigned char shifted[20];
+       struct object_id shifted;
 
        if (!*subtree_shift) {
-               shift_tree(one->object.sha1, two->object.sha1, shifted, 0);
+               shift_tree(&one->object.oid, &two->object.oid, &shifted, 0);
        } else {
-               shift_tree_by(one->object.sha1, two->object.sha1, shifted,
+               shift_tree_by(&one->object.oid, &two->object.oid, &shifted,
                              subtree_shift);
        }
-       if (!hashcmp(two->object.sha1, shifted))
+       if (!oidcmp(&two->object.oid, &shifted))
                return two;
-       return lookup_tree(shifted);
+       return lookup_tree(shifted.hash);
 }
 
 static struct commit *make_virtual_commit(struct tree *tree, const char *comment)
 {
        struct commit *commit = alloc_commit_node();
-       struct merge_remote_desc *desc = xmalloc(sizeof(*desc));
 
-       desc->name = comment;
-       desc->obj = (struct object *)commit;
+       set_merge_remote_desc(commit, comment, (struct object *)commit);
        commit->tree = tree;
-       commit->util = desc;
        commit->object.parsed = 1;
        return commit;
 }
@@ -184,7 +181,7 @@ static void output_commit_title(struct merge_options *o, struct commit *commit)
        if (commit->util)
                printf("virtual %s\n", merge_remote_util(commit)->name);
        else {
-               printf("%s ", find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV));
+               printf("%s ", find_unique_abbrev(commit->object.oid.hash, DEFAULT_ABBREV));
                if (parse_commit(commit) != 0)
                        printf(_("(bad commit)\n"));
                else {
@@ -202,12 +199,21 @@ static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
                const char *path, int stage, int refresh, int options)
 {
        struct cache_entry *ce;
-       ce = make_cache_entry(mode, sha1 ? sha1 : null_sha1, path, stage,
-                             (refresh ? (CE_MATCH_REFRESH |
-                                         CE_MATCH_IGNORE_MISSING) : 0 ));
+       int ret;
+
+       ce = make_cache_entry(mode, sha1 ? sha1 : null_sha1, path, stage, 0);
        if (!ce)
                return error(_("addinfo_cache failed for path '%s'"), path);
-       return add_cache_entry(ce, options);
+
+       ret = add_cache_entry(ce, options);
+       if (refresh) {
+               struct cache_entry *nce;
+
+               nce = refresh_cache_entry(ce, CE_MATCH_REFRESH | CE_MATCH_IGNORE_MISSING);
+               if (nce != ce)
+                       ret = add_cache_entry(nce, options);
+       }
+       return ret;
 }
 
 static void init_tree_desc_from_tree(struct tree_desc *desc, struct tree *tree)
@@ -313,11 +319,11 @@ static struct stage_data *insert_stage_data(const char *path,
 {
        struct string_list_item *item;
        struct stage_data *e = xcalloc(1, sizeof(struct stage_data));
-       get_tree_entry(o->object.sha1, path,
+       get_tree_entry(o->object.oid.hash, path,
                        e->stages[1].sha, &e->stages[1].mode);
-       get_tree_entry(a->object.sha1, path,
+       get_tree_entry(a->object.oid.hash, path,
                        e->stages[2].sha, &e->stages[2].mode);
-       get_tree_entry(b->object.sha1, path,
+       get_tree_entry(b->object.oid.hash, path,
                        e->stages[3].sha, &e->stages[3].mode);
        item = string_list_insert(entries, path);
        item->util = e;
@@ -400,7 +406,7 @@ static void record_df_conflict_files(struct merge_options *o,
         * and the file need to be present, then the D/F file will be
         * reinstated with a new unique name at the time it is processed.
         */
-       struct string_list df_sorted_entries;
+       struct string_list df_sorted_entries = STRING_LIST_INIT_NODUP;
        const char *last_file = NULL;
        int last_len = 0;
        int i;
@@ -413,7 +419,6 @@ static void record_df_conflict_files(struct merge_options *o,
                return;
 
        /* Ensure D/F conflicts are adjacent in the entries list. */
-       memset(&df_sorted_entries, 0, sizeof(struct string_list));
        for (i = 0; i < entries->nr; i++) {
                struct string_list_item *next = &entries->items[i];
                string_list_append(&df_sorted_entries, next->string)->util =
@@ -482,6 +487,9 @@ static struct string_list *get_renames(struct merge_options *o,
        struct diff_options opts;
 
        renames = xcalloc(1, sizeof(struct string_list));
+       if (!o->detect_rename)
+               return renames;
+
        diff_setup(&opts);
        DIFF_OPT_SET(&opts, RECURSIVE);
        DIFF_OPT_CLR(&opts, RENAME_EMPTY);
@@ -493,7 +501,7 @@ static struct string_list *get_renames(struct merge_options *o,
        opts.show_rename_progress = o->show_rename_progress;
        opts.output_format = DIFF_FORMAT_NO_OUTPUT;
        diff_setup_done(&opts);
-       diff_tree_sha1(o_tree->object.sha1, tree->object.sha1, "", &opts);
+       diff_tree_sha1(o_tree->object.oid.hash, tree->object.oid.hash, "", &opts);
        diffcore_std(&opts);
        if (opts.needed_rename_limit > o->needed_rename_limit)
                o->needed_rename_limit = opts.needed_rename_limit;
@@ -619,7 +627,7 @@ static char *unique_path(struct merge_options *o, const char *path, const char *
        base_len = newpath.len;
        while (string_list_has_string(&o->current_file_set, newpath.buf) ||
               string_list_has_string(&o->current_directory_set, newpath.buf) ||
-              file_exists(newpath.buf)) {
+              (!o->call_depth && file_exists(newpath.buf))) {
                strbuf_setlen(&newpath, base_len);
                strbuf_addf(&newpath, "_%d", suffix++);
        }
@@ -630,25 +638,24 @@ static char *unique_path(struct merge_options *o, const char *path, const char *
 
 static int dir_in_way(const char *path, int check_working_copy)
 {
-       int pos, pathlen = strlen(path);
-       char *dirpath = xmalloc(pathlen + 2);
+       int pos;
+       struct strbuf dirpath = STRBUF_INIT;
        struct stat st;
 
-       strcpy(dirpath, path);
-       dirpath[pathlen] = '/';
-       dirpath[pathlen+1] = '\0';
+       strbuf_addstr(&dirpath, path);
+       strbuf_addch(&dirpath, '/');
 
-       pos = cache_name_pos(dirpath, pathlen+1);
+       pos = cache_name_pos(dirpath.buf, dirpath.len);
 
        if (pos < 0)
                pos = -1 - pos;
        if (pos < active_nr &&
-           !strncmp(dirpath, active_cache[pos]->name, pathlen+1)) {
-               free(dirpath);
+           !strncmp(dirpath.buf, active_cache[pos]->name, dirpath.len)) {
+               strbuf_release(&dirpath);
                return 1;
        }
 
-       free(dirpath);
+       strbuf_release(&dirpath);
        return check_working_copy && !lstat(path, &st) && S_ISDIR(st.st_mode);
 }
 
@@ -1232,8 +1239,8 @@ static void conflict_rename_rename_2to1(struct merge_options *o,
               a->path, c1->path, ci->branch1,
               b->path, c2->path, ci->branch2);
 
-       remove_file(o, 1, a->path, would_lose_untracked(a->path));
-       remove_file(o, 1, b->path, would_lose_untracked(b->path));
+       remove_file(o, 1, a->path, o->call_depth || would_lose_untracked(a->path));
+       remove_file(o, 1, b->path, o->call_depth || would_lose_untracked(b->path));
 
        mfi_c1 = merge_file_special_markers(o, a, c1, &ci->ren1_other,
                                            o->branch1, c1->path,
@@ -1771,8 +1778,6 @@ static int process_entry(struct merge_options *o,
                        output(o, 1, _("CONFLICT (%s): There is a directory with name %s in %s. "
                               "Adding %s as %s"),
                               conf, path, other_branch, path, new_path);
-                       if (o->call_depth)
-                               remove_file_from_cache(path);
                        update_file(o, 0, sha, mode, new_path);
                        if (o->call_depth)
                                remove_file_from_cache(path);
@@ -1813,7 +1818,7 @@ int merge_trees(struct merge_options *o,
                common = shift_tree_object(head, common, o->subtree_shift);
        }
 
-       if (sha_eq(common->object.sha1, merge->object.sha1)) {
+       if (sha_eq(common->object.oid.hash, merge->object.oid.hash)) {
                output(o, 0, _("Already up-to-date!"));
                *result = head;
                return 1;
@@ -1824,8 +1829,8 @@ int merge_trees(struct merge_options *o,
        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));
+                           oid_to_hex(&head->object.oid),
+                           oid_to_hex(&merge->object.oid));
                else
                        exit(128);
        }
@@ -2040,6 +2045,7 @@ void init_merge_options(struct merge_options *o)
        o->diff_rename_limit = -1;
        o->merge_rename_limit = -1;
        o->renormalize = 0;
+       o->detect_rename = 1;
        merge_recursive_config(o);
        if (getenv("GIT_MERGE_VERBOSITY"))
                o->verbosity =
@@ -2089,9 +2095,17 @@ int parse_merge_opt(struct merge_options *o, const char *s)
                o->renormalize = 1;
        else if (!strcmp(s, "no-renormalize"))
                o->renormalize = 0;
-       else if (skip_prefix(s, "rename-threshold=", &arg)) {
+       else if (!strcmp(s, "no-renames"))
+               o->detect_rename = 0;
+       else if (!strcmp(s, "find-renames")) {
+               o->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;
        }
        else
                return -1;