sapling/eden/scm/tests/test-revset-t.py
Jun Wu 2a99866d7b codemod: update license headers
Summary:
The "Portions" license cannot be updated automatically. So this is a manual
update using:

  sd -s 'Portions Copyright (c) Facebook, Inc. and its affiliates.' 'Portions Copyright (c) Meta Platforms, Inc. and affiliates.' `rg -l Facebook`
  sd -s 'Copyright (c) Facebook, Inc. and its affiliates.' 'Copyright (c) Meta Platforms, Inc. and affiliates.' `rg -l Facebook`

Differential Revision: D33420114

fbshipit-source-id: 49ae00a7b62e3b8cc6c5dd839b3c104a75e72a56
2022-01-05 14:43:32 -08:00

2690 lines
59 KiB
Python

# coding=utf-8
# -*- coding: utf-8 -*-
# Copyright (c) Meta Platforms, Inc. and affiliates.
# Copyright (c) Mercurial Contributors.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
import os
import sys
from edenscm.mercurial.pycompat import decodeutf8
from testutil.dott import feature, sh, shlib, testtmp # noqa: F401
sh % "setconfig experimental.allowfilepeer=True"
sh % "enable commitextras"
sh % "setconfig 'ui.allowemptycommit=1'"
sh % "HGENCODING=utf-8"
sh % "cat" << r'''
import edenscm.mercurial.revset
baseset = edenscm.mercurial.revset.baseset
def r3232(repo, subset, x):
""""simple revset that return [3,2,3,2]
revisions duplicated on purpose.
"""
if 3 not in subset:
if 2 in subset:
return baseset([2,2], repo=repo)
return baseset(repo=repo)
return baseset([3,3,2,2], repo=repo)
edenscm.mercurial.revset.symbols['r3232'] = r3232
''' > "testrevset.py"
(
sh % "cat"
<< r"""
[extensions]
testrevset=$TESTTMP/testrevset.py
"""
>> "$HGRCPATH"
)
def _try(*args):
return sh.hg("debugrevspec", "--debug", *args)
def trylist(*args):
return sh.hg("debugrevlistspec", "--debug", *args)
def log(arg):
return sh.hg("log", "-T", "{rev}\n", "-r", arg)
_currentbranch = None
def setbranch(branch):
global _currentbranch
_currentbranch = branch
def commit(*args):
if _currentbranch:
sh.hg("bookmark", "-i")
sh.hg("commit", "--extra=branch=%s" % _currentbranch, *args)
sh.hg("bookmark", "-f", "--", _currentbranch)
os.environ[_currentbranch] = sh.hg("log", "-r", ".", "-T", "{node}")
else:
sh.hg("commit", *args)
shlib.__dict__.update(
{
"try": _try,
"trylist": trylist,
"log": log,
"setbranch": setbranch,
"commit": commit,
}
)
# extension to build '_intlist()' and '_hexlist()', which is necessary because
# these predicates use '\0' as a separator:
sh % "cat" << r"""
from __future__ import absolute_import
from edenscm.mercurial import (
node as nodemod,
registrar,
revset,
revsetlang,
smartset,
)
cmdtable = {}
command = registrar.command(cmdtable)
@command('debugrevlistspec',
[('', 'optimize', None, 'print parsed tree after optimizing'),
('', 'bin', None, 'unhexlify arguments')])
def debugrevlistspec(ui, repo, fmt, *args, **opts):
if opts['bin']:
args = map(nodemod.bin, args)
expr = revsetlang.formatspec(fmt, list(args))
if ui.verbose:
tree = revsetlang.parse(expr, lookup=repo.__contains__)
ui.note(revsetlang.prettyformat(tree), "\n")
if opts["optimize"]:
opttree = revsetlang.optimize(revsetlang.analyze(tree))
ui.note("* optimized:\n", revsetlang.prettyformat(opttree),
"\n")
func = revset.match(ui, expr, repo)
revs = func(repo)
if ui.verbose:
ui.note("* set:\n", smartset.prettyformat(revs), "\n")
for c in revs:
ui.write("%s\n" % c)
""" > "debugrevlistspec.py"
(
sh % "cat"
<< r"""
[extensions]
debugrevlistspec = $TESTTMP/debugrevlistspec.py
"""
>> "$HGRCPATH"
)
sh % "hg init repo"
sh % "cd repo"
sh % "echo a" > "a"
sh % "setbranch a"
sh % "commit -Aqm0"
sh % "echo b" > "b"
sh % "setbranch b"
sh % "commit -Aqm1"
sh % "rm a"
sh % "setbranch a-b-c-"
sh % "commit -Aqm2 -u Bob"
sh % "hg log -r 'extra('\\''branch'\\'', '\\''a-b-c-'\\'')' --template '{rev}\\n'" == "2"
sh % "hg log -r 'extra('\\''branch'\\'')' --template '{rev}\\n'" == r"""
0
1
2"""
sh % "hg log -r 'extra('\\''branch'\\'', '\\''re:a'\\'')' --template '{rev} {branch}\\n'" == r"""
0 a
2 a-b-c-"""
sh % "hg co 1" == """
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(leaving bookmark a-b-c-)"""
sh % "setbranch +a+b+c+"
sh % "commit -Aqm3"
sh % "hg co -C 2" == """
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
(leaving bookmark +a+b+c+)"""
sh % "echo bb" > "b"
sh % "setbranch -a-b-c-"
sh % "commit -Aqm4 -d 'May 12 2005 UTC'"
sh % "hg co -C 3" == """
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
(leaving bookmark -a-b-c-)"""
sh % "setbranch '!a/b/c/'"
sh % "commit '-Aqm5 bug'"
sh % "hg merge 4" == r"""
1 files updated, 0 files merged, 1 files removed, 0 files unresolved
(branch merge, don't forget to commit)"""
sh % "setbranch _a_b_c_"
sh % "commit '-Aqm6 issue619'"
sh % "setbranch .a.b.c."
sh % "commit -Aqm7"
sh % "setbranch all"
sh % "hg co 4" == """
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
(leaving bookmark .a.b.c.)"""
sh % decodeutf8(b"setbranch '\xc3\xa9'")
sh % "commit -Aqm9"
sh % "hg book -fr 6 1.0"
sh % "echo 'e0cc66ef77e8b6f711815af4e001a6594fde3ba5 1.0'" >> ".hgtags"
sh % "hg book -i"
sh % "hg commit -Aqm 'add 1.0 tag'"
sh % "hg bookmark -r6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
sh % "hg clone --quiet -U -r 7 . ../remote1"
sh % "hg clone --quiet -U -r 8 . ../remote2"
sh % "echo '[paths]'" >> ".hg/hgrc"
sh % "echo 'default = ../remote1'" >> ".hg/hgrc"
# trivial
sh % "try '0:1'" == r"""
(range
(symbol '0')
(symbol '1'))
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:d75937da8da0322d18c3771fb029ffd88b996c89+0:1]>>
0
1"""
sh % "try --optimize ':'" == r"""
(rangeall
None)
* optimized:
(rangeall
None)
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:6a4f54cc779b5949146617ba046459baab4a496f+0:9]>>
0
1
2
3
4
5
6
7
8
9"""
sh % "try '3::6'" == r"""
(dagrange
(symbol '3')
(symbol '6'))
* set:
<nameset+
<spans [904fa392b9415cad2ad08ac82d39bed6cfbcaa1c:e0cc66ef77e8b6f711815af4e001a6594fde3ba5+5:6, 8528aa5637f252b36e034c373e36890ace37524c+3]>>
3
5
6"""
sh % "try '0|1|2'" == r"""
(or
(list
(symbol '0')
(symbol '1')
(symbol '2')))
* set:
<baseset [0, 1, 2]>
0
1
2"""
# names that should work without quoting
sh % "try a" == r"""
(symbol 'a')
* set:
<baseset [0]>
0"""
sh % "try b-a" == r"""
(minus
(symbol 'b')
(symbol 'a'))
* set:
<filteredset
<baseset [1]>,
<not
<baseset [0]>>>
1"""
sh % "try _a_b_c_" == r"""
(symbol '_a_b_c_')
* set:
<baseset [6]>
6"""
sh % "try _a_b_c_-a" == r"""
(minus
(symbol '_a_b_c_')
(symbol 'a'))
* set:
<filteredset
<baseset [6]>,
<not
<baseset [0]>>>
6"""
sh % "try .a.b.c." == r"""
(symbol '.a.b.c.')
* set:
<baseset [7]>
7"""
sh % "try .a.b.c.-a" == r"""
(minus
(symbol '.a.b.c.')
(symbol 'a'))
* set:
<filteredset
<baseset [7]>,
<not
<baseset [0]>>>
7"""
# names that should be caught by fallback mechanism
sh % "try -- -a-b-c-" == r"""
(symbol '-a-b-c-')
* set:
<baseset [4]>
4"""
sh % "log -a-b-c-" == "4"
sh % "try +a+b+c+" == r"""
(symbol '+a+b+c+')
* set:
<baseset [3]>
3"""
sh % "try '+a+b+c+:'" == r"""
(rangepost
(symbol '+a+b+c+'))
* set:
<nameset+
<spans [8528aa5637f252b36e034c373e36890ace37524c:6a4f54cc779b5949146617ba046459baab4a496f+3:9]>>
3
4
5
6
7
8
9"""
sh % "try ':+a+b+c+'" == r"""
(rangepre
(symbol '+a+b+c+'))
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:8528aa5637f252b36e034c373e36890ace37524c+0:3]>>
0
1
2
3"""
sh % "try -- '-a-b-c-:+a+b+c+'" == r"""
(range
(symbol '-a-b-c-')
(symbol '+a+b+c+'))
* set:
<nameset-
<spans [8528aa5637f252b36e034c373e36890ace37524c:2326846efdab34abffaf5ad2e7831f64a8ebb017+3:4]>>
4
3"""
sh % "log '-a-b-c-:+a+b+c+'" == r"""
4
3"""
sh % "try -- -a-b-c--a" == r"""
(minus
(minus
(minus
(negate
(symbol 'a'))
(symbol 'b'))
(symbol 'c'))
(negate
(symbol 'a')))
abort: unknown revision '-a'!
[255]"""
if sys.version_info[0] >= 3:
sh % decodeutf8(
b"try '\xc3\xa9'"
) == """
(symbol 'é')
* set:
<baseset [8]>
8"""
else:
sh % "try '\xc3\xa9'" == r"""
(symbol '\xc3\xa9')
* set:
<baseset [8]>
8"""
# no quoting needed
sh % "log '::a-b-c-'" == r"""
0
1
2"""
# quoting needed
sh % "try '\"-a-b-c-\"-a'" == r"""
(minus
(string '-a-b-c-')
(symbol 'a'))
* set:
<filteredset
<baseset [4]>,
<not
<baseset [0]>>>
4"""
sh % "log '1 or 2'" == r"""
1
2"""
sh % "log '1|2'" == r"""
1
2"""
sh % "log '1 and 2'"
sh % "log '1&2'"
sh % "try '1&2|3'" == r"""
(or
(list
(and
(symbol '1')
(symbol '2'))
(symbol '3')))
* set:
<addset
<baseset []>,
<baseset [3]>>
3"""
sh % "try '1|2&3'" == r"""
(or
(list
(symbol '1')
(and
(symbol '2')
(symbol '3'))))
* set:
<addset
<baseset [1]>,
<baseset []>>
1"""
sh % "try '1&2&3'" == r"""
(and
(and
(symbol '1')
(symbol '2'))
(symbol '3'))
* set:
<baseset []>"""
sh % "try '1|(2|3)'" == r"""
(or
(list
(symbol '1')
(group
(or
(list
(symbol '2')
(symbol '3'))))))
* set:
<addset
<baseset [1]>,
<baseset [2, 3]>>
1
2
3"""
sh % "log 1.0" == "6"
sh % "log a" == "0"
sh % "log 2785f51ee" == "0"
sh % "log 'date(2005)'" == "4"
sh % "log 'date(this is a test)'" == r"""
hg: parse error at 10: unexpected token: symbol
(date(this is a test)
^ here)
[255]"""
sh % "log 'date()'" == r"""
hg: parse error: date requires a string
[255]"""
sh % "log date" == r"""
abort: unknown revision 'date'!
[255]"""
sh % "log 'date('" == r"""
hg: parse error at 5: not a prefix: end
(date(
^ here)
[255]"""
sh % "log 'date(\"\\xy\")'" == r"""
hg: parse error: invalid \x escape* (glob)
[255]"""
sh % "log 'date(tip)'" == r"""
hg: parse error: invalid date: 'tip'
[255]"""
sh % "log '0:date'" == r"""
abort: unknown revision 'date'!
[255]"""
sh % "log '::\"date\"'" == r"""
abort: unknown revision 'date'!
[255]"""
sh % "hg book date -r 4"
sh % "log '0:date'" == r"""
0
1
2
3
4"""
sh % "log '::date'" == r"""
0
1
2
4"""
sh % "log '::\"date\"'" == r"""
0
1
2
4"""
sh % "log 'date(2005) and 1::'" == "4"
sh % "hg book -d date"
# function name should be a symbol
sh % "log '\"date\"(2005)'" == r"""
hg: parse error: not a symbol
[255]"""
# keyword arguments
sh % "log 'extra(branch, value=a)'" == "0"
sh % "log 'extra(branch, a, b)'" == r"""
hg: parse error: extra takes at most 2 positional arguments
[255]"""
sh % "log 'extra(a, label=b)'" == r"""
hg: parse error: extra got multiple values for keyword argument 'label'
[255]"""
sh % "log 'extra(label=branch, default)'" == r"""
hg: parse error: extra got an invalid argument
[255]"""
sh % "log 'extra(branch, foo+bar=baz)'" == r"""
hg: parse error: extra got an invalid argument
[255]"""
sh % "log 'extra(unknown=branch)'" == r"""
hg: parse error: extra got an unexpected keyword argument 'unknown'
[255]"""
sh % "try 'foo=bar|baz'" == r"""
(keyvalue
(symbol 'foo')
(or
(list
(symbol 'bar')
(symbol 'baz'))))
hg: parse error: can't use a key-value pair in this context
[255]"""
# right-hand side should be optimized recursively
sh % "try --optimize 'foo=(not public())'" == r"""
(keyvalue
(symbol 'foo')
(group
(not
(func
(symbol 'public')
None))))
* optimized:
(keyvalue
(symbol 'foo')
(func
(symbol '_notpublic')
None))
hg: parse error: can't use a key-value pair in this context
[255]"""
# relation-subscript operator has the highest binding strength (as function call):
sh % "hg debugrevspec -p parsed 'tip:tip^#generations[-1]'" == r"""
* parsed:
(range
(symbol 'tip')
(relsubscript
(parentpost
(symbol 'tip'))
(symbol 'generations')
(negate
(symbol '1'))))
9
8
7
6
5
4"""
sh % "hg debugrevspec -p parsed --no-show-revs 'not public()#generations[0]'" == r"""
* parsed:
(not
(relsubscript
(func
(symbol 'public')
None)
(symbol 'generations')
(symbol '0')))"""
# left-hand side of relation-subscript operator should be optimized recursively:
sh % "hg debugrevspec -p analyzed -p optimized --no-show-revs '(not public())#generations[0]'" == r"""
* analyzed:
(relsubscript
(not
(func
(symbol 'public')
None))
(symbol 'generations')
(symbol '0'))
* optimized:
(relsubscript
(func
(symbol '_notpublic')
None)
(symbol 'generations')
(symbol '0'))"""
# resolution of subscript and relation-subscript ternary operators:
sh % "hg debugrevspec -p analyzed 'tip[0]'" == r"""
* analyzed:
(subscript
(symbol 'tip')
(symbol '0'))
hg: parse error: can't use a subscript in this context
[255]"""
sh % "hg debugrevspec -p analyzed 'tip#rel[0]'" == r"""
* analyzed:
(relsubscript
(symbol 'tip')
(symbol 'rel')
(symbol '0'))
hg: parse error: unknown identifier: rel
[255]"""
sh % "hg debugrevspec -p analyzed '(tip#rel)[0]'" == r"""
* analyzed:
(subscript
(relation
(symbol 'tip')
(symbol 'rel'))
(symbol '0'))
hg: parse error: can't use a subscript in this context
[255]"""
sh % "hg debugrevspec -p analyzed 'tip#rel[0][1]'" == r"""
* analyzed:
(subscript
(relsubscript
(symbol 'tip')
(symbol 'rel')
(symbol '0'))
(symbol '1'))
hg: parse error: can't use a subscript in this context
[255]"""
sh % "hg debugrevspec -p analyzed 'tip#rel0#rel1[1]'" == r"""
* analyzed:
(relsubscript
(relation
(symbol 'tip')
(symbol 'rel0'))
(symbol 'rel1')
(symbol '1'))
hg: parse error: unknown identifier: rel1
[255]"""
sh % "hg debugrevspec -p analyzed 'tip#rel0[0]#rel1[1]'" == r"""
* analyzed:
(relsubscript
(relsubscript
(symbol 'tip')
(symbol 'rel0')
(symbol '0'))
(symbol 'rel1')
(symbol '1'))
hg: parse error: unknown identifier: rel1
[255]"""
# parse errors of relation, subscript and relation-subscript operators:
sh % "hg debugrevspec '[0]'" == r"""
hg: parse error at 0: not a prefix: [
([0]
^ here)
[255]"""
sh % "hg debugrevspec '.#'" == r"""
hg: parse error at 2: not a prefix: end
(.#
^ here)
[255]"""
sh % "hg debugrevspec '#rel'" == r"""
hg: parse error at 0: not a prefix: #
(#rel
^ here)
[255]"""
sh % "hg debugrevspec '.#rel[0'" == r"""
hg: parse error at 7: unexpected token: end
(.#rel[0
^ here)
[255]"""
sh % "hg debugrevspec '.]'" == r"""
hg: parse error at 1: invalid token
(.]
^ here)
[255]"""
sh % "hg debugrevspec '.#generations[a]'" == r"""
hg: parse error: relation subscript must be an integer
[255]"""
sh % "hg debugrevspec '.#generations[1-2]'" == r"""
hg: parse error: relation subscript must be an integer
[255]"""
# parsed tree at stages:
sh % "hg debugrevspec -p all '()'" == r"""
* parsed:
(group
None)
* expanded:
(group
None)
* concatenated:
(group
None)
* analyzed:
None
* optimized:
None
hg: parse error: missing argument
[255]"""
sh % "hg debugrevspec --no-optimized -p all '()'" == r"""
* parsed:
(group
None)
* expanded:
(group
None)
* concatenated:
(group
None)
* analyzed:
None
hg: parse error: missing argument
[255]"""
sh % "hg debugrevspec -p parsed -p analyzed -p optimized '(0|1)-1'" == r"""
* parsed:
(minus
(group
(or
(list
(symbol '0')
(symbol '1'))))
(symbol '1'))
* analyzed:
(and
(or
(list
(symbol '0')
(symbol '1')))
(not
(symbol '1')))
* optimized:
(difference
(func
(symbol '_list')
(string '0\x001'))
(symbol '1'))
0"""
sh % "hg debugrevspec -p unknown 0" == r"""
abort: invalid stage name: unknown
[255]"""
sh % "hg debugrevspec -p all --optimize 0" == r"""
abort: cannot use --optimize with --show-stage
[255]"""
# verify optimized tree:
sh % "hg debugrevspec --verify '0|1'"
sh % "hg debugrevspec --verify -v -p analyzed -p optimized 'r3232() & 2'" == r"""
* analyzed:
(and
(func
(symbol 'r3232')
None)
(symbol '2'))
* optimized:
(andsmally
(func
(symbol 'r3232')
None)
(symbol '2'))
* analyzed set:
<baseset [2]>
* optimized set:
<baseset [2, 2]>
--- analyzed
+++ optimized
2
+2
[1]"""
sh % "hg debugrevspec --no-optimized --verify-optimized 0" == r"""
abort: cannot use --verify-optimized with --no-optimized
[255]"""
# Test that symbols only get parsed as functions if there's an opening
# parenthesis.
sh % "hg book only -r 9"
sh % "log 'only(only)'" == r"""
8
9"""
# ':y' behaves like '0:y', but can't be rewritten as such since the revision '0'
# may be hidden (issue5385)
sh % "try -p parsed -p analyzed ':'" == r"""
* parsed:
(rangeall
None)
* analyzed:
(rangeall
None)
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:6a4f54cc779b5949146617ba046459baab4a496f+0:9]>>
0
1
2
3
4
5
6
7
8
9"""
sh % "try -p analyzed ':1'" == r"""
* analyzed:
(rangepre
(symbol '1'))
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:d75937da8da0322d18c3771fb029ffd88b996c89+0:1]>>
0
1"""
sh % "try -p analyzed ':(1|2)'" == r"""
* analyzed:
(rangepre
(or
(list
(symbol '1')
(symbol '2'))))
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:5ed5505e9f1c21de2345daabdd7913fe53e4acd2+0:2]>>
0
1
2"""
sh % "try -p analyzed ':(1&2)'" == r"""
* analyzed:
(rangepre
(and
(symbol '1')
(symbol '2')))
* set:
<baseset []>"""
# infix/suffix resolution of ^ operator (issue2884):
# x^:y means (x^):y
sh % "try '1^:2'" == r"""
(range
(parentpost
(symbol '1'))
(symbol '2'))
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:5ed5505e9f1c21de2345daabdd7913fe53e4acd2+0:2]>>
0
1
2"""
sh % "try '1^::2'" == r"""
(dagrange
(parentpost
(symbol '1'))
(symbol '2'))
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:5ed5505e9f1c21de2345daabdd7913fe53e4acd2+0:2]>>
0
1
2"""
sh % "try '9^:'" == r"""
(rangepost
(parentpost
(symbol '9')))
* set:
<nameset+
<spans [d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532c:6a4f54cc779b5949146617ba046459baab4a496f+8:9]>>
8
9"""
# x^:y should be resolved before omitting group operators
sh % "try '1^(:2)'" == r"""
(parent
(symbol '1')
(group
(rangepre
(symbol '2'))))
hg: parse error: ^ expects a number 0, 1, or 2
[255]"""
# x^:y should be resolved recursively
sh % "try 'sort(1^:2)'" == r"""
(func
(symbol 'sort')
(range
(parentpost
(symbol '1'))
(symbol '2')))
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:5ed5505e9f1c21de2345daabdd7913fe53e4acd2+0:2]>>
0
1
2"""
sh % "try '(3^:4)^:2'" == r"""
(range
(parentpost
(group
(range
(parentpost
(symbol '3'))
(symbol '4'))))
(symbol '2'))
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:5ed5505e9f1c21de2345daabdd7913fe53e4acd2+0:2]>>
0
1
2"""
sh % "try '(3^::4)^::2'" == r"""
(dagrange
(parentpost
(group
(dagrange
(parentpost
(symbol '3'))
(symbol '4'))))
(symbol '2'))
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:5ed5505e9f1c21de2345daabdd7913fe53e4acd2+0:2]>>
0
1
2"""
sh % "try '(9^:)^:'" == r"""
(rangepost
(parentpost
(group
(rangepost
(parentpost
(symbol '9'))))))
* set:
<nameset+
<spans [2326846efdab34abffaf5ad2e7831f64a8ebb017:6a4f54cc779b5949146617ba046459baab4a496f+4:9]>>
4
5
6
7
8
9"""
# x^ in alias should also be resolved
sh % "try A --config 'revsetalias.A=1^:2'" == r"""
(symbol 'A')
* expanded:
(range
(parentpost
(symbol '1'))
(symbol '2'))
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:5ed5505e9f1c21de2345daabdd7913fe53e4acd2+0:2]>>
0
1
2"""
sh % "try 'A:2' --config 'revsetalias.A=1^'" == r"""
(range
(symbol 'A')
(symbol '2'))
* expanded:
(range
(parentpost
(symbol '1'))
(symbol '2'))
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:5ed5505e9f1c21de2345daabdd7913fe53e4acd2+0:2]>>
0
1
2"""
# but not beyond the boundary of alias expansion, because the resolution should
# be made at the parsing stage
sh % "try '1^A' --config 'revsetalias.A=:2'" == r"""
(parent
(symbol '1')
(symbol 'A'))
* expanded:
(parent
(symbol '1')
(rangepre
(symbol '2')))
hg: parse error: ^ expects a number 0, 1, or 2
[255]"""
# ancestor can accept 0 or more arguments
sh % "log 'ancestor()'"
sh % "log 'ancestor(1)'" == "1"
sh % "log 'ancestor(4,5)'" == "1"
sh % "log 'ancestor(4,5) and 4'"
sh % "log 'ancestor(0,0,1,3)'" == "0"
sh % "log 'ancestor(3,1,5,3,5,1)'" == "1"
sh % "log 'ancestor(0,1,3,5)'" == "0"
sh % "log 'ancestor(1,2,3,4,5)'" == "1"
# test ancestors
sh % "hg log -G -T '{rev}\\n' --config 'experimental.graphshorten=True'" == r"""
@ 9
o 8
│ o 7
│ o 6
╭─┤
│ o 5
o │ 4
│ o 3
o │ 2
├─╯
o 1
o 0"""
sh % "log 'ancestors(5)'" == r"""
0
1
3
5"""
sh % "log 'ancestor(ancestors(5))'" == "0"
sh % "log '::r3232()'" == r"""
0
1
2
3"""
# test ancestors with depth limit
# (depth=0 selects the node itself)
sh % "log 'reverse(ancestors(9, depth=0))'" == "9"
# (interleaved: '4' would be missing if heap queue were higher depth first)
sh % "log 'reverse(ancestors(8:9, depth=1))'" == r"""
9
8
4"""
# (interleaved: '2' would be missing if heap queue were higher depth first)
sh % "log 'reverse(ancestors(7+8, depth=2))'" == r"""
8
7
6
5
4
2"""
# (walk example above by separate queries)
sh % "log 'reverse(ancestors(8, depth=2)) + reverse(ancestors(7, depth=2))'" == r"""
8
7
6
5
4
2"""
# (walk 2nd and 3rd ancestors)
sh % "log 'reverse(ancestors(7, depth=3, startdepth=2))'" == r"""
5
4
3
2"""
# (interleaved: '4' would be missing if higher-depth ancestors weren't scanned)
sh % "log 'reverse(ancestors(7+8, depth=2, startdepth=2))'" == r"""
5
4
2"""
# (note that 'ancestors(x, depth=y, startdepth=z)' does not identical to
# 'ancestors(x, depth=y) - ancestors(x, depth=z-1)' because a node may have
# multiple depths)
sh % "log 'reverse(ancestors(7+8, depth=2) - ancestors(7+8, depth=1))'" == r"""
5
2"""
# test bad arguments passed to ancestors()
sh % "log 'ancestors(., depth=-1)'" == r"""
hg: parse error: negative depth
[255]"""
sh % "log 'ancestors(., depth=foo)'" == r"""
hg: parse error: ancestors expects an integer depth
[255]"""
# test descendants
sh % "hg log -G -T '{rev}\\n' --config 'experimental.graphshorten=True'" == r"""
@ 9
o 8
│ o 7
│ o 6
╭─┤
│ o 5
o │ 4
│ o 3
o │ 2
├─╯
o 1
o 0"""
# (null is ultimate root and has optimized path)
sh % "log 'null:4 & descendants(null)'" == r"""
0
1
2
3
4"""
# (including merge)
sh % "log ':8 & descendants(2)'" == r"""
2
4
6
7
8"""
# (multiple roots)
sh % "log ':8 & descendants(2+5)'" == r"""
2
4
5
6
7
8"""
# test descendants with depth limit
# (depth=0 selects the node itself)
sh % "log 'descendants(0, depth=0)'" == "0"
sh % "log 'null: & descendants(null, depth=0)'" == ""
# (p2 = null should be ignored)
sh % "log 'null: & descendants(null, depth=2)'" == ""
# (multiple paths: depth(6) = (2, 3))
sh % "log 'descendants(1+3, depth=2)'" == r"""
1
2
3
4
5
6"""
# (multiple paths: depth(5) = (1, 2), depth(6) = (2, 3))
sh % "log 'descendants(3+1, depth=2, startdepth=2)'" == r"""
4
5
6"""
# (multiple depths: depth(6) = (0, 2, 4), search for depth=2)
sh % "log 'descendants(0+3+6, depth=3, startdepth=1)'" == r"""
1
2
3
4
5
6
7"""
# (multiple depths: depth(6) = (0, 4), no match)
sh % "log 'descendants(0+6, depth=3, startdepth=1)'" == r"""
1
2
3
4
5
7"""
# test ancestors/descendants relation subscript:
sh % "log 'tip#generations[0]'" == "9"
sh % "log '.#generations[-1]'" == "8"
sh % "log '.#g[(-1)]'" == "8"
sh % "hg debugrevspec -p parsed 'roots(:)#g[2]'" == r"""
* parsed:
(relsubscript
(func
(symbol 'roots')
(rangeall
None))
(symbol 'g')
(symbol '2'))
2
3"""
# test author
sh % "log 'author(bob)'" == "2"
sh % "log 'author(\"re:bob|test\")'" == r"""
0
1
2
3
4
5
6
7
8
9"""
sh % "log 'author(r\"re:\\S\")'" == r"""
0
1
2
3
4
5
6
7
8
9"""
sh % "log 'children(ancestor(4,5))'" == r"""
2
3"""
sh % "log 'children(4)'" == r"""
6
8"""
sh % "log 'children(null)'" == ""
sh % "log 'closed()'"
sh % "log 'contains(a)'" == r"""
0
1
3
5"""
sh % "log 'contains(\"../repo/a\")'" == r"""
0
1
3
5"""
sh % "log 'desc(B)'" == "5"
sh % "hg log -r 'desc(r\"re:S?u\")' --template '{rev} {desc|firstline}\\n'" == r"""
5 5 bug
6 6 issue619"""
sh % "log 'descendants(2 or 3)'" == r"""
2
3
4
5
6
7
8
9"""
sh % "log 'file(\"b*\")'" == r"""
1
4"""
sh % "log 'filelog(\"b\")'" == r"""
1
4"""
sh % "log 'filelog(\"../repo/b\")'" == r"""
1
4"""
sh % "log 'follow()'" == r"""
0
1
2
4
8
9"""
sh % "log 'grep(\"issue\\\\d+\")'" == "6"
sh % "try 'grep(\"(\")'" == r"""
(func
(symbol 'grep')
(string '('))
hg: parse error: invalid match pattern: * (glob)
[255]"""
sh % "try 'grep(\"\\bissue\\\\d+\")'" == r"""
(func
(symbol 'grep')
(string '\x08issue\\d+'))
* set:
<filteredset
<fullreposet+ [0..=9]>,
<grep '\x08issue\\d+'>>"""
sh % "try 'grep(r\"\\bissue\\d+\")'" == r"""
(func
(symbol 'grep')
(string '\\bissue\\d+'))
* set:
<filteredset
<fullreposet+ [0..=9]>,
<grep '\\bissue\\d+'>>
6"""
sh % "try 'grep(r\"\\\")'" == r"""
hg: parse error at 7: unterminated string
(grep(r"\")
^ here)
[255]"""
sh % "log 'head()'" == r"""
7
9"""
sh % "log 'heads(6::)'" == "7"
sh % "log 'keyword(issue)'" == "6"
sh % "log 'keyword(\"test a\")'"
# Test first (=limit) and last
sh % "log 'limit(head(), 1)'" == "7"
sh % "log 'limit(author(\"re:bob|test\"), 3, 5)'" == r"""
5
6
7"""
sh % "log 'limit(author(\"re:bob|test\"), offset=6)'" == "6"
sh % "log 'limit(author(\"re:bob|test\"), offset=10)'"
sh % "log 'limit(all(), 1, -1)'" == r"""
hg: parse error: negative offset
[255]"""
sh % "log 'limit(all(), -1)'" == r"""
hg: parse error: negative number to select
[255]"""
sh % "log 'limit(all(), 0)'"
sh % "log 'last(all(), -1)'" == r"""
hg: parse error: negative number to select
[255]"""
sh % "log 'last(all(), 0)'"
sh % "log 'last(all(), 1)'" == "9"
sh % "log 'last(all(), 2)'" == r"""
8
9"""
# Test smartset.slice() by first/last()
# (using unoptimized set, filteredset as example)
sh % "hg debugrevspec --no-show-revs -s '0:7 & all()'" == r"""
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:013af1973af4a1932911a575960a876af6c02aaa+0:7]>>"""
sh % "log 'limit(0:7 & all(), 3, 4)'" == r"""
4
5
6"""
sh % "log 'limit(7:0 & all(), 3, 4)'" == r"""
3
2
1"""
sh % "log 'last(0:7 & all(), 2)'" == r"""
6
7"""
# (using baseset)
sh % "hg debugrevspec --no-show-revs -s 0+1+2+3+4+5+6+7" == r"""
* set:
<baseset [0, 1, 2, 3, 4, 5, 6, 7]>"""
sh % "hg debugrevspec --no-show-revs -s '0::7'" == r"""
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:013af1973af4a1932911a575960a876af6c02aaa+0:7]>>"""
sh % "log 'limit(0+1+2+3+4+5+6+7, 3, 4)'" == r"""
4
5
6"""
sh % "log 'limit(sort(0::7, rev), 3, 4)'" == r"""
4
5
6"""
sh % "log 'limit(sort(0::7, -rev), 3, 4)'" == r"""
3
2
1"""
sh % "log 'last(sort(0::7, rev), 2)'" == r"""
6
7"""
sh % "hg debugrevspec -s 'limit(sort(0::7, rev), 3, 6)'" == r"""
* set:
<nameset+
<spans [e0cc66ef77e8b6f711815af4e001a6594fde3ba5:013af1973af4a1932911a575960a876af6c02aaa+6:7]>>
6
7"""
sh % "hg debugrevspec -s 'limit(sort(0::7, rev), 3, 9)'" == r"""
* set:
<baseset []>"""
sh % "hg debugrevspec -s 'limit(sort(0::7, -rev), 3, 6)'" == r"""
* set:
<nameset-
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:d75937da8da0322d18c3771fb029ffd88b996c89+0:1]>>
1
0"""
sh % "hg debugrevspec -s 'limit(sort(0::7, -rev), 3, 9)'" == r"""
* set:
<nameset-
<spans []>>"""
sh % "hg debugrevspec -s 'limit(0::7, 0)'" == r"""
* set:
<baseset []>"""
# (using spanset)
sh % "hg debugrevspec --no-show-revs -s '0:7'" == r"""
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:013af1973af4a1932911a575960a876af6c02aaa+0:7]>>"""
sh % "log 'limit(0:7, 3, 4)'" == r"""
4
5
6"""
sh % "log 'limit(7:0, 3, 4)'" == r"""
3
2
1"""
sh % "log 'limit(0:7, 3, 6)'" == r"""
6
7"""
sh % "log 'limit(7:0, 3, 6)'" == r"""
1
0"""
sh % "log 'last(0:7, 2)'" == r"""
6
7"""
sh % "hg debugrevspec -s 'limit(0:7, 3, 6)'" == r"""
* set:
<nameset+
<spans [e0cc66ef77e8b6f711815af4e001a6594fde3ba5:013af1973af4a1932911a575960a876af6c02aaa+6:7]>>
6
7"""
sh % "hg debugrevspec -s 'limit(0:7, 3, 9)'" == r"""
* set:
<baseset []>"""
sh % "hg debugrevspec -s 'limit(7:0, 3, 6)'" == r"""
* set:
<nameset-
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:d75937da8da0322d18c3771fb029ffd88b996c89+0:1]>>
1
0"""
sh % "hg debugrevspec -s 'limit(7:0, 3, 9)'" == r"""
* set:
<nameset-
<spans []>>"""
sh % "hg debugrevspec -s 'limit(0:7, 0)'" == r"""
* set:
<baseset []>"""
# Test order of first/last revisions
sh % "hg debugrevspec -s 'first(4:0, 3) & 3:'" == r"""
* set:
<nameset-
<spans [8528aa5637f252b36e034c373e36890ace37524c:2326846efdab34abffaf5ad2e7831f64a8ebb017+3:4]>>
4
3"""
sh % "hg debugrevspec -s '3: & first(4:0, 3)'" == r"""
* set:
<nameset+
<spans [8528aa5637f252b36e034c373e36890ace37524c:2326846efdab34abffaf5ad2e7831f64a8ebb017+3:4]>>
3
4"""
sh % "hg debugrevspec -s 'last(4:0, 3) & :1'" == r"""
* set:
<nameset-
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:d75937da8da0322d18c3771fb029ffd88b996c89+0:1]>>
1
0"""
sh % "hg debugrevspec -s ':1 & last(4:0, 3)'" == r"""
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:d75937da8da0322d18c3771fb029ffd88b996c89+0:1]>>
0
1"""
# Test scmutil.revsingle() should return the last revision
sh % "hg debugrevspec -s 'last(0::)'" == r"""
* set:
<nameset+
<spans [6a4f54cc779b5949146617ba046459baab4a496f+9]>>
9"""
sh % "hg identify -r '0::' --num" == "9"
# Test matching
sh % "log 'matching(6)'" == "6"
sh % "log 'matching(6:7, \"phase parents user date branch summary files description\")'" == r"""
6
7"""
# Testing min and max
# max: simple
sh % "log 'max(contains(a))'" == "5"
# max: simple on unordered set)
sh % "log 'max((4+0+2+5+7) and contains(a))'" == "5"
# max: no result
sh % "log 'max(contains(stringthatdoesnotappearanywhere))'"
# max: no result on unordered set
sh % "log 'max((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'"
# min: simple
sh % "log 'min(contains(a))'" == "0"
# min: simple on unordered set
sh % "log 'min((4+0+2+5+7) and contains(a))'" == "0"
# min: empty
sh % "log 'min(contains(stringthatdoesnotappearanywhere))'"
# min: empty on unordered set
sh % "log 'min((4+0+2+5+7) and contains(stringthatdoesnotappearanywhere))'"
sh % "log 'merge()'" == "6"
sh % "log 'modifies(b)'" == "4"
sh % "log 'modifies(\"path:b\")'" == "4"
sh % "log 'modifies(\"*\")'" == r"""
4
6"""
sh % "log 'modifies(\"set:modified()\")'" == "4"
sh % "log 'id(5)'" == "2"
sh % "log 'only(9)'" == r"""
8
9"""
sh % "log 'only(8)'" == "8"
sh % "log 'only(9, 5)'" == r"""
2
4
8
9"""
sh % "log 'only(7 + 9, 5 + 2)'" == r"""
4
6
7
8
9"""
# Test empty set input
sh % "log 'only(p2())'"
sh % "log 'only(p1(), p2())'" == r"""
0
1
2
4
8
9"""
# Test '%' operator
sh % "log '9%'" == r"""
8
9"""
sh % "log '9%5'" == r"""
2
4
8
9"""
sh % "log '(7 + 9)%(5 + 2)'" == r"""
4
6
7
8
9"""
# Test operand of '%' is optimized recursively (issue4670)
sh % "try --optimize '8:9-8%'" == r"""
(onlypost
(minus
(range
(symbol '8')
(symbol '9'))
(symbol '8')))
* optimized:
(func
(symbol 'only')
(difference
(range
(symbol '8')
(symbol '9'))
(symbol '8')))
* set:
<nameset+
<spans [d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532c:6a4f54cc779b5949146617ba046459baab4a496f+8:9]>>
8
9"""
sh % "try --optimize '(9)%(5)'" == r"""
(only
(group
(symbol '9'))
(group
(symbol '5')))
* optimized:
(func
(symbol 'only')
(list
(symbol '9')
(symbol '5')))
* set:
<nameset+
<spans [d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532c:6a4f54cc779b5949146617ba046459baab4a496f+8:9, 2326846efdab34abffaf5ad2e7831f64a8ebb017+4, 5ed5505e9f1c21de2345daabdd7913fe53e4acd2+2]>>
2
4
8
9"""
# Test the order of operations
sh % "log '7 + 9%5 + 2'" == r"""
7
2
4
8
9"""
# Test explicit numeric revision
sh % "log 'rev(-2)'"
sh % "log 'rev(-1)'" == "-1"
sh % "log 'rev(0)'" == "0"
sh % "log 'rev(9)'" == "9"
sh % "log 'rev(10)'"
sh % "log 'rev(tip)'" == r"""
hg: parse error: rev expects a number
[255]"""
# Test hexadecimal revision
sh % "log 'id(2)'" == r"""
abort: 00changelog.i@2: ambiguous identifier!
[255]"""
sh % "log 'id(23268)'" == "4"
sh % "log 'id(2785f51eece)'" == "0"
sh % "log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532c)'" == "8"
sh % "log 'id(d5d0dcbdc4a)'"
sh % "log 'id(d5d0dcbdc4w)'"
sh % "log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532d)'"
sh % "log 'id(d5d0dcbdc4d9ff5dbb2d336f32f0bb561c1a532q)'"
sh % "log 'id(1.0)'"
sh % "log 'id(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)'"
# Test null revision
sh % "log '(null)'" == "-1"
sh % "log '(null:0)'" == r"""
-1
0"""
sh % "log '(0:null)'" == "0"
sh % "log 'null::0'" == "0"
sh % "log 'null:tip - 0:'" == "-1"
sh % "log 'null: and null::'" | "head -1" == "0"
sh % "log 'null: or 0:'" | "head -2" == r"""
-1
0"""
sh % "log 'ancestors(null)'" == "-1"
sh % "log 'reverse(null:)'" | "tail -2" == r"""
0
-1"""
sh % "log 'first(null:)'" == "-1"
sh % "log 'min(null:)'"
# BROKEN: should be '-1'
sh % "log 'tip:null and all()'" | "tail -2" == r"""
1
0"""
# Test working-directory revision
sh % "hg debugrevspec 'wdir()'" == "2147483647"
sh % "hg debugrevspec 'wdir()^'" == "9"
sh % "hg up 7" == "0 files updated, 0 files merged, 1 files removed, 0 files unresolved"
sh % "hg debugrevspec 'wdir()^'" == "7"
sh % "hg debugrevspec 'wdir()^0'" == "2147483647"
sh % "hg debugrevspec 'wdir()~3'" == r"""
abort: working directory revision cannot be specified
[255]"""
sh % "hg debugrevspec 'ancestors(wdir())'" == r"""
abort: 2147483647 cannot be found!
[255]"""
sh % "hg debugrevspec 'wdir()~0'" == r"""
abort: working directory revision cannot be specified
[255]"""
sh % "hg debugrevspec 'p1(wdir())'" == "7"
sh % "hg debugrevspec 'p2(wdir())'"
sh % "hg debugrevspec 'parents(wdir())'" == r"""
abort: 2147483647 cannot be found!
[255]"""
sh % "hg debugrevspec 'wdir()^1'" == "7"
sh % "hg debugrevspec 'wdir()^2'"
sh % "hg debugrevspec 'wdir()^3'" == r"""
hg: parse error: ^ expects a number 0, 1, or 2
[255]"""
# DAG ranges with wdir()
sh % "hg debugrevspec 'wdir()::1'"
sh % "hg debugrevspec 'wdir()::wdir()'" == r"""
abort: 2147483647 cannot be found!
[255]"""
sh % "hg debugrevspec 'wdir()::(1+wdir())'" == r"""
abort: 2147483647 cannot be found!
[255]"""
sh % "hg debugrevspec '6::wdir()'" == r"""
abort: 2147483647 cannot be found!
[255]"""
sh % "hg debugrevspec '5::(wdir()+7)'" == r"""
abort: 2147483647 cannot be found!
[255]"""
sh % "hg debugrevspec '(1+wdir())::(2+wdir())'" == r"""
abort: 2147483647 cannot be found!
[255]"""
# For tests consistency
sh % "hg up 9" == "1 files updated, 0 files merged, 0 files removed, 0 files unresolved"
sh % "hg debugrevspec 'tip or wdir()'" == r"""
9
2147483647"""
sh % "hg debugrevspec '0:tip and wdir()'"
sh % "log '0:wdir()'" | "tail -3" == r"""
abort: 2147483647 cannot be found!
[255]"""
sh % "log 'wdir():0'" | "head -3" == r"""
2147483647
9
8"""
sh % "log 'wdir():wdir()'" == "2147483647"
sh % "log '(all() + wdir()) & min(. + wdir())'" == "9"
sh % "log '(all() + wdir()) & max(. + wdir())'" == ""
sh % "log 'first(wdir() + .)'" == "2147483647"
sh % "log 'last(. + wdir())'" == "2147483647"
# Test working-directory integer revision and node id
# (BUG: '0:wdir()' is still needed to populate wdir revision)
sh % "hg debugrevspec '0:wdir() & 2147483647'" == ""
sh % "hg debugrevspec '0:wdir() & rev(2147483647)'" == r"""
abort: 2147483647 cannot be found!
[255]"""
sh % "hg debugrevspec '0:wdir() & ffffffffffffffffffffffffffffffffffffffff'" == ""
sh % "hg debugrevspec '0:wdir() & ffffffffffff'" == r"""
abort: unknown revision 'ffffffffffff'!
[255]"""
sh % "hg debugrevspec '0:wdir() & id(ffffffffffffffffffffffffffffffffffffffff)'" == r"""
abort: 2147483647 cannot be found!
[255]"""
sh % "hg debugrevspec '0:wdir() & id(ffffffffffff)'" == ""
sh % "cd .."
# Test short 'ff...' hash collision
# (BUG: '0:wdir()' is still needed to populate wdir revision)
sh % "hg init wdir-hashcollision"
sh % "cd wdir-hashcollision"
(
sh % "cat"
<< r"""
[experimental]
evolution.createmarkers=True
"""
>> ".hg/hgrc"
)
sh % "echo 0" > "a"
sh % "hg ci -qAm 0"
for i in [2463, 2961, 6726, 78127]:
sh.hg("up", "-q", "0")
with open("a", "wb") as f:
f.write(b"%i\n" % i)
sh.hg("ci", "-qm", "%s" % i)
sh % "hg up -q null"
sh % "hg log -r '0:wdir()' -T '{rev}:{node} {shortest(node, 3)}\\n'" == r"""
abort: 2147483647 cannot be found!
[255]"""
sh % "hg debugobsolete fffbae3886c8fbb2114296380d276fd37715d571" == ""
sh % "hg debugrevspec '0:wdir() & fff'" == r"""
abort: 00changelog.i@fff: ambiguous identifier!
[255]"""
sh % "hg debugrevspec '0:wdir() & ffff'" == "4"
sh % "hg debugrevspec '0:wdir() & fffb'" == r"""
abort: 00changelog.i@fffb: ambiguous identifier!
[255]"""
# BROKEN should be '2' (node lookup uses unfiltered repo since dc25ed84bee8)
sh % "hg debugrevspec '0:wdir() & id(fffb)'" == r"""
abort: 00changelog.i@fffb: ambiguous identifier!
[255]"""
sh % "hg debugrevspec '0:wdir() & ffff8'" == "4"
sh % "hg debugrevspec '0:wdir() & fffff'" == r"""
abort: unknown revision 'fffff'!
[255]"""
sh % "cd .."
sh % "cd repo"
sh % "log 'outgoing()'" == r"""
8
9"""
sh % "log 'outgoing(\"../remote1\")'" == r"""
8
9"""
sh % "log 'outgoing(\"../remote2\")'" == r"""
3
5
6
7
9"""
sh % "log 'p1(merge())'" == "5"
sh % "log 'p2(merge())'" == "4"
sh % "log 'parents(merge())'" == r"""
4
5"""
sh % "log 'removes(a)'" == r"""
2
6"""
sh % "log 'roots(all())'" == "0"
sh % "log 'reverse(2 or 3 or 4 or 5)'" == r"""
5
4
3
2"""
sh % "log 'reverse(all())'" == r"""
9
8
7
6
5
4
3
2
1
0"""
sh % "log 'reverse(all()) & filelog(b)'" == r"""
4
1"""
sh % "log 'rev(5)'" == "5"
sh % "log 'sort(limit(reverse(all()), 3))'" == r"""
7
8
9"""
sh % "log 'sort(2 or 3 or 4 or 5, date)'" == r"""
2
3
5
4"""
# Test order of revisions in compound expression
# ----------------------------------------------
# The general rule is that only the outermost (= leftmost) predicate can
# enforce its ordering requirement. The other predicates should take the
# ordering defined by it.
# 'A & B' should follow the order of 'A':
sh % "log '2:0 & 0::2'" == r"""
2
1
0"""
# 'head()' combines sets in right order:
sh % "log '9:7 & head()'" == r"""
9
7"""
# 'x:y' takes ordering parameter into account:
sh % "try -p optimized '3:0 & 0:3 & not 2:1'" == r"""
* optimized:
(difference
(and
(range
(symbol '3')
(symbol '0'))
(range
(symbol '0')
(symbol '3')))
(range
(symbol '2')
(symbol '1')))
* set:
<nameset-
<spans [8528aa5637f252b36e034c373e36890ace37524c+3, 2785f51eece5a23075c6f1d74702d8d9cb8bf0d4+0]>>
3
0"""
# 'a + b', which is optimized to '_list(a b)', should take the ordering of
# the left expression:
sh % "try --optimize '2:0 & (0 + 1 + 2)'" == r"""
(and
(range
(symbol '2')
(symbol '0'))
(group
(or
(list
(symbol '0')
(symbol '1')
(symbol '2')))))
* optimized:
(and
(range
(symbol '2')
(symbol '0'))
(func
(symbol '_list')
(string '0\x001\x002')))
* set:
<nameset-
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:5ed5505e9f1c21de2345daabdd7913fe53e4acd2+0:2]>>
2
1
0"""
# 'A + B' should take the ordering of the left expression:
sh % "try --optimize '2:0 & (0:1 + 2)'" == r"""
(and
(range
(symbol '2')
(symbol '0'))
(group
(or
(list
(range
(symbol '0')
(symbol '1'))
(symbol '2')))))
* optimized:
(and
(range
(symbol '2')
(symbol '0'))
(or
(list
(range
(symbol '0')
(symbol '1'))
(symbol '2'))))
* set:
<nameset-
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:5ed5505e9f1c21de2345daabdd7913fe53e4acd2+0:2]>>
2
1
0"""
# '_intlist(a b)' should behave like 'a + b':
sh % "trylist --optimize '2:0 & %ld' 0 1 2" == r"""
(and
(range
(symbol '2')
(symbol '0'))
(func
(symbol '_intlist')
(string '0\x001\x002')))
* optimized:
(andsmally
(range
(symbol '2')
(symbol '0'))
(func
(symbol '_intlist')
(string '0\x001\x002')))
* set:
<nameset-
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:5ed5505e9f1c21de2345daabdd7913fe53e4acd2+0:2]>>
2
1
0"""
sh % "trylist --optimize '%ld & 2:0' 0 2 1" == r"""
(and
(func
(symbol '_intlist')
(string '0\x002\x001'))
(range
(symbol '2')
(symbol '0')))
* optimized:
(and
(func
(symbol '_intlist')
(string '0\x002\x001'))
(range
(symbol '2')
(symbol '0')))
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:5ed5505e9f1c21de2345daabdd7913fe53e4acd2+0:2]>>
0
1
2"""
# '_hexlist(a b)' should behave like 'a + b':
args = sh.hg("log", "-T", "{node} ", "-r0:2")
sh % (
"trylist --optimize --bin '2:0 & %%ln' %s" % args
) == r"""
(and
(range
(symbol '2')
(symbol '0'))
(func
(symbol '_hexlist')
(string '2785f51eece5a23075c6f1d74702d8d9cb8bf0d4\x00d75937da8da0322d18c3771fb029ffd88b996c89\x005ed5505e9f1c21de2345daabdd7913fe53e4acd2')))
* optimized:
(and
(range
(symbol '2')
(symbol '0'))
(func
(symbol '_hexlist')
(string '2785f51eece5a23075c6f1d74702d8d9cb8bf0d4\x00d75937da8da0322d18c3771fb029ffd88b996c89\x005ed5505e9f1c21de2345daabdd7913fe53e4acd2')))
* set:
<nameset-
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:5ed5505e9f1c21de2345daabdd7913fe53e4acd2+0:2]>>
2
1
0"""
args = sh.hg("log", "-T", "{node} ", "-r0+2+1")
sh % (
"trylist --optimize --bin '%%ln & 2:0' %s" % args
) == r"""
(and
(func
(symbol '_hexlist')
(string '*')) (glob)
(range
(symbol '2')
(symbol '0')))
* optimized:
(andsmally
(func
(symbol '_hexlist')
(string '*')) (glob)
(range
(symbol '2')
(symbol '0')))
* set:
<baseset [0, 2, 1]>
0
2
1"""
# '_list' should not go through the slow follow-order path if order doesn't
# matter:
sh % "try -p optimized '2:0 & not (0 + 1)'" == r"""
* optimized:
(difference
(range
(symbol '2')
(symbol '0'))
(func
(symbol '_list')
(string '0\x001')))
* set:
<nameset-
<spans [5ed5505e9f1c21de2345daabdd7913fe53e4acd2+2]>>
2"""
sh % "try -p optimized '2:0 & not (0:2 & (0 + 1))'" == r"""
* optimized:
(difference
(range
(symbol '2')
(symbol '0'))
(and
(range
(symbol '0')
(symbol '2'))
(func
(symbol '_list')
(string '0\x001'))))
* set:
<nameset-
<spans [5ed5505e9f1c21de2345daabdd7913fe53e4acd2+2]>>
2"""
# because 'present()' does nothing other than suppressing an error, the
# ordering requirement should be forwarded to the nested expression
sh % "try -p optimized 'present(2 + 0 + 1)'" == r"""
* optimized:
(func
(symbol 'present')
(func
(symbol '_list')
(string '2\x000\x001')))
* set:
<baseset [2, 0, 1]>
2
0
1"""
sh % "try --optimize '2:0 & present(0 + 1 + 2)'" == r"""
(and
(range
(symbol '2')
(symbol '0'))
(func
(symbol 'present')
(or
(list
(symbol '0')
(symbol '1')
(symbol '2')))))
* optimized:
(and
(range
(symbol '2')
(symbol '0'))
(func
(symbol 'present')
(func
(symbol '_list')
(string '0\x001\x002'))))
* set:
<nameset-
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:5ed5505e9f1c21de2345daabdd7913fe53e4acd2+0:2]>>
2
1
0"""
# 'reverse()' should take effect only if it is the outermost expression:
sh % "try --optimize '0:2 & reverse(all())'" == r"""
(and
(range
(symbol '0')
(symbol '2'))
(func
(symbol 'reverse')
(func
(symbol 'all')
None)))
* optimized:
(and
(range
(symbol '0')
(symbol '2'))
(func
(symbol 'reverse')
(func
(symbol 'all')
None)))
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:5ed5505e9f1c21de2345daabdd7913fe53e4acd2+0:2]>>
0
1
2"""
# 'sort()' should take effect only if it is the outermost expression:
sh % "try --optimize '0:2 & sort(all(), -rev)'" == r"""
(and
(range
(symbol '0')
(symbol '2'))
(func
(symbol 'sort')
(list
(func
(symbol 'all')
None)
(negate
(symbol 'rev')))))
* optimized:
(and
(range
(symbol '0')
(symbol '2'))
(func
(symbol 'sort')
(list
(func
(symbol 'all')
None)
(string '-rev'))))
* set:
<nameset+
<spans [2785f51eece5a23075c6f1d74702d8d9cb8bf0d4:5ed5505e9f1c21de2345daabdd7913fe53e4acd2+0:2]>>
0
1
2"""
# invalid argument passed to noop sort():
sh % "log '0:2 & sort()'" == r"""
hg: parse error: sort requires one or two arguments
[255]"""
sh % "log '0:2 & sort(all(), -invalid)'" == r"""
hg: parse error: unknown sort key '-invalid'
[255]"""
# for 'A & f(B)', 'B' should not be affected by the order of 'A':
sh % "try --optimize '2:0 & first(1 + 0 + 2)'" == r"""
(and
(range
(symbol '2')
(symbol '0'))
(func
(symbol 'first')
(or
(list
(symbol '1')
(symbol '0')
(symbol '2')))))
* optimized:
(and
(range
(symbol '2')
(symbol '0'))
(func
(symbol 'first')
(func
(symbol '_list')
(string '1\x000\x002'))))
* set:
<nameset-
<spans [d75937da8da0322d18c3771fb029ffd88b996c89+1]>>
1"""
sh % "try --optimize '2:0 & not last(0 + 2 + 1)'" == r"""
(and
(range
(symbol '2')
(symbol '0'))
(not
(func
(symbol 'last')
(or
(list
(symbol '0')
(symbol '2')
(symbol '1'))))))
* optimized:
(difference
(range
(symbol '2')
(symbol '0'))
(func
(symbol 'last')
(func
(symbol '_list')
(string '0\x002\x001'))))
* set:
<nameset-
<spans [5ed5505e9f1c21de2345daabdd7913fe53e4acd2+2, 2785f51eece5a23075c6f1d74702d8d9cb8bf0d4+0]>>
2
0"""
# for 'A & (op)(B)', 'B' should not be affected by the order of 'A':
sh % "try --optimize '2:0 & (1 + 0 + 2):(0 + 2 + 1)'" == r"""
(and
(range
(symbol '2')
(symbol '0'))
(range
(group
(or
(list
(symbol '1')
(symbol '0')
(symbol '2'))))
(group
(or
(list
(symbol '0')
(symbol '2')
(symbol '1'))))))
* optimized:
(and
(range
(symbol '2')
(symbol '0'))
(range
(func
(symbol '_list')
(string '1\x000\x002'))
(func
(symbol '_list')
(string '0\x002\x001'))))
* set:
<nameset-
<spans [d75937da8da0322d18c3771fb029ffd88b996c89+1]>>
1"""
# 'A & B' can be rewritten as 'flipand(B, A)' by weight.
sh % "try --optimize 'contains(\"glob:*\") & (2 + 0 + 1)'" == r"""
(and
(func
(symbol 'contains')
(string 'glob:*'))
(group
(or
(list
(symbol '2')
(symbol '0')
(symbol '1')))))
* optimized:
(andsmally
(func
(symbol 'contains')
(string 'glob:*'))
(func
(symbol '_list')
(string '2\x000\x001')))
* set:
<filteredset
<baseset+ [0, 1, 2]>,
<contains 'glob:*'>>
0
1
2"""
# and in this example, 'A & B' is rewritten as 'B & A', but 'A' overrides
# the order appropriately:
sh % "try --optimize 'reverse(contains(\"glob:*\")) & (0 + 2 + 1)'" == r"""
(and
(func
(symbol 'reverse')
(func
(symbol 'contains')
(string 'glob:*')))
(group
(or
(list
(symbol '0')
(symbol '2')
(symbol '1')))))
* optimized:
(andsmally
(func
(symbol 'reverse')
(func
(symbol 'contains')
(string 'glob:*')))
(func
(symbol '_list')
(string '0\x002\x001')))
* set:
<filteredset
<baseset- [0, 1, 2]>,
<contains 'glob:*'>>
2
1
0"""
# test sort revset
# --------------------------------------------
# test when adding two unordered revsets
sh % "log 'sort(keyword(issue) or modifies(b))'" == r"""
4
6"""
# test when sorting a reversed collection in the same way it is
sh % "log 'sort(reverse(all()), -rev)'" == r"""
9
8
7
6
5
4
3
2
1
0"""
# test when sorting a reversed collection
sh % "log 'sort(reverse(all()), rev)'" == r"""
0
1
2
3
4
5
6
7
8
9"""
# test sorting two sorted collections in different orders
sh % "log 'sort(outgoing() or reverse(removes(a)), rev)'" == r"""
2
6
8
9"""
# test sorting two sorted collections in different orders backwards
sh % "log 'sort(outgoing() or reverse(removes(a)), -rev)'" == r"""
9
8
6
2"""
# test empty sort key which is noop
sh % "log 'sort(0 + 2 + 1, \"\")'" == r"""
0
2
1"""
# test invalid sort keys
sh % "log 'sort(all(), -invalid)'" == r"""
hg: parse error: unknown sort key '-invalid'
[255]"""
sh % "cd .."
# test sorting by multiple keys including variable-length strings
sh % "hg init sorting"
sh % "cd sorting"
(
sh % "cat"
<< r"""
[ui]
logtemplate = '{rev} {branch|p5}{desc|p5}{author|p5}{date|hgdate}\n'
[templatealias]
p5(s) = pad(s, 5)
"""
>> ".hg/hgrc"
)
sh % "setbranch b12"
sh % "commit -m m111 -u u112 -d '111 10800'"
sh % "setbranch b11"
sh % "commit -m m12 -u u111 -d '112 7200'"
sh % "setbranch b111"
sh % "commit -m m11 -u u12 -d '111 3600'"
sh % "setbranch b112"
sh % "commit -m m111 -u u11 -d '120 0'"
# compare revisions (has fast path):
sh % "hg log -r 'sort(all(), rev)'" == r"""
0 b12 m111 u112 111 10800
1 b11 m12 u111 112 7200
2 b111 m11 u12 111 3600
3 b112 m111 u11 120 0"""
sh % "hg log -r 'sort(all(), -rev)'" == r"""
3 b112 m111 u11 120 0
2 b111 m11 u12 111 3600
1 b11 m12 u111 112 7200
0 b12 m111 u112 111 10800"""
# compare variable-length strings (issue5218):
sh % "hg log -r 'sort(all(), branch)'" == r"""
1 b11 m12 u111 112 7200
2 b111 m11 u12 111 3600
3 b112 m111 u11 120 0
0 b12 m111 u112 111 10800"""
sh % "hg log -r 'sort(all(), -branch)'" == r"""
0 b12 m111 u112 111 10800
3 b112 m111 u11 120 0
2 b111 m11 u12 111 3600
1 b11 m12 u111 112 7200"""
sh % "hg log -r 'sort(all(), desc)'" == r"""
2 b111 m11 u12 111 3600
0 b12 m111 u112 111 10800
3 b112 m111 u11 120 0
1 b11 m12 u111 112 7200"""
sh % "hg log -r 'sort(all(), -desc)'" == r"""
1 b11 m12 u111 112 7200
0 b12 m111 u112 111 10800
3 b112 m111 u11 120 0
2 b111 m11 u12 111 3600"""
sh % "hg log -r 'sort(all(), user)'" == r"""
3 b112 m111 u11 120 0
1 b11 m12 u111 112 7200
0 b12 m111 u112 111 10800
2 b111 m11 u12 111 3600"""
sh % "hg log -r 'sort(all(), -user)'" == r"""
2 b111 m11 u12 111 3600
0 b12 m111 u112 111 10800
1 b11 m12 u111 112 7200
3 b112 m111 u11 120 0"""
# compare dates (tz offset should have no effect):
sh % "hg log -r 'sort(all(), date)'" == r"""
0 b12 m111 u112 111 10800
2 b111 m11 u12 111 3600
1 b11 m12 u111 112 7200
3 b112 m111 u11 120 0"""
sh % "hg log -r 'sort(all(), -date)'" == r"""
3 b112 m111 u11 120 0
1 b11 m12 u111 112 7200
0 b12 m111 u112 111 10800
2 b111 m11 u12 111 3600"""
# be aware that 'sort(x, -k)' is not exactly the same as 'reverse(sort(x, k))'
# because '-k' reverses the comparison, not the list itself:
sh % "hg log -r 'sort(0 + 2, date)'" == r"""
0 b12 m111 u112 111 10800
2 b111 m11 u12 111 3600"""
sh % "hg log -r 'sort(0 + 2, -date)'" == r"""
0 b12 m111 u112 111 10800
2 b111 m11 u12 111 3600"""
sh % "hg log -r 'reverse(sort(0 + 2, date))'" == r"""
2 b111 m11 u12 111 3600
0 b12 m111 u112 111 10800"""
# sort by multiple keys:
sh % "hg log -r 'sort(all(), \"branch -rev\")'" == r"""
1 b11 m12 u111 112 7200
2 b111 m11 u12 111 3600
3 b112 m111 u11 120 0
0 b12 m111 u112 111 10800"""
sh % "hg log -r 'sort(all(), \"-desc -date\")'" == r"""
1 b11 m12 u111 112 7200
3 b112 m111 u11 120 0
0 b12 m111 u112 111 10800
2 b111 m11 u12 111 3600"""
sh % "hg log -r 'sort(all(), \"user -branch date rev\")'" == r"""
3 b112 m111 u11 120 0
1 b11 m12 u111 112 7200
0 b12 m111 u112 111 10800
2 b111 m11 u12 111 3600"""
# toposort prioritises graph branches
sh % "hg up 2" == """
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
(leaving bookmark b112)"""
sh % "touch a"
sh % "hg addremove" == "adding a"
sh % "hg ci -m t1 -u tu -d '130 0'"
sh % "echo a" >> "a"
sh % "hg ci -m t2 -u tu -d '130 0'"
sh % "hg book book1"
sh % "hg up 4" == r"""
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(leaving bookmark book1)"""
sh % "touch a"
sh % "hg addremove"
sh % "hg ci -m t3 -u tu -d '130 0'"
sh % "hg log -r 'sort(all(), topo)'" == r"""
6 b111 t3 tu 130 0
5 b111 t2 tu 130 0
4 b111 t1 tu 130 0
3 b112 m111 u11 120 0
2 b111 m11 u12 111 3600
1 b11 m12 u111 112 7200
0 b12 m111 u112 111 10800"""
sh % "hg log -r 'sort(all(), -topo)'" == r"""
0 b12 m111 u112 111 10800
1 b11 m12 u111 112 7200
2 b111 m11 u12 111 3600
3 b112 m111 u11 120 0
4 b111 t1 tu 130 0
5 b111 t2 tu 130 0
6 b111 t3 tu 130 0"""
sh % "hg log -r 'sort(all(), topo, topo.firstbranch=book1)'" == r"""
5 b111 t2 tu 130 0
6 b111 t3 tu 130 0
4 b111 t1 tu 130 0
3 b112 m111 u11 120 0
2 b111 m11 u12 111 3600
1 b11 m12 u111 112 7200
0 b12 m111 u112 111 10800"""
# topographical sorting can't be combined with other sort keys, and you can't
# use the topo.firstbranch option when topo sort is not active:
sh % "hg log -r 'sort(all(), \"topo user\")'" == r"""
hg: parse error: topo sort order cannot be combined with other sort keys
[255]"""
sh % "hg log -r 'sort(all(), user, topo.firstbranch=book1)'" == r"""
hg: parse error: topo.firstbranch can only be used when using the topo sort key
[255]"""
# topo.firstbranch should accept any kind of expressions:
sh % "hg log -r 'sort(0, topo, topo.firstbranch=(book1))'" == "0 b12 m111 u112 111 10800"
sh % "cd .."
sh % "cd repo"
# test multiline revset with errors
sh % "hg log -r '\n. +\n.^ +'" == r"""
hg: parse error at 9: not a prefix: end
( . + .^ +
^ here)
[255]"""
# test ancestorspec with multiple base revisions
sh % "log '(. + .^)~1'" == r"""
4
8"""