Patchwork [RFC] revset: lookup descendents for negative arguments to ancestor operator

login
register
mail settings
Submitter David Soria Parra
Date May 27, 2017, 5:26 p.m.
Message ID <47c710c797624b6d5c84.1495905969@davidsp-mbp.dhcp.thefacebook.com>
Download mbox | patch
Permalink /patch/20964/
State Accepted
Headers show

Comments

David Soria Parra - May 27, 2017, 5:26 p.m.
# HG changeset patch
# User David Soria Parra <davidsp@fb.com>
# Date 1495905909 25200
#      Sat May 27 10:25:09 2017 -0700
# Node ID 47c710c797624b6d5c84c493a873ea8beb563a74
# Parent  b647b923486f38d83b92089eafa9faafaa79785d
revset: lookup descendents for negative arguments to ancestor operator

Negative offsets to the `~` operator now search for descendents. The search is
aborted when a node has more than one child as we do not have a definition for
'nth child'. Optionally we can introduce such a notion and take the nth child
ordered by rev number.

The current revset language does provides a short operator for ancestor lookup
but not for descendents. This gives user a simple revset to move to the previous
changeset, e.g. `hg up '.~1'` but not to the 'next' changeset. With this change
userse can now use `.~-1` as a shortcut to move to the next changeset.
This fits better into allowing users to specify revisions via revsets and
avoiding the need for special `hg next` and `hg prev` operations.

The alternative to negative offsets is adding a new operator. We do not have
many operators in ascii left that do not require bash escaping (',', '_', and
'/' come to mind). If we decide that we should add a more convenient short
operator such as ('/', e.g. './1') we can later add it and allow ascendents
lookup via negative numbers.
Denis Laxalde - May 29, 2017, 12:45 p.m.
David Soria Parra a écrit :
> # HG changeset patch
> # User David Soria Parra <davidsp@fb.com>
> # Date 1495905909 25200
> #      Sat May 27 10:25:09 2017 -0700
> # Node ID 47c710c797624b6d5c84c493a873ea8beb563a74
> # Parent  b647b923486f38d83b92089eafa9faafaa79785d
> revset: lookup descendents for negative arguments to ancestor operator
>
> Negative offsets to the `~` operator now search for descendents. The search is
> aborted when a node has more than one child as we do not have a definition for
> 'nth child'. Optionally we can introduce such a notion and take the nth child
> ordered by rev number.

My first though is that using a minus sign to move forward in history is
also a bit puzzling...

> The current revset language does provides a short operator for ancestor lookup
> but not for descendents. This gives user a simple revset to move to the previous
> changeset, e.g. `hg up '.~1'` but not to the 'next' changeset. With this change
> userse can now use `.~-1` as a shortcut to move to the next changeset.
> This fits better into allowing users to specify revisions via revsets and
> avoiding the need for special `hg next` and `hg prev` operations.

The :: operator comes to mind when one mentions "descendants", except
that it does not only yield descendants only but also the source
revision. So one might use `hg up 'limit(.::, 2)'` instead of `hg next`.
With a revsetalias "next=limit(.::, 2)", it's quite handy I think. It's
missing the abort in case of ambiguous destination / multiple children.
On the other hand, while I think aborting makes sense when used with `hg
update`, for log-like commands, I'm not sure it's very useful over .::,
especially with graph-log output. (Also `hg up '.~1'` will not abort if
. is a merge changeset with ambiguous destination; so this will not be
symmetrical with `hg up '.~-1'`.)

> The alternative to negative offsets is adding a new operator. We do not have
> many operators in ascii left that do not require bash escaping (',', '_', and
> '/' come to mind). If we decide that we should add a more convenient short
> operator such as ('/', e.g. './1') we can later add it and allow ascendents
> lookup via negative numbers.
>
Yuya Nishihara - May 29, 2017, 2:28 p.m.
On Mon, 29 May 2017 14:45:39 +0200, Denis Laxalde wrote:
> David Soria Parra a écrit :
> > # HG changeset patch
> > # User David Soria Parra <davidsp@fb.com>
> > # Date 1495905909 25200
> > #      Sat May 27 10:25:09 2017 -0700
> > # Node ID 47c710c797624b6d5c84c493a873ea8beb563a74
> > # Parent  b647b923486f38d83b92089eafa9faafaa79785d
> > revset: lookup descendents for negative arguments to ancestor operator
> >
> > Negative offsets to the `~` operator now search for descendents. The search is
> > aborted when a node has more than one child as we do not have a definition for
> > 'nth child'. Optionally we can introduce such a notion and take the nth child
> > ordered by rev number.
> 
> My first though is that using a minus sign to move forward in history is
> also a bit puzzling...

