RFC: revset relation operator

Sean Farley sean at farley.io
Tue Oct 13 16:13:41 CDT 2015


Matt Mackall <mpm at selenic.com> writes:

> On Tue, 2015-10-13 at 13:28 -0700, Sean Farley wrote:
>> Durham Goode <durham at fb.com> writes:
>> 
>> > On 10/12/15 7:07 AM, Augie Fackler wrote:
>> >> On Sun, Oct 11, 2015 at 05:45:24PM -0500, Matt Mackall wrote:
>> >>> It would be nice if we had a convenience syntax for finding things
>> >>> related to a given changeset. Currently, we have a couple of these for
>> >>> parents, ancestors, and descendants.
>> >>>
>> >>>   foo^  # first parent
>> >>>   foo^2 # second parent
>> >>>   foo^^ # first parent of first parent
>> >>>   foo~2 # same
>> >>>   ::foo # ancestors, inclusive
>> >>>   foo:: # descendants, inclusize
>> >>>
>> >>> But we have nothing directly equivalent to parents(), nor any shorthand
>> >>> for children(), successors(), origin(), destination(), or any other type
>> >>> of relation we may add. We'd also like a way to specify next, previous,
>> >>> all, all exclusive, last, etc.
>> >>>
>> >>> So my proposal[1] is to add a bracketed postfix (one of {}, [], or <>,
>> >>> but perhaps {} is the least bad) that looks like this:
>> >>>
>> >>>   foo{1}     # children(foo)
>> >>>   foo{2}     # children(children(foo))
>> >>>   foo{}      # defaults to 1, so children(foo)
>> >>>   foo{0}     # synonym for foo
>> >>>   foo{-1}    # parents(foo) (both of 'em)
>> >>>   foo{-}     # same
>> >>>   foo{*}     # foo:: - foo (exclusive)
>> >>>   foo{**}    # foo:: (inclusive)
>> >>>   foo{-*}    # ::foo - foo
>> >>>   foo{$}     # heads(foo::) aka "the last children"
>> >>>   foo{-4}::foo # last five changesets in a branch
>> >>>
>> >>> This makes a lot of our most common expressions shorter. To talk about
>> >>> other types of relations, we use a suffix character:
>> >>>
>> >>>   foo{1g}    # immediate grafts of foo
>> >>>   foo{-g}    # origin for grafts
>> >>>   foo{o}     # successor(foo)
>> >>>   foo{$o}    # final successor of foo
>> >> Neat. The one-character suffix thing gives me a little pause as
>> >> possibly-not-entirely-self-documenting. Maybe it could be whole [a-z]
>> >> words, and we could allow unambiguous prefixes?
>> > I thought about using a multidimensional array style syntax for allowing 
>> > full words instead of single letters:
>> >
>> > foo{1g} == foo{1, graft}
>> >
>> > which allow for more self-documenting uses.
>> >
>> > I also thought about using [] to have the nice side effect of implying a 
>> > array style access:
>> >
>> > foo[-1]
>> > foo[1, graft]
>> > foo[$][-1o]
>> 
>> Surprising to me: this actually works in bash.
>
> The first one will suddenly but probably harmlessly fail if you have
> files named "foo-" or "foo1".

Ah, righto.

> Since we're on this topic, <> is interesting if you fail to quote it:
>
> $ echo quux > bar
>
> $ echo foo<bar>
> bash: syntax error near unexpected token `newline'
>
> $ echo foo<> bar
> foo  <- oops, silently lost operator
>
> $ cat bar
> quux  <- but bar is undamaged
>
> $ echo foo<nosuch> bar
> bash: nosuch: no such file or directory
>
> $ echo foo<exists> bar # oops!
> $ cat bar
> foo <- oops

I should probably add this to the revset operator wiki page.

> It's pretty hard to hurt yourself with this syntax but not impossible.
> And it always requires quoting. {} is probably the best choice since it
> almost always works without quoting. 

I like {} but will award bonus points if we could use (perhaps some
superset of) template syntax.

> The "$" thing can get us in trouble if we follow it with a letter since
> that'll trigger env substitution. So maybe the relation type needs to go
> first.

(nods)


More information about the Mercurial-devel mailing list