Re: [PATCH v3 04/24] merge-recursive: provide a better label for diff3 common ancestor
- From
Elijah Newren <newren@gmail.com>
- Date
- Aug 16, 2019, 22:39 UTC
- Message-ID
- <CABPp-BHuJB6RZ0htNa8Vmah++MiQFTvcGSDpdhtQ1cZBFwZSNQ@mail.gmail.com>
- In-Reply-To
- <xmqqpnl4ztfl.fsf@gitster-ct.c.googlers.com>
On Fri, Aug 16, 2019 at 2:33 PM Junio C Hamano <gitster@pobox.com> wrote:
Show 16 quoted lines
> > Elijah Newren <newren@gmail.com> writes: > > > @@ -3507,6 +3507,11 @@ int merge_recursive(struct merge_options *opt, > > struct commit *merged_common_ancestors; > > struct tree *mrtree; > > int clean; > > + int num_merge_bases; > > + struct strbuf merge_base_abbrev = STRBUF_INIT; > > + > > + if (!opt->call_depth) > > + assert(opt->ancestor == NULL); > > Hmph. Do we have anything to say on this field when call_depth is > not zero? Is it OK for opt->ancestor to be sometimes NULL and non > NULL some other times?
I was specifically trying to add a check for external callers of merge_recursive() to make sure they called it correctly. Since merge_recursive() sets opt->ancestor before calling itself recursively, I had to hide the assertion behind an if-check, namely on call_depth.
We could add an assertion that opt->ancestor != NULL when opt->call_depth > 0, but it seemed odd to document pre-conditions for how merge_recursive() calls itself. Anyway, this code block actually becomes a bit cleaner later in the series when I create separate merge_recursive() and merge_recursive_internal() functions, as the assertion can just go into merge_recursive() and not be protected by the opt->call_depth check.
Show 38 quoted lines
> > @@ -3528,6 +3533,7 @@ int merge_recursive(struct merge_options *opt,
> > output_commit_title(opt, iter->item);
> > }
> >
> > + num_merge_bases = commit_list_count(ca);
>
> Criss-cross merge with very large number of merge bases is rare, so
> it is OK to count them all, even though we only care about "is it
> zero, is it one, or is it two or more?"
>
> I suspect this does not have to count, though, if we really wanted
> to avoid counting.
>
> > merged_common_ancestors = pop_commit(&ca);
> > if (merged_common_ancestors == NULL) {
> > /* if there is no common ancestor, use an empty tree */
>
> Here is the case where we can already decide the ancestor name for
> the later merge_trees() should be "empty tree".
>
> And if merged_common_ancestors is not NULL, ca may have run out (in
> which case, we only have a single merge base), or ca still has
> another merge base (in which case, we have two or more). So, if you
> add
> ancestor_name = "empty tree";
> } else if (ca) {
> ancestor_name = "merged common ancestors";
> } else {
> ancestor_name = abbrev_name(merged_common_ancestors);
> }
>
> to that if() statement above, that should be sufficient, no?
>
> opt is used for inner merge in the for() loop, so you would probably
> need another "char *" variable without contaminating opt->ancestor_name
> at this point, and then assign the value in the temporary to the
> opt->ancestor field where the original always assigned "merged
> common ancestors".Sure, I can make these changes.
Show 12 quoted lines
> > @@ -3568,10 +3574,23 @@ int merge_recursive(struct merge_options *opt,
> > if (!opt->call_depth)
> > repo_read_index(opt->repo);
> >
> > - opt->ancestor = "merged common ancestors";
> > + switch (num_merge_bases) {
> > + case 0:
> > + opt->ancestor = "<empty tree>";
>
> Also, I do not see a reason why you want angle bra-ket pair around
> "empty tree". You are already using "merged common ancestors"
> literal phrase without any special marker syntax.Oh good point; will drop.