merge-ort, diffcore-rename: tweak dirs_removed and relevant_source type

As noted in the previous commit, we want to be able to take advantage of the "majority rules" portion of directory rename detection to avoid detecting more renames than necessary. However, for diffcore-rename to take advantage of that, it needs to know whether a rename source file was needed for just directory rename detection reasons, or if it is wanted for potential three-way content merging. Modify relevant_sources from a strset to a strintmap, so we can encode additional information. We also modify dirs_removed from a strset to a strintmap at the same time because trying to determine what files are needed for directory rename detection will require us tracking a bit more information for each directory. This commit only changes the types of the two variables from strset to strintmap; it does not actually store any special values yet and for now only checks for presence of entries in the strintmap. Thus, the code is functionally identical to how it behaved before. Future commits will start associating values with each key for these two maps. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Elijah Newren committed Mar 13, 2021 at 22:22 UTC a49b55d52e7dcfd628b6328c9098d734ebe7a97d
3 files changed +41 -40
diffcore-rename.c
+24 -23
@@ -371,7 +371,7 @@ struct dir_rename_info {
371 struct strintmap idx_map;
372 struct strmap dir_rename_guess;
373 struct strmap *dir_rename_count;
374 - struct strset *relevant_source_dirs;
374 + struct strintmap *relevant_source_dirs;
375 unsigned setup;
376 };
377
@@ -429,7 +429,7 @@ static void increment_count(struct dir_rename_info *info,
429 }
430
431 static void update_dir_rename_counts(struct dir_rename_info *info,
432 - struct strset *dirs_removed,
432 + struct strintmap *dirs_removed,
433 const char *oldname,
434 const char *newname)
435 {
@@ -464,7 +464,7 @@ static void update_dir_rename_counts(struct dir_rename_info *info,
464 /* Get old_dir, skip if its directory isn't relevant. */
465 dirname_munge(old_dir);
466 if (info->relevant_source_dirs &&
467 - !strset_contains(info->relevant_source_dirs, old_dir))
467 + !strintmap_contains(info->relevant_source_dirs, old_dir))
468 break;
469
470 /* Get new_dir */
@@ -509,7 +509,7 @@ static void update_dir_rename_counts(struct dir_rename_info *info,
509 }
510 }
511
512 - if (strset_contains(dirs_removed, old_dir))
512 + if (strintmap_contains(dirs_removed, old_dir))
513 increment_count(info, old_dir, new_dir);
514 else
515 break;
@@ -527,8 +527,8 @@ static void update_dir_rename_counts(struct dir_rename_info *info,
527 }
528
529 static void initialize_dir_rename_info(struct dir_rename_info *info,
530 - struct strset *relevant_sources,
531 - struct strset *dirs_removed,
530 + struct strintmap *relevant_sources,
531 + struct strintmap *dirs_removed,
532 struct strmap *dir_rename_count)
533 {
534 struct hashmap_iter iter;
@@ -555,12 +555,13 @@ static void initialize_dir_rename_info(struct dir_rename_info *info,
555 info->relevant_source_dirs = dirs_removed; /* might be NULL */
556 } else {
557 info->relevant_source_dirs = xmalloc(sizeof(struct strintmap));
558 - strset_init(info->relevant_source_dirs);
559 - strset_for_each_entry(relevant_sources, &iter, entry) {
558 + strintmap_init(info->relevant_source_dirs, 0 /* unused */);
559 + strintmap_for_each_entry(relevant_sources, &iter, entry) {
560 char *dirname = get_dirname(entry->key);
561 if (!dirs_removed ||
562 - strset_contains(dirs_removed, dirname))
563 - strset_add(info->relevant_source_dirs, dirname);
562 + strintmap_contains(dirs_removed, dirname))
563 + strintmap_set(info->relevant_source_dirs,
564 + dirname, 0 /* value irrelevant */);
565 free(dirname);
566 }
567 }
@@ -624,7 +625,7 @@ void partial_clear_dir_rename_count(struct strmap *dir_rename_count)
625 }
626
627 static void cleanup_dir_rename_info(struct dir_rename_info *info,
627 - struct strset *dirs_removed,
628 + struct strintmap *dirs_removed,
629 int keep_dir_rename_count)
630 {
631 struct hashmap_iter iter;
@@ -644,7 +645,7 @@ static void cleanup_dir_rename_info(struct dir_rename_info *info,
645 /* relevant_source_dirs */
646 if (info->relevant_source_dirs &&
647 info->relevant_source_dirs != dirs_removed) {
647 - strset_clear(info->relevant_source_dirs);
648 + strintmap_clear(info->relevant_source_dirs);
649 FREE_AND_NULL(info->relevant_source_dirs);
650 }
651
@@ -666,7 +667,7 @@ static void cleanup_dir_rename_info(struct dir_rename_info *info,
667 const char *source_dir = entry->key;
668 struct strintmap *counts = entry->value;
669
669 - if (!strset_contains(dirs_removed, source_dir)) {
670 + if (!strintmap_contains(dirs_removed, source_dir)) {
671 string_list_append(&to_remove, source_dir);
672 strintmap_clear(counts);
673 continue;
@@ -770,8 +771,8 @@ static int idx_possible_rename(char *filename, struct dir_rename_info *info)
771 static int find_basename_matches(struct diff_options *options,
772 int minimum_score,
773 struct dir_rename_info *info,
773 - struct strset *relevant_sources,
774 - struct strset *dirs_removed)
774 + struct strintmap *relevant_sources,
775 + struct strintmap *dirs_removed)
776 {
777 /*
778 * When I checked in early 2020, over 76% of file renames in linux
@@ -863,7 +864,7 @@ static int find_basename_matches(struct diff_options *options,
864
865 /* Skip irrelevant sources */
866 if (relevant_sources &&
866 - !strset_contains(relevant_sources, filename))
867 + !strintmap_contains(relevant_sources, filename))
868 continue;
869
870 /*
@@ -994,7 +995,7 @@ static int find_renames(struct diff_score *mx,
995 int minimum_score,
996 int copies,
997 struct dir_rename_info *info,
997 - struct strset *dirs_removed)
998 + struct strintmap *dirs_removed)
999 {
1000 int count = 0, i;
1001
@@ -1019,7 +1020,7 @@ static int find_renames(struct diff_score *mx,
1020 }
1021
1022 static void remove_unneeded_paths_from_src(int detecting_copies,
1022 - struct strset *interesting)
1023 + struct strintmap *interesting)
1024 {
1025 int i, new_num_src;
1026
@@ -1061,7 +1062,7 @@ static void remove_unneeded_paths_from_src(int detecting_copies,
1062 continue;
1063
1064 /* If we don't care about the source path, skip it */
1064 - if (interesting && !strset_contains(interesting, one->path))
1065 + if (interesting && !strintmap_contains(interesting, one->path))
1066 continue;
1067
1068 if (new_num_src < i)
@@ -1074,8 +1075,8 @@ static void remove_unneeded_paths_from_src(int detecting_copies,
1075 }
1076
1077 static void handle_early_known_dir_renames(struct dir_rename_info *info,
1077 - struct strset *relevant_sources,
1078 - struct strset *dirs_removed)
1078 + struct strintmap *relevant_sources,
1079 + struct strintmap *dirs_removed)
1080 {
1081 /*
1082 * Not yet implemented; directory renames are determined via an
@@ -1092,8 +1093,8 @@ static void handle_early_known_dir_renames(struct dir_rename_info *info,
1093 }
1094
1095 void diffcore_rename_extended(struct diff_options *options,
1095 - struct strset *relevant_sources,
1096 - struct strset *dirs_removed,
1096 + struct strintmap *relevant_sources,
1097 + struct strintmap *dirs_removed,
1098 struct strmap *dir_rename_count)
1099 {
1100 int detect_rename = options->detect_rename;
diffcore.h
+3 -3
@@ -8,8 +8,8 @@
8
9 struct diff_options;
10 struct repository;
11 +struct strintmap;
12 struct strmap;
12 -struct strset;
13 struct userdiff_driver;
14
15 /* This header file is internal between diff.c and its diff transformers
@@ -166,8 +166,8 @@ void partial_clear_dir_rename_count(struct strmap *dir_rename_count);
166 void diffcore_break(struct repository *, int);
167 void diffcore_rename(struct diff_options *);
168 void diffcore_rename_extended(struct diff_options *options,
169 - struct strset *relevant_sources,
170 - struct strset *dirs_removed,
169 + struct strintmap *relevant_sources,
170 + struct strintmap *dirs_removed,
171 struct strmap *dir_rename_count);
172 void diffcore_merge_broken(void);
173 void diffcore_pickaxe(struct diff_options *);
merge-ort.c
+14 -14
@@ -74,7 +74,7 @@ struct rename_info {
74 /*
75 * dirs_removed: directories removed on a given side of history.
76 */
77 - struct strset dirs_removed[3];
77 + struct strintmap dirs_removed[3];
78
79 /*
80 * dir_rename_count: tracking where parts of a directory were renamed to
@@ -106,7 +106,7 @@ struct rename_info {
106 * If neither of those are true, we can skip rename detection for
107 * that path.
108 */
109 - struct strset relevant_sources[3];
109 + struct strintmap relevant_sources[3];
110
111 /*
112 * dir_rename_mask:
@@ -362,8 +362,8 @@ static void clear_or_reinit_internal_opts(struct merge_options_internal *opti,
362 int i;
363 void (*strmap_func)(struct strmap *, int) =
364 reinitialize ? strmap_partial_clear : strmap_clear;
365 - void (*strset_func)(struct strset *) =
366 - reinitialize ? strset_partial_clear : strset_clear;
365 + void (*strintmap_func)(struct strintmap *) =
366 + reinitialize ? strintmap_partial_clear : strintmap_clear;
367
368 /*
369 * We marked opti->paths with strdup_strings = 0, so that we
@@ -395,7 +395,7 @@ static void clear_or_reinit_internal_opts(struct merge_options_internal *opti,
395
396 /* Free memory used by various renames maps */
397 for (i = MERGE_SIDE1; i <= MERGE_SIDE2; ++i) {
398 - strset_func(&renames->dirs_removed[i]);
398 + strintmap_func(&renames->dirs_removed[i]);
399
400 partial_clear_dir_rename_count(&renames->dir_rename_count[i]);
401 if (!reinitialize)
@@ -403,7 +403,7 @@ static void clear_or_reinit_internal_opts(struct merge_options_internal *opti,
403
404 strmap_func(&renames->dir_renames[i], 0);
405
406 - strset_func(&renames->relevant_sources[i]);
406 + strintmap_func(&renames->relevant_sources[i]);
407 }
408
409 if (!reinitialize) {
@@ -674,7 +674,7 @@ static void add_pair(struct merge_options *opt,
674 unsigned location_relevant = (dir_rename_mask == 0x07);
675
676 if (content_relevant || location_relevant)
677 - strset_add(&renames->relevant_sources[side], pathname);
677 + strintmap_set(&renames->relevant_sources[side], pathname, 1);
678 }
679
680 one = alloc_filespec(pathname);
@@ -730,9 +730,9 @@ static void collect_rename_info(struct merge_options *opt,
730 /* absent_mask = 0x07 - dirmask; sides = absent_mask/2 */
731 unsigned sides = (0x07 - dirmask)/2;
732 if (sides & 1)
733 - strset_add(&renames->dirs_removed[1], fullname);
733 + strintmap_set(&renames->dirs_removed[1], fullname, 1);
734 if (sides & 2)
735 - strset_add(&renames->dirs_removed[2], fullname);
735 + strintmap_set(&renames->dirs_removed[2], fullname, 1);
736 }
737
738 if (filemask == 0 || filemask == 7)
@@ -2161,7 +2161,7 @@ static inline int possible_side_renames(struct rename_info *renames,
2161 unsigned side_index)
2162 {
2163 return renames->pairs[side_index].nr > 0 &&
2164 - !strset_empty(&renames->relevant_sources[side_index]);
2164 + !strintmap_empty(&renames->relevant_sources[side_index]);
2165 }
2166
2167 static inline int possible_renames(struct rename_info *renames)
@@ -3445,14 +3445,14 @@ static void merge_start(struct merge_options *opt, struct merge_result *result)
3445 /* Initialization of various renames fields */
3446 renames = &opt->priv->renames;
3447 for (i = MERGE_SIDE1; i <= MERGE_SIDE2; i++) {
3448 - strset_init_with_options(&renames->dirs_removed[i],
3449 - NULL, 0);
3448 + strintmap_init_with_options(&renames->dirs_removed[i],
3449 + 0, NULL, 0);
3450 strmap_init_with_options(&renames->dir_rename_count[i],
3451 NULL, 1);
3452 strmap_init_with_options(&renames->dir_renames[i],
3453 NULL, 0);
3454 - strset_init_with_options(&renames->relevant_sources[i],
3455 - NULL, 0);
3454 + strintmap_init_with_options(&renames->relevant_sources[i],
3455 + 0, NULL, 0);
3456 }
3457
3458 /*