Skip to content

Commit c138fd9

Browse files
committed
diffcore-rename: check if we have enough renames for directories early on
As noted in the past two commits, we only need to track dir_rename_count for directories that we directly need directory renames for. Further, now that we are tracking the number of unmatched pairs for each directory left to count, we can determine if a directory already has enough renames to determine how directory rename detection will go for that directory. For such directories, demote them from RELEVANT_FOR_SELF to RELEVANT_FOR_ANCESTOR, as there still may be an ancestor of that directory that we need renames for. The next commit will use this information to update individual paths in relevant_sources. Signed-off-by: Elijah Newren <[email protected]>
1 parent 04e5683 commit c138fd9

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

diffcore-rename.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,26 @@ static const char *get_highest_rename_path(struct strintmap *counts)
409409

410410
static char *UNKNOWN_DIR = "/"; /* placeholder -- short, illegal directory */
411411

412+
static int dir_rename_already_determinable(struct strintmap *counts)
413+
{
414+
struct hashmap_iter iter;
415+
struct strmap_entry *entry;
416+
int first = 0, second = 0, unknown = 0;
417+
strintmap_for_each_entry(counts, &iter, entry) {
418+
const char *destination_dir = entry->key;
419+
intptr_t count = (intptr_t)entry->value;
420+
if (!strcmp(destination_dir, UNKNOWN_DIR)) {
421+
unknown = count;
422+
} else if (count >= first) {
423+
second = first;
424+
first = count;
425+
} else if (count >= second) {
426+
second = count;
427+
}
428+
}
429+
return first > second + unknown;
430+
}
431+
412432
static void increment_count(struct dir_rename_info *info,
413433
char *old_dir,
414434
char *new_dir)
@@ -1063,6 +1083,8 @@ static void handle_early_known_dir_renames(struct dir_rename_info *info,
10631083
struct strintmap *dirs_removed)
10641084
{
10651085
int i;
1086+
struct hashmap_iter iter;
1087+
struct strmap_entry *entry;
10661088

10671089
if (!dirs_removed || !relevant_sources)
10681090
return; /* nothing to cull */
@@ -1098,6 +1120,18 @@ static void handle_early_known_dir_renames(struct dir_rename_info *info,
10981120
*/
10991121
free(old_dir);
11001122
}
1123+
1124+
strmap_for_each_entry(info->dir_rename_count, &iter, entry) {
1125+
/* entry->key is source_dir */
1126+
struct strintmap *counts = entry->value;
1127+
1128+
if (strintmap_get(dirs_removed, entry->key) ==
1129+
RELEVANT_FOR_SELF &&
1130+
dir_rename_already_determinable(counts)) {
1131+
strintmap_set(dirs_removed, entry->key,
1132+
RELEVANT_FOR_ANCESTOR);
1133+
}
1134+
}
11011135
}
11021136

11031137
void diffcore_rename_extended(struct diff_options *options,

0 commit comments

Comments
 (0)