RFC: revset relation operator

Ryan McElroy rm at fb.com
Wed Oct 14 00:03:20 CDT 2015


On 10/12/2015 2:26 PM, Matt Mackall wrote:
> On Mon, 2015-10-12 at 10:07 -0400, Augie Fackler wrote:
>> On Sun, Oct 11, 2015 at 05:45:24PM -0500, Matt Mackall wrote:
>> I think the specific feedback I'm looking for here is how do folks 
>> feel about: - using {} for the operator

I think this is the best choice

> - allowing empty {} to be children()

I don't like the implicit syntax for children or other cases. Mercurial 
get's it right, in my opinion, that rev~ is a syntax error (git says 
this is equivalent to rev~1, which is surprising behavior to me). It's 
hard to get implicit behavior right, so I'd suggest starting with 
explicit behavior (ie, no implicit 1 in {}) and then moving towards 
implicit only as it becomes super clear what the right path is (if that 
ever happens). If we start out with the wrong implicit behavior, we'll 
end up with the equivalent of `hg update` semantics.

However, a short form for children seems really important to me as well. 
Things I've considered over the last year:

foo{   # the opening curly brace looks like dag children coming out of 
foo. But there are obvious parsing problems here.
foo*  # the idea being that it's things "pointing" at foo (and it's one 
character), with the obvious glob downside
foo;   # parent's ^ points up, the semicolon kind of points down. Again, 
terminal escpaing implications
foo/   # kind of implies things descending from foo in the subdirectory 
sense. One downside is that forwardslash is used in bookmarks often (but 
so it - and we've been able to handle that, albeit imperfectly).

Of these, I like the last, the forward slash, the best. But this maybe 
should be a separate discussion.

> - allowing bare "-" with no numeral

Also dislike, same reason as above. It's not clear to me that this is 
"right" and so I think we should avoid it until it's clear.

> - using * and ** (and -* and -**) for all

I can't even remember what * is unless I go back and re-read, so it's 
pretty clear to me it's nonobvious what * refers to. (/me goes back and 
reads)

Ah... ancestors and descendants... I think we already dedicate :: (as 
well as ..) to the ancestor/descendent use cases, and a new syntax is 
confusing and unnecessary. Also, star just doesn't feel like a character 
we should introduce if it doesn't fit really well because it has so many 
other well-understood semantics in the world (globs, regexes)

However, the inclusive vs exclusive idea I feel *is* important and we 
should figure out how to have exclusive versions of ::. I think that can 
be a separate discussion, but since we're kinda bike-shedding anyway, 
I'll throw this into the ring:

(1) We may need only one "direction" of exclusivity because the parent 
revset or children revset can provide the "other way".
(2) Since a parent revset is more firmly established, I'd suggest that 
exclusivity be established in the direction of "exclude the beginning rev"
(3) As a concrete proposal, triple colon could be "exclude the starting rev:

(A:::B) == (A::B - A)

If you need A::B -B, it's easy enough to write A::B^ today anyway, so an 
exclusive operator in that "direction" is less useful in my opinion.

> - using $ (and -$) for end/last

The functionality seems super useful. The character seems to map well.

Question: does foo{-$} mean the roots reachable from foo? (That's how I 
interpret it, but I didn't see it spelled out in the email)

> - suffix characters/words for relation dimension

I actually prefer the commas syntax (with unique prefixes -- not unique 
suffixes of the words*) since it's more explicit. If we find that it's 
cumbersome to use the commas, we can drop the requirement later, but it 
will be hard to require a comma later.

I'm also not sure why we would prefer the type of relation coming second 
at all. Which of these reads more naturally?:
foo{succ, 2}
foo{2, succ}

To me, its' clear that the first is the 2nd succesor. The first it's 
non-obvious I'm asking for something different than foo{2} which is the 
second child (maybe).

*By unique prefixes, I mean (and I think Augie meant) that if the full 
word is graft, as long as there are no othre full words that start with 
g, you can abbreviate graft as g, eg:

foo{1,graft} == foo{1,gr} == foo{1,g}

The idea of following grafts around seems a little odd to me though. 
What's the use case? Is there a way to follow grafts backwards? Is a 
graft different than a rebase --keep? Why or why not? Why not generalize 
graft to copy? What if you then amend the copy, is it still a copy? It 
seems there are a lot of questions here. I'd suggest this not be the 
first part of this proposal we implement.

Additional questions: with is o == successor?

The possible operations I can think of (with their unique prefixes, 
other potential short forms):


> - any common operations I might be forgetting


parents (pa, ^), not really needed because there are better operators, 
perhaps included only for completeness?
children (ch, /), hopefully not needed because there's a better syntax
successors (s), useful for evolve
predecessors (pr), useful for evolve
journal (j), useful for recovery once we have it in core
graft (g), I don't see how this is useful
copy (co), not sure if useful, but a superset of graft (includes rebase 
--keep, histedit --keep for example)
sibling (si), maybe useful, but other ways to specify it, eg 'foo^/'  # 
this makes me realize operator precedence rules are pretty important!
base (b), as in the "rebase closure base" , which is the last commit 
before common ancestor
only (o), similar to above, but only a single line of commits (currently 
exists as the revset operator)

>
> This is kind of a lot of new weird syntax all at once and I haven't
> completely convinced myself that it's not too horrible.
>

I agree there's a lot here. I'd suggest starting with the most important 
thing, which I think you and I agree is children. Then we can think 
about what we need that is hard to do today, like successors, and play 
around with it in an extension first (if possible), so we can screw up a 
few times before setting things in stone.

~Ryan


More information about the Mercurial-devel mailing list