merge-ort: add outline of get_provisional_directory_renames()
This function is based on merge-recursive.c's get_directory_renames(), except that the first half has been split out into a not-yet-implemented compute_rename_counts(). The primary difference here is our lack of the non_unique_new_dir boolean in our strmap. The lack of that field will at first cause us to fail testcase 2b of t6423; however, future optimizations will obviate the need for that ugly field so we have just left it out. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Elijah Newren committed
Jan 19, 2021 at 19:53 UTC
04264d4079a4423f32d85d7833d63faa5ace4e33
1 file changed
+56
-1
merge-ort.c
+56
-1
@@ -721,11 +721,66 @@ static int handle_content_merge(struct merge_options *opt,
721
722
/*** Function Grouping: functions related to directory rename detection ***/
723
724
+static void compute_rename_counts(struct diff_queue_struct *pairs,
725
+ struct strmap *dir_rename_count,
726
+ struct strset *dirs_removed)
727
+{
728
+ die("Not yet implemented!");
729
+}
730
+
731
static void get_provisional_directory_renames(struct merge_options *opt,
732
unsigned side,
733
int *clean)
734
{
728
- die("Not yet implemented!");
735
+ struct hashmap_iter iter;
736
+ struct strmap_entry *entry;
737
+ struct rename_info *renames = &opt->priv->renames;
738
+
739
+ compute_rename_counts(&renames->pairs[side],
740
+ &renames->dir_rename_count[side],
741
+ &renames->dirs_removed[side]);
742
+ /*
743
+ * Collapse
744
+ * dir_rename_count: old_directory -> {new_directory -> count}
745
+ * down to
746
+ * dir_renames: old_directory -> best_new_directory
747
+ * where best_new_directory is the one with the unique highest count.
748
+ */
749
+ strmap_for_each_entry(&renames->dir_rename_count[side], &iter, entry) {
750
+ const char *source_dir = entry->key;
751
+ struct strintmap *counts = entry->value;
752
+ struct hashmap_iter count_iter;
753
+ struct strmap_entry *count_entry;
754
+ int max = 0;
755
+ int bad_max = 0;
756
+ const char *best = NULL;
757
+
758
+ strintmap_for_each_entry(counts, &count_iter, count_entry) {
759
+ const char *target_dir = count_entry->key;
760
+ intptr_t count = (intptr_t)count_entry->value;
761
+
762
+ if (count == max)
763
+ bad_max = max;
764
+ else if (count > max) {
765
+ max = count;
766
+ best = target_dir;
767
+ }
768
+ }
769
+
770
+ if (bad_max == max) {
771
+ path_msg(opt, source_dir, 0,
772
+ _("CONFLICT (directory rename split): "
773
+ "Unclear where to rename %s to; it was "
774
+ "renamed to multiple other directories, with "
775
+ "no destination getting a majority of the "
776
+ "files."),
777
+ source_dir);
778
+ *clean = 0;
779
+ } else {
780
+ strmap_put(&renames->dir_renames[side],
781
+ source_dir, (void*)best);
782
+ }
783
+ }
784
}
785
786
static void handle_directory_level_conflicts(struct merge_options *opt)