I agree it's a bit puzzling, but I also think it's an acceptable extension to
the `~` operator as long as descendants history is linear. However, from
implementation POV, it would be unnecessarily expensive to make sure there's
no more than one child.

> > The current revset language does provides a short operator for ancestor lookup
> > but not for descendents. This gives user a simple revset to move to the previous
> > changeset, e.g. `hg up '.~1'` but not to the 'next' changeset. With this change
> > userse can now use `.~-1` as a shortcut to move to the next changeset.
> > This fits better into allowing users to specify revisions via revsets and
> > avoiding the need for special `hg next` and `hg prev` operations.
> 
> The :: operator comes to mind when one mentions "descendants", except
> that it does not only yield descendants only but also the source
> revision. So one might use `hg up 'limit(.::, 2)'` instead of `hg next`.
> With a revsetalias "next=limit(.::, 2)", it's quite handy I think. It's
> missing the abort in case of ambiguous destination / multiple children.
> On the other hand, while I think aborting makes sense when used with `hg
> update`, for log-like commands, I'm not sure it's very useful over .::,
> especially with graph-log output. (Also `hg up '.~1'` will not abort if
> . is a merge changeset with ambiguous destination; so this will not be
> symmetrical with `hg up '.~-1'`.)
> 
> > The alternative to negative offsets is adding a new operator. We do not have
> > many operators in ascii left that do not require bash escaping (',', '_', and
> > '/' come to mind). If we decide that we should add a more convenient short
> > operator such as ('/', e.g. './1') we can later add it and allow ascendents
> > lookup via negative numbers.

These characters can't be used. '_' and '/' are taken as symbols, and ','
would complicate the language.
Sean Farley - May 31, 2017, 3:57 a.m.
David Soria Parra <davidsp@fb.com> writes:

> # HG changeset patch
> # User David Soria Parra <davidsp@fb.com>
> # Date 1495905909 25200
> #      Sat May 27 10:25:09 2017 -0700
> # Node ID 47c710c797624b6d5c84c493a873ea8beb563a74
> # Parent  b647b923486f38d83b92089eafa9faafaa79785d
> revset: lookup descendents for negative arguments to ancestor operator
>
> Negative offsets to the `~` operator now search for descendents. The search is
> aborted when a node has more than one child as we do not have a definition for
> 'nth child'. Optionally we can introduce such a notion and take the nth child
> ordered by rev number.
>
> The current revset language does provides a short operator for ancestor lookup
> but not for descendents. This gives user a simple revset to move to the previous
> changeset, e.g. `hg up '.~1'` but not to the 'next' changeset. With this change
> userse can now use `.~-1` as a shortcut to move to the next changeset.
> This fits better into allowing users to specify revisions via revsets and
> avoiding the need for special `hg next` and `hg prev` operations.

Thanks for picking this back up! Back in the day, I had an idea for this
that was: x^-1 (first child), x^-2 (second child; ordered by rev num)
since that seems to be symmetric to what we have now.

x^-1^-1 would then be equivalent to x~-2. This eventually all got
derailed before and during the last London sprint when mpm suggested the
following:

