|
|
@ -77,9 +77,6 @@ struct stage_data |
|
|
|
unsigned processed:1; |
|
|
|
unsigned processed: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 show(struct merge_options *o, int v) |
|
|
|
static int show(struct merge_options *o, int v) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return (!o->call_depth && o->verbosity >= v) || o->verbosity >= 5; |
|
|
|
return (!o->call_depth && o->verbosity >= v) || o->verbosity >= 5; |
|
|
@ -232,25 +229,27 @@ static int save_files_dirs(const unsigned char *sha1, |
|
|
|
{ |
|
|
|
{ |
|
|
|
int len = strlen(path); |
|
|
|
int len = strlen(path); |
|
|
|
char *newpath = xmalloc(baselen + len + 1); |
|
|
|
char *newpath = xmalloc(baselen + len + 1); |
|
|
|
|
|
|
|
struct merge_options *o = context; |
|
|
|
|
|
|
|
|
|
|
|
memcpy(newpath, base, baselen); |
|
|
|
memcpy(newpath, base, baselen); |
|
|
|
memcpy(newpath + baselen, path, len); |
|
|
|
memcpy(newpath + baselen, path, len); |
|
|
|
newpath[baselen + len] = '\0'; |
|
|
|
newpath[baselen + len] = '\0'; |
|
|
|
|
|
|
|
|
|
|
|
if (S_ISDIR(mode)) |
|
|
|
if (S_ISDIR(mode)) |
|
|
|
string_list_insert(newpath, ¤t_directory_set); |
|
|
|
string_list_insert(newpath, &o->current_directory_set); |
|
|
|
else |
|
|
|
else |
|
|
|
string_list_insert(newpath, ¤t_file_set); |
|
|
|
string_list_insert(newpath, &o->current_file_set); |
|
|
|
free(newpath); |
|
|
|
free(newpath); |
|
|
|
|
|
|
|
|
|
|
|
return READ_TREE_RECURSIVE; |
|
|
|
return READ_TREE_RECURSIVE; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static int get_files_dirs(struct tree *tree) |
|
|
|
static int get_files_dirs(struct merge_options *o, struct tree *tree) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int n; |
|
|
|
int n; |
|
|
|
if (read_tree_recursive(tree, "", 0, 0, NULL, save_files_dirs, NULL)) |
|
|
|
if (read_tree_recursive(tree, "", 0, 0, NULL, save_files_dirs, o)) |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
n = current_file_set.nr + current_directory_set.nr; |
|
|
|
n = o->current_file_set.nr + o->current_directory_set.nr; |
|
|
|
return n; |
|
|
|
return n; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -434,7 +433,7 @@ static int remove_file(struct merge_options *o, int clean, |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static char *unique_path(const char *path, const char *branch) |
|
|
|
static char *unique_path(struct merge_options *o, const char *path, const char *branch) |
|
|
|
{ |
|
|
|
{ |
|
|
|
char *newpath = xmalloc(strlen(path) + 1 + strlen(branch) + 8 + 1); |
|
|
|
char *newpath = xmalloc(strlen(path) + 1 + strlen(branch) + 8 + 1); |
|
|
|
int suffix = 0; |
|
|
|
int suffix = 0; |
|
|
@ -446,12 +445,12 @@ static char *unique_path(const char *path, const char *branch) |
|
|
|
for (; *p; ++p) |
|
|
|
for (; *p; ++p) |
|
|
|
if ('/' == *p) |
|
|
|
if ('/' == *p) |
|
|
|
*p = '_'; |
|
|
|
*p = '_'; |
|
|
|
while (string_list_has_string(¤t_file_set, newpath) || |
|
|
|
while (string_list_has_string(&o->current_file_set, newpath) || |
|
|
|
string_list_has_string(¤t_directory_set, newpath) || |
|
|
|
string_list_has_string(&o->current_directory_set, newpath) || |
|
|
|
lstat(newpath, &st) == 0) |
|
|
|
lstat(newpath, &st) == 0) |
|
|
|
sprintf(p, "_%d", suffix++); |
|
|
|
sprintf(p, "_%d", suffix++); |
|
|
|
|
|
|
|
|
|
|
|
string_list_insert(newpath, ¤t_file_set); |
|
|
|
string_list_insert(newpath, &o->current_file_set); |
|
|
|
return newpath; |
|
|
|
return newpath; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -716,14 +715,14 @@ static void conflict_rename_rename(struct merge_options *o, |
|
|
|
const char *ren2_dst = ren2->pair->two->path; |
|
|
|
const char *ren2_dst = ren2->pair->two->path; |
|
|
|
const char *dst_name1 = ren1_dst; |
|
|
|
const char *dst_name1 = ren1_dst; |
|
|
|
const char *dst_name2 = ren2_dst; |
|
|
|
const char *dst_name2 = ren2_dst; |
|
|
|
if (string_list_has_string(¤t_directory_set, ren1_dst)) { |
|
|
|
if (string_list_has_string(&o->current_directory_set, ren1_dst)) { |
|
|
|
dst_name1 = del[delp++] = unique_path(ren1_dst, branch1); |
|
|
|
dst_name1 = del[delp++] = unique_path(o, ren1_dst, branch1); |
|
|
|
output(o, 1, "%s is a directory in %s adding as %s instead", |
|
|
|
output(o, 1, "%s is a directory in %s adding as %s instead", |
|
|
|
ren1_dst, branch2, dst_name1); |
|
|
|
ren1_dst, branch2, dst_name1); |
|
|
|
remove_file(o, 0, ren1_dst, 0); |
|
|
|
remove_file(o, 0, ren1_dst, 0); |
|
|
|
} |
|
|
|
} |
|
|
|
if (string_list_has_string(¤t_directory_set, ren2_dst)) { |
|
|
|
if (string_list_has_string(&o->current_directory_set, ren2_dst)) { |
|
|
|
dst_name2 = del[delp++] = unique_path(ren2_dst, branch2); |
|
|
|
dst_name2 = del[delp++] = unique_path(o, ren2_dst, branch2); |
|
|
|
output(o, 1, "%s is a directory in %s adding as %s instead", |
|
|
|
output(o, 1, "%s is a directory in %s adding as %s instead", |
|
|
|
ren2_dst, branch1, dst_name2); |
|
|
|
ren2_dst, branch1, dst_name2); |
|
|
|
remove_file(o, 0, ren2_dst, 0); |
|
|
|
remove_file(o, 0, ren2_dst, 0); |
|
|
@ -749,7 +748,7 @@ static void conflict_rename_dir(struct merge_options *o, |
|
|
|
struct rename *ren1, |
|
|
|
struct rename *ren1, |
|
|
|
const char *branch1) |
|
|
|
const char *branch1) |
|
|
|
{ |
|
|
|
{ |
|
|
|
char *new_path = unique_path(ren1->pair->two->path, branch1); |
|
|
|
char *new_path = unique_path(o, ren1->pair->two->path, branch1); |
|
|
|
output(o, 1, "Renaming %s to %s instead", ren1->pair->one->path, new_path); |
|
|
|
output(o, 1, "Renaming %s to %s instead", ren1->pair->one->path, new_path); |
|
|
|
remove_file(o, 0, ren1->pair->two->path, 0); |
|
|
|
remove_file(o, 0, ren1->pair->two->path, 0); |
|
|
|
update_file(o, 0, ren1->pair->two->sha1, ren1->pair->two->mode, new_path); |
|
|
|
update_file(o, 0, ren1->pair->two->sha1, ren1->pair->two->mode, new_path); |
|
|
@ -762,8 +761,8 @@ static void conflict_rename_rename_2(struct merge_options *o, |
|
|
|
struct rename *ren2, |
|
|
|
struct rename *ren2, |
|
|
|
const char *branch2) |
|
|
|
const char *branch2) |
|
|
|
{ |
|
|
|
{ |
|
|
|
char *new_path1 = unique_path(ren1->pair->two->path, branch1); |
|
|
|
char *new_path1 = unique_path(o, ren1->pair->two->path, branch1); |
|
|
|
char *new_path2 = unique_path(ren2->pair->two->path, branch2); |
|
|
|
char *new_path2 = unique_path(o, ren2->pair->two->path, branch2); |
|
|
|
output(o, 1, "Renaming %s to %s and %s to %s instead", |
|
|
|
output(o, 1, "Renaming %s to %s and %s to %s instead", |
|
|
|
ren1->pair->one->path, new_path1, |
|
|
|
ren1->pair->one->path, new_path1, |
|
|
|
ren2->pair->one->path, new_path2); |
|
|
|
ren2->pair->one->path, new_path2); |
|
|
@ -913,7 +912,7 @@ static int process_renames(struct merge_options *o, |
|
|
|
|
|
|
|
|
|
|
|
try_merge = 0; |
|
|
|
try_merge = 0; |
|
|
|
|
|
|
|
|
|
|
|
if (string_list_has_string(¤t_directory_set, ren1_dst)) { |
|
|
|
if (string_list_has_string(&o->current_directory_set, ren1_dst)) { |
|
|
|
clean_merge = 0; |
|
|
|
clean_merge = 0; |
|
|
|
output(o, 1, "CONFLICT (rename/directory): Rename %s->%s in %s " |
|
|
|
output(o, 1, "CONFLICT (rename/directory): Rename %s->%s in %s " |
|
|
|
" directory %s added in %s", |
|
|
|
" directory %s added in %s", |
|
|
@ -935,7 +934,7 @@ static int process_renames(struct merge_options *o, |
|
|
|
"%s added in %s", |
|
|
|
"%s added in %s", |
|
|
|
ren1_src, ren1_dst, branch1, |
|
|
|
ren1_src, ren1_dst, branch1, |
|
|
|
ren1_dst, branch2); |
|
|
|
ren1_dst, branch2); |
|
|
|
new_path = unique_path(ren1_dst, branch2); |
|
|
|
new_path = unique_path(o, ren1_dst, branch2); |
|
|
|
output(o, 1, "Adding as %s instead", new_path); |
|
|
|
output(o, 1, "Adding as %s instead", new_path); |
|
|
|
update_file(o, 0, dst_other.sha1, dst_other.mode, new_path); |
|
|
|
update_file(o, 0, dst_other.sha1, dst_other.mode, new_path); |
|
|
|
} else if ((item = string_list_lookup(ren1_dst, renames2Dst))) { |
|
|
|
} else if ((item = string_list_lookup(ren1_dst, renames2Dst))) { |
|
|
@ -1073,8 +1072,8 @@ static int process_entry(struct merge_options *o, |
|
|
|
sha = b_sha; |
|
|
|
sha = b_sha; |
|
|
|
conf = "directory/file"; |
|
|
|
conf = "directory/file"; |
|
|
|
} |
|
|
|
} |
|
|
|
if (string_list_has_string(¤t_directory_set, path)) { |
|
|
|
if (string_list_has_string(&o->current_directory_set, path)) { |
|
|
|
const char *new_path = unique_path(path, add_branch); |
|
|
|
const char *new_path = unique_path(o, path, add_branch); |
|
|
|
clean_merge = 0; |
|
|
|
clean_merge = 0; |
|
|
|
output(o, 1, "CONFLICT (%s): There is a directory with name %s in %s. " |
|
|
|
output(o, 1, "CONFLICT (%s): There is a directory with name %s in %s. " |
|
|
|
"Adding %s as %s", |
|
|
|
"Adding %s as %s", |
|
|
@ -1165,10 +1164,10 @@ int merge_trees(struct merge_options *o, |
|
|
|
if (unmerged_cache()) { |
|
|
|
if (unmerged_cache()) { |
|
|
|
struct string_list *entries, *re_head, *re_merge; |
|
|
|
struct string_list *entries, *re_head, *re_merge; |
|
|
|
int i; |
|
|
|
int i; |
|
|
|
string_list_clear(¤t_file_set, 1); |
|
|
|
string_list_clear(&o->current_file_set, 1); |
|
|
|
string_list_clear(¤t_directory_set, 1); |
|
|
|
string_list_clear(&o->current_directory_set, 1); |
|
|
|
get_files_dirs(head); |
|
|
|
get_files_dirs(o, head); |
|
|
|
get_files_dirs(merge); |
|
|
|
get_files_dirs(o, merge); |
|
|
|
|
|
|
|
|
|
|
|
entries = get_unmerged(); |
|
|
|
entries = get_unmerged(); |
|
|
|
re_head = get_renames(o, head, common, head, merge, entries); |
|
|
|
re_head = get_renames(o, head, common, head, merge, entries); |
|
|
@ -1374,4 +1373,8 @@ void init_merge_options(struct merge_options *o) |
|
|
|
if (o->verbosity >= 5) |
|
|
|
if (o->verbosity >= 5) |
|
|
|
o->buffer_output = 0; |
|
|
|
o->buffer_output = 0; |
|
|
|
strbuf_init(&o->obuf, 0); |
|
|
|
strbuf_init(&o->obuf, 0); |
|
|
|
|
|
|
|
memset(&o->current_file_set, 0, sizeof(struct string_list)); |
|
|
|
|
|
|
|
o->current_file_set.strdup_strings = 1; |
|
|
|
|
|
|
|
memset(&o->current_directory_set, 0, sizeof(struct string_list)); |
|
|
|
|
|
|
|
o->current_directory_set.strdup_strings = 1; |
|
|
|
} |
|
|
|
} |
|
|
|