Subject: Re: [PATCH 6/8] commit: provide a fast multi-tip contains function

From: Junio C Hamano <[email-masked]>
Date: Thu, 26 Jun 2014 12:19:52 -0700

Junio C Hamano <[email-masked]> writes:

> The only time you can say "Ah, we've seen this one and no need to
> dig further" is when you are propagating a colour C and the parent
> in question is already painted in C (it is OK to be painted as
> reachable from more tips), I would think, so shouldn't the loop be
> more like, after painting each tip and placing it in the queue:
>
>  * Dequeue one, check the L/R bits in it and call that C
>
>  * Iterate over its parents P:
>
>    * check the L/R bits in P and call that Cp.
>
>    * If Cp is already a superset of C, there is no point putting P
>      to the queue to be processed.
>
>    * If Cp is not a superset of C, then update L/R bits in P to mark
>      it reachable from tips represented by C and put P to the queue.
>
> until you ran out of queue?

Actually that will cause you to dig down to the root, so it won't be
nice.

If you are trying to do "branch --with $commit", what you would want
is not exactly "paint-down-to-common(all branches, $commit)", but
something that paints down to $commit from all branches, with an
optimization that cuts off the traversal at a commit that is
reachable from $commit.  If a traversal from branch B reached such a
commit that is reachable from $commit, you can stop the traversal
because propagating the bit for B further down to its parents will
not reach the $commit you are interested in.

So the termination condition for this a single Left (I'll use Left
for $commit and Right for "all branches") case is "if a commit is
already painted as reachable from $commit, do not propagate bits
further down".

What does it mean to look for "branch --with $commit1 $commit2"
(i.e. more than one in the Left set)?  If we are trying to see which
branches reach _both_ of these commits, then replace the ablve with
"if a commit is already painted as reachable from both $commit{1,2},
then painting it with any branch bits is futile---its parents will
never reach either $commit1 nor $commit2", so the additional
termination condition will be "If left bits are full, then stop".

I do not know how you can optimize the traversal if you are trying
to see which branches reach at least one of these commits, though.