Submitter | Sean Farley |
---|---|

Date | Oct. 4, 2014, 4:57 p.m. |

Message ID | <c3bd6d6457bf42d2fbca.1412441879@1.0.0.127.in-addr.arpa> |

Download | mbox | patch |

Permalink | /patch/6115/ |

State | Changes Requested |

Headers | show |

## Comments

Sean Farley writes: > # HG changeset patch > # User Sean Farley <sean.michael.farley@gmail.com> > # Date 1412441841 25200 > # Sat Oct 04 09:57:21 2014 -0700 > # Node ID c3bd6d6457bf42d2fbcaba89cf0418a0d0604239 > # Parent 78c916f24dd99a56e4c29153a5df3bd7d1c40edd > revset: allow negative integers to list child revs Sorry, I forgot to flag this as RFC.

On 10/04/2014 06:57 PM, Sean Farley wrote: > # HG changeset patch > # User Sean Farley <sean.michael.farley@gmail.com> > # Date 1412441841 25200 > # Sat Oct 04 09:57:21 2014 -0700 > # Node ID c3bd6d6457bf42d2fbcaba89cf0418a0d0604239 > # Parent 78c916f24dd99a56e4c29153a5df3bd7d1c40edd > revset: allow negative integers to list child revs > > With the heavy use of changeset evolution, it often becomes convenient (read: > necessary) to refer to a child revset easily. "child revset"? "refer to children in revsets"? Is that "children" in the normal sense, where all the changesets that have X as parent are children of X? Can you say more about the use case for this? When do you know that it is the 4th and not the 3rd child you want? Is it finding the n'th child found among immediate children in some ordering, or is it iteratively taking the "best" child? (That (and the ordering) should be clarified in patch description and documentation.) (Assuming it is following a chain of "first child", it would be more consistent if it was like X~-2. The common case in a DAG is to have only one ancestor, and a chain of "first ancestors" is thus usually quite obvious and well defined (and usually converging if it is ambiguous). I think it is less obvious what "chain of first child" would be ... and it would be more fragile.) /Mads > This patch introduces ^-1 as a > way to do that. > > RFC: This syntax was the most appropriate that I could find: ^{0,1,2} refers to > a changeset's zeroth (meaning itself), first, or second parent. Therefore, > ^{-1,-2,-3,...} refers to the nth child of a changeset. > > TODO: > - If accepted we'd have to change the error message away from just saying "0, > 1, or 2" > > - Allow or disallow .~-N > > - Add documentation / examples > > diff --git a/mercurial/revset.py b/mercurial/revset.py > --- a/mercurial/revset.py > +++ b/mercurial/revset.py > @@ -1250,11 +1250,11 @@ def parentspec(repo, subset, x, n): > ``set^1`` (or ``set^``), ``set^2`` > First or second parent, respectively, of all changesets in set. > """ > try: > n = int(n[1]) > - if n not in (0, 1, 2): > + if n > 2: > raise ValueError > except (TypeError, ValueError): > raise error.ParseError(_("^ expects a number 0, 1, or 2")) > ps = set() > cl = repo.changelog > @@ -1265,10 +1265,16 @@ def parentspec(repo, subset, x, n): > ps.add(cl.parentrevs(r)[0]) > elif n == 2: > parents = cl.parentrevs(r) > if len(parents) > 1: > ps.add(parents[1]) > + else: # negative number means the nth-child > + children = cl.children(repo[r].node()) > + idx = -n-1 > + if children and idx < len(children): > + ps.add(repo[children[idx]].rev()) > + > return subset & ps > > def present(repo, subset, x): > """``present(set)`` > An empty set, if any revision in set isn't found; otherwise, > diff --git a/tests/test-revset.t b/tests/test-revset.t > --- a/tests/test-revset.t > +++ b/tests/test-revset.t > @@ -778,10 +778,18 @@ multiple revspecs > 4 > 5 > 6 > 7 > > +test getting child revs > + > + $ log 'merge()~3^-1' > + 2 > + $ log 'merge()~3^-2' > + 3 > + > + > test usage in revpair (with "+") > > (real pair) > > $ hg diff -r 'tip^^' -r 'tip' > _______________________________________________ > Mercurial-devel mailing list > Mercurial-devel@selenic.com > http://selenic.com/mailman/listinfo/mercurial-devel