(added to https://www.mercurial-scm.org/wiki/RevsetOperatorPlan)

http://markmail.org/message/sjnnwa43s4eksu62

Nothing ever came of it but it might provide some insight into previous
pitfalls.
Yuya Nishihara - May 31, 2017, 1:50 p.m.
On Mon, 29 May 2017 23:28:20 +0900, Yuya Nishihara wrote:
> On Mon, 29 May 2017 14:45:39 +0200, Denis Laxalde wrote:
> > David Soria Parra a écrit :
> > > # HG changeset patch
> > > # User David Soria Parra <davidsp@fb.com>
> > > # Date 1495905909 25200
> > > #      Sat May 27 10:25:09 2017 -0700
> > > # Node ID 47c710c797624b6d5c84c493a873ea8beb563a74
> > > # Parent  b647b923486f38d83b92089eafa9faafaa79785d
> > > revset: lookup descendents for negative arguments to ancestor operator
> > >
> > > Negative offsets to the `~` operator now search for descendents. The search is
> > > aborted when a node has more than one child as we do not have a definition for
> > > 'nth child'. Optionally we can introduce such a notion and take the nth child
> > > ordered by rev number.
> > 
> > My first though is that using a minus sign to move forward in history is
> > also a bit puzzling...
> 
> I agree it's a bit puzzling, but I also think it's an acceptable extension to
> the `~` operator as long as descendants history is linear. However, from
> implementation POV, it would be unnecessarily expensive to make sure there's
> no more than one child.

So I'm against the current proposal. FWIW, if we can define the first
descendant as the nearest child in revision number space, the computation
will be cheaper.

  for r in cl.revs(lastp + 1):
      if lastp in cl.parentrevs(r):
          print 'nth child', r
          lastp = r

I remember mpm's proposal, but I believe it will be a big project. If we
can introduce a quite useful and consistent notation by extending the existing
operator, there should be no reason to reject it.

(IRC isn't useful for asynchronous communication :)
David Soria Parra - May 31, 2017, 4:21 p.m.
On Wed, May 31, 2017 at 10:50:15PM +0900, Yuya Nishihara wrote:
> On Mon, 29 May 2017 23:28:20 +0900, Yuya Nishihara wrote:
> > On Mon, 29 May 2017 14:45:39 +0200, Denis Laxalde wrote:
> > 
> > I agree it's a bit puzzling, but I also think it's an acceptable extension to
> > the `~` operator as long as descendants history is linear. However, from
> > implementation POV, it would be unnecessarily expensive to make sure there's
> > no more than one child.
> 
> So I'm against the current proposal. FWIW, if we can define the first
> descendant as the nearest child in revision number space, the computation
> will be cheaper.

I considered this and decided to not introduce this notion of nearest
child. I feel that the notion of revnumber as an ordering is unintuitive for
users of a decentralized version control system as it adds an concept of
ordering on the existing dag, and rev numbers are rarely used by users for
ordering (hence people use :: far more than : in revsets). I feel while the
computation is faster it might often lead to unexpected results. The user must
know the revision numbers of children in order to know what 'hg update .~-2'
would do. That's why I felt restricting it the way i did in the patch was more
sensibile for userbility.
Sean Farley - May 31, 2017, 5:34 p.m.
David Soria Parra <dsp@experimentalworks.net> writes:

> On Wed, May 31, 2017 at 10:50:15PM +0900, Yuya Nishihara wrote:
>> On Mon, 29 May 2017 23:28:20 +0900, Yuya Nishihara wrote:
>> > On Mon, 29 May 2017 14:45:39 +0200, Denis Laxalde wrote:
>> > 
>> > I agree it's a bit puzzling, but I also think it's an acceptable extension to
>> > the `~` operator as long as descendants history is linear. However, from
>> > implementation POV, it would be unnecessarily expensive to make sure there's
>> > no more than one child.
>> 
>> So I'm against the current proposal. FWIW, if we can define the first
>> descendant as the nearest child in revision number space, the computation
>> will be cheaper.
>
> I considered this and decided to not introduce this notion of nearest
> child. I feel that the notion of revnumber as an ordering is unintuitive for
> users of a decentralized version control system as it adds an concept of
> ordering on the existing dag,

But this is what Mercurial has always done.

> and rev numbers are rarely used by users for
> ordering (hence people use :: far more than : in revsets).

I don't think that's sound reasoning. As a counter argument, Bitbucket
manually sorts each git repo so that it has a faux rev number. We then
use that number for children / descendant calculations.

> I feel while the
> computation is faster it might often lead to unexpected results. The user must
> know the revision numbers of children in order to know what 'hg update .~-2'
> would do. That's why I felt restricting it the way i did in the patch was more
> sensibile for userbility.

I'm unsure. On one hand, I'd like to get something through. But on the
other, we have years of precedence of using rev numbers.
David Soria Parra - May 31, 2017, 5:49 p.m.
On Wed, May 31, 2017 at 10:34:55AM -0700, Sean Farley wrote:
> David Soria Parra <dsp@experimentalworks.net> writes:
> 
> > On Wed, May 31, 2017 at 10:50:15PM +0900, Yuya Nishihara wrote:
> >> On Mon, 29 May 2017 23:28:20 +0900, Yuya Nishihara wrote:
> >> > On Mon, 29 May 2017 14:45:39 +0200, Denis Laxalde wrote:
> >> > 
> >> > I agree it's a bit puzzling, but I also think it's an acceptable extension to
> >> > the `~` operator as long as descendants history is linear. However, from
> >> > implementation POV, it would be unnecessarily expensive to make sure there's
> >> > no more than one child.
> >> 
> >> So I'm against the current proposal. FWIW, if we can define the first
> >> descendant as the nearest child in revision number space, the computation
> >> will be cheaper.
> >
> > I considered this and decided to not introduce this notion of nearest
> > child. I feel that the notion of revnumber as an ordering is unintuitive for
> > users of a decentralized version control system as it adds an concept of
> > ordering on the existing dag,
> 
> But this is what Mercurial has always done.

I think we have always used it as an optional method rather than a way to
disambiguate.

> > and rev numbers are rarely used by users for
> > ordering (hence people use :: far more than : in revsets).
> 
> I don't think that's sound reasoning. As a counter argument, Bitbucket
> manually sorts each git repo so that it has a faux rev number. We then
> use that number for children / descendant calculations.
> 
> > I feel while the
> > computation is faster it might often lead to unexpected results. The user must
> > know the revision numbers of children in order to know what 'hg update .~-2'
> > would do. That's why I felt restricting it the way i did in the patch was more
> > sensibile for userbility.
> 
> I'm unsure. On one hand, I'd like to get something through. But on the
> other, we have years of precedence of using rev numbers.

I don't mind changing the proposal if we agree. I prefer having something in and
don't feel too strongly about my current approach, although i think it's much
more user friendly than relying on revnumbers.
Augie Fackler - May 31, 2017, 6:17 p.m.
On Wed, May 31, 2017 at 10:49:09AM -0700, David Soria Parra wrote:
> On Wed, May 31, 2017 at 10:34:55AM -0700, Sean Farley wrote:
> > David Soria Parra <dsp@experimentalworks.net> writes:
> >
> > > On Wed, May 31, 2017 at 10:50:15PM +0900, Yuya Nishihara wrote:
> > >> On Mon, 29 May 2017 23:28:20 +0900, Yuya Nishihara wrote:
> > >> > On Mon, 29 May 2017 14:45:39 +0200, Denis Laxalde wrote:
> > >> >
> > >> > I agree it's a bit puzzling, but I also think it's an acceptable extension to
> > >> > the `~` operator as long as descendants history is linear. However, from
> > >> > implementation POV, it would be unnecessarily expensive to make sure there's
> > >> > no more than one child.
> > >>
> > >> So I'm against the current proposal. FWIW, if we can define the first
> > >> descendant as the nearest child in revision number space, the computation
> > >> will be cheaper.
> > >
> > > I considered this and decided to not introduce this notion of nearest
> > > child. I feel that the notion of revnumber as an ordering is unintuitive for
> > > users of a decentralized version control system as it adds an concept of
> > > ordering on the existing dag,
> >
> > But this is what Mercurial has always done.
>
> I think we have always used it as an optional method rather than a way to
> disambiguate.
>
> > > and rev numbers are rarely used by users for
> > > ordering (hence people use :: far more than : in revsets).
> >
> > I don't think that's sound reasoning. As a counter argument, Bitbucket
> > manually sorts each git repo so that it has a faux rev number. We then
> > use that number for children / descendant calculations.
> >
> > > I feel while the
> > > computation is faster it might often lead to unexpected results. The user must
> > > know the revision numbers of children in order to know what 'hg update .~-2'
> > > would do. That's why I felt restricting it the way i did in the patch was more
> > > sensibile for userbility.
> >
> > I'm unsure. On one hand, I'd like to get something through. But on the
> > other, we have years of precedence of using rev numbers.
>
> I don't mind changing the proposal if we agree. I prefer having something in and
> don't feel too strongly about my current approach, although i think it's much
> more user friendly than relying on revnumbers.

It's easy to allow child traversal only if it's unambigious, and come
back to it later and be more permissive later. It'll be hard to go the
other way though.

(I'm lightly in favor of this series, +0-ish, but I need to re-read
mpm's operator plan and see how they overlap, it's been too long.)

> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
David Soria Parra - June 5, 2017, 4:19 p.m.
On Wed, May 31, 2017 at 02:17:58PM -0400, Augie Fackler wrote:
> 
> It's easy to allow child traversal only if it's unambigious, and come
> back to it later and be more permissive later. It'll be hard to go the
> other way though.
> 
> (I'm lightly in favor of this series, +0-ish, but I need to re-read
> mpm's operator plan and see how they overlap, it's been too long.)
> 

What's the conclusion on the RFC patch? Is that something we want with the
current restrictions? Of other people like greg, sid, etc need to weight in?

-David
Sean Farley - June 5, 2017, 6:55 p.m.
David Soria Parra <dsp@experimentalworks.net> writes:

> On Wed, May 31, 2017 at 02:17:58PM -0400, Augie Fackler wrote:
>> 
>> It's easy to allow child traversal only if it's unambigious, and come
>> back to it later and be more permissive later. It'll be hard to go the
>> other way though.
>> 
>> (I'm lightly in favor of this series, +0-ish, but I need to re-read
>> mpm's operator plan and see how they overlap, it's been too long.)
>> 
>
> What's the conclusion on the RFC patch? Is that something we want with the
> current restrictions? Of other people like greg, sid, etc need to weight in?

I agree with Augie's error-now-easier-permissive-later argument, for
what it's worth. I can change my vote to a +0 as well.
Yuya Nishihara - June 6, 2017, 12:27 p.m.
On Mon, 05 Jun 2017 11:55:21 -0700, Sean Farley wrote:
> David Soria Parra <dsp@experimentalworks.net> writes:
> 
> > On Wed, May 31, 2017 at 02:17:58PM -0400, Augie Fackler wrote:
> >> 
> >> It's easy to allow child traversal only if it's unambigious, and come
> >> back to it later and be more permissive later. It'll be hard to go the
> >> other way though.
> >> 
> >> (I'm lightly in favor of this series, +0-ish, but I need to re-read
> >> mpm's operator plan and see how they overlap, it's been too long.)
> >> 
> >
> > What's the conclusion on the RFC patch? Is that something we want with the
> > current restrictions? Of other people like greg, sid, etc need to weight in?
> 
> I agree with Augie's error-now-easier-permissive-later argument, for
> what it's worth. I can change my vote to a +0 as well.

I don't strongly disagree with that. If people like it, please feel free to
move forward. FWIW, calling children() repeatedly wouldn't be the best way
to scan descendant revisions.
Augie Fackler - June 6, 2017, 7:40 p.m.
On Tue, Jun 06, 2017 at 09:27:54PM +0900, Yuya Nishihara wrote:
> On Mon, 05 Jun 2017 11:55:21 -0700, Sean Farley wrote:
> > David Soria Parra <dsp@experimentalworks.net> writes:
> >
> > > On Wed, May 31, 2017 at 02:17:58PM -0400, Augie Fackler wrote:
> > >>
> > >> It's easy to allow child traversal only if it's unambigious, and come
> > >> back to it later and be more permissive later. It'll be hard to go the
> > >> other way though.
> > >>
> > >> (I'm lightly in favor of this series, +0-ish, but I need to re-read
> > >> mpm's operator plan and see how they overlap, it's been too long.)
> > >>
> > >
> > > What's the conclusion on the RFC patch? Is that something we want with the
> > > current restrictions? Of other people like greg, sid, etc need to weight in?
> >
> > I agree with Augie's error-now-easier-permissive-later argument, for
> > what it's worth. I can change my vote to a +0 as well.
>
> I don't strongly disagree with that. If people like it, please feel free to
> move forward. FWIW, calling children() repeatedly wouldn't be the best way
> to scan descendant revisions.

In the name of not letting the perfect be the enemy of the good, I'm
moving forward and queueing this patch, on the following logic:

 * This syntax doesn't seem like it would ever make sense for anything else
 * mpm's revset operator plan, while pretty well liked by everyone, is big
   enough I'm skeptical it'll get picked up in the near term by anyone
 * We can always stop advertising this syntax if we get a better solution in place.

David, thank you for picking this back up and finding a way to get
something shipped. I know it was more than a little uphill to get to this point.
via Mercurial-devel - June 6, 2017, 7:54 p.m.
Thank you! I'll try to follow up with a faster implementation soon (traversing revs manually instead of using children()).

> -----Original Message-----
> From: Augie Fackler [mailto:raf@durin42.com]
> Sent: Tuesday, June 6, 2017 12:40 PM
> To: Yuya Nishihara <yuya@tcha.org>
> Cc: Sean Farley <sean@farley.io>; David Soria Parra
> <dsp@experimentalworks.net>; Denis Laxalde <denis@laxalde.org>; David
> Soria Parra <david.soriaparra@oculus.com>; mercurial-devel@mercurial-
> scm.org
> Subject: Re: [PATCH RFC] revset: lookup descendents for negative
> arguments to ancestor operator
> 
> On Tue, Jun 06, 2017 at 09:27:54PM +0900, Yuya Nishihara wrote:
> > On Mon, 05 Jun 2017 11:55:21 -0700, Sean Farley wrote:
> > > David Soria Parra <dsp@experimentalworks.net> writes:
> > >
> > > > On Wed, May 31, 2017 at 02:17:58PM -0400, Augie Fackler wrote:
> > > >>
> > > >> It's easy to allow child traversal only if it's unambigious, and come
> > > >> back to it later and be more permissive later. It'll be hard to go the
> > > >> other way though.
> > > >>
> > > >> (I'm lightly in favor of this series, +0-ish, but I need to re-read
> > > >> mpm's operator plan and see how they overlap, it's been too long.)
> > > >>
> > > >
> > > > What's the conclusion on the RFC patch? Is that something we want
> with the
> > > > current restrictions? Of other people like greg, sid, etc need to weight
> in?
> > >
> > > I agree with Augie's error-now-easier-permissive-later argument, for
> > > what it's worth. I can change my vote to a +0 as well.
> >
> > I don't strongly disagree with that. If people like it, please feel free to
> > move forward. FWIW, calling children() repeatedly wouldn't be the best
> way
> > to scan descendant revisions.
> 
> In the name of not letting the perfect be the enemy of the good, I'm
> moving forward and queueing this patch, on the following logic:
> 
>  * This syntax doesn't seem like it would ever make sense for anything else
>  * mpm's revset operator plan, while pretty well liked by everyone, is big
>    enough I'm skeptical it'll get picked up in the near term by anyone
>  * We can always stop advertising this syntax if we get a better solution in
> place.
> 
> David, thank you for picking this back up and finding a way to get
> something shipped. I know it was more than a little uphill to get to this point.
Sean Farley - June 11, 2017, 7:36 p.m.
Augie Fackler <raf@durin42.com> writes:

> On Tue, Jun 06, 2017 at 09:27:54PM +0900, Yuya Nishihara wrote:
>> On Mon, 05 Jun 2017 11:55:21 -0700, Sean Farley wrote:
>> > David Soria Parra <dsp@experimentalworks.net> writes:
>> >
>> > > On Wed, May 31, 2017 at 02:17:58PM -0400, Augie Fackler wrote:
>> > >>
>> > >> It's easy to allow child traversal only if it's unambigious, and come
>> > >> back to it later and be more permissive later. It'll be hard to go the
>> > >> other way though.
>> > >>
>> > >> (I'm lightly in favor of this series, +0-ish, but I need to re-read
>> > >> mpm's operator plan and see how they overlap, it's been too long.)
>> > >>
>> > >
>> > > What's the conclusion on the RFC patch? Is that something we want with the
>> > > current restrictions? Of other people like greg, sid, etc need to weight in?
>> >
>> > I agree with Augie's error-now-easier-permissive-later argument, for
>> > what it's worth. I can change my vote to a +0 as well.
>>
>> I don't strongly disagree with that. If people like it, please feel free to
>> move forward. FWIW, calling children() repeatedly wouldn't be the best way
>> to scan descendant revisions.
>
> In the name of not letting the perfect be the enemy of the good, I'm
> moving forward and queueing this patch, on the following logic:
>
>  * This syntax doesn't seem like it would ever make sense for anything else
>  * mpm's revset operator plan, while pretty well liked by everyone, is big
>    enough I'm skeptical it'll get picked up in the near term by anyone

Could we maybe pick apart some of his proposal into smaller bites? For
instance, the '{ }' operators might be doable in the shorter term
(perhaps for subscripting?).
Yuya Nishihara - June 12, 2017, 2:04 p.m.
On Sun, 11 Jun 2017 12:36:51 -0700, Sean Farley wrote:
> Augie Fackler <raf@durin42.com> writes:
> 
> > On Tue, Jun 06, 2017 at 09:27:54PM +0900, Yuya Nishihara wrote:
> >> On Mon, 05 Jun 2017 11:55:21 -0700, Sean Farley wrote:
> >> > David Soria Parra <dsp@experimentalworks.net> writes:
> >> >
> >> > > On Wed, May 31, 2017 at 02:17:58PM -0400, Augie Fackler wrote:
> >> > >>
> >> > >> It's easy to allow child traversal only if it's unambigious, and come
> >> > >> back to it later and be more permissive later. It'll be hard to go the
> >> > >> other way though.
> >> > >>
> >> > >> (I'm lightly in favor of this series, +0-ish, but I need to re-read
> >> > >> mpm's operator plan and see how they overlap, it's been too long.)
> >> > >>
> >> > >
> >> > > What's the conclusion on the RFC patch? Is that something we want with the
> >> > > current restrictions? Of other people like greg, sid, etc need to weight in?
> >> >
> >> > I agree with Augie's error-now-easier-permissive-later argument, for
> >> > what it's worth. I can change my vote to a +0 as well.
> >>
> >> I don't strongly disagree with that. If people like it, please feel free to
> >> move forward. FWIW, calling children() repeatedly wouldn't be the best way
> >> to scan descendant revisions.
> >
> > In the name of not letting the perfect be the enemy of the good, I'm
> > moving forward and queueing this patch, on the following logic:
> >
> >  * This syntax doesn't seem like it would ever make sense for anything else
> >  * mpm's revset operator plan, while pretty well liked by everyone, is big
> >    enough I'm skeptical it'll get picked up in the near term by anyone
> 
> Could we maybe pick apart some of his proposal into smaller bites? For
> instance, the '{ }' operators might be doable in the shorter term
> (perhaps for subscripting?).

Sounds good. '{' n '}' operator should be easily implemented as long as n is
a plain int or symbol. I suggest keeping this feature experimental for a
couple of months so we can choose the best shorthand notation.
Sean Farley - June 12, 2017, 10:25 p.m.
Yuya Nishihara <yuya@tcha.org> writes:

> On Sun, 11 Jun 2017 12:36:51 -0700, Sean Farley wrote:
>> Augie Fackler <raf@durin42.com> writes:
>> 
>> > On Tue, Jun 06, 2017 at 09:27:54PM +0900, Yuya Nishihara wrote:
>> >> On Mon, 05 Jun 2017 11:55:21 -0700, Sean Farley wrote:
>> >> > David Soria Parra <dsp@experimentalworks.net> writes:
>> >> >
>> >> > > On Wed, May 31, 2017 at 02:17:58PM -0400, Augie Fackler wrote:
>> >> > >>
>> >> > >> It's easy to allow child traversal only if it's unambigious, and come
>> >> > >> back to it later and be more permissive later. It'll be hard to go the
>> >> > >> other way though.
>> >> > >>
>> >> > >> (I'm lightly in favor of this series, +0-ish, but I need to re-read
>> >> > >> mpm's operator plan and see how they overlap, it's been too long.)
>> >> > >>
>> >> > >
>> >> > > What's the conclusion on the RFC patch? Is that something we want with the
>> >> > > current restrictions? Of other people like greg, sid, etc need to weight in?
>> >> >
>> >> > I agree with Augie's error-now-easier-permissive-later argument, for
>> >> > what it's worth. I can change my vote to a +0 as well.
>> >>
>> >> I don't strongly disagree with that. If people like it, please feel free to
>> >> move forward. FWIW, calling children() repeatedly wouldn't be the best way
>> >> to scan descendant revisions.
>> >
>> > In the name of not letting the perfect be the enemy of the good, I'm
>> > moving forward and queueing this patch, on the following logic:
>> >
>> >  * This syntax doesn't seem like it would ever make sense for anything else
>> >  * mpm's revset operator plan, while pretty well liked by everyone, is big
>> >    enough I'm skeptical it'll get picked up in the near term by anyone
>> 
>> Could we maybe pick apart some of his proposal into smaller bites? For
>> instance, the '{ }' operators might be doable in the shorter term
>> (perhaps for subscripting?).
>
> Sounds good. '{' n '}' operator should be easily implemented as long as n is
> a plain int or symbol. I suggest keeping this feature experimental for a
> couple of months so we can choose the best shorthand notation.

Sounds good to me (though it's not a high priority for me right now).

Patch

diff --git a/mercurial/help/revisions.txt b/mercurial/help/revisions.txt
--- a/mercurial/help/revisions.txt
+++ b/mercurial/help/revisions.txt
@@ -97,6 +97,7 @@ 
 
 ``x~n``
   The nth first ancestor of x; ``x~0`` is x; ``x~3`` is ``x^^^``.
+  For n < 0, the nth unambiguous descendent of x.
 
 ``x ## y``
   Concatenate strings and identifiers into one string.
diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -378,12 +378,33 @@ 
     # Like ``ancestors(set)`` but follows only the first parents.
     return _ancestors(repo, subset, x, followfirst=True)
 
+def _childrenspec(repo, subset, x, n, order):
+    """Changesets that are the Nth child of a changeset
+    in set.
+    """
+    cs = set()
+    for r in getset(repo, fullreposet(repo), x):
+        for i in range(n):
+            c = repo[r].children()
+            if len(c) == 0:
+                break
+            if len(c) > 1:
+                raise error.RepoLookupError(
+                    _("revision in set has more than one child"))
+            r = c[0]
+        else:
+            cs.add(r)
+    return subset & cs
+
 def ancestorspec(repo, subset, x, n, order):
     """``set~n``
     Changesets that are the Nth ancestor (first parents only) of a changeset
     in set.
     """
     n = getinteger(n, _("~ expects a number"))
+    if n < 0:
+        # children lookup
+        return _childrenspec(repo, subset, x, -n, order)
     ps = set()
     cl = repo.changelog
     for r in getset(repo, fullreposet(repo), x):
diff --git a/tests/test-revset.t b/tests/test-revset.t
--- a/tests/test-revset.t
+++ b/tests/test-revset.t
@@ -2881,6 +2881,14 @@ 
   $ log 'merge()^^^'
   1
 
+  $ log '(merge() | 0)~-1'
+  7
+  1
+  $ log 'merge()~-1'
+  7
+  $ log 'tip~-1'
+  $ log '(tip | merge())~-1'
+  7
   $ log 'merge()~0'
   6
   $ log 'merge()~1'
@@ -2901,6 +2909,10 @@ 
   hg: parse error: ^ expects a number 0, 1, or 2
   [255]
 
+  $ log 'branchpoint()~-1'
+  abort: revset has more than one child!
+  [255]
+
 Bogus function gets suggestions
   $ log 'add()'
   hg: parse error: unknown identifier: add