From 44c48a909ae3d49afcaedb2b2cd042d1e329ee93 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 13 Aug 2010 12:17:45 -0700 Subject: diff --follow: do call diffcore_std() as necessary Usually, diff frontends populate the output queue with filepairs without any rename information and call diffcore_std() to sort the renames out. When --follow is in effect, however, diff-tree family of frontend has a hack that looks like this: diff-tree frontend -> diff_tree_sha1() . populate diff_queued_diff . if --follow is in effect and there is only one change that creates the target path, then -> try_to_follow_renames() -> diff_tree_sha1() with no pathspec but with -C -> diffcore_std() to find renames . if rename is found, tweak diff_queued_diff and put a single filepair that records the found rename there -> diffcore_std() . tweak elements on diff_queued_diff by - rename detection - path ordering - pickaxe filtering We need to skip parts of the second call to diffcore_std() that is related to rename detection, and do so only when try_to_follow_renames() did find a rename. Earlier 1da6175 (Make diffcore_std only can run once before a diff_flush, 2010-05-06) tried to deal with this issue incorrectly; it unconditionally disabled any second call to diffcore_std(). This hopefully fixes the breakage. Signed-off-by: Junio C Hamano --- diff.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'diff.c') diff --git a/diff.c b/diff.c index bf65892f78..93004922de 100644 --- a/diff.c +++ b/diff.c @@ -4064,25 +4064,24 @@ void diffcore_fix_diff_index(struct diff_options *options) void diffcore_std(struct diff_options *options) { - /* We never run this function more than one time, because the - * rename/copy detection logic can only run once. - */ - if (diff_queued_diff.run) - return; - if (options->skip_stat_unmatch) diffcore_skip_stat_unmatch(options); - if (options->break_opt != -1) - diffcore_break(options->break_opt); - if (options->detect_rename) - diffcore_rename(options); - if (options->break_opt != -1) - diffcore_merge_broken(); + if (!options->found_follow) { + /* See try_to_follow_renames() in tree-diff.c */ + if (options->break_opt != -1) + diffcore_break(options->break_opt); + if (options->detect_rename) + diffcore_rename(options); + if (options->break_opt != -1) + diffcore_merge_broken(); + } if (options->pickaxe) diffcore_pickaxe(options->pickaxe, options->pickaxe_opts); if (options->orderfile) diffcore_order(options->orderfile); - diff_resolve_rename_copy(); + if (!options->found_follow) + /* See try_to_follow_renames() in tree-diff.c */ + diff_resolve_rename_copy(); diffcore_apply_filter(options->filter); if (diff_queued_diff.nr && !DIFF_OPT_TST(options, DIFF_FROM_CONTENTS)) @@ -4090,7 +4089,7 @@ void diffcore_std(struct diff_options *options) else DIFF_OPT_CLR(options, HAS_CHANGES); - diff_queued_diff.run = 1; + options->found_follow = 0; } int diff_result_code(struct diff_options *opt, int status) -- cgit 1.2.3-korg