Mads Kiilerich writes: > On 10/04/2014 06:57 PM, Sean Farley wrote: >> # HG changeset patch >> # User Sean Farley <sean.michael.farley@gmail.com> >> # Date 1412441841 25200 >> # Sat Oct 04 09:57:21 2014 -0700 >> # Node ID c3bd6d6457bf42d2fbcaba89cf0418a0d0604239 >> # Parent 78c916f24dd99a56e4c29153a5df3bd7d1c40edd >> revset: allow negative integers to list child revs >> >> With the heavy use of changeset evolution, it often becomes convenient (read: >> necessary) to refer to a child revset easily. > > "child revset"? "refer to children in revsets"? Whoops, yes, I meant children of a changeset. > Is that "children" in the normal sense, where all the changesets that > have X as parent are children of X? Yes. > Can you say more about the use case for this? When do you know that it > is the 4th and not the 3rd child you want? This comes up very frequently in evolve where you easily have a parent of a commit and no easy way (revset way) to refer to the child. > Is it finding the n'th child found among immediate children in some > ordering, or is it iteratively taking the "best" child? (That (and the > ordering) should be clarified in patch description and documentation.) Good question. The ordering is given by changelog.children. It would seem to be the revision number order. Thoughts on putting a (documented) order on this? > (Assuming it is following a chain of "first child", it would be more > consistent if it was like X~-2. The common case in a DAG is to have only > one ancestor, and a chain of "first ancestors" is thus usually quite > obvious and well defined (and usually converging if it is ambiguous). I > think it is less obvious what "chain of first child" would be ... and it > would be more fragile.) I haven't thought of a good way to do this. With this patch, X^-2 refers to the second child (for now, we won't worry about order). X^-50 would be the 50th child. X~-50 would be ... the 50th first child? I don't know.

On 10/04/2014 09:57 AM, Sean Farley wrote: > # HG changeset patch > # User Sean Farley <sean.michael.farley@gmail.com> > # Date 1412441841 25200 > # Sat Oct 04 09:57:21 2014 -0700 > # Node ID c3bd6d6457bf42d2fbcaba89cf0418a0d0604239 > # Parent 78c916f24dd99a56e4c29153a5df3bd7d1c40edd > revset: allow negative integers to list child revs I like the idea of having a shorthand for children, but I'm not in favour of the shorthand being to select particular children. I think the shorthand we need is for 'all children' instead. I might be OK with '^-1' to mean 'all children'.

Siddharth Agarwal writes: > On 10/04/2014 09:57 AM, Sean Farley wrote: >> # HG changeset patch >> # User Sean Farley <sean.michael.farley@gmail.com> >> # Date 1412441841 25200 >> # Sat Oct 04 09:57:21 2014 -0700 >> # Node ID c3bd6d6457bf42d2fbcaba89cf0418a0d0604239 >> # Parent 78c916f24dd99a56e4c29153a5df3bd7d1c40edd >> revset: allow negative integers to list child revs > > I like the idea of having a shorthand for children, but I'm not in > favour of the shorthand being to select particular children. I think the > shorthand we need is for 'all children' instead. That's fair. Would you want to support index notation? e.g. X[N] for the Nth child? It might get funky with ordering as Mads pointed out. > I might be OK with '^-1' to mean 'all children'. Yeah, that might be ok, too.

On 10/06/2014 07:33 PM, Siddharth Agarwal wrote: > On 10/04/2014 09:57 AM, Sean Farley wrote: >> # HG changeset patch >> # User Sean Farley <sean.michael.farley@gmail.com> >> # Date 1412441841 25200 >> # Sat Oct 04 09:57:21 2014 -0700 >> # Node ID c3bd6d6457bf42d2fbcaba89cf0418a0d0604239 >> # Parent 78c916f24dd99a56e4c29153a5df3bd7d1c40edd >> revset: allow negative integers to list child revs > > I like the idea of having a shorthand for children, Yeah, it seems like this really is a shorthand for children(X)? > but I'm not in favour of the shorthand being to select particular > children. I think the shorthand we need is for 'all children' instead. Yes, it seems about right that the singlerev interpretation of that would be the tipmost child. > > I might be OK with '^-1' to mean 'all children'. It could however be confusing that x^n gives a single revision for n = 0, 1, 2 but a set for n = -1. The n in x^n designates which options to use. The n in x~n designates distance from x. It would thus be more consistent to use x~-1 ... and it would also be more that x~-2 should mean children(children(X)). Any use of negative numbers would also make x^-1 more ambiguous (unless precedence is considered). Some other symbol would be nice. The best (but not so good) candidates could be something with ! or the ~^ combination. /Mads

