{"thread":{"id":"61931","subject":"[PATCH 1/2] remerge-diff: lazily prpare temporary objdir on demand","startedAt":"2024-08-09T22:30:53Z","lastAt":"2024-09-08T21:16:28Z","messageCount":6,"participants":["Junio C Hamano","Eric Sunshine","Elijah Newren"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"500581","messageId":"xmqqv8099vms.fsf@gitster.g","threadId":"61931","inReplyTo":null,"subject":"[PATCH 1/2] remerge-diff: lazily prpare temporary objdir on demand","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-08-09T22:30:51Z","receivedAt":"2024-08-09T22:30:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"It is error prone for each caller that sets revs.remerge_diff bit\nto be responsible for preparing a temporary object directory and\nrotate it into the list of alternate object stores, making it the\nprimary object store.\n\nInstead, remove the code to set up and arrange the temporary object\ndirectory from the current callers and implement it in the code that\nruns remerge-diff logic.  The code to undo the futzing of the list\nof alternate object store is still spread across the callers, but we\nwill deal with it in future steps.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n\n * So here are two patches to illustate how the code to do the lazy\n   set-up and centralized tear down looks like.  The first part is\n   the lazy set-up.\n\n builtin/diff-tree.c |  7 -------\n builtin/log.c       |  7 -------\n log-tree.c          | 16 ++++++++++++----\n 3 files changed, 12 insertions(+), 18 deletions(-)\n\ndiff --git a/builtin/diff-tree.c b/builtin/diff-tree.c\nindex 12012ea093..af51cd29c6 100644\n--- a/builtin/diff-tree.c\n+++ b/builtin/diff-tree.c\n@@ -168,13 +168,6 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)\n \n \topt->diffopt.rotate_to_strict = 1;\n \n-\tif (opt->remerge_diff) {\n-\t\topt->remerge_objdir = tmp_objdir_create(\"remerge-diff\");\n-\t\tif (!opt->remerge_objdir)\n-\t\t\tdie(_(\"unable to create temporary object directory\"));\n-\t\ttmp_objdir_replace_primary_odb(opt->remerge_objdir, 1);\n-\t}\n-\n \t/*\n \t * NOTE!  We expect \"a..b\" to expand to \"^a b\" but it is\n \t * perfectly valid for revision range parser to yield \"b ^a\",\ndiff --git a/builtin/log.c b/builtin/log.c\nindex af6403cb71..227823a16e 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -494,13 +494,6 @@ static int cmd_log_walk_no_free(struct rev_info *rev)\n \tint saved_nrl = 0;\n \tint saved_dcctc = 0;\n \n-\tif (rev->remerge_diff) {\n-\t\trev->remerge_objdir = tmp_objdir_create(\"remerge-diff\");\n-\t\tif (!rev->remerge_objdir)\n-\t\t\tdie(_(\"unable to create temporary object directory\"));\n-\t\ttmp_objdir_replace_primary_odb(rev->remerge_objdir, 1);\n-\t}\n-\n \tif (rev->early_output)\n \t\tsetup_early_output();\n \ndiff --git a/log-tree.c b/log-tree.c\nindex 337b9334cd..83e648b7cd 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -1019,6 +1019,17 @@ static int do_remerge_diff(struct rev_info *opt,\n \tstruct strbuf parent1_desc = STRBUF_INIT;\n \tstruct strbuf parent2_desc = STRBUF_INIT;\n \n+\t/*\n+\t * Lazily prepare a temporary object directory and rotate it\n+\t * into the alternative object store list as the primary.\n+\t */\n+\tif (opt->remerge_diff && !opt->remerge_objdir) {\n+\t\topt->remerge_objdir = tmp_objdir_create(\"remerge-diff\");\n+\t\tif (!opt->remerge_objdir)\n+\t\t\treturn error(_(\"unable to create temporary object directory\"));\n+\t\ttmp_objdir_replace_primary_odb(opt->remerge_objdir, 1);\n+\t}\n+\n \t/* Setup merge options */\n \tinit_merge_options(&o, the_repository);\n \to.show_rename_progress = 0;\n@@ -1053,10 +1064,7 @@ static int do_remerge_diff(struct rev_info *opt,\n \tmerge_finalize(&o, &res);\n \n \t/* Clean up the contents of the temporary object directory */\n-\tif (opt->remerge_objdir)\n-\t\ttmp_objdir_discard_objects(opt->remerge_objdir);\n-\telse\n-\t\tBUG(\"did a remerge diff without remerge_objdir?!?\");\n+\ttmp_objdir_discard_objects(opt->remerge_objdir);\n \n \treturn !opt->loginfo;\n }\n-- \n2.46.0-326-g1e046905fc\n\n"},{"id":"500582","messageId":"xmqqr0ax9vlk.fsf@gitster.g","threadId":"61931","inReplyTo":"xmqqv8099vms.fsf@gitster.g","subject":"[PATCH 2/2] remerge-diff: clean up temporary objdir at a central place","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-08-09T22:31:35Z","receivedAt":"2024-08-09T22:31:40Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"After running a diff between two things, or a series of diffs while\nwalking the history, the diff computation is concluded by a call to\ndiff_result_code() to extract the exit status of the diff machinery.\n\nThe function can work on \"struct diffopt\", but all the callers\nhistorically and currently pass \"struct diffopt\" that is embedded in\nthe \"struct rev_info\" that is used to hold the remerge_diff bit and\nthe remerge_objdir variable that points at the temporary object\ndirectory in use.\n\nRedefine diff_result_code() to take the whole \"struct rev_info\" to\ngive it an access to these members related to remerge-diff, so that\nit can get rid of the temporary object directory for any and all\ncallers that used the feature.  We can lose the equivalent code to\ndo so from the code paths for individual commands, diff-tree, diff,\nand log.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n builtin/describe.c          |  2 +-\n builtin/diff-files.c        |  2 +-\n builtin/diff-index.c        |  2 +-\n builtin/diff-tree.c         |  7 +------\n builtin/diff.c              |  2 +-\n builtin/log.c               | 11 ++++-------\n builtin/stash.c             |  6 +++---\n builtin/submodule--helper.c |  2 +-\n diff-no-index.c             |  2 +-\n diff.c                      | 10 +++++++++-\n diff.h                      |  2 +-\n wt-status.c                 |  4 ++--\n 12 files changed, 26 insertions(+), 26 deletions(-)\n\ndiff --git a/builtin/describe.c b/builtin/describe.c\nindex d6c77a714f..a1457d59e8 100644\n--- a/builtin/describe.c\n+++ b/builtin/describe.c\n@@ -687,7 +687,7 @@ int cmd_describe(int argc, const char **argv, const char *prefix)\n \t\t\t\tBUG(\"malformed internal diff-index command line\");\n \t\t\trun_diff_index(&revs, 0);\n \n-\t\t\tif (!diff_result_code(&revs.diffopt))\n+\t\t\tif (!diff_result_code(&revs))\n \t\t\t\tsuffix = NULL;\n \t\t\telse\n \t\t\t\tsuffix = dirty;\ndiff --git a/builtin/diff-files.c b/builtin/diff-files.c\nindex 018011f29e..dd0b76e7d5 100644\n--- a/builtin/diff-files.c\n+++ b/builtin/diff-files.c\n@@ -82,7 +82,7 @@ int cmd_diff_files(int argc, const char **argv, const char *prefix)\n \tif (repo_read_index_preload(the_repository, &rev.diffopt.pathspec, 0) < 0)\n \t\tdie_errno(\"repo_read_index_preload\");\n \trun_diff_files(&rev, options);\n-\tresult = diff_result_code(&rev.diffopt);\n+\tresult = diff_result_code(&rev);\n \trelease_revisions(&rev);\n \treturn result;\n }\ndiff --git a/builtin/diff-index.c b/builtin/diff-index.c\nindex 3e05260ac0..560c099524 100644\n--- a/builtin/diff-index.c\n+++ b/builtin/diff-index.c\n@@ -71,7 +71,7 @@ int cmd_diff_index(int argc, const char **argv, const char *prefix)\n \t\treturn -1;\n \t}\n \trun_diff_index(&rev, option);\n-\tresult = diff_result_code(&rev.diffopt);\n+\tresult = diff_result_code(&rev);\n \trelease_revisions(&rev);\n \treturn result;\n }\ndiff --git a/builtin/diff-tree.c b/builtin/diff-tree.c\nindex af51cd29c6..995225ef5f 100644\n--- a/builtin/diff-tree.c\n+++ b/builtin/diff-tree.c\n@@ -232,10 +232,5 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix)\n \t\tdiff_free(&opt->diffopt);\n \t}\n \n-\tif (opt->remerge_diff) {\n-\t\ttmp_objdir_destroy(opt->remerge_objdir);\n-\t\topt->remerge_objdir = NULL;\n-\t}\n-\n-\treturn diff_result_code(&opt->diffopt);\n+\treturn diff_result_code(opt);\n }\ndiff --git a/builtin/diff.c b/builtin/diff.c\nindex 6e196e0c7d..a5834704aa 100644\n--- a/builtin/diff.c\n+++ b/builtin/diff.c\n@@ -605,7 +605,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)\n \t\tbuiltin_diff_combined(&rev, argc, argv,\n \t\t\t\t      ent.objects, ent.nr,\n \t\t\t\t      first_non_parent);\n-\tresult = diff_result_code(&rev.diffopt);\n+\tresult = diff_result_code(&rev);\n \tif (1 < rev.diffopt.skip_stat_unmatch)\n \t\trefresh_index_quietly();\n \trelease_revisions(&rev);\ndiff --git a/builtin/log.c b/builtin/log.c\nindex 227823a16e..b1a8fa73b1 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -493,6 +493,7 @@ static int cmd_log_walk_no_free(struct rev_info *rev)\n \tstruct commit *commit;\n \tint saved_nrl = 0;\n \tint saved_dcctc = 0;\n+\tint result;\n \n \tif (rev->early_output)\n \t\tsetup_early_output();\n@@ -533,16 +534,12 @@ static int cmd_log_walk_no_free(struct rev_info *rev)\n \trev->diffopt.degraded_cc_to_c = saved_dcctc;\n \trev->diffopt.needed_rename_limit = saved_nrl;\n \n-\tif (rev->remerge_diff) {\n-\t\ttmp_objdir_destroy(rev->remerge_objdir);\n-\t\trev->remerge_objdir = NULL;\n-\t}\n-\n+\tresult = diff_result_code(rev);\n \tif (rev->diffopt.output_format & DIFF_FORMAT_CHECKDIFF &&\n \t    rev->diffopt.flags.check_failed) {\n-\t\treturn 02;\n+\t\tresult = 02;\n \t}\n-\treturn diff_result_code(&rev->diffopt);\n+\treturn result;\n }\n \n static int cmd_log_walk(struct rev_info *rev)\ndiff --git a/builtin/stash.c b/builtin/stash.c\nindex 7fb355bff0..6dc70a6be2 100644\n--- a/builtin/stash.c\n+++ b/builtin/stash.c\n@@ -972,7 +972,7 @@ static int show_stash(int argc, const char **argv, const char *prefix)\n \t}\n \tlog_tree_diff_flush(&rev);\n \n-\tret = diff_result_code(&rev.diffopt);\n+\tret = diff_result_code(&rev);\n cleanup:\n \tstrvec_clear(&stash_args);\n \tfree_stash_info(&info);\n@@ -1116,13 +1116,13 @@ static int check_changes_tracked_files(const struct pathspec *ps)\n \tdiff_setup_done(&rev.diffopt);\n \n \trun_diff_index(&rev, DIFF_INDEX_CACHED);\n-\tif (diff_result_code(&rev.diffopt)) {\n+\tif (diff_result_code(&rev)) {\n \t\tret = 1;\n \t\tgoto done;\n \t}\n \n \trun_diff_files(&rev, 0);\n-\tif (diff_result_code(&rev.diffopt)) {\n+\tif (diff_result_code(&rev)) {\n \t\tret = 1;\n \t\tgoto done;\n \t}\ndiff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c\nindex cc0db6336c..96d2889907 100644\n--- a/builtin/submodule--helper.c\n+++ b/builtin/submodule--helper.c\n@@ -675,7 +675,7 @@ static void status_submodule(const char *path, const struct object_id *ce_oid,\n \tsetup_revisions(diff_files_args.nr, diff_files_args.v, &rev, &opt);\n \trun_diff_files(&rev, 0);\n \n-\tif (!diff_result_code(&rev.diffopt)) {\n+\tif (!diff_result_code(&rev)) {\n \t\tprint_status(flags, ' ', path, ce_oid,\n \t\t\t     displaypath);\n \t} else if (!(flags & OPT_CACHED)) {\ndiff --git a/diff-no-index.c b/diff-no-index.c\nindex 3a8965672c..c5fb06e6d1 100644\n--- a/diff-no-index.c\n+++ b/diff-no-index.c\n@@ -362,7 +362,7 @@ int diff_no_index(struct rev_info *revs,\n \t * The return code for --no-index imitates diff(1):\n \t * 0 = no changes, 1 = changes, else error\n \t */\n-\tret = diff_result_code(&revs->diffopt);\n+\tret = diff_result_code(revs);\n \n out:\n \tfor (i = 0; i < ARRAY_SIZE(to_free); i++)\ndiff --git a/diff.c b/diff.c\nindex ccfa1fca0d..970ea47710 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -9,6 +9,7 @@\n #include \"environment.h\"\n #include \"gettext.h\"\n #include \"tempfile.h\"\n+#include \"revision.h\"\n #include \"quote.h\"\n #include \"diff.h\"\n #include \"diffcore.h\"\n@@ -26,6 +27,7 @@\n #include \"merge-ll.h\"\n #include \"string-list.h\"\n #include \"strvec.h\"\n+#include \"tmp-objdir.h\"\n #include \"graph.h\"\n #include \"oid-array.h\"\n #include \"packfile.h\"\n@@ -7012,10 +7014,16 @@ void diffcore_std(struct diff_options *options)\n \toptions->found_follow = 0;\n }\n \n-int diff_result_code(struct diff_options *opt)\n+int diff_result_code(struct rev_info *revs)\n {\n+\tstruct diff_options *opt = &revs->diffopt;\n \tint result = 0;\n \n+\tif (revs->remerge_diff) {\n+\t\ttmp_objdir_destroy(revs->remerge_objdir);\n+\t\trevs->remerge_objdir = NULL;\n+\t}\n+\n \tdiff_warn_rename_limit(\"diff.renameLimit\",\n \t\t\t       opt->needed_rename_limit,\n \t\t\t       opt->degraded_cc_to_c);\ndiff --git a/diff.h b/diff.h\nindex 66bd8aeb29..1966ba6bb7 100644\n--- a/diff.h\n+++ b/diff.h\n@@ -648,7 +648,7 @@ int do_diff_cache(const struct object_id *, struct diff_options *);\n int diff_flush_patch_id(struct diff_options *, struct object_id *, int);\n void flush_one_hunk(struct object_id *result, git_hash_ctx *ctx);\n \n-int diff_result_code(struct diff_options *);\n+int diff_result_code(struct rev_info *);\n \n int diff_no_index(struct rev_info *,\n \t\t  int implicit_no_index, int, const char **);\ndiff --git a/wt-status.c b/wt-status.c\nindex 9e8c08003b..d1c3f3dc4d 100644\n--- a/wt-status.c\n+++ b/wt-status.c\n@@ -2582,7 +2582,7 @@ int has_unstaged_changes(struct repository *r, int ignore_submodules)\n \trev_info.diffopt.flags.quick = 1;\n \tdiff_setup_done(&rev_info.diffopt);\n \trun_diff_files(&rev_info, 0);\n-\tresult = diff_result_code(&rev_info.diffopt);\n+\tresult = diff_result_code(&rev_info);\n \trelease_revisions(&rev_info);\n \treturn result;\n }\n@@ -2616,7 +2616,7 @@ int has_uncommitted_changes(struct repository *r,\n \n \tdiff_setup_done(&rev_info.diffopt);\n \trun_diff_index(&rev_info, DIFF_INDEX_CACHED);\n-\tresult = diff_result_code(&rev_info.diffopt);\n+\tresult = diff_result_code(&rev_info);\n \trelease_revisions(&rev_info);\n \treturn result;\n }\n-- \n2.46.0-326-g1e046905fc\n\n"},{"id":"500584","messageId":"CAPig+cRYOe7dQg7qwHmHZW9WfVGJ68wWSQHikz-v+_ZhhTkG3Q@mail.gmail.com","threadId":"61931","inReplyTo":"xmqqv8099vms.fsf@gitster.g","subject":"Re: [PATCH 1/2] remerge-diff: lazily prpare temporary objdir on demand","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2024-08-09T22:37:52Z","receivedAt":"2024-08-09T22:38:05Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Aug 9, 2024 at 6:31 PM Junio C Hamano <gitster@pobox.com> wrote:\n> remerge-diff: lazily prpare temporary objdir on demand\n\ns/prpare/prepare/\n\n> It is error prone for each caller that sets revs.remerge_diff bit\n> to be responsible for preparing a temporary object directory and\n> rotate it into the list of alternate object stores, making it the\n> primary object store.\n>\n> Instead, remove the code to set up and arrange the temporary object\n> directory from the current callers and implement it in the code that\n> runs remerge-diff logic.  The code to undo the futzing of the list\n> of alternate object store is still spread across the callers, but we\n> will deal with it in future steps.\n>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n"},{"id":"500613","messageId":"xmqqbk1y8gm1.fsf@gitster.g","threadId":"61931","inReplyTo":"xmqqr0ax9vlk.fsf@gitster.g","subject":"Re: [PATCH 2/2] remerge-diff: clean up temporary objdir at a central place","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-08-12T05:17:26Z","receivedAt":"2024-08-12T05:17:34Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> After running a diff between two things, or a series of diffs while\n> walking the history, the diff computation is concluded by a call to\n> diff_result_code() to extract the exit status of the diff machinery.\n>\n> The function can work on \"struct diffopt\", but all the callers\n> historically and currently pass \"struct diffopt\" that is embedded in\n> the \"struct rev_info\" that is used to hold the remerge_diff bit and\n> the remerge_objdir variable that points at the temporary object\n> directory in use.\n>\n> Redefine diff_result_code() to take the whole \"struct rev_info\" to\n> give it an access to these members related to remerge-diff, so that\n> it can get rid of the temporary object directory for any and all\n> callers that used the feature.  We can lose the equivalent code to\n> do so from the code paths for individual commands, diff-tree, diff,\n> and log.\n>\n> Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> ---\n\nI forgot to add that I am not happy with this \"centralized tear\ndown\" step, even though I am reasonably happy with the \"lazy set-up\"\nstep.  I wonder why the remerge-diff related members have to exist\nin the rev_info structure in the first place, instead of being in\nthe diffopt structure?  Moving them to diffopt may make the end\nresult much more pleasant to read.\n"},{"id":"501085","messageId":"CABPp-BGmeg3x-F2ZjLzqcDYzSMOfz8Q3BDKUtB=vMO90yJRb3A@mail.gmail.com","threadId":"61931","inReplyTo":"xmqqbk1y8gm1.fsf@gitster.g","subject":"Re: [PATCH 2/2] remerge-diff: clean up temporary objdir at a central place","fromName":"Elijah Newren","fromEmail":"newren@gmail.com","sentAt":"2024-08-16T06:19:37Z","receivedAt":"2024-08-16T06:19:51Z","isPatch":true,"sender":{"key":"newren@gmail.com","avatar":"https://avatars.githubusercontent.com/u/5455730?v=4"},"body":"On Sun, Aug 11, 2024 at 10:17 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n> > After running a diff between two things, or a series of diffs while\n> > walking the history, the diff computation is concluded by a call to\n> > diff_result_code() to extract the exit status of the diff machinery.\n> >\n> > The function can work on \"struct diffopt\", but all the callers\n> > historically and currently pass \"struct diffopt\" that is embedded in\n> > the \"struct rev_info\" that is used to hold the remerge_diff bit and\n> > the remerge_objdir variable that points at the temporary object\n> > directory in use.\n> >\n> > Redefine diff_result_code() to take the whole \"struct rev_info\" to\n> > give it an access to these members related to remerge-diff, so that\n> > it can get rid of the temporary object directory for any and all\n> > callers that used the feature.  We can lose the equivalent code to\n> > do so from the code paths for individual commands, diff-tree, diff,\n> > and log.\n> >\n> > Signed-off-by: Junio C Hamano <gitster@pobox.com>\n> > ---\n>\n> I forgot to add that I am not happy with this \"centralized tear\n> down\" step, even though I am reasonably happy with the \"lazy set-up\"\n> step.  I wonder why the remerge-diff related members have to exist\n> in the rev_info structure in the first place, instead of being in\n> the diffopt structure?  Moving them to diffopt may make the end\n> result much more pleasant to read.\n\nI'm not sure they need to exist in the rev_info structure.  I was\nprobably thinking that e.g. log --remerge-diff would \"need to do lots\nof diffs\" but I only needed the temporary store setup once, and once\nin my mind matched better with rev_info.  I wasn't aware of\ndiff_options.no_free or anything surrounding it.  If we can do the\ntemporary store setup in diffopt and only do it once for all N diffs\nin a `git log --remerge-diff` run, then we could move this stuff from\nrev_info to diffopt.\n"},{"id":"502410","messageId":"xmqqed5tx2vv.fsf@gitster.g","threadId":"61931","inReplyTo":"CABPp-BGmeg3x-F2ZjLzqcDYzSMOfz8Q3BDKUtB=vMO90yJRb3A@mail.gmail.com","subject":"Re: [PATCH 2/2] remerge-diff: clean up temporary objdir at a central place","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2024-09-08T21:16:20Z","receivedAt":"2024-09-08T21:16:28Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Elijah Newren <newren@gmail.com> writes:\n\n>> I forgot to add that I am not happy with this \"centralized tear\n>> down\" step, even though I am reasonably happy with the \"lazy set-up\"\n>> step.  I wonder why the remerge-diff related members have to exist\n>> in the rev_info structure in the first place, instead of being in\n>> the diffopt structure?  Moving them to diffopt may make the end\n>> result much more pleasant to read.\n>\n> I'm not sure they need to exist in the rev_info structure.  I was\n> probably thinking that e.g. log --remerge-diff would \"need to do lots\n> of diffs\" but I only needed the temporary store setup once, and once\n> in my mind matched better with rev_info.  I wasn't aware of\n> diff_options.no_free or anything surrounding it.  If we can do the\n> temporary store setup in diffopt and only do it once for all N diffs\n> in a `git log --remerge-diff` run, then we could move this stuff from\n> rev_info to diffopt.\n\nAfter staring at the data structure around this area for a while, I\nthink these two patches are OK, especially within the current\nstructure.  rev_info structure has a set of bits that are marked as\n\"Diff flags\" (some of which are not about diff at all, though; for\nexample, verbose_header and no_commit_id belong more to the \"Format\ninfo\" group), and those related to merges do belong there, as they\nneed more than \"here are two tree-like things I want to compare\".\n\nSo, I'll mark these two patches for 'next' now.\n\nThanks.\n\n"}]}