Skip to content

Commit 44c48a9

Browse files
committed
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 <[email protected]>
1 parent 39f75d2 commit 44c48a9

File tree

4 files changed

+27
-16
lines changed

4 files changed

+27
-16
lines changed

diff.c

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4064,33 +4064,32 @@ void diffcore_fix_diff_index(struct diff_options *options)
40644064

40654065
void diffcore_std(struct diff_options *options)
40664066
{
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-
40734067
if (options->skip_stat_unmatch)
40744068
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+
}
40814078
if (options->pickaxe)
40824079
diffcore_pickaxe(options->pickaxe, options->pickaxe_opts);
40834080
if (options->orderfile)
40844081
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();
40864085
diffcore_apply_filter(options->filter);
40874086

40884087
if (diff_queued_diff.nr && !DIFF_OPT_TST(options, DIFF_FROM_CONTENTS))
40894088
DIFF_OPT_SET(options, HAS_CHANGES);
40904089
else
40914090
DIFF_OPT_CLR(options, HAS_CHANGES);
40924091

4093-
diff_queued_diff.run = 1;
4092+
options->found_follow = 0;
40944093
}
40954094

40964095
int diff_result_code(struct diff_options *opt, int status)

diff.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ struct diff_options {
126126
/* this is set by diffcore for DIFF_FORMAT_PATCH */
127127
int found_changes;
128128

129+
/* to support internal diff recursion by --follow hack*/
130+
int found_follow;
131+
129132
FILE *file;
130133
int close_file;
131134

diffcore.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,11 @@ struct diff_queue_struct {
9191
struct diff_filepair **queue;
9292
int alloc;
9393
int nr;
94-
int run;
9594
};
9695
#define DIFF_QUEUE_CLEAR(q) \
9796
do { \
9897
(q)->queue = NULL; \
9998
(q)->nr = (q)->alloc = 0; \
100-
(q)->run = 0; \
10199
} while (0)
102100

103101
extern struct diff_queue_struct diff_queued_diff;

tree-diff.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co
359359
diff_tree_release_paths(&diff_opts);
360360

361361
/* Go through the new set of filepairing, and see if we find a more interesting one */
362+
opt->found_follow = 0;
362363
for (i = 0; i < q->nr; i++) {
363364
struct diff_filepair *p = q->queue[i];
364365

@@ -376,6 +377,16 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co
376377
diff_tree_release_paths(opt);
377378
opt->paths[0] = xstrdup(p->one->path);
378379
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;
379390
break;
380391
}
381392
}

0 commit comments

Comments
 (0)