Mads Kiilerich writes: > On 10/06/2014 07:33 PM, Siddharth Agarwal wrote: >> On 10/04/2014 09:57 AM, Sean Farley wrote: >>> # HG changeset patch >>> # User Sean Farley <sean.michael.farley@gmail.com> >>> # Date 1412441841 25200 >>> # Sat Oct 04 09:57:21 2014 -0700 >>> # Node ID c3bd6d6457bf42d2fbcaba89cf0418a0d0604239 >>> # Parent 78c916f24dd99a56e4c29153a5df3bd7d1c40edd >>> revset: allow negative integers to list child revs >> >> I like the idea of having a shorthand for children, > > Yeah, it seems like this really is a shorthand for children(X)? > >> but I'm not in favour of the shorthand being to select particular >> children. I think the shorthand we need is for 'all children' instead. > > Yes, it seems about right that the singlerev interpretation of that > would be the tipmost child. > >> >> I might be OK with '^-1' to mean 'all children'. > > It could however be confusing that x^n gives a single revision for n = > 0, 1, 2 but a set for n = -1. > > The n in x^n designates which options to use. The n in x~n designates > distance from x. It would thus be more consistent to use x~-1 ... and it > would also be more that x~-2 should mean children(children(X)). Sure, this works for me. By that, I mean, X~-2 is children(children(X)).

On 10/04/2014 09:57 AM, Sean Farley wrote: > # HG changeset patch > # User Sean Farley <sean.michael.farley@gmail.com> > # Date 1412441841 25200 > # Sat Oct 04 09:57:21 2014 -0700 > # Node ID c3bd6d6457bf42d2fbcaba89cf0418a0d0604239 > # Parent 78c916f24dd99a56e4c29153a5df3bd7d1c40edd > revset: allow negative integers to list child revs Quick reply on various subject. As X^1 and X^2 return a single revision (per X) (short version for p1(X) and P2(X)) It would be a bad idea to have X^-1 return multiple revision. first(children(X)) have less good defined semantic as first(parents(X)) as it no deterministic and will change over time. the first parent of a changeset is carved in stone. The amount of Children change over time and with history rewriting, their order change over time. So you cannot really predict the order. You need to (a) have one parent or (b) look the number up (c) use a more precise revsets: children(X) and ::bookmarkname children(X) and desc(yyy) With evolution, the children revset become less useful when you have unstable changeset. Because you may have obsolete or non obsolete children. (hg next was an alias for `hg log --rev `children(.) - obsolete()` for some time). Handling this requires to use more complex revsets. Given all the issue above, I'm not convinced about the benefit of a children append notation. We'll have to mix it with other revset to get something useful in a lot of case. I agree that children(X) is a bit cumbersome. So I support the mpm proposal for c(x))ion so much. However, I'm curious about your use case. Can you details them? So that we have a better idea of the issue you are trying to solve here ?

Pierre-Yves David writes: > On 10/04/2014 09:57 AM, Sean Farley wrote: >> # HG changeset patch >> # User Sean Farley <sean.michael.farley@gmail.com> >> # Date 1412441841 25200 >> # Sat Oct 04 09:57:21 2014 -0700 >> # Node ID c3bd6d6457bf42d2fbcaba89cf0418a0d0604239 >> # Parent 78c916f24dd99a56e4c29153a5df3bd7d1c40edd >> revset: allow negative integers to list child revs > > Quick reply on various subject. > > As X^1 and X^2 return a single revision (per X) (short version for p1(X) > and P2(X)) It would be a bad idea to have X^-1 return multiple revision. I agree. > first(children(X)) have less good defined semantic as first(parents(X)) > as it no deterministic and will change over time. the first parent of a > changeset is carved in stone. The amount of Children change over time > and with history rewriting, their order change over time. So you cannot > really predict the order. You need to (a) have one parent or (b) look > the number up (c) use a more precise revsets: > children(X) and ::bookmarkname > children(X) and desc(yyy) They should always be returned in the revlog order. That is what we currently do with referring to children via revision numbers. This would be no added confusion. > With evolution, the children revset become less useful when you have > unstable changeset. Because you may have obsolete or non obsolete > children. (hg next was an alias for `hg log --rev `children(.) - > obsolete()` for some time). Handling this requires to use more complex > revsets. Yes, evolution does throw a wrench into thing but that's another patch series. > Given all the issue above, I'm not convinced about the benefit of a > children append notation. We'll have to mix it with other revset to get > something useful in a lot of case. I agree that children(X) is a bit > cumbersome. So I support the mpm proposal for c(x))ion so much. Anyone can use revset alias to make 'c' into 'children'. That's not the point here. > However, I'm curious about your use case. Can you details them? So that > we have a better idea of the issue you are trying to solve here ? There are many, many cases of navigating relative to the currently checked out revision '.'. Given the following DAG: A <-- X <-- C B <-/ \-- D Where A and B are parents of X, and C and D are children of X, where X is my current changeset, we can (with this proposal) refer to each changeset A, B, C, and D with X^1, X^2, X^-1, X^-2, respectively. The most common case for this (and the reason I wrote this patch) was when I was patch reviewing via 'hg prev' / 'hg next'. So, I would end up in the middle of some line of history and would want to see the diff of the next child. Though, this is not the only case, it is a common one for me (bisection being another frequent one). As another (future) example, let's pretend we have '<-' and '->' mean successor and precursor, respectively, then referring to the changeset that 'hg evolve' would rebase onto our current changeset: hg log -r .->^-1 I don't think -> is a good operator but this is just an example.

