On Thu, Jul 25, 2019 at 12:51 PM Johannes Schindelin
<[email protected]> wrote:
>
> Hi Elijah,
>
> On Thu, 25 Jul 2019, Elijah Newren wrote:
>
> > We had a rule to enforce that the index matches head, but it was found
> > at the beginning of merge_trees() and would only trigger when
> > opt->call_depth was 0. Since merge_recursive() doesn't call
> > merge_trees() until after returning from recursing, this meant that the
> > check wasn't triggered by merge_recursive() until it had first finished
> > all the intermediate merges to create virtual merge bases. That is a
> > potentially huge amount of computation (and writing of intermediate
> > merge results into the .git/objects directory) before it errors out and
> > says, in effect, "Sorry, I can't do any merging because you have some
> > local changes that would be overwritten."
> >
> > Further, not enforcing this requirement earlier allowed other bugs (such
> > as an unintentional unconditional dropping and reloading of the index in
> > merge_recursive() even when no recursion was necessary), to mask bugs in
> > other callers (which were fixed in the commit prior to this one).
> >
> > Make sure we do the index == head check at the beginning of the merge,
> > and error out immediately if it fails.
>
> Very clear commit message.
>
> > diff --git a/merge-recursive.c b/merge-recursive.c
> > index 37bb94fb4d..b762ecd7bd 100644
> > --- a/merge-recursive.c
> > +++ b/merge-recursive.c
> > @@ -3381,21 +3381,14 @@ static int process_entry(struct merge_options *opt,
> > return clean_merge;
> > }
> >
> > -int merge_trees(struct merge_options *opt,
> > - struct tree *head,
> > - struct tree *merge,
> > - struct tree *common,
> > - struct tree **result)
> > +static int merge_trees_internal(struct merge_options *opt,
>
> In other, similar cases, we seem to use the suffix `_1`. Not sure
> whether you want to change that here.
Hmm, we do seem to use `_1` about 2.5 times as frequently as
`_internal`, but both do seem to be in use to me (e.g.
init_tree_desc_internal, convert_to_working_tree_internal,
repo_parse_commit_internal). `_1` does have the advantage of being
shorter, which makes lines fit in 80 columns better, but `_internal`
seems like a clearer description to me.
So...I'm not sure what's best here. I don't have a strong opinion,
but I'm inclined towards laziness and leaving it alone unless someone
else has strong opinions.
> > +{
> > + struct strbuf sb = STRBUF_INIT;
> > +
> > + assert(opt->branch1 && opt->branch2);
> > +
> > + if (repo_index_has_changes(opt->repo, head, &sb)) {
> > + err(opt, _("Your local changes to the following files would
> > be overwritten by merge:\n %s"),
> > + sb.buf);
>
> I know that you did not introduce this leak, but maybe we could slip an
> `strbuf_release(&sb);` in at this point?
Ooh, good point. I'll fix that up for round 2.
> > + return -1;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static void merge_finalize(struct merge_options *opt)
> > +{
> > + /* Common code for wrapping up merges will be added here later */
> > +}
>
> I was about to comment that this complicates this here diff and that we
> should do this when we need it, but I just peeked into the next patch,
> and it uses it, so I leave this here paragraph only to show that I
> actually reviewed this part, too.
>
> And of course, if we have a `merge_finalize()`, then a `merge_start()`
> does not sound all that bad, either.
>
> The rest looks good to me.
Thanks!