@@ -2333,6 +2333,47 @@ static void resolve_diffpair_statuses(struct diff_queue_struct *q)
}
}
+static void possibly_cache_new_pair(struct rename_info *renames,
+ struct diff_filepair *p,
+ unsigned side,
+ char *new_path)
+{
+ char *old_value;
+
+ if (!new_path) {
+ int val = strintmap_get(&renames->relevant_sources[side],
+ p->one->path);
+ if (val == 0) {
+ assert(p->status == 'D');
+ strset_add(&renames->cached_irrelevant[side],
+ p->one->path);
+ }
+ if (val <= 0)
+ return;
+ }
+ if (p->status == 'D') {
+ /*
+ * If we already had this delete, we'll just set it's value
+ * to NULL again, so no harm.
+ */
+ strmap_put(&renames->cached_pairs[side], p->one->path, NULL);
+ } else if (p->status == 'R') {
+ if (!new_path)
+ new_path = p->two->path;
+ new_path = xstrdup(new_path);
+ old_value = strmap_put(&renames->cached_pairs[side],
+ p->one->path, new_path);
+ strset_add(&renames->cached_target_names[side], new_path);
+ free(old_value);
+ } else if (p->status == 'A' && new_path) {
+ new_path = xstrdup(new_path);
+ old_value = strmap_put(&renames->cached_pairs[side],
+ p->two->path, new_path);
+ strset_add(&renames->cached_target_names[side], new_path);
+ assert(!old_value);
+ }
+}
+
static int compare_pairs(const void *a_, const void *b_)
{
const struct diff_filepair *a = *((const struct diff_filepair **)a_);
@@ -2414,6 +2455,7 @@ static int collect_renames(struct merge_options *opt,
struct diff_filepair *p = side_pairs->queue[i];
char *new_path; /* non-NULL only with directory renames */
+ possibly_cache_new_pair(renames, p, side_index, NULL);
if (p->status != 'A' && p->status != 'R') {
diff_free_filepair(p);
continue;
@@ -2430,7 +2472,7 @@ static int collect_renames(struct merge_options *opt,
diff_free_filepair(p);
continue;
}
-
+ possibly_cache_new_pair(renames, p, side_index, new_path);
if (new_path)
apply_directory_rename_modifications(opt, p, new_path);
@@ -3709,8 +3751,16 @@ static void merge_start(struct merge_options *opt, struct merge_result *result)
NULL, 1);
strmap_init_with_options(&renames->dir_renames[i],
NULL, 0);
+ /*
+ * relevant_sources uses -1 for the default, because we need
+ * to be able to distinguish not-in-strintmap from valid
+ * relevant_source values from enum file_rename_relevance.
+ * In particular, possibly_cache_new_pair() expects a negative
+ * value for not-found entries.
+ */
strintmap_init_with_options(&renames->relevant_sources[i],
- 0, NULL, 0);
+ -1 /* explicitly invalid */,
+ NULL, 0);
strmap_init_with_options(&renames->cached_pairs[i],
NULL, 1);
strset_init_with_options(&renames->cached_irrelevant[i],