On 10/07/2014 11:40 AM, Sean Farley wrote: > > Pierre-Yves David writes: > >> On 10/04/2014 09:57 AM, Sean Farley wrote: >>> # HG changeset patch >>> # User Sean Farley <sean.michael.farley@gmail.com> >>> # Date 1412441841 25200 >>> # Sat Oct 04 09:57:21 2014 -0700 >>> # Node ID c3bd6d6457bf42d2fbcaba89cf0418a0d0604239 >>> # Parent 78c916f24dd99a56e4c29153a5df3bd7d1c40edd >>> revset: allow negative integers to list child revs >> >> Quick reply on various subject. >> >> As X^1 and X^2 return a single revision (per X) (short version for p1(X) >> and P2(X)) It would be a bad idea to have X^-1 return multiple revision. > > I agree. > >> first(children(X)) have less good defined semantic as first(parents(X)) >> as it no deterministic and will change over time. the first parent of a >> changeset is carved in stone. The amount of Children change over time >> and with history rewriting, their order change over time. So you cannot >> really predict the order. You need to (a) have one parent or (b) look >> the number up (c) use a more precise revsets: >> children(X) and ::bookmarkname >> children(X) and desc(yyy) > > They should always be returned in the revlog order. That is what we > currently do with referring to children via revision numbers. This would > be no added confusion. You got me wrong. Their will of course be returned in revlog order. This means that if you have three child A, B, C. You initially have children(X) = A, B, C Then you amend A. So you get children(X) = B, C, A And C get touched. So you get children(X) = B, A, C Then you pull a new version X from someone with a children D. You evolve and you end up with: children(X) = D, B, A, C So you cannot blindly rely on c(X, 1) to give you stable result. And normal human being have too look up the revset or use more precise revset. (will get to reply to the rest later)

Pierre-Yves David writes: > On 10/07/2014 11:40 AM, Sean Farley wrote: >> >> Pierre-Yves David writes: >> >>> On 10/04/2014 09:57 AM, Sean Farley wrote: >>>> # HG changeset patch >>>> # User Sean Farley <sean.michael.farley@gmail.com> >>>> # Date 1412441841 25200 >>>> # Sat Oct 04 09:57:21 2014 -0700 >>>> # Node ID c3bd6d6457bf42d2fbcaba89cf0418a0d0604239 >>>> # Parent 78c916f24dd99a56e4c29153a5df3bd7d1c40edd >>>> revset: allow negative integers to list child revs >>> >>> Quick reply on various subject. >>> >>> As X^1 and X^2 return a single revision (per X) (short version for p1(X) >>> and P2(X)) It would be a bad idea to have X^-1 return multiple revision. >> >> I agree. >> >>> first(children(X)) have less good defined semantic as first(parents(X)) >>> as it no deterministic and will change over time. the first parent of a >>> changeset is carved in stone. The amount of Children change over time >>> and with history rewriting, their order change over time. So you cannot >>> really predict the order. You need to (a) have one parent or (b) look >>> the number up (c) use a more precise revsets: >>> children(X) and ::bookmarkname >>> children(X) and desc(yyy) >> >> They should always be returned in the revlog order. That is what we >> currently do with referring to children via revision numbers. This would >> be no added confusion. > > You got me wrong. Their will of course be returned in revlog order. This > means that if you have three child A, B, C. You initially have > > children(X) = A, B, C > > Then you amend A. So you get > > children(X) = B, C, A > > And C get touched. So you get > > > children(X) = B, A, C > > Then you pull a new version X from someone with a children D. You evolve > and you end up with: > > children(X) = D, B, A, C > > So you cannot blindly rely on c(X, 1) to give you stable result. And > normal human being have too look up the revset or use more precise revset. > > (will get to reply to the rest later) Yes, of course, but this is derailing the current discussion. We have the concept of local revision numbers and this patch is a way to refer to that. I would suggest another discussion about the order of children().

