@ -2260,6 +2260,27 @@ static void compute_collisions(struct strmap *collisions,
@@ -2260,6 +2260,27 @@ static void compute_collisions(struct strmap *collisions,
}
}
static void free_collisions(struct strmap *collisions)
{
struct hashmap_iter iter;
struct strmap_entry *entry;
/* Free each value in the collisions map */
strmap_for_each_entry(collisions, &iter, entry) {
struct collision_info *info = entry->value;
string_list_clear(&info->source_files, 0);
}
/*
* In compute_collisions(), we set collisions.strdup_strings to 0
* so that we wouldn't have to make another copy of the new_path
* allocated by apply_dir_rename(). But now that we've used them
* and have no other references to these strings, it is time to
* deallocate them.
*/
free_strmap_strings(collisions);
strmap_clear(collisions, 1);
}
static char *check_for_directory_rename(struct merge_options *opt,
const char *path,
unsigned side_index,
@ -2268,18 +2289,23 @@ static char *check_for_directory_rename(struct merge_options *opt,
@@ -2268,18 +2289,23 @@ static char *check_for_directory_rename(struct merge_options *opt,
struct strmap *collisions,
int *clean_merge)
{
char *new_path = NULL;
char *new_path;
struct strmap_entry *rename_info;
struct strmap_entry *otherinfo = NULL;
struct strmap_entry *otherinfo;
const char *new_dir;
int other_side = 3 - side_index;
/*
* Cases where we don't have or don't want a directory rename for
* this path.
*/
if (strmap_empty(dir_renames))
return new_path;
return NULL;
if (strmap_get(&collisions[other_side], path))
return NULL;
rename_info = check_dir_renamed(path, dir_renames);
if (!rename_info)
return new_path;
/* old_dir = rename_info->key; */
new_dir = rename_info->value;
return NULL;
/*
* This next part is a little weird. We do not want to do an
@ -2305,6 +2331,7 @@ static char *check_for_directory_rename(struct merge_options *opt,
@@ -2305,6 +2331,7 @@ static char *check_for_directory_rename(struct merge_options *opt,
* As it turns out, this also prevents N-way transient rename
* confusion; See testcases 9c and 9d of t6043.
*/
new_dir = rename_info->value; /* old_dir = rename_info->key; */
otherinfo = strmap_get_entry(dir_rename_exclusions, new_dir);
if (otherinfo) {
path_msg(opt, rename_info->key, 1,
@ -2315,7 +2342,8 @@ static char *check_for_directory_rename(struct merge_options *opt,
@@ -2315,7 +2342,8 @@ static char *check_for_directory_rename(struct merge_options *opt,
}
new_path = handle_path_level_conflicts(opt, path, side_index,
rename_info, collisions);
rename_info,
&collisions[side_index]);
*clean_merge &= (new_path != NULL);
return new_path;
@ -3024,18 +3052,15 @@ static int detect_regular_renames(struct merge_options *opt,
@@ -3024,18 +3052,15 @@ static int detect_regular_renames(struct merge_options *opt,
static int collect_renames(struct merge_options *opt,
struct diff_queue_struct *result,
unsigned side_index,
struct strmap *collisions,
struct strmap *dir_renames_for_side,
struct strmap *rename_exclusions)
{
int i, clean = 1;
struct strmap collisions;
struct diff_queue_struct *side_pairs;
struct hashmap_iter iter;
struct strmap_entry *entry;
struct rename_info *renames = &opt->priv->renames;
side_pairs = &renames->pairs[side_index];
compute_collisions(&collisions, dir_renames_for_side, side_pairs);
for (i = 0; i < side_pairs->nr; ++i) {
struct diff_filepair *p = side_pairs->queue[i];
@ -3051,7 +3076,7 @@ static int collect_renames(struct merge_options *opt,
@@ -3051,7 +3076,7 @@ static int collect_renames(struct merge_options *opt,
side_index,
dir_renames_for_side,
rename_exclusions,
&collisions,
collisions,
&clean);
possibly_cache_new_pair(renames, p, side_index, new_path);
@ -3077,20 +3102,6 @@ static int collect_renames(struct merge_options *opt,
@@ -3077,20 +3102,6 @@ static int collect_renames(struct merge_options *opt,
result->queue[result->nr++] = p;
}
/* Free each value in the collisions map */
strmap_for_each_entry(&collisions, &iter, entry) {
struct collision_info *info = entry->value;
string_list_clear(&info->source_files, 0);
}
/*
* In compute_collisions(), we set collisions.strdup_strings to 0
* so that we wouldn't have to make another copy of the new_path
* allocated by apply_dir_rename(). But now that we've used them
* and have no other references to these strings, it is time to
* deallocate them.
*/
free_strmap_strings(&collisions);
strmap_clear(&collisions, 1);
return clean;
}
@ -3101,6 +3112,7 @@ static int detect_and_process_renames(struct merge_options *opt,
@@ -3101,6 +3112,7 @@ static int detect_and_process_renames(struct merge_options *opt,
{
struct diff_queue_struct combined = { 0 };
struct rename_info *renames = &opt->priv->renames;
struct strmap collisions[3];
int need_dir_renames, s, i, clean = 1;
unsigned detection_run = 0;
@ -3150,12 +3162,22 @@ static int detect_and_process_renames(struct merge_options *opt,
@@ -3150,12 +3162,22 @@ static int detect_and_process_renames(struct merge_options *opt,
ALLOC_GROW(combined.queue,
renames->pairs[1].nr + renames->pairs[2].nr,
combined.alloc);
for (i = MERGE_SIDE1; i <= MERGE_SIDE2; i++) {
int other_side = 3 - i;
compute_collisions(&collisions[i],
&renames->dir_renames[other_side],
&renames->pairs[i]);
}
clean &= collect_renames(opt, &combined, MERGE_SIDE1,
collisions,
&renames->dir_renames[2],
&renames->dir_renames[1]);
clean &= collect_renames(opt, &combined, MERGE_SIDE2,
collisions,
&renames->dir_renames[1],
&renames->dir_renames[2]);
for (i = MERGE_SIDE1; i <= MERGE_SIDE2; i++)
free_collisions(&collisions[i]);
STABLE_QSORT(combined.queue, combined.nr, compare_pairs);
trace2_region_leave("merge", "directory renames", opt->repo);