X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=builtin-merge-recursive.c;h=43e55bf90154c51b94527b2ab7eb7c60fe36e9ec;hb=2c47789d817aaf745a5ce5d5f79619c634cc8566;hp=910c0d20e7ba1128c705a49bfd9966212c5420b2;hpb=32a27b56662b1c7aa13f98c95f170ba5290c7559;p=git.git diff --git a/builtin-merge-recursive.c b/builtin-merge-recursive.c index 910c0d20e..43e55bf90 100644 --- a/builtin-merge-recursive.c +++ b/builtin-merge-recursive.c @@ -13,7 +13,7 @@ #include "diffcore.h" #include "tag.h" #include "unpack-trees.h" -#include "path-list.h" +#include "string-list.h" #include "xdiff-interface.h" #include "ll-merge.h" #include "interpolate.h" @@ -42,14 +42,6 @@ static struct tree *shift_tree_object(struct tree *one, struct tree *two) * - *(int *)commit->object.sha1 set to the virtual id. */ -static unsigned commit_list_count(const struct commit_list *l) -{ - unsigned c = 0; - for (; l; l = l->next ) - c++; - return c; -} - static struct commit *make_virtual_commit(struct tree *tree, const char *comment) { struct commit *commit = xcalloc(1, sizeof(struct commit)); @@ -87,12 +79,13 @@ struct stage_data unsigned processed:1; }; -static struct path_list current_file_set = {NULL, 0, 0, 1}; -static struct path_list current_directory_set = {NULL, 0, 0, 1}; +static struct string_list current_file_set = {NULL, 0, 0, 1}; +static struct string_list current_directory_set = {NULL, 0, 0, 1}; static int call_depth = 0; static int verbosity = 2; -static int rename_limit = -1; +static int diff_rename_limit = -1; +static int merge_rename_limit = -1; static int buffer_output = 1; static struct strbuf obuf = STRBUF_INIT; @@ -255,7 +248,7 @@ struct tree *write_tree_from_memory(void) static int save_files_dirs(const unsigned char *sha1, const char *base, int baselen, const char *path, - unsigned int mode, int stage) + unsigned int mode, int stage, void *context) { int len = strlen(path); char *newpath = xmalloc(baselen + len + 1); @@ -264,9 +257,9 @@ static int save_files_dirs(const unsigned char *sha1, newpath[baselen + len] = '\0'; if (S_ISDIR(mode)) - path_list_insert(newpath, ¤t_directory_set); + string_list_insert(newpath, ¤t_directory_set); else - path_list_insert(newpath, ¤t_file_set); + string_list_insert(newpath, ¤t_file_set); free(newpath); return READ_TREE_RECURSIVE; @@ -275,7 +268,7 @@ static int save_files_dirs(const unsigned char *sha1, static int get_files_dirs(struct tree *tree) { int n; - if (read_tree_recursive(tree, "", 0, 0, NULL, save_files_dirs) != 0) + if (read_tree_recursive(tree, "", 0, 0, NULL, save_files_dirs, NULL)) return 0; n = current_file_set.nr + current_directory_set.nr; return n; @@ -287,9 +280,9 @@ static int get_files_dirs(struct tree *tree) */ static struct stage_data *insert_stage_data(const char *path, struct tree *o, struct tree *a, struct tree *b, - struct path_list *entries) + struct string_list *entries) { - struct path_list_item *item; + struct string_list_item *item; struct stage_data *e = xcalloc(1, sizeof(struct stage_data)); get_tree_entry(o->object.sha1, path, e->stages[1].sha, &e->stages[1].mode); @@ -297,7 +290,7 @@ static struct stage_data *insert_stage_data(const char *path, e->stages[2].sha, &e->stages[2].mode); get_tree_entry(b->object.sha1, path, e->stages[3].sha, &e->stages[3].mode); - item = path_list_insert(path, entries); + item = string_list_insert(path, entries); item->util = e; return e; } @@ -306,23 +299,23 @@ static struct stage_data *insert_stage_data(const char *path, * Create a dictionary mapping file names to stage_data objects. The * dictionary contains one entry for every path with a non-zero stage entry. */ -static struct path_list *get_unmerged(void) +static struct string_list *get_unmerged(void) { - struct path_list *unmerged = xcalloc(1, sizeof(struct path_list)); + struct string_list *unmerged = xcalloc(1, sizeof(struct string_list)); int i; - unmerged->strdup_paths = 1; + unmerged->strdup_strings = 1; for (i = 0; i < active_nr; i++) { - struct path_list_item *item; + struct string_list_item *item; struct stage_data *e; struct cache_entry *ce = active_cache[i]; if (!ce_stage(ce)) continue; - item = path_list_lookup(ce->name, unmerged); + item = string_list_lookup(ce->name, unmerged); if (!item) { - item = path_list_insert(ce->name, unmerged); + item = string_list_insert(ce->name, unmerged); item->util = xcalloc(1, sizeof(struct stage_data)); } e = item->util; @@ -347,28 +340,31 @@ struct rename * 'b_tree') to be able to associate the correct cache entries with * the rename information. 'tree' is always equal to either a_tree or b_tree. */ -static struct path_list *get_renames(struct tree *tree, +static struct string_list *get_renames(struct tree *tree, struct tree *o_tree, struct tree *a_tree, struct tree *b_tree, - struct path_list *entries) + struct string_list *entries) { int i; - struct path_list *renames; + struct string_list *renames; struct diff_options opts; - renames = xcalloc(1, sizeof(struct path_list)); + renames = xcalloc(1, sizeof(struct string_list)); diff_setup(&opts); DIFF_OPT_SET(&opts, RECURSIVE); opts.detect_rename = DIFF_DETECT_RENAME; - opts.rename_limit = rename_limit; + opts.rename_limit = merge_rename_limit >= 0 ? merge_rename_limit : + diff_rename_limit >= 0 ? diff_rename_limit : + 500; + opts.warn_on_too_large_rename = 1; opts.output_format = DIFF_FORMAT_NO_OUTPUT; if (diff_setup_done(&opts) < 0) die("diff setup failed"); diff_tree_sha1(o_tree->object.sha1, tree->object.sha1, "", &opts); diffcore_std(&opts); for (i = 0; i < diff_queued_diff.nr; ++i) { - struct path_list_item *item; + struct string_list_item *item; struct rename *re; struct diff_filepair *pair = diff_queued_diff.queue[i]; if (pair->status != 'R') { @@ -378,20 +374,20 @@ static struct path_list *get_renames(struct tree *tree, re = xmalloc(sizeof(*re)); re->processed = 0; re->pair = pair; - item = path_list_lookup(re->pair->one->path, entries); + item = string_list_lookup(re->pair->one->path, entries); if (!item) re->src_entry = insert_stage_data(re->pair->one->path, o_tree, a_tree, b_tree, entries); else re->src_entry = item->util; - item = path_list_lookup(re->pair->two->path, entries); + item = string_list_lookup(re->pair->two->path, entries); if (!item) re->dst_entry = insert_stage_data(re->pair->two->path, o_tree, a_tree, b_tree, entries); else re->dst_entry = item->util; - item = path_list_insert(pair->one->path, renames); + item = string_list_insert(pair->one->path, renames); item->util = re; } opts.output_format = DIFF_FORMAT_NO_OUTPUT; @@ -468,24 +464,15 @@ static char *unique_path(const char *path, const char *branch) for (; *p; ++p) if ('/' == *p) *p = '_'; - while (path_list_has_path(¤t_file_set, newpath) || - path_list_has_path(¤t_directory_set, newpath) || + while (string_list_has_string(¤t_file_set, newpath) || + string_list_has_string(¤t_directory_set, newpath) || lstat(newpath, &st) == 0) sprintf(p, "_%d", suffix++); - path_list_insert(newpath, ¤t_file_set); + string_list_insert(newpath, ¤t_file_set); return newpath; } -static int mkdir_p(const char *path, unsigned long mode) -{ - /* path points to cache entries, so xstrdup before messing with it */ - char *buf = xstrdup(path); - int result = safe_create_leading_directories(buf); - free(buf); - return result; -} - static void flush_buffer(int fd, const char *buf, unsigned long size) { while (size > 0) { @@ -508,7 +495,7 @@ static int make_room_for_path(const char *path) int status; const char *msg = "failed to create path '%s'%s"; - status = mkdir_p(path, 0777); + status = safe_create_leading_directories_const(path); if (status) { if (status == -3) { /* something else exists */ @@ -551,9 +538,19 @@ static void update_file_flags(const unsigned char *sha, die("cannot read object %s '%s'", sha1_to_hex(sha), path); if (type != OBJ_BLOB) die("blob expected for %s '%s'", sha1_to_hex(sha), path); + if (S_ISREG(mode)) { + struct strbuf strbuf; + strbuf_init(&strbuf, 0); + if (convert_to_working_tree(path, buf, size, &strbuf)) { + free(buf); + size = strbuf.len; + buf = strbuf_detach(&strbuf, NULL); + } + } if (make_room_for_path(path) < 0) { update_wd = 0; + free(buf); goto update_index; } if (S_ISREG(mode) || (!has_symlinks && S_ISLNK(mode))) { @@ -569,13 +566,14 @@ static void update_file_flags(const unsigned char *sha, close(fd); } else if (S_ISLNK(mode)) { char *lnk = xmemdupz(buf, size); - mkdir_p(path, 0777); + safe_create_leading_directories_const(path); unlink(path); symlink(lnk, path); free(lnk); } else die("do not know what to do with %06o %s '%s'", mode, sha1_to_hex(sha), path); + free(buf); } update_index: if (update_cache) @@ -729,13 +727,13 @@ static void conflict_rename_rename(struct rename *ren1, const char *ren2_dst = ren2->pair->two->path; const char *dst_name1 = ren1_dst; const char *dst_name2 = ren2_dst; - if (path_list_has_path(¤t_directory_set, ren1_dst)) { + if (string_list_has_string(¤t_directory_set, ren1_dst)) { dst_name1 = del[delp++] = unique_path(ren1_dst, branch1); output(1, "%s is a directory in %s added as %s instead", ren1_dst, branch2, dst_name1); remove_file(0, ren1_dst, 0); } - if (path_list_has_path(¤t_directory_set, ren2_dst)) { + if (string_list_has_string(¤t_directory_set, ren2_dst)) { dst_name2 = del[delp++] = unique_path(ren2_dst, branch2); output(1, "%s is a directory in %s added as %s instead", ren2_dst, branch1, dst_name2); @@ -785,30 +783,30 @@ static void conflict_rename_rename_2(struct rename *ren1, free(new_path1); } -static int process_renames(struct path_list *a_renames, - struct path_list *b_renames, +static int process_renames(struct string_list *a_renames, + struct string_list *b_renames, const char *a_branch, const char *b_branch) { int clean_merge = 1, i, j; - struct path_list a_by_dst = {NULL, 0, 0, 0}, b_by_dst = {NULL, 0, 0, 0}; + struct string_list a_by_dst = {NULL, 0, 0, 0}, b_by_dst = {NULL, 0, 0, 0}; const struct rename *sre; for (i = 0; i < a_renames->nr; i++) { sre = a_renames->items[i].util; - path_list_insert(sre->pair->two->path, &a_by_dst)->util + string_list_insert(sre->pair->two->path, &a_by_dst)->util = sre->dst_entry; } for (i = 0; i < b_renames->nr; i++) { sre = b_renames->items[i].util; - path_list_insert(sre->pair->two->path, &b_by_dst)->util + string_list_insert(sre->pair->two->path, &b_by_dst)->util = sre->dst_entry; } for (i = 0, j = 0; i < a_renames->nr || j < b_renames->nr;) { int compare; char *src; - struct path_list *renames1, *renames2, *renames2Dst; + struct string_list *renames1, *renames2, *renames2Dst; struct rename *ren1 = NULL, *ren2 = NULL; const char *branch1, *branch2; const char *ren1_src, *ren1_dst; @@ -820,8 +818,8 @@ static int process_renames(struct path_list *a_renames, compare = -1; ren1 = a_renames->items[i++].util; } else { - compare = strcmp(a_renames->items[i].path, - b_renames->items[j].path); + compare = strcmp(a_renames->items[i].string, + b_renames->items[j].string); if (compare <= 0) ren1 = a_renames->items[i++].util; if (compare >= 0) @@ -910,7 +908,7 @@ static int process_renames(struct path_list *a_renames, } } else { /* Renamed in 1, maybe changed in 2 */ - struct path_list_item *item; + struct string_list_item *item; /* we only use sha1 and mode of these */ struct diff_filespec src_other, dst_other; int try_merge, stage = a_renames == renames1 ? 3: 2; @@ -924,7 +922,7 @@ static int process_renames(struct path_list *a_renames, try_merge = 0; - if (path_list_has_path(¤t_directory_set, ren1_dst)) { + if (string_list_has_string(¤t_directory_set, ren1_dst)) { clean_merge = 0; output(1, "CONFLICT (rename/directory): Renamed %s->%s in %s " " directory %s added in %s", @@ -949,7 +947,7 @@ static int process_renames(struct path_list *a_renames, new_path = unique_path(ren1_dst, branch2); output(1, "Added as %s instead", new_path); update_file(0, dst_other.sha1, dst_other.mode, new_path); - } else if ((item = path_list_lookup(ren1_dst, renames2Dst))) { + } else if ((item = string_list_lookup(ren1_dst, renames2Dst))) { ren2 = item->util; clean_merge = 0; ren2->processed = 1; @@ -1005,8 +1003,8 @@ static int process_renames(struct path_list *a_renames, } } } - path_list_clear(&a_by_dst, 0); - path_list_clear(&b_by_dst, 0); + string_list_clear(&a_by_dst, 0); + string_list_clear(&b_by_dst, 0); return clean_merge; } @@ -1084,7 +1082,7 @@ static int process_entry(const char *path, struct stage_data *entry, sha = b_sha; conf = "directory/file"; } - if (path_list_has_path(¤t_directory_set, path)) { + if (string_list_has_string(¤t_directory_set, path)) { const char *new_path = unique_path(path, add_branch); clean_merge = 0; output(1, "CONFLICT (%s): There is a directory with name %s in %s. " @@ -1175,10 +1173,10 @@ int merge_trees(struct tree *head, sha1_to_hex(merge->object.sha1)); if (unmerged_cache()) { - struct path_list *entries, *re_head, *re_merge; + struct string_list *entries, *re_head, *re_merge; int i; - path_list_clear(¤t_file_set, 1); - path_list_clear(¤t_directory_set, 1); + string_list_clear(¤t_file_set, 1); + string_list_clear(¤t_directory_set, 1); get_files_dirs(head); get_files_dirs(merge); @@ -1188,16 +1186,16 @@ int merge_trees(struct tree *head, clean = process_renames(re_head, re_merge, branch1, branch2); for (i = 0; i < entries->nr; i++) { - const char *path = entries->items[i].path; + const char *path = entries->items[i].string; struct stage_data *e = entries->items[i].util; if (!e->processed && !process_entry(path, e, branch1, branch2)) clean = 0; } - path_list_clear(re_merge, 0); - path_list_clear(re_head, 0); - path_list_clear(entries, 1); + string_list_clear(re_merge, 0); + string_list_clear(re_head, 0); + string_list_clear(entries, 1); } else @@ -1336,17 +1334,21 @@ static struct commit *get_ref(const char *ref) return (struct commit *)object; } -static int merge_config(const char *var, const char *value) +static int merge_config(const char *var, const char *value, void *cb) { if (!strcasecmp(var, "merge.verbosity")) { verbosity = git_config_int(var, value); return 0; } if (!strcasecmp(var, "diff.renamelimit")) { - rename_limit = git_config_int(var, value); + diff_rename_limit = git_config_int(var, value); + return 0; + } + if (!strcasecmp(var, "merge.renamelimit")) { + merge_rename_limit = git_config_int(var, value); return 0; } - return git_default_config(var, value); + return git_default_config(var, value, cb); } int cmd_merge_recursive(int argc, const char **argv, const char *prefix) @@ -1367,7 +1369,7 @@ int cmd_merge_recursive(int argc, const char **argv, const char *prefix) subtree_merge = 1; } - git_config(merge_config); + git_config(merge_config, NULL); if (getenv("GIT_MERGE_VERBOSITY")) verbosity = strtol(getenv("GIT_MERGE_VERBOSITY"), NULL, 10);