On 10/07/2014 01:01 PM, Sean Farley wrote: > > Pierre-Yves David writes: > >> On 10/07/2014 11:40 AM, Sean Farley wrote: >>> >>> Pierre-Yves David writes: >>> >>>> On 10/04/2014 09:57 AM, Sean Farley wrote: >>>>> # HG changeset patch >>>>> # User Sean Farley <sean.michael.farley@gmail.com> >>>>> # Date 1412441841 25200 >>>>> # Sat Oct 04 09:57:21 2014 -0700 >>>>> # Node ID c3bd6d6457bf42d2fbcaba89cf0418a0d0604239 >>>>> # Parent 78c916f24dd99a56e4c29153a5df3bd7d1c40edd >>>>> revset: allow negative integers to list child revs >>>> >>>> Quick reply on various subject. >>>> >>>> As X^1 and X^2 return a single revision (per X) (short version for p1(X) >>>> and P2(X)) It would be a bad idea to have X^-1 return multiple revision. >>> >>> I agree. >>> >>>> first(children(X)) have less good defined semantic as first(parents(X)) >>>> as it no deterministic and will change over time. the first parent of a >>>> changeset is carved in stone. The amount of Children change over time >>>> and with history rewriting, their order change over time. So you cannot >>>> really predict the order. You need to (a) have one parent or (b) look >>>> the number up (c) use a more precise revsets: >>>> children(X) and ::bookmarkname >>>> children(X) and desc(yyy) >>> >>> They should always be returned in the revlog order. That is what we >>> currently do with referring to children via revision numbers. This would >>> be no added confusion. >> >> You got me wrong. Their will of course be returned in revlog order. This >> means that if you have three child A, B, C. You initially have >> >> children(X) = A, B, C >> >> Then you amend A. So you get >> >> children(X) = B, C, A >> >> And C get touched. So you get >> >> >> children(X) = B, A, C >> >> Then you pull a new version X from someone with a children D. You evolve >> and you end up with: >> >> children(X) = D, B, A, C >> >> So you cannot blindly rely on c(X, 1) to give you stable result. And >> normal human being have too look up the revset or use more precise revset. >> >> (will get to reply to the rest later) > > Yes, of course, but this is derailing the current discussion. We have > the concept of local revision numbers and this patch is a way to refer > to that. I would suggest another discussion about the order of > children(). This is not to challenge the order of children(X). This is to point out that children can barely be used alone and therefor having a supershort version of it is not that useful.

Pierre-Yves David writes: > On 10/07/2014 01:01 PM, Sean Farley wrote: >> >> Pierre-Yves David writes: >> >>> On 10/07/2014 11:40 AM, Sean Farley wrote: >>>> >>>> Pierre-Yves David writes: >>>> >>>>> On 10/04/2014 09:57 AM, Sean Farley wrote: >>>>>> # HG changeset patch >>>>>> # User Sean Farley <sean.michael.farley@gmail.com> >>>>>> # Date 1412441841 25200 >>>>>> # Sat Oct 04 09:57:21 2014 -0700 >>>>>> # Node ID c3bd6d6457bf42d2fbcaba89cf0418a0d0604239 >>>>>> # Parent 78c916f24dd99a56e4c29153a5df3bd7d1c40edd >>>>>> revset: allow negative integers to list child revs >>>>> >>>>> Quick reply on various subject. >>>>> >>>>> As X^1 and X^2 return a single revision (per X) (short version for p1(X) >>>>> and P2(X)) It would be a bad idea to have X^-1 return multiple revision. >>>> >>>> I agree. >>>> >>>>> first(children(X)) have less good defined semantic as first(parents(X)) >>>>> as it no deterministic and will change over time. the first parent of a >>>>> changeset is carved in stone. The amount of Children change over time >>>>> and with history rewriting, their order change over time. So you cannot >>>>> really predict the order. You need to (a) have one parent or (b) look >>>>> the number up (c) use a more precise revsets: >>>>> children(X) and ::bookmarkname >>>>> children(X) and desc(yyy) >>>> >>>> They should always be returned in the revlog order. That is what we >>>> currently do with referring to children via revision numbers. This would >>>> be no added confusion. >>> >>> You got me wrong. Their will of course be returned in revlog order. This >>> means that if you have three child A, B, C. You initially have >>> >>> children(X) = A, B, C >>> >>> Then you amend A. So you get >>> >>> children(X) = B, C, A >>> >>> And C get touched. So you get >>> >>> >>> children(X) = B, A, C >>> >>> Then you pull a new version X from someone with a children D. You evolve >>> and you end up with: >>> >>> children(X) = D, B, A, C >>> >>> So you cannot blindly rely on c(X, 1) to give you stable result. And >>> normal human being have too look up the revset or use more precise revset. >>> >>> (will get to reply to the rest later) >> >> Yes, of course, but this is derailing the current discussion. We have >> the concept of local revision numbers and this patch is a way to refer >> to that. I would suggest another discussion about the order of >> children(). > > This is not to challenge the order of children(X). This is to point out > that children can barely be used alone and therefor having a supershort > version of it is not that useful. I'm surprised you are being this stubborn about it. It is very, very common to have a set of linear changes. It is even still common to be in a situation where you only have a reference to the parent of a changeset.

