diff options
Diffstat (limited to 'merge-recursive.c')
-rw-r--r-- | merge-recursive.c | 74 |
1 files changed, 43 insertions, 31 deletions
diff --git a/merge-recursive.c b/merge-recursive.c index 1c9c30db6c..65cb5d6c1f 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -26,17 +26,17 @@ 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) @@ -184,7 +184,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 { @@ -313,11 +313,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; @@ -482,6 +482,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 +496,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; @@ -611,7 +614,6 @@ static char *unique_path(struct merge_options *o, const char *path, const char * { struct strbuf newpath = STRBUF_INIT; int suffix = 0; - struct stat st; size_t base_len; strbuf_addf(&newpath, "%s~", path); @@ -620,7 +622,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) || - lstat(newpath.buf, &st) == 0) { + (!o->call_depth && file_exists(newpath.buf))) { strbuf_setlen(&newpath, base_len); strbuf_addf(&newpath, "_%d", suffix++); } @@ -631,25 +633,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); } @@ -1233,8 +1234,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, @@ -1532,13 +1533,17 @@ static int read_sha1_strbuf(const unsigned char *sha1, struct strbuf *dst) } static int blob_unchanged(const unsigned char *o_sha, + unsigned o_mode, const unsigned char *a_sha, + unsigned a_mode, int renormalize, const char *path) { struct strbuf o = STRBUF_INIT; struct strbuf a = STRBUF_INIT; int ret = 0; /* assume changed for safety */ + if (a_mode != o_mode) + return 0; if (sha_eq(o_sha, a_sha)) return 1; if (!renormalize) @@ -1724,8 +1729,8 @@ static int process_entry(struct merge_options *o, } else if (o_sha && (!a_sha || !b_sha)) { /* Case A: Deleted in one */ if ((!a_sha && !b_sha) || - (!b_sha && blob_unchanged(o_sha, a_sha, normalize, path)) || - (!a_sha && blob_unchanged(o_sha, b_sha, normalize, path))) { + (!b_sha && blob_unchanged(o_sha, o_mode, a_sha, a_mode, normalize, path)) || + (!a_sha && blob_unchanged(o_sha, o_mode, b_sha, b_mode, normalize, path))) { /* Deleted in both or deleted in one and * unchanged in the other */ if (a_sha) @@ -1768,8 +1773,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); @@ -1810,7 +1813,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; @@ -1821,8 +1824,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); } @@ -2037,6 +2040,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 = @@ -2086,9 +2090,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; |