Junio C Hamano <gitster@xxxxxxxxx> writes: > Constantine Plotnikov <constantine.plotnikov@xxxxxxxxx> writes: > >> Somewhere between the git 1.7.0.2 and the git 1.7.2.0 the rename >> detection started to fail with fatal error on some files in our >> repository. The bug could be seen on the public IntelliJ IDEA >> repository (about 760M in size), but our users have reported it as >> well. > ... > But what 1da6175 (Make diffcore_std only can run once before a diff_flush, > 2010-05-06) did is clearly wrong. Not wanting to call resolve-rename-copy > does not mean we do not want to run the rest of what diffcore_std() does > at all! For example, "-S" and "--diff-filter=" options are processed in > that function; the exit status of the command based on the presense of > difference is computed in the function, too. This reverts 1da6175 (Make diffcore_std only can run once before a diff_flush, 2010-05-06) and replaces it with an uglier looking but hopefully correct fix. Constantine, does it fix your issue? diff.c | 27 +++++++++++++-------------- diff.h | 3 +++ diffcore.h | 2 -- tree-diff.c | 12 ++++++++++++ 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/diff.c b/diff.c index bf65892..9300492 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) diff --git a/diff.h b/diff.h index 063d10a..6fff024 100644 --- a/diff.h +++ b/diff.h @@ -126,6 +126,9 @@ struct diff_options { /* this is set by diffcore for DIFF_FORMAT_PATCH */ int found_changes; + /* to support internal diff recursion by --follow hack*/ + int found_follow; + FILE *file; int close_file; diff --git a/diffcore.h b/diffcore.h index 05ebc11..8b3241a 100644 --- a/diffcore.h +++ b/diffcore.h @@ -91,13 +91,11 @@ struct diff_queue_struct { struct diff_filepair **queue; int alloc; int nr; - int run; }; #define DIFF_QUEUE_CLEAR(q) \ do { \ (q)->queue = NULL; \ (q)->nr = (q)->alloc = 0; \ - (q)->run = 0; \ } while (0) extern struct diff_queue_struct diff_queued_diff; diff --git a/tree-diff.c b/tree-diff.c index 5b68c08..293cc91 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -350,6 +350,7 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co diff_opts.output_format = DIFF_FORMAT_NO_OUTPUT; diff_opts.single_follow = opt->paths[0]; diff_opts.break_opt = opt->break_opt; + paths[0] = NULL; diff_tree_setup_paths(paths, &diff_opts); if (diff_setup_done(&diff_opts) < 0) @@ -359,6 +360,7 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co diff_tree_release_paths(&diff_opts); /* Go through the new set of filepairing, and see if we find a more interesting one */ + opt->found_follow = 0; for (i = 0; i < q->nr; i++) { struct diff_filepair *p = q->queue[i]; @@ -376,6 +378,16 @@ static void try_to_follow_renames(struct tree_desc *t1, struct tree_desc *t2, co diff_tree_release_paths(opt); opt->paths[0] = xstrdup(p->one->path); diff_tree_setup_paths(opt->paths, opt); + + /* + * The caller expects us to return a set of vanilla + * filepairs to let a later call to diffcore_std() + * it makes to sort the renames out (among other + * things), but we already have found renames + * ourselves; signal diffcore_std() not to muck with + * rename information. + */ + opt->found_follow = 1; break; } } -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html