On Oct 7, 2014, at 4:12 PM, Sean Farley <sean.michael.farley@gmail.com> wrote: >>> Yes, of course, but this is derailing the current discussion. We have >>> the concept of local revision numbers and this patch is a way to refer >>> to that. I would suggest another discussion about the order of >>> children(). >> >> This is not to challenge the order of children(X). This is to point out >> that children can barely be used alone and therefor having a supershort >> version of it is not that useful. > > I'm surprised you are being this stubborn about it. It is very, very > common to have a set of linear changes. It is even still common to be in > a situation where you only have a reference to the parent of a > changeset. I could see a claim that an "only child of" operator would be more useful than an "arbitrary child" operator (that is, abort if len(children) != 1). Maybe that'd be the useful middle ground here?

Augie Fackler writes: > On Oct 7, 2014, at 4:12 PM, Sean Farley <sean.michael.farley@gmail.com> wrote: > >>>> Yes, of course, but this is derailing the current discussion. We have >>>> the concept of local revision numbers and this patch is a way to refer >>>> to that. I would suggest another discussion about the order of >>>> children(). >>> >>> This is not to challenge the order of children(X). This is to point out >>> that children can barely be used alone and therefor having a supershort >>> version of it is not that useful. >> >> I'm surprised you are being this stubborn about it. It is very, very >> common to have a set of linear changes. It is even still common to be in >> a situation where you only have a reference to the parent of a >> changeset. > > I could see a claim that an "only child of" operator would be more useful than an "arbitrary child" operator (that is, abort if len(children) != 1). Maybe that'd be the useful middle ground here? I really don't see the problem with an arbitrary child operator. For most cases, the use would be with one child. If someone wants to use it for the second child, then that is also deterministic: ordered by local revnum.

On Tue, Oct 7, 2014 at 8:44 PM, Sean Farley <sean.michael.farley@gmail.com> wrote: > > Augie Fackler writes: > >> On Oct 7, 2014, at 4:12 PM, Sean Farley <sean.michael.farley@gmail.com> wrote: >> >>>>> Yes, of course, but this is derailing the current discussion. We have >>>>> the concept of local revision numbers and this patch is a way to refer >>>>> to that. I would suggest another discussion about the order of >>>>> children(). >>>> >>>> This is not to challenge the order of children(X). This is to point out >>>> that children can barely be used alone and therefor having a supershort >>>> version of it is not that useful. >>> >>> I'm surprised you are being this stubborn about it. It is very, very >>> common to have a set of linear changes. It is even still common to be in >>> a situation where you only have a reference to the parent of a >>> changeset. >> >> I could see a claim that an "only child of" operator would be more useful than an "arbitrary child" operator (that is, abort if len(children) != 1). Maybe that'd be the useful middle ground here? > > I really don't see the problem with an arbitrary child operator. For > most cases, the use would be with one child. If someone wants to use it > for the second child, then that is also deterministic: ordered by local > revnum. I don't disagree, but I can see Pierre-Yves's position: we are adding a little bit to the rope of surprising behavior by allowing nth-child selection, and maybe it's worth avoiding. Was just trying to offer a suggestion that (in my mind) solves the immediate pain around wanting a child-of operator (which I do), and Pierre-Yves's worry so we can make progress.

