diff mbox series

[2/3] merge-ort: shuffle the computation and cleanup of potential collisions

Message ID d8c13e56209ebb6d1d3c521b6522a1bc64909108.1655871652.git.gitgitgadget@gmail.com (mailing list archive)
State Superseded
Headers show
Series Fix dual rename into each other plus conflicting adds | expand

Commit Message

Elijah Newren June 22, 2022, 4:20 a.m. UTC
From: Elijah Newren <newren@gmail.com>

Run compute_collisions() for renames on both sides of history before
any calls to collect_renames(), and do not free the computed collisions
until after both calls to collect_renames().  This is just a code
reorganization at this point that doesn't make sense on its own, but
will permit us to use the computed collision info from both sides
within each call to collect_renames() in a subsequent commit.

Signed-off-by: Elijah Newren <newren@gmail.com>
---
 merge-ort.c | 56 ++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 36 insertions(+), 20 deletions(-)

Comments

Jonathan Tan June 27, 2022, 6:48 p.m. UTC | #1
"Elijah Newren via GitGitGadget" <gitgitgadget@gmail.com> writes:
> @@ -2314,7 +2335,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]);

Is this a fix of a latent bug? handle_path_level_conflicts() is not
changed in this patch.
Calvin Wan June 27, 2022, 9:04 p.m. UTC | #2
Jonathan Tan <jonathantanmy@google.com> writes:
> "Elijah Newren via GitGitGadget" <gitgitgadget@gmail.com> writes:
> > @@ -2314,7 +2335,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]);
> 
> Is this a fix of a latent bug? handle_path_level_conflicts() is not
> changed in this patch.
> 

I don't think so. IIUC this is what's happening given the callstack:

detect_and_process_renames()
  - Now defines `struct strmap collisions[3];` and computes all
    three collisions here
  - Passes collisions into collect_renames()
collect_renames()
  - Originally defined as `struct strmap collisions;` and computed
    collisions in here
  - Now takes collisions as an argument
  - Passes collisions into check_for_directory_rename()
check_for_directory_rename()
  - Collisions isn't used in this function at all except to pass into
    handle_path_level_conflicts
handle_path_level_conflicts()
  - Expecting pointer to singular collisions, not an array so side_index
    is now required
Elijah Newren June 30, 2022, 12:05 a.m. UTC | #3
On Mon, Jun 27, 2022 at 2:04 PM Calvin Wan <calvinwan@google.com> wrote:
>
> Jonathan Tan <jonathantanmy@google.com> writes:
> > "Elijah Newren via GitGitGadget" <gitgitgadget@gmail.com> writes:
> > > @@ -2314,7 +2335,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]);
> >
> > Is this a fix of a latent bug? handle_path_level_conflicts() is not
> > changed in this patch.
> >
>
> I don't think so. IIUC this is what's happening given the callstack:
>
> detect_and_process_renames()
>   - Now defines `struct strmap collisions[3];` and computes all
>     three collisions here
>   - Passes collisions into collect_renames()
> collect_renames()
>   - Originally defined as `struct strmap collisions;` and computed
>     collisions in here
>   - Now takes collisions as an argument
>   - Passes collisions into check_for_directory_rename()
> check_for_directory_rename()
>   - Collisions isn't used in this function at all except to pass into
>     handle_path_level_conflicts
> handle_path_level_conflicts()
>   - Expecting pointer to singular collisions, not an array so side_index
>     is now required

Sweet, thanks for answering for me.  This is exactly right.
diff mbox series

Patch

diff --git a/merge-ort.c b/merge-ort.c
index 8545354dafd..fa6667de18c 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -2259,6 +2259,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,
@@ -2314,7 +2335,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;
@@ -3023,18 +3045,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];
@@ -3050,7 +3069,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);
@@ -3076,20 +3095,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;
 }
 
@@ -3100,6 +3105,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;
 
@@ -3149,12 +3155,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 (int 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 (int 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);