[PATCH V6] revset: support ranges in #generations relation

Yuya Nishihara yuya at tcha.org
Fri Jan 18 08:31:24 EST 2019


On Fri, 18 Jan 2019 17:56:33 +0800, Anton Shestakov wrote:
> # HG changeset patch
> # User Anton Shestakov <av6 at dwimlabs.net>
> # Date 1547564229 -28800
> #      Tue Jan 15 22:57:09 2019 +0800
> # Node ID 6069a3fcef9b0f9e80cd884c38f6a9e2a35e757a
> # Parent  8aca89a694d4bd7d25877b3652fb83e187ea1802
> revset: support ranges in #generations relation

> +    >>> _splitrange(0, 0)        # [0:0]
> +    ([None, None], [0, 1])

Ancestors should be preferred. Computing descendants is way expensive.
I should pointed out it before, sorry.

> +    if a is None or a < 0:
> +        if b is None or b >= 0:
> +            if b == 0:
> +                depths[0][0] = 0
> +            else:
> +                depths[0][0] = 1
> +        else:
> +            depths[0][0] = -b
> +        if a is None:
> +            depths[0][1] = None
> +        else:
> +            depths[0][1] = -a + 1
> +
> +    if b is None or b > 0 or (a == 0 and b == 0):
> +        if a is None or a < 0:
> +            depths[1][0] = 0
> +        else:
> +            depths[1][0] = a
> +        if b is None:
> +            depths[1][1] = None
> +        else:
> +            depths[1][1] = b + 1
> +
> +    return depths

Playing with this for a while, I came to think that we should first replace
None with saner integer value.

    if a is None:
        a = -(dagop._maxlogdepth - 1)
    if b is None:
        b = +(dagop._maxlogdepth - 1)

We have to make maxlogdepth public, and fix dagop.revdescendats() to map it
to fast path, but eliminating None will greatly simplify the function:

    anc = dec = None
    if a == b == 0:
        anc = (0, 1)
    if a < 0:
        anc = (-min(b, 0), -a + 1)
    if b > 0:
        dec = (max(a, 0), b + 1)
    return anc, dec

> +def generationsrel(repo, subset, x, rel, a, b, order):
> +    # TODO: rewrite tests, and drop startdepth argument from ancestors() and
> +    # descendants() predicates
> +    depths = _splitrange(a, b)
> +    ancstart, ancstop = depths[0]
> +    descstart, descstop = depths[1]
> +
> +    if ancstart is not None and descstart is not None:
> +        return (_ancestors(repo, subset, x, False, ancstart, ancstop) +
> +                _descendants(repo, subset, x, False, descstart, descstop))
> +    elif ancstart is not None:
> +        return _ancestors(repo, subset, x, False, ancstart, ancstop)
> +    elif descstart is not None:
> +        return _descendants(repo, subset, x, False, descstart, descstop)
> +
> +    return baseset()

As a follow-up, it's better to not evaluate 'x' twice.

  heads = getset(repo, fullreposet(repo), x)
  ...
  anc = dagop.revancestors(...)
  dec = dagop.revdescendats(...)
  return subset & (anc + dec)


More information about the Mercurial-devel mailing list