On 10/07/2014 11:40 AM, Sean Farley wrote: > > Pierre-Yves David writes: > >> On 10/04/2014 09:57 AM, Sean Farley wrote: >>> # HG changeset patch >>> # User Sean Farley <sean.michael.farley@gmail.com> >>> # Date 1412441841 25200 >>> # Sat Oct 04 09:57:21 2014 -0700 >>> # Node ID c3bd6d6457bf42d2fbcaba89cf0418a0d0604239 >>> # Parent 78c916f24dd99a56e4c29153a5df3bd7d1c40edd >>> revset: allow negative integers to list child revs >> >> Quick reply on various subject. >> >> As X^1 and X^2 return a single revision (per X) (short version for p1(X) >> and P2(X)) It would be a bad idea to have X^-1 return multiple revision. > > I agree. Quick dance to highlight we agree on some of this ;-) >> However, I'm curious about your use case. Can you details them? So that >> we have a better idea of the issue you are trying to solve here ? > > There are many, many cases of navigating relative to the currently > checked out revision '.'. Given the following DAG: > > A <-- X <-- C > B <-/ \-- D > > Where A and B are parents of X, and C and D are children of X, where X > is my current changeset, we can (with this proposal) refer to each > changeset A, B, C, and D with X^1, X^2, X^-1, X^-2, respectively. But X^-1 and X^-2 are going to be unreliable over time (see my other email). The reason as why I'm asking for usecase is because I, as a hardcore and long term user of evolution an hiking along the graph, have rarely been found in situation where I could reliably count on children(x). > The most common case for this (and the reason I wrote this patch) was > when I was patch reviewing via 'hg prev' / 'hg next'. So, I would end up > in the middle of some line of history and would want to see the diff of > the next child. > > Though, this is not the only case, it is a common one for me (bisection > being another frequent one). > > As another (future) example, let's pretend we have '<-' and '->' mean > successor and precursor, respectively, then referring to the changeset > that 'hg evolve' would rebase onto our current changeset: (Lets index each paragraph 1, 2 and 3) I would like to hear more about your bisect usecase (2). (1) and (3) seems similar to me. In both case, I read them as "I want to select the "next" changesets (target of `hg next`). (For (3) this requires issue4390 to be implemented). And given that `hg next` could not stay a simple as `hg up children(.)` I'm doubting that an operator for `children` will do the trick here. Augies proposal made me think that -maybe- we need a `next(x)` revset. See other emails for details. I'm eager to ear about your bisection case.

On 10/07/2014 05:44 PM, Sean Farley wrote: > > Augie Fackler writes: > >> On Oct 7, 2014, at 4:12 PM, Sean Farley <sean.michael.farley@gmail.com> wrote: >> >>>>> Yes, of course, but this is derailing the current discussion. We have >>>>> the concept of local revision numbers and this patch is a way to refer >>>>> to that. I would suggest another discussion about the order of >>>>> children(). >>>> >>>> This is not to challenge the order of children(X). This is to point out >>>> that children can barely be used alone and therefor having a supershort >>>> version of it is not that useful. >>> >>> I'm surprised you are being this stubborn about it. It is very, very >>> common to have a set of linear changes. It is even still common to be in >>> a situation where you only have a reference to the parent of a >>> changeset. The things I'm fighting againts here, is feature creep. I'm not fan of adding new operator because: 1) We have a limited set of char that can be operator. 2) Rarely used operator makes revset harder to read since it is harder to remember "::" than to read "ancestors" out. Revset readability is an important argument for newbies. So I'm questioning: 1) The necessity for an operator poking at children in general 2) The fact that this operator will be actually useful alone in most case. This (2) is the reason why I'm stubborn at pointing all the issue with a children operator. And I'll keep pointing at them until I'm under the impression that people involved in that discussion have properly understood them. This limitation themselves will maybe not get people to change their mind, but they should be aware of them before taking a decision. >> I could see a claim that an "only child of" operator would be more useful than an "arbitrary child" operator (that is, abort if len(children) != 1). Maybe that'd be the useful middle ground here? Things are a bit more complex that than. You can have multiple children, but only one is non-obsolete: o B' | | o C | | | x B | / |/ A This is the reason `hg next` exist in the first place. Because children(x) was not doing the job at rulling out obsolete changesets (and because I wanted ambiguity pointed out.) Maybe a `next(X)` revset would be useful. It would return the target for `hg next` when no ambiguity exists. (I'm not sure what it would do in the face of ambiguity). It could also grow capability to select the changeset that would be evolve by an `hg next --evolve` call. > I really don't see the problem with an arbitrary child operator. For > most cases, the use would be with one child. You usecase for it seems very connected to evolution. Where it is fairly common end up with more than one changesets. > If someone wants to use it > for the second child, then that is also deterministic: ordered by local > revnum. Again. The order of children is not deterministic enough to be useful. Of course it is stable under exact same condition (because it is ordered by revnum). But it far much more unstable other stuff. For example, `p1(e8832cf1abf6)` will always give you the same result. And this is even true in different repository. `children(e8832cf1abf6)` is not going to give stable results (in mutable history). While history is getting rewritten. revision number of (semantic) changeset changes. o B: fix doc | | o A: add feature. \ / o O: base At some point of time `first(children(O))` will return `A: add feature`. And at some other point of time it may return `B: fix doc` (because `A` could have been touched in between, so its revnum was bumped). Therefore, one can not blindly use children(x) to refer to one in many children. Because unlike X^1, X^-1 is not going to return stable result. (end of explanation of why children give unstable result. Can I get you to acknowledge this?) So whenever there is multiple children involved it is very likely that the user have to either: a) Explicitly look the children b) Use a more precise revset (eg: `children(x) and ancestors(y)`) So, in my opinion, the benefit of a short operator is likely to get nullified by either and explicit reference (case a) or the need to build a complex revset anyway.

Pierre-Yves David writes: > On 10/07/2014 05:44 PM, Sean Farley wrote: >> >> Augie Fackler writes: >> >>> On Oct 7, 2014, at 4:12 PM, Sean Farley <sean.michael.farley@gmail.com> wrote: >>> >>>>>> Yes, of course, but this is derailing the current discussion. We have >>>>>> the concept of local revision numbers and this patch is a way to refer >>>>>> to that. I would suggest another discussion about the order of >>>>>> children(). >>>>> >>>>> This is not to challenge the order of children(X). This is to point out >>>>> that children can barely be used alone and therefor having a supershort >>>>> version of it is not that useful. >>>> >>>> I'm surprised you are being this stubborn about it. It is very, very >>>> common to have a set of linear changes. It is even still common to be in >>>> a situation where you only have a reference to the parent of a >>>> changeset. > > The things I'm fighting againts here, is feature creep. I'm not fan of > adding new operator because: This isn't a new operator. It's extending the use of '^' and doesn't force a new character. At this point, I'm only interested in what mpm has to say about it and what direction he wants to go.

On 10/08/2014 08:09 PM, Sean Farley wrote: > > Pierre-Yves David writes: > >> On 10/07/2014 05:44 PM, Sean Farley wrote: >>> >>> Augie Fackler writes: >>> >>>> On Oct 7, 2014, at 4:12 PM, Sean Farley <sean.michael.farley@gmail.com> wrote: >>>> >>>>>>> Yes, of course, but this is derailing the current discussion. We have >>>>>>> the concept of local revision numbers and this patch is a way to refer >>>>>>> to that. I would suggest another discussion about the order of >>>>>>> children(). >>>>>> >>>>>> This is not to challenge the order of children(X). This is to point out >>>>>> that children can barely be used alone and therefor having a supershort >>>>>> version of it is not that useful. >>>>> >>>>> I'm surprised you are being this stubborn about it. It is very, very >>>>> common to have a set of linear changes. It is even still common to be in >>>>> a situation where you only have a reference to the parent of a >>>>> changeset. >> >> The things I'm fighting againts here, is feature creep. I'm not fan of >> adding new operator because: > > This isn't a new operator. It's extending the use of '^' and doesn't > force a new character. > > At this point, I'm only interested in what mpm has to say about it and > what direction he wants to go. Can I get you to look at the rest of the email and acknowledge the other points?

## Patch

diff --git a/mercurial/revset.py b/mercurial/revset.py --- a/mercurial/revset.py +++ b/mercurial/revset.py @@ -1250,11 +1250,11 @@ def parentspec(repo, subset, x, n): ``set^1`` (or ``set^``), ``set^2`` First or second parent, respectively, of all changesets in set. """ try: n = int(n[1]) - if n not in (0, 1, 2): + if n > 2: raise ValueError except (TypeError, ValueError): raise error.ParseError(_("^ expects a number 0, 1, or 2")) ps = set() cl = repo.changelog @@ -1265,10 +1265,16 @@ def parentspec(repo, subset, x, n): ps.add(cl.parentrevs(r)[0]) elif n == 2: parents = cl.parentrevs(r) if len(parents) > 1: ps.add(parents[1]) + else: # negative number means the nth-child + children = cl.children(repo[r].node()) + idx = -n-1 + if children and idx < len(children): + ps.add(repo[children[idx]].rev()) + return subset & ps def present(repo, subset, x): """``present(set)`` An empty set, if any revision in set isn't found; otherwise, diff --git a/tests/test-revset.t b/tests/test-revset.t --- a/tests/test-revset.t +++ b/tests/test-revset.t @@ -778,10 +778,18 @@ multiple revspecs 4 5 6 7 +test getting child revs + + $ log 'merge()~3^-1' + 2 + $ log 'merge()~3^-2' + 3 + + test usage in revpair (with "+") (real pair) $ hg diff -r 'tip^^' -r 'tip'