Create a new function, get_diffpairs() to compute the diff_filepairs between two trees. While these are currently only used in get_renames(), I want them to be available to some new functions. No actual logic changes yet. Signed-off-by: Elijah Newren <newren@xxxxxxxxx> --- merge-recursive.c | 81 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 21 deletions(-) diff --git a/merge-recursive.c b/merge-recursive.c index f40c70990c..8c9543d85c 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -1315,24 +1315,15 @@ static int conflict_rename_rename_2to1(struct merge_options *o, } /* - * Get information of all renames which occurred between 'o_tree' and - * 'tree'. We need the three trees in the merge ('o_tree', 'a_tree' and - * 'b_tree') to be able to associate the correct cache entries with - * the rename information. 'tree' is always equal to either a_tree or b_tree. + * Get the diff_filepairs changed between o_tree and tree. */ -static struct string_list *get_renames(struct merge_options *o, - struct tree *tree, - struct tree *o_tree, - struct tree *a_tree, - struct tree *b_tree, - struct string_list *entries) +static struct diff_queue_struct *get_diffpairs(struct merge_options *o, + struct tree *o_tree, + struct tree *tree) { - int i; - struct string_list *renames; + struct diff_queue_struct *ret; struct diff_options opts; - renames = xcalloc(1, sizeof(struct string_list)); - diff_setup(&opts); DIFF_OPT_SET(&opts, RECURSIVE); DIFF_OPT_CLR(&opts, RENAME_EMPTY); @@ -1348,10 +1339,43 @@ static struct string_list *get_renames(struct merge_options *o, diffcore_std(&opts); if (opts.needed_rename_limit > o->needed_rename_limit) o->needed_rename_limit = opts.needed_rename_limit; - for (i = 0; i < diff_queued_diff.nr; ++i) { + + ret = malloc(sizeof(struct diff_queue_struct)); + ret->queue = diff_queued_diff.queue; + ret->nr = diff_queued_diff.nr; + // Ignore diff_queued_diff.alloc; we won't be changing the size at all + + opts.output_format = DIFF_FORMAT_NO_OUTPUT; + diff_queued_diff.nr = 0; + diff_queued_diff.queue = NULL; + diff_flush(&opts); + return ret; +} + +/* + * Get information of all renames which occurred in 'pairs', making use of + * any implicit directory renames inferred from the other side of history. + * We need the three trees in the merge ('o_tree', 'a_tree' and 'b_tree') + * to be able to associate the correct cache entries with the rename + * information; tree is always equal to either a_tree or b_tree. + */ +static struct string_list *get_renames(struct merge_options *o, + struct diff_queue_struct *pairs, + struct tree *tree, + struct tree *o_tree, + struct tree *a_tree, + struct tree *b_tree, + struct string_list *entries) +{ + int i; + struct string_list *renames; + + renames = xcalloc(1, sizeof(struct string_list)); + + for (i = 0; i < pairs->nr; ++i) { struct string_list_item *item; struct rename *re; - struct diff_filepair *pair = diff_queued_diff.queue[i]; + struct diff_filepair *pair = pairs->queue[i]; if (pair->status != 'R') { diff_free_filepair(pair); continue; @@ -1375,9 +1399,6 @@ static struct string_list *get_renames(struct merge_options *o, item = string_list_insert(renames, pair->one->path); item->util = re; } - opts.output_format = DIFF_FORMAT_NO_OUTPUT; - diff_queued_diff.nr = 0; - diff_flush(&opts); return renames; } @@ -1649,15 +1670,33 @@ static struct rename_info *handle_renames(struct merge_options *o, int *clean) { struct rename_info *rei = xcalloc(1, sizeof(struct rename_info)); + struct diff_queue_struct *head_pairs, *merge_pairs; *clean = 1; if (!o->detect_rename) return NULL; - rei->head_renames = get_renames(o, head, common, head, merge, entries); - rei->merge_renames = get_renames(o, merge, common, head, merge, entries); + head_pairs = get_diffpairs(o, common, head); + merge_pairs = get_diffpairs(o, common, merge); + + rei->head_renames = get_renames(o, head_pairs, head, + common, head, merge, entries); + rei->merge_renames = get_renames(o, merge_pairs, merge, + common, head, merge, entries); *clean = process_renames(o, rei->head_renames, rei->merge_renames); +cleanup: + /* + * Some cleanup is deferred until cleanup_renames() because the + * data structures are still needed and referenced in + * process_entry(). But there are a few things we can free now. + */ + + free(head_pairs->queue); + free(head_pairs); + free(merge_pairs->queue); + free(merge_pairs); + return rei; } -- 2.15.0.5.g9567be9905