@matheusbsbs / matheus-bagliano / commits / 44c48a909a
Fork 0

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 <gitster@pobox.com>

Junio C Hamano committed Aug 13, 2010 at 12:17 UTC 44c48a909ae3d49afcaedb2b2cd042d1e329ee93
4 files changed +27 -16
diff.c
+13 -14
@@ -4064,25 +4064,24 @@ void diffcore_fix_diff_index(struct diff_options *options)
4064
4065 void diffcore_std(struct diff_options *options)
4066 {
4067 - /* We never run this function more than one time, because the
4068 - * rename/copy detection logic can only run once.
4069 - */
4070 - if (diff_queued_diff.run)
4071 - return;
4072 -
4067 if (options->skip_stat_unmatch)
4068 diffcore_skip_stat_unmatch(options);
4075 - if (options->break_opt != -1)
4076 - diffcore_break(options->break_opt);
4077 - if (options->detect_rename)
4078 - diffcore_rename(options);
4079 - if (options->break_opt != -1)
4080 - diffcore_merge_broken();
4069 + if (!options->found_follow) {
4070 + /* See try_to_follow_renames() in tree-diff.c */
4071 + if (options->break_opt != -1)
4072 + diffcore_break(options->break_opt);
4073 + if (options->detect_rename)
4074 + diffcore_rename(options);
4075 + if (options->break_opt != -1)
4076 + diffcore_merge_broken();
4077 + }
4078 if (options->pickaxe)
4079 diffcore_pickaxe(options->pickaxe, options->pickaxe_opts);
4080 if (options->orderfile)
4081 diffcore_order(options->orderfile);
4085 - diff_resolve_rename_copy();
4082 + if (!options->found_follow)
4083 + /* See try_to_follow_renames() in tree-diff.c */
4084 + diff_resolve_rename_copy();
4085 diffcore_apply_filter(options->filter);
4086
4087 if (diff_queued_diff.nr && !DIFF_OPT_TST(options, DIFF_FROM_CONTENTS))
@@ -4090,7 +4089,7 @@ void diffcore_std(struct diff_options *options)
4089 else
4090 DIFF_OPT_CLR(options, HAS_CHANGES);
4091
4093 - diff_queued_diff.run = 1;
4092 + options->found_follow = 0;
4093 }
4094
4095 int diff_result_code(struct diff_options *opt, int status)
diff.h
+3
@@ -126,6 +126,9 @@ struct diff_options {
126 /* this is set by diffcore for DIFF_FORMAT_PATCH */
127 int found_changes;
128
129 + /* to support internal diff recursion by --follow hack*/
130 + int found_follow;
131 +
132 FILE *file;
133 int close_file;
134
diffcore.h
-2
@@ -91,13 +91,11 @@ struct diff_queue_struct {
91 struct diff_filepair **queue;
92 int alloc;
93 int nr;
94 - int run;
94 };
95 #define DIFF_QUEUE_CLEAR(q) \
96 do { \
97 (q)->queue = NULL; \
98 (q)->nr = (q)->alloc = 0; \
100 - (q)->run = 0; \
99 } while (0)
100
101 extern struct diff_queue_struct diff_queued_diff;
tree-diff.c
+11
@@ -359,6 +359,7 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co
359 diff_tree_release_paths(&diff_opts);
360
361 /* Go through the new set of filepairing, and see if we find a more interesting one */
362 + opt->found_follow = 0;
363 for (i = 0; i < q->nr; i++) {
364 struct diff_filepair *p = q->queue[i];
365
@@ -376,6 +377,16 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co
377 diff_tree_release_paths(opt);
378 opt->paths[0] = xstrdup(p->one->path);
379 diff_tree_setup_paths(opt->paths, opt);
380 +
381 + /*
382 + * The caller expects us to return a set of vanilla
383 + * filepairs to let a later call to diffcore_std()
384 + * it makes to sort the renames out (among other
385 + * things), but we already have found renames
386 + * ourselves; signal diffcore_std() not to muck with
387 + * rename information.
388 + */
389 + opt->found_follow = 1;
390 break;
391 }
392 }