Re: [PATCH 04/19] merge-recursive: exit early if index != head
- From
Elijah Newren <newren@gmail.com>
- Date
- Jul 25, 2019, 20:12 UTC
- Message-ID
- <CABPp-BEfqsCn11kHEAdHX9+fFv6iiSLV9TTL5XaZ_aDccNft6w@mail.gmail.com>
- In-Reply-To
- <nycvar.QRO.7.76.6.1907252142470.21907@tvgsbejvaqbjf.bet>
On Thu, Jul 25, 2019 at 12:51 PM Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
Show 43 quoted lines
> > 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.
Show 11 quoted lines
> > +{
> > + 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.
Show 20 quoted lines